This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
realtime:documentation:howto:applications:memory:mlockall_globals_sample [2017/06/08 17:26] jithu |
realtime:documentation:howto:applications:memory:mlockall_globals_sample [2017/06/10 00:28] (current) jithu |
||
---|---|---|---|
Line 3: | Line 3: | ||
<code c> | <code c> | ||
- | /* This application checks whether mlockall() forces all pages of a | + | /* |
+ | * # gcc -o check_global check_global.c -Wall -O3 | ||
+ | * # ./check_global | ||
+ | * # ./check_global -nolockmem (will cause faults) | ||
+ | * This application checks whether mlockall() forces all pages of a | ||
* global array into RAM. Normally, the OS maps a 'copy on write' MMU page | * global array into RAM. Normally, the OS maps a 'copy on write' MMU page | ||
* to such arrays meaning that reading from the array returns only zeros and | * to such arrays meaning that reading from the array returns only zeros and | ||
Line 10: | Line 14: | ||
*/ | */ | ||
#include <stdio.h> | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
#include <string.h> | #include <string.h> | ||
- | #include <unistd.h> | ||
#include <sys/mman.h> | #include <sys/mman.h> | ||
#include <sys/resource.h> | #include <sys/resource.h> | ||
- | + | #include <unistd.h> | |
+ | |||
+ | /* Define the global array*/ | ||
+ | #define NUM_PAGES 5000 | ||
+ | #define PAGE_SZ (1024 * 4) /* Assume 4kb pages*/ | ||
+ | char glob_buffer[NUM_PAGES * PAGE_SZ]; | ||
/* Lock the application in memory to avoid page faults*/ | /* Lock the application in memory to avoid page faults*/ | ||
- | static void lockApplication(void) | + | static void lock_application(void) |
{ | { | ||
- | if (mlockall(MCL_CURRENT | MCL_FUTURE) != 0 ) | + | if (mlockall(MCL_CURRENT | MCL_FUTURE) != 0) { |
- | { | + | perror("mlockall() failed - root ?"); |
- | perror( "mlockall() failed" ); | + | exit(-1); |
} | } | ||
} | } | ||
- | + | ||
- | /* Dump minor and major page faults that occurred since the previous call*/ | + | /* Dump minor and major page faults that occurred since the previous call */ |
- | static bool dumpPageFaults(void) | + | static int dump_page_faults(void) |
{ | { | ||
- | bool l_PageFaultsDetected = false; | + | int new_minor_page_faults, new_major_page_faults; |
- | static bool ls_Init = false; | + | int page_faults_detected = 0; |
- | static struct rusage ls_RusagePrevious; | + | static struct rusage rusage_prev; |
- | struct rusage l_Rusage; | + | static int init; |
- | + | struct rusage rusage; | |
- | getrusage(RUSAGE_SELF, &l_Rusage); | + | |
- | int a_NewMinorPageFaults = l_Rusage.ru_minflt - ls_RusagePrevious.ru_minflt; | + | getrusage(RUSAGE_SELF, &rusage); |
- | int a_NewMajorPageFaults = l_Rusage.ru_majflt - ls_RusagePrevious.ru_majflt; | + | new_minor_page_faults = rusage.ru_minflt - rusage_prev.ru_minflt; |
- | ls_RusagePrevious.ru_minflt = l_Rusage.ru_minflt; | + | new_major_page_faults = rusage.ru_majflt - rusage_prev.ru_majflt; |
- | ls_RusagePrevious.ru_majflt = l_Rusage.ru_majflt; | + | rusage_prev.ru_minflt = rusage.ru_minflt; |
- | + | rusage_prev.ru_majflt = rusage.ru_majflt; | |
- | if (ls_Init) | + | |
- | { | + | if (init) { |
- | if ((a_NewMinorPageFaults > 0) || (a_NewMajorPageFaults > 0)) | + | if ((new_minor_page_faults > 0) || |
- | { | + | (new_major_page_faults > 0)) { |
- | printf ("New minor/major page faults: %d/%d\n", | + | printf("New minor/major page faults: %d/%d\n", |
- | a_NewMinorPageFaults, | + | new_minor_page_faults, new_major_page_faults); |
- | a_NewMajorPageFaults); | + | page_faults_detected = 1; |
- | l_PageFaultsDetected = true; | + | |
} | } | ||
} | } | ||
- | ls_Init = true; | + | init = 1; |
- | return l_PageFaultsDetected; | + | return page_faults_detected; |
} | } | ||
- | + | ||
- | /* Define the global array*/ | + | |
- | const static int gs_BufferPages = 5000; | + | |
- | const static int gs_PageSize = 1024*4; /* Assume 4kb pages*/ | + | |
- | static char gs_Buffer[gs_BufferPages*gs_PageSize]; | + | |
- | + | ||
int main(int argc, char *argv[]) | int main(int argc, char *argv[]) | ||
{ | { | ||
- | bool l_LockMemory = true; | + | int unexpected_pagefaults_detected; |
+ | int lock_memory = 1; | ||
+ | int buff_value; | ||
int i; | int i; | ||
- | for (i=1; i<argc; i++) | + | |
- | { | + | for (i = 1; i < argc; i++) { |
- | if (strncmp (argv[i], "-nolockmem", 10) == 0) | + | if (strncmp(argv[i], "-nolockmem", 10) == 0) { |
- | { | + | |
/* Results in many page faults! */ | /* Results in many page faults! */ | ||
- | l_LockMemory = false; | + | lock_memory = 0; |
} | } | ||
} | } | ||
- | + | ||
- | if (l_LockMemory) | + | if (lock_memory) { |
- | { | + | lock_application(); |
- | lockApplication(); | + | printf("Current and future memory locked in RAM\n"); |
- | printf ("Current and future memory locked in RAM\n"); | + | |
} | } | ||
- | (void)dumpPageFaults(); /* Set the baseline*/ | + | (void)dump_page_faults(); /* Set the baseline*/ |
- | + | ||
- | /* printf something so we avoid introducing a page fault simply by performing | + | /* From this point onwards we no longer expect any page faults */ |
- | * the potentially first printf call. | + | unexpected_pagefaults_detected = 0; |
- | */ | + | |
- | const int l_PageSize = sysconf(_SC_PAGESIZE); | + | for (i = 0; i < NUM_PAGES; i++) { |
- | printf ("Page size = %d\n", l_PageSize); | + | buff_value = (int) (glob_buffer[i * PAGE_SZ]); |
- | + | ||
- | (void)dumpPageFaults(); | + | if (buff_value != 0) { |
- | + | printf("Reading unexpected value %d on page %d of global buffer.\n", | |
- | /* From this point onwards we no longer expect to have any page faults.*/ | + | buff_value, i); |
- | bool l_UnexpectedPageFaultsDetected = false; | + | |
- | for (i=0; i<gs_BufferPages; i++) | + | |
- | { | + | |
- | int l_Value = static_cast<int>(gs_Buffer[i*gs_PageSize]); | + | |
- | if (l_Value != 0) | + | |
- | { | + | |
- | printf ("Reading unexpected value %d on page %d of static buffer.\n", | + | |
- | l_Value, | + | |
- | i); | + | |
- | } | + | |
- | if (dumpPageFaults()) | + | |
- | { | + | |
- | l_UnexpectedPageFaultsDetected = true; | + | |
} | } | ||
- | gs_Buffer[(i*gs_PageSize)+1] = 1; | + | if (dump_page_faults()) |
- | if (dumpPageFaults()) | + | unexpected_pagefaults_detected = 1; |
- | { | + | |
- | printf ("Writing to page %d of static buffer caused page fault(s)\n", i); | + | glob_buffer[(i * PAGE_SZ) + 1] = 1; |
- | l_UnexpectedPageFaultsDetected = true; | + | if (dump_page_faults()) { |
+ | printf("Writing to page %d of global buffer caused page fault(s)\n", | ||
+ | i); | ||
+ | unexpected_pagefaults_detected = 1; | ||
} | } | ||
} | } | ||
- | + | ||
- | printf ("Done, result: %s\n", | + | printf("Done, result: %s\n", |
- | l_UnexpectedPageFaultsDetected ? "failed":"success"); | + | unexpected_pagefaults_detected ? "failed" : "success"); |
- | return (l_UnexpectedPageFaultsDetected ? 1:0); | + | return unexpected_pagefaults_detected ? 1 : 0; |
} | } | ||
</code> | </code> |