User Tools

Site Tools


realtime:documentation:howto:applications:memory:mlockall_globals_sample

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
realtime:documentation:howto:applications:memory:mlockall_globals_sample [2017/06/01 01:47]
jithu created
realtime:documentation:howto:applications:memory:mlockall_globals_sample [2017/06/10 00:28] (current)
jithu
Line 1: Line 1:
 ====== Sample to verify the effect of mlockall() on globals ====== ====== Sample to verify the effect of mlockall() on globals ======
-Global variables and arrays are not part of the binary, but are allocated by the OS at process ​startup. The virtual memory pages associated to this data is not immediately mapped to physical pages of RAM, meaning that page faults occur on access. It turns out that the mlockall() call forces all global variables and arrays into RAM, meaning that subsequent access to this memory does not result in page faults. As such, using global variables and arrays does not introduce any additional problems for real time applications. You can verify this behavior using the following program (run as '​root'​ to allow the mlockall() operation)+Global variables and arrays are not part of the binary, but are allocated by the OS at application ​startup. The virtual memory pages associated to this data is not immediately mapped to physical pages of RAM, meaning that page faults occur on access. It turns out that the mlockall() call forces all global variables and arrays into RAM, meaning that subsequent access to this memory does not result in page faults. As such, using global variables and arrays does not introduce any additional problems for real time applications. You can verify this behavior using the following program (run as '​root'​ to allow the mlockall() operation)
  
 <code c> <code c>
-// This application checks whether mlockall() forces all pages of a +/
-// global array into RAM. Normally, the OS maps a 'copy on write' MMU page + * # gcc -o check_global ​ check_global.c -Wall -O3 
-// to such arrays meaning that reading from the array returns only zeros and + * # ./check_global 
-// the first write results in a page fault so a physical page of RAM is + * # ./​check_global -nolockmem ​ (will cause faults) 
-// mapped to it (and initialised to zero before the write occurs). + ​* ​This application checks whether mlockall() forces all pages of a 
 + 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 
 + the first write results in a page fault so a physical page of RAM is 
 + mapped to it (and initialised to zero before the write occurs). 
 + */
 #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); + getrusage(RUSAGE_SELF,​ &rusage); 
- int a_NewMinorPageFaults ​l_Rusage.ru_minflt - ls_RusagePrevious.ru_minflt;​ + new_minor_page_faults ​rusage.ru_minflt - rusage_prev.ru_minflt;​ 
- int a_NewMajorPageFaults ​l_Rusage.ru_majflt - ls_RusagePrevious.ru_majflt;​ + new_major_page_faults ​rusage.ru_majflt - rusage_prev.ru_majflt;​ 
- ls_RusagePrevious.ru_minflt = l_Rusage.ru_minflt;​ + rusage_prev.ru_minflt = rusage.ru_minflt;​ 
- ls_RusagePrevious.ru_majflt = l_Rusage.ru_majflt;+ rusage_prev.ru_majflt = rusage.ru_majflt;
  
- if (ls_Init) + if (init) { 
- + if ((new_minor_page_faults ​> 0) || 
- if ((a_NewMinorPageFaults ​> 0) || (a_NewMajorPageFaults ​> 0)) +     ​(new_major_page_faults ​> 0)) { 
- + printf("​New minor/major page faults: %d/​%d\n",​ 
- printf ("New minor/major page faults: %d/​%d\n",​ +        ​new_minor_page_faultsnew_major_page_faults); 
- a_NewMinorPageFaults, + page_faults_detected ​1;
- a_NewMajorPageFaults); +
- 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! + lock_memory ​0;
- l_LockMemory ​false;+
  }  }
  }  }
  
- 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);​ +
- printf ("Page size = %d\n", l_PageSize);​ +
-  +
- (void)dumpPageFaults();+
  
- // From this point onwards we no longer expect to have any page faults. + for (i = 0; i < NUM_PAGES; i++) { 
- bool l_UnexpectedPageFaultsDetected = false; + buff_value ​(int(glob_buffer[i * PAGE_SZ]); 
- for (i=0; i<gs_BufferPages; i++) + 
- + if (buff_value ​!= 0) { 
- int l_Value ​static_cast<​int>(gs_Buffer[i*gs_PageSize]); + printf("​Reading unexpected value %d on page %d of global ​buffer.\n",​ 
- if (l_Value ​!= 0) + buff_value, i);
- +
- printf ("​Reading unexpected value %d on page %d of static ​buffer.\n",​ +
- l_Value, +
- i);+
  }  }
- if (dumpPageFaults()) + if (dump_page_faults()) 
- { + unexpected_pagefaults_detected ​1
- l_UnexpectedPageFaultsDetected ​true+ 
- } + glob_buffer[(i * PAGE_SZ) + 1] = 1; 
- gs_Buffer[(i*gs_PageSize)+1] = 1; + if (dump_page_faults()) { 
- if (dumpPageFaults()) + printf("​Writing to page %d of global ​buffer caused page fault(s)\n",​ 
- +  i); 
- printf ("​Writing to page %d of static ​buffer caused page fault(s)\n",​ i); + unexpected_pagefaults_detected ​1;
- l_UnexpectedPageFaultsDetected ​true;+
  }  }
  }  }
  
- 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>​
realtime/documentation/howto/applications/memory/mlockall_globals_sample.1496281667.txt.gz · Last modified: 2017/06/01 01:47 by jithu