81 lines
2.9 KiB
C
81 lines
2.9 KiB
C
|
|
// 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 <stddef.h>
|
|||
|
|
#include <stdlib.h>
|
|||
|
|
#include <unistd.h>
|
|||
|
|
|
|||
|
|
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
|