// ss_prefault_box.h - Box: SuperSlab Page Prefaulting Policy // Purpose: Control SuperSlab prefault strategy (MAP_POPULATE / manual touch) // Box Theory: // - This box owns「いつ / どの程度 pf を前倒しするか」というポリシーだけを担当。 // - 実際の mmap は ss_os_acquire_box(下層)、Superslab 初期化は ss_allocation_box(上層)が担当。 // // Responsibilities: // - HAKMEM_SS_PREFAULT の値から prefault ポリシーを決定 // - 必要に応じて SuperSlab 全域を 1 回だけ touch して page-in する // // ENV: // HAKMEM_SS_PREFAULT=0 Off (既存動作に近い。g_ss_populate_once のワンショットのみ) // HAKMEM_SS_PREFAULT=1 POPULATE (MAP_POPULATE のみ使用) // HAKMEM_SS_PREFAULT=2 TOUCH (MAP_POPULATE + 手動4KB touch) // HAKMEM_SS_PREFAULT=3 ASYNC (予約値。現状は TOUCH と同等に扱う) // // Default: // - 未指定時は 1 (POPULATE) とし、SuperSlab 取得時の page fault を大きく削減する。 #ifndef HAKMEM_SS_PREFAULT_BOX_H #define HAKMEM_SS_PREFAULT_BOX_H #include #include #include typedef enum { SS_PREFAULT_OFF = 0, // No prefault (legacy: g_ss_populate_once のみ) SS_PREFAULT_POPULATE = 1, // MAP_POPULATE only SS_PREFAULT_TOUCH = 2, // MAP_POPULATE + manual page touch SS_PREFAULT_ASYNC = 3 // Reserved for future background prefault } SSPrefaultPolicy; // Return current prefault policy (parsed once from HAKMEM_SS_PREFAULT). static inline SSPrefaultPolicy ss_prefault_policy(void) { static int cached = -1; if (cached != -1) { return (SSPrefaultPolicy)cached; } // 一時的な安全デフォルト: OFF // (4MB MAP_POPULATE 問題の影響を避けつつ、必要なときだけ明示的に ON にする) int policy = SS_PREFAULT_OFF; const char* env = getenv("HAKMEM_SS_PREFAULT"); if (env && *env) { int v = atoi(env); if (v < 0) v = 0; if (v > 3) v = 3; policy = v; } cached = policy; return (SSPrefaultPolicy)policy; } // Prefault a contiguous SuperSlab region by touching one byte per page. // Caller is expected to call this「mmap直後」に 1 回だけ実行する。 static inline void ss_prefault_region(void* addr, size_t size) { SSPrefaultPolicy policy = ss_prefault_policy(); if (policy < SS_PREFAULT_TOUCH) { // POPULATE または OFF の場合は手動 touch は行わない。 return; } if (!addr || size == 0) { return; } long ps = sysconf(_SC_PAGESIZE); size_t page = (ps > 0) ? (size_t)ps : (size_t)4096; volatile char* p = (volatile char*)addr; for (size_t off = 0; off < size; off += page) { (void)p[off]; } // Ensure last byte is also touched (covers exact multiples). (void)p[size - 1]; } #endif // HAKMEM_SS_PREFAULT_BOX_H