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

Both sides previous revision Previous revision
Next revision
Previous revision
realtime:documentation:howto:applications:memory:mlockall_globals_sample [2017/06/08 17:24]
jithu modified comment style - this code Alex van der Wal's from RT wiki
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+/
 + * # 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_faultsnew_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()) + 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.1496942679.txt.gz · Last modified: 2017/06/08 17:24 by jithu