// lazy_pages_table.c // // Compact demo of lazy allocation / demand paging. // Prints a summary row every N pages (default 512). // // Linux: // - RSS from /proc/self/statm // - optional PFN/PA from /proc/self/pagemap // // macOS: // - resident size from Mach task_info // - no physical-address reporting in normal user-space // // Build: // cc -O0 -g lazy_pages_table.c -o lazy_pages_table // // Run: // ./lazy_pages_table // ./lazy_pages_table 8192 512 // sudo ./lazy_pages_table 8192 512 // // External inspection while paused: // Linux: cat /proc//smaps // macOS: vmmap #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #ifdef __APPLE__ #include #endif static size_t get_page_size(void) { long p = sysconf(_SC_PAGESIZE); if (p <= 0) { perror("sysconf(_SC_PAGESIZE)"); exit(1); } return (size_t)p; } static size_t get_resident_bytes(void) { #ifdef __linux__ FILE *f = fopen("/proc/self/statm", "r"); if (!f) { perror("fopen(/proc/self/statm)"); exit(1); } unsigned long total_pages = 0, resident_pages = 0; if (fscanf(f, "%lu %lu", &total_pages, &resident_pages) != 2) { fprintf(stderr, "failed to parse /proc/self/statm\n"); fclose(f); exit(1); } fclose(f); return resident_pages * get_page_size(); #elif defined(__APPLE__) struct mach_task_basic_info info; mach_msg_type_number_t count = MACH_TASK_BASIC_INFO_COUNT; kern_return_t kr = task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&info, &count); if (kr != KERN_SUCCESS) { fprintf(stderr, "task_info failed\n"); exit(1); } return (size_t)info.resident_size; #else return 0; #endif } #ifdef __linux__ static int open_pagemap(void) { return open("/proc/self/pagemap", O_RDONLY); } static uint64_t read_pagemap_entry(int fd, void *vaddr, size_t page_size) { uint64_t vpn = (uint64_t)(uintptr_t)vaddr / page_size; off_t offset = (off_t)(vpn * sizeof(uint64_t)); uint64_t entry = 0; ssize_t n = pread(fd, &entry, sizeof(entry), offset); if (n != (ssize_t)sizeof(entry)) { return 0; } return entry; } static int pagemap_present(uint64_t entry) { return (int)((entry >> 63) & 1ULL); } static uint64_t pagemap_pfn(uint64_t entry) { return entry & ((1ULL << 55) - 1); } #endif static void print_header(void) { #ifdef __linux__ printf("%12s %12s %18s %18s %18s %10s\n", "touched", "RSS_KB", "last_VA", "PFN", "PA", "present"); #else printf("%12s %12s %18s %18s %18s %10s\n", "touched", "RSS_KB", "last_VA", "PFN", "PA", "present"); #endif } int main(int argc, char **argv) { size_t page_size = get_page_size(); size_t num_pages = 8192; size_t print_every = 512; if (argc > 1) { num_pages = strtoull(argv[1], NULL, 0); if (num_pages == 0) { fprintf(stderr, "usage: %s [num_pages] [print_every]\n", argv[0]); return 1; } } if (argc > 2) { print_every = strtoull(argv[2], NULL, 0); if (print_every == 0) { fprintf(stderr, "print_every must be > 0\n"); return 1; } } size_t len = num_pages * page_size; printf("PID=%d\n", getpid()); printf("page_size=%zu bytes\n", page_size); printf("mapping=%zu pages (%.2f MiB)\n", num_pages, (double)len / (1024.0 * 1024.0)); #ifdef __linux__ printf("OS=Linux (sudo may be needed for PFN visibility)\n"); printf("inspect with: cat /proc/%d/smaps\n", getpid()); #elif defined(__APPLE__) printf("OS=macOS\n"); printf("inspect with: vmmap %d\n", getpid()); #endif printf("\n"); char *buf = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (buf == MAP_FAILED) { perror("mmap"); return 1; } printf("mapped region: [%p, %p)\n", buf, buf + len); printf("after mmap: RSS_KB=%zu\n\n", get_resident_bytes() / 1024); #ifdef __linux__ int pagemap_fd = open_pagemap(); if (pagemap_fd < 0) { fprintf(stderr, "warning: could not open /proc/self/pagemap: %s\n", strerror(errno)); } #endif print_header(); for (size_t i = 0; i < num_pages; i++) { size_t off = i * page_size; void *va = buf + off; // Force actual allocation of a private page. buf[off] = (char)(i & 0xff); if ((i + 1) % print_every == 0 || i < 8 || i + 1 == num_pages) { size_t rss_kb = get_resident_bytes() / 1024; #ifdef __linux__ if (pagemap_fd >= 0) { uint64_t entry = read_pagemap_entry(pagemap_fd, va, page_size); int present = pagemap_present(entry); uint64_t pfn = pagemap_pfn(entry); if (present && pfn != 0) { uintptr_t pa = (uintptr_t)(pfn * page_size) + ((uintptr_t)va & (page_size - 1)); printf("%12zu %12zu %18p %18" PRIx64 " %18" PRIxPTR " %10d\n", i + 1, rss_kb, va, pfn, pa, present); } else { printf("%12zu %12zu %18p %18s %18s %10d\n", i + 1, rss_kb, va, present ? "" : "", present ? "" : "", present); } } else { printf("%12zu %12zu %18p %18s %18s %10s\n", i + 1, rss_kb, va, "", "", "?"); } #else printf("%12zu %12zu %18p %18s %18s %10s\n", i + 1, rss_kb, va, "N/A", "N/A", "N/A"); #endif } } #ifdef __linux__ if (pagemap_fd >= 0) { close(pagemap_fd); } #endif printf("\nDone touching %zu pages.\n", num_pages); printf("Press Enter to exit...\n"); getchar(); if (munmap(buf, len) != 0) { perror("munmap"); return 1; } return 0; }