PAPI  5.3.0.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
linux-memory.c
Go to the documentation of this file.
1 /****************************/
2 /* THIS IS OPEN SOURCE CODE */
3 /****************************/
4 
5 /*
6 * File: linux-memory.c
7 * Author: Kevin London
8 * london@cs.utk.edu
9 * Mods: Dan Terpstra
10 * terpstra@eecs.utk.edu
11 * cache and TLB info exported to a separate file
12 * which is not OS or driver dependent
13 * Mods: Vince Weaver
14 * vweaver1@eecs.utk.edu
15 * Merge all of the various copies of linux-related
16 * memory detection info this file.
17 */
18 
19 #include <dirent.h>
20 #include <fcntl.h>
21 #include <string.h>
22 #include <errno.h>
23 #include <ctype.h>
24 
25 #include "papi.h"
26 #include "papi_internal.h"
27 #include "papi_memory.h" /* papi_calloc() */
28 
29 #include "x86_cpuid_info.h"
30 
31 #include "linux-lock.h"
32 
33 /* 2.6.19 has this:
34 VmPeak: 4588 kB
35 VmSize: 4584 kB
36 VmLck: 0 kB
37 VmHWM: 1548 kB
38 VmRSS: 1548 kB
39 VmData: 312 kB
40 VmStk: 88 kB
41 VmExe: 684 kB
42 VmLib: 1360 kB
43 VmPTE: 20 kB
44 */
45 
46 
47 int
49 {
50  char fn[PATH_MAX], tmp[PATH_MAX];
51  FILE *f;
52  int ret;
53  long long sz = 0, lck = 0, res = 0, shr = 0, stk = 0, txt = 0, dat =
54  0, dum = 0, lib = 0, hwm = 0;
55 
56  sprintf( fn, "/proc/%ld/status", ( long ) getpid( ) );
57  f = fopen( fn, "r" );
58  if ( f == NULL ) {
59  PAPIERROR( "fopen(%s): %s\n", fn, strerror( errno ) );
60  return PAPI_ESYS;
61  }
62  while ( 1 ) {
63  if ( fgets( tmp, PATH_MAX, f ) == NULL )
64  break;
65  if ( strspn( tmp, "VmSize:" ) == strlen( "VmSize:" ) ) {
66  sscanf( tmp + strlen( "VmSize:" ), "%lld", &sz );
67  d->size = sz;
68  continue;
69  }
70  if ( strspn( tmp, "VmHWM:" ) == strlen( "VmHWM:" ) ) {
71  sscanf( tmp + strlen( "VmHWM:" ), "%lld", &hwm );
72  d->high_water_mark = hwm;
73  continue;
74  }
75  if ( strspn( tmp, "VmLck:" ) == strlen( "VmLck:" ) ) {
76  sscanf( tmp + strlen( "VmLck:" ), "%lld", &lck );
77  d->locked = lck;
78  continue;
79  }
80  if ( strspn( tmp, "VmRSS:" ) == strlen( "VmRSS:" ) ) {
81  sscanf( tmp + strlen( "VmRSS:" ), "%lld", &res );
82  d->resident = res;
83  continue;
84  }
85  if ( strspn( tmp, "VmData:" ) == strlen( "VmData:" ) ) {
86  sscanf( tmp + strlen( "VmData:" ), "%lld", &dat );
87  d->heap = dat;
88  continue;
89  }
90  if ( strspn( tmp, "VmStk:" ) == strlen( "VmStk:" ) ) {
91  sscanf( tmp + strlen( "VmStk:" ), "%lld", &stk );
92  d->stack = stk;
93  continue;
94  }
95  if ( strspn( tmp, "VmExe:" ) == strlen( "VmExe:" ) ) {
96  sscanf( tmp + strlen( "VmExe:" ), "%lld", &txt );
97  d->text = txt;
98  continue;
99  }
100  if ( strspn( tmp, "VmLib:" ) == strlen( "VmLib:" ) ) {
101  sscanf( tmp + strlen( "VmLib:" ), "%lld", &lib );
102  d->library = lib;
103  continue;
104  }
105  }
106  fclose( f );
107 
108  sprintf( fn, "/proc/%ld/statm", ( long ) getpid( ) );
109  f = fopen( fn, "r" );
110  if ( f == NULL ) {
111  PAPIERROR( "fopen(%s): %s\n", fn, strerror( errno ) );
112  return PAPI_ESYS;
113  }
114  ret =
115  fscanf( f, "%lld %lld %lld %lld %lld %lld %lld", &dum, &dum, &shr, &dum,
116  &dum, &dat, &dum );
117  if ( ret != 7 ) {
118  PAPIERROR( "fscanf(7 items): %d\n", ret );
119  fclose(f);
120  return PAPI_ESYS;
121  }
122  d->pagesize = getpagesize( );
123  d->shared = ( shr * d->pagesize ) / 1024;
124  fclose( f );
125 
126  return PAPI_OK;
127 }
128 
129 /*
130  * Architecture-specific cache detection code
131  */
132 
133 
134 #if defined(__i386__)||defined(__x86_64__)
135 static int
136 x86_get_memory_info( PAPI_hw_info_t * hw_info )
137 {
138  int retval = PAPI_OK;
139 
140  switch ( hw_info->vendor ) {
141  case PAPI_VENDOR_AMD:
142  case PAPI_VENDOR_INTEL:
143  retval = _x86_cache_info( &hw_info->mem_hierarchy );
144  break;
145  default:
146  PAPIERROR( "Unknown vendor in memory information call for x86." );
147  return PAPI_ENOIMPL;
148  }
149  return retval;
150 }
151 #endif
152 
153 #if defined(__ia64__)
154 static int
155 get_number( char *buf )
156 {
157  char numbers[] = "0123456789";
158  int num;
159  char *tmp, *end;
160 
161  tmp = strpbrk( buf, numbers );
162  if ( tmp != NULL ) {
163  end = tmp;
164  while ( isdigit( *end ) )
165  end++;
166  *end = '\0';
167  num = atoi( tmp );
168  return num;
169  }
170 
171  PAPIERROR( "Number could not be parsed from %s", buf );
172  return -1;
173 }
174 
175 static void
176 fline( FILE * fp, char *rline )
177 {
178  char *tmp, *end, c;
179 
180  tmp = rline;
181  end = &rline[1023];
182 
183  memset( rline, '\0', 1024 );
184 
185  do {
186  if ( feof( fp ) )
187  return;
188  c = getc( fp );
189  }
190  while ( isspace( c ) || c == '\n' || c == '\r' );
191 
192  ungetc( c, fp );
193 
194  for ( ;; ) {
195  if ( feof( fp ) ) {
196  return;
197  }
198  c = getc( fp );
199  if ( c == '\n' || c == '\r' )
200  break;
201  *tmp++ = c;
202  if ( tmp == end ) {
203  *tmp = '\0';
204  return;
205  }
206  }
207  return;
208 }
209 
210 static int
211 ia64_get_memory_info( PAPI_hw_info_t * hw_info )
212 {
213  int retval = 0;
214  FILE *f;
215  int clevel = 0, cindex = -1;
216  char buf[1024];
217  int num, i, j;
218  PAPI_mh_info_t *meminfo = &hw_info->mem_hierarchy;
219  PAPI_mh_level_t *L = hw_info->mem_hierarchy.level;
220 
221  f = fopen( "/proc/pal/cpu0/cache_info", "r" );
222 
223  if ( !f ) {
224  PAPIERROR( "fopen(/proc/pal/cpu0/cache_info) returned < 0" );
225  return PAPI_ESYS;
226  }
227 
228  while ( !feof( f ) ) {
229  fline( f, buf );
230  if ( buf[0] == '\0' )
231  break;
232  if ( !strncmp( buf, "Data Cache", 10 ) ) {
233  cindex = 1;
234  clevel = get_number( buf );
235  L[clevel - 1].cache[cindex].type = PAPI_MH_TYPE_DATA;
236  } else if ( !strncmp( buf, "Instruction Cache", 17 ) ) {
237  cindex = 0;
238  clevel = get_number( buf );
239  L[clevel - 1].cache[cindex].type = PAPI_MH_TYPE_INST;
240  } else if ( !strncmp( buf, "Data/Instruction Cache", 22 ) ) {
241  cindex = 0;
242  clevel = get_number( buf );
243  L[clevel - 1].cache[cindex].type = PAPI_MH_TYPE_UNIFIED;
244  } else {
245  if ( ( clevel == 0 || clevel > 3 ) && cindex >= 0 ) {
246  PAPIERROR
247  ( "Cache type could not be recognized, please send /proc/pal/cpu0/cache_info" );
248  return PAPI_EBUG;
249  }
250 
251  if ( !strncmp( buf, "Size", 4 ) ) {
252  num = get_number( buf );
253  L[clevel - 1].cache[cindex].size = num;
254  } else if ( !strncmp( buf, "Associativity", 13 ) ) {
255  num = get_number( buf );
256  L[clevel - 1].cache[cindex].associativity = num;
257  } else if ( !strncmp( buf, "Line size", 9 ) ) {
258  num = get_number( buf );
259  L[clevel - 1].cache[cindex].line_size = num;
260  L[clevel - 1].cache[cindex].num_lines =
261  L[clevel - 1].cache[cindex].size / num;
262  }
263  }
264  }
265 
266  fclose( f );
267 
268  f = fopen( "/proc/pal/cpu0/vm_info", "r" );
269  /* No errors on fopen as I am not sure this is always on the systems */
270  if ( f != NULL ) {
271  cindex = -1;
272  clevel = 0;
273  while ( !feof( f ) ) {
274  fline( f, buf );
275  if ( buf[0] == '\0' )
276  break;
277  if ( !strncmp( buf, "Data Translation", 16 ) ) {
278  cindex = 1;
279  clevel = get_number( buf );
280  L[clevel - 1].tlb[cindex].type = PAPI_MH_TYPE_DATA;
281  } else if ( !strncmp( buf, "Instruction Translation", 23 ) ) {
282  cindex = 0;
283  clevel = get_number( buf );
284  L[clevel - 1].tlb[cindex].type = PAPI_MH_TYPE_INST;
285  } else {
286  if ( ( clevel == 0 || clevel > 2 ) && cindex >= 0 ) {
287  PAPIERROR
288  ( "TLB type could not be recognized, send /proc/pal/cpu0/vm_info" );
289  return PAPI_EBUG;
290  }
291 
292  if ( !strncmp( buf, "Number of entries", 17 ) ) {
293  num = get_number( buf );
294  L[clevel - 1].tlb[cindex].num_entries = num;
295  } else if ( !strncmp( buf, "Associativity", 13 ) ) {
296  num = get_number( buf );
297  L[clevel - 1].tlb[cindex].associativity = num;
298  }
299  }
300  }
301  fclose( f );
302  }
303 
304  /* Compute and store the number of levels of hierarchy actually used */
305  for ( i = 0; i < PAPI_MH_MAX_LEVELS; i++ ) {
306  for ( j = 0; j < 2; j++ ) {
307  if ( L[i].tlb[j].type != PAPI_MH_TYPE_EMPTY ||
308  L[i].cache[j].type != PAPI_MH_TYPE_EMPTY )
309  meminfo->levels = i + 1;
310  }
311  }
312  return retval;
313 }
314 #endif
315 
316 #if defined(__powerpc__)
317 
318 PAPI_mh_info_t sys_mem_info[4] = {
319  {2, // 970 begin
320  {
321  { // level 1 begins
322  { // tlb's begin
323  {PAPI_MH_TYPE_UNIFIED, 1024, 4, 0}
324  ,
325  {PAPI_MH_TYPE_EMPTY, -1, -1, -1}
326  }
327  ,
328  { // caches begin
329  {PAPI_MH_TYPE_INST, 65536, 128, 512, 1}
330  ,
331  {PAPI_MH_TYPE_DATA, 32768, 128, 256, 2}
332  }
333  }
334  ,
335  { // level 2 begins
336  { // tlb's begin
337  {PAPI_MH_TYPE_EMPTY, -1, -1, -1}
338  ,
339  {PAPI_MH_TYPE_EMPTY, -1, -1, -1}
340  }
341  ,
342  { // caches begin
343  {PAPI_MH_TYPE_UNIFIED, 524288, 128, 4096, 8}
344  ,
345  {PAPI_MH_TYPE_EMPTY, -1, -1, -1, -1}
346  }
347  }
348  ,
349  }
350  }
351  , // 970 end
352  {3,
353  {
354  { // level 1 begins
355  { // tlb's begin
356  {PAPI_MH_TYPE_UNIFIED, 1024, 4, 0}
357  ,
358  {PAPI_MH_TYPE_EMPTY, -1, -1, -1}
359  }
360  ,
361  { // caches begin
362  {PAPI_MH_TYPE_INST, 65536, 128, 512, 2}
363  ,
364  {PAPI_MH_TYPE_DATA, 32768, 128, 256, 4}
365  }
366  }
367  ,
368  { // level 2 begins
369  { // tlb's begin
370  {PAPI_MH_TYPE_EMPTY, -1, -1, -1}
371  ,
372  {PAPI_MH_TYPE_EMPTY, -1, -1, -1}
373  }
374  ,
375  { // caches begin
376  {PAPI_MH_TYPE_UNIFIED, 1966080, 128, 15360, 10}
377  ,
378  {PAPI_MH_TYPE_EMPTY, -1, -1, -1, -1}
379  }
380  }
381  ,
382  { // level 3 begins
383  { // tlb's begin
384  {PAPI_MH_TYPE_EMPTY, -1, -1, -1}
385  ,
386  {PAPI_MH_TYPE_EMPTY, -1, -1, -1}
387  }
388  ,
389  { // caches begin
390  {PAPI_MH_TYPE_UNIFIED, 37748736, 256, 147456, 12}
391  ,
392  {PAPI_MH_TYPE_EMPTY, -1, -1, -1, -1}
393  }
394  }
395  ,
396  }
397  }
398  , // POWER5 end
399  {3,
400  {
401  { // level 1 begins
402  { // tlb's begin
406  {PAPI_MH_TYPE_INST, 128, 2, 0}
407  ,
408  {PAPI_MH_TYPE_DATA, 128, 128, 0}
409  }
410  ,
411  { // caches begin
412  {PAPI_MH_TYPE_INST, 65536, 128, 512, 4}
413  ,
414  {PAPI_MH_TYPE_DATA, 65536, 128, 512, 8}
415  }
416  }
417  ,
418  { // level 2 begins
419  { // tlb's begin
420  {PAPI_MH_TYPE_EMPTY, -1, -1, -1}
421  ,
422  {PAPI_MH_TYPE_EMPTY, -1, -1, -1}
423  }
424  ,
425  { // caches begin
426  {PAPI_MH_TYPE_UNIFIED, 4194304, 128, 16384, 8}
427  ,
428  {PAPI_MH_TYPE_EMPTY, -1, -1, -1, -1}
429  }
430  }
431  ,
432  { // level 3 begins
433  { // tlb's begin
434  {PAPI_MH_TYPE_EMPTY, -1, -1, -1}
435  ,
436  {PAPI_MH_TYPE_EMPTY, -1, -1, -1}
437  }
438  ,
439  { // caches begin
443  {PAPI_MH_TYPE_UNIFIED, 33554432, 128, 262144, 16}
444  ,
445  {PAPI_MH_TYPE_EMPTY, -1, -1, -1, -1}
446  }
447  }
448  ,
449  }
450  }
451  , // POWER6 end
452  {3,
453  {
454  [0] = { // level 1 begins
455  .tlb = {
459  [0] = { .type = PAPI_MH_TYPE_INST,
460  .num_entries = 64, .page_size = 0, .associativity = 2 }
461  ,
462  [1] = { .type = PAPI_MH_TYPE_DATA,
463  .num_entries = 64, .page_size = 0,
464  .associativity = SHRT_MAX }
465  }
466  ,
467  .cache = { // level 1 caches begin
468  [0] = { .type = PAPI_MH_TYPE_INST | PAPI_MH_TYPE_PSEUDO_LRU,
469  .size = 32768, .line_size = 128, .num_lines = 64,
470  .associativity = 4 }
471  ,
473  .size = 32768, .line_size = 128, .num_lines = 32,
474  .associativity = 8 }
475  }
476  }
477  ,
478  [1] = { // level 2 begins
479  .tlb = {
480  [0] = { .type = PAPI_MH_TYPE_EMPTY, .num_entries = -1,
481  .page_size = -1, .associativity = -1 }
482  ,
483  [1] = { .type = PAPI_MH_TYPE_EMPTY, .num_entries = -1,
484  .page_size = -1, .associativity = -1 }
485  }
486  ,
487  .cache = {
489  .size = 524288, .line_size = 128, .num_lines = 256,
490  .associativity = 8 }
491  ,
492  [1] = { .type = PAPI_MH_TYPE_EMPTY, .size = -1, .line_size = -1,
493  .num_lines = -1, .associativity = -1 }
494  }
495  }
496  ,
497  [2] = { // level 3 begins
498  .tlb = {
499  [0] = { .type = PAPI_MH_TYPE_EMPTY, .num_entries = -1,
500  .page_size = -1, .associativity = -1 }
501  ,
502  [1] = { .type = PAPI_MH_TYPE_EMPTY, .num_entries = -1,
503  .page_size = -1, .associativity = -1 }
504  }
505  ,
506  .cache = {
508  .size = 4194304, .line_size = 128, .num_lines = 4096,
509  .associativity = 8 }
510  ,
511  [1] = { .type = PAPI_MH_TYPE_EMPTY, .size = -1, .line_size = -1,
512  .num_lines = -1, .associativity = -1 }
513  }
514  }
515  ,
516  }
517  }, // POWER7 end
518  {3,
519  {
520  [0] = { // level 1 begins
521  .tlb = {
525  [0] = { .type = PAPI_MH_TYPE_INST,
526  .num_entries = 72, .page_size = 0,
527  .associativity = SHRT_MAX }
528  ,
529  [1] = { .type = PAPI_MH_TYPE_DATA,
530  .num_entries = 48, .page_size = 0,
531  .associativity = SHRT_MAX }
532  }
533  ,
534  .cache = { // level 1 caches begin
535  [0] = { .type = PAPI_MH_TYPE_INST | PAPI_MH_TYPE_PSEUDO_LRU,
536  .size = 32768, .line_size = 128, .num_lines = 64,
537  .associativity = 8 }
538  ,
540  .size = 65536, .line_size = 128, .num_lines = 512,
541  .associativity = 8 }
542  }
543  }
544  ,
545  [1] = { // level 2 begins
546  .tlb = {
547  [0] = { .type = PAPI_MH_TYPE_UNIFIED, .num_entries = 2048,
548  .page_size = 0, .associativity = 4 }
549  ,
550  [1] = { .type = PAPI_MH_TYPE_EMPTY, .num_entries = -1,
551  .page_size = -1, .associativity = -1 }
552  }
553  ,
554  .cache = {
556  .size = 262144, .line_size = 128, .num_lines = 256,
557  .associativity = 8 }
558  ,
559  [1] = { .type = PAPI_MH_TYPE_EMPTY, .size = -1, .line_size = -1,
560  .num_lines = -1, .associativity = -1 }
561  }
562  }
563  ,
564  [2] = { // level 3 begins
565  .tlb = {
566  [0] = { .type = PAPI_MH_TYPE_EMPTY, .num_entries = -1,
567  .page_size = -1, .associativity = -1 }
568  ,
569  [1] = { .type = PAPI_MH_TYPE_EMPTY, .num_entries = -1,
570  .page_size = -1, .associativity = -1 }
571  }
572  ,
573  .cache = {
575  .size = 8388608, .line_size = 128, .num_lines = 65536,
576  .associativity = 8 }
577  ,
578  [1] = { .type = PAPI_MH_TYPE_EMPTY, .size = -1, .line_size = -1,
579  .num_lines = -1, .associativity = -1 }
580  }
581  }
582  ,
583  }
584  } // POWER8 end
585 };
586 
587 #define SPRN_PVR 0x11F /* Processor Version Register */
588 #define PVR_PROCESSOR_SHIFT 16
589 static unsigned int
590 mfpvr( void )
591 {
592  unsigned long pvr;
593 
594  asm( "mfspr %0,%1": "=r"( pvr ):"i"( SPRN_PVR ) );
595  return pvr;
596 
597 }
598 
599 int
600 ppc64_get_memory_info( PAPI_hw_info_t * hw_info )
601 {
602  unsigned int pvr = mfpvr( ) >> PVR_PROCESSOR_SHIFT;
603 
604  int index;
605  switch ( pvr ) {
606  case 0x39: /* PPC970 */
607  case 0x3C: /* PPC970FX */
608  case 0x44: /* PPC970MP */
609  case 0x45: /* PPC970GX */
610  index = 0;
611  break;
612  case 0x3A: /* POWER5 */
613  case 0x3B: /* POWER5+ */
614  index = 1;
615  break;
616  case 0x3E: /* POWER6 */
617  index = 2;
618  break;
619  case 0x3F: /* POWER7 */
620  index = 3;
621  break;
622  case 0x4b: /*POWER8*/
623  index = 4;
624  break;
625  default:
626  index = -1;
627  break;
628  }
629 
630  if ( index != -1 ) {
631  int cache_level;
632  PAPI_mh_info_t sys_mh_inf = sys_mem_info[index];
633  PAPI_mh_info_t *mh_inf = &hw_info->mem_hierarchy;
634  mh_inf->levels = sys_mh_inf.levels;
635  PAPI_mh_level_t *level = mh_inf->level;
636  PAPI_mh_level_t sys_mh_level;
637  for ( cache_level = 0; cache_level < sys_mh_inf.levels; cache_level++ ) {
638  sys_mh_level = sys_mh_inf.level[cache_level];
639  int cache_idx;
640  for ( cache_idx = 0; cache_idx < 2; cache_idx++ ) {
641  // process TLB info
642  PAPI_mh_tlb_info_t curr_tlb = sys_mh_level.tlb[cache_idx];
643  int type = curr_tlb.type;
644  if ( type != PAPI_MH_TYPE_EMPTY ) {
645  level[cache_level].tlb[cache_idx].type = type;
646  level[cache_level].tlb[cache_idx].associativity =
647  curr_tlb.associativity;
648  level[cache_level].tlb[cache_idx].num_entries =
649  curr_tlb.num_entries;
650  }
651  }
652  for ( cache_idx = 0; cache_idx < 2; cache_idx++ ) {
653  // process cache info
654  PAPI_mh_cache_info_t curr_cache = sys_mh_level.cache[cache_idx];
655  int type = curr_cache.type;
656  if ( type != PAPI_MH_TYPE_EMPTY ) {
657  level[cache_level].cache[cache_idx].type = type;
658  level[cache_level].cache[cache_idx].associativity =
659  curr_cache.associativity;
660  level[cache_level].cache[cache_idx].size = curr_cache.size;
661  level[cache_level].cache[cache_idx].line_size =
662  curr_cache.line_size;
663  level[cache_level].cache[cache_idx].num_lines =
664  curr_cache.num_lines;
665  }
666  }
667  }
668  }
669  return 0;
670 }
671 #endif
672 
673 
674 
675 #if defined(__sparc__)
676 static int
677 sparc_sysfs_cpu_attr( char *name, char **result )
678 {
679  const char *path_base = "/sys/devices/system/cpu/";
680  char path_buf[PATH_MAX];
681  char val_buf[32];
682  DIR *sys_cpu;
683 
684  sys_cpu = opendir( path_base );
685  if ( sys_cpu ) {
686  struct dirent *cpu;
687 
688  while ( ( cpu = readdir( sys_cpu ) ) != NULL ) {
689  int fd;
690 
691  if ( strncmp( "cpu", cpu->d_name, 3 ) )
692  continue;
693  strcpy( path_buf, path_base );
694  strcat( path_buf, cpu->d_name );
695  strcat( path_buf, "/" );
696  strcat( path_buf, name );
697 
698  fd = open( path_buf, O_RDONLY );
699  if ( fd < 0 )
700  continue;
701 
702  if ( read( fd, val_buf, 32 ) < 0 )
703  continue;
704  close( fd );
705 
706  *result = strdup( val_buf );
707  return 0;
708  }
709  }
710  closedir( sys_cpu );
711  return -1;
712 }
713 
714 static int
715 sparc_cpu_attr( char *name, unsigned long long *val )
716 {
717  char *buf;
718  int r;
719 
720  r = sparc_sysfs_cpu_attr( name, &buf );
721  if ( r == -1 )
722  return -1;
723 
724  sscanf( buf, "%llu", val );
725 
726  free( buf );
727 
728  return 0;
729 }
730 
731 static char *
732 search_cpu_info( FILE * f, char *search_str, char *line )
733 {
734  /* This code courtesy of our friends in Germany. Thanks Rudolph Berrend\
735  orf! */
736  /* See the home page for the German version of PAPI. */
737 
738  char *s;
739 
740  while ( fgets( line, 256, f ) != NULL ) {
741  if ( strstr( line, search_str ) != NULL ) {
742  /* ignore all characters in line up to : */
743  for ( s = line; *s && ( *s != ':' ); ++s );
744  if ( *s )
745  return s;
746  }
747  }
748  return NULL;
749 
750  /* End stolen code */
751 }
752 
753 
754 static int
755 sparc_get_memory_info( PAPI_hw_info_t * hw_info )
756 {
757  unsigned long long cache_size, cache_line_size;
758  /* unsigned long long cycles_per_second; */
759  char maxargs[PAPI_HUGE_STR_LEN];
760  /* PAPI_mh_tlb_info_t *tlb; */
761  PAPI_mh_level_t *level;
762  char *s, *t;
763  FILE *f;
764 
765  /* First, fix up the cpu vendor/model/etc. values */
766  strcpy( hw_info->vendor_string, "Sun" );
767  hw_info->vendor = PAPI_VENDOR_SUN;
768 
769  f = fopen( "/proc/cpuinfo", "r" );
770  if ( !f )
771  return PAPI_ESYS;
772 
773  rewind( f );
774  s = search_cpu_info( f, "cpu", maxargs );
775  if ( !s ) {
776  fclose( f );
777  return PAPI_ESYS;
778  }
779 
780  t = strchr( s + 2, '\n' );
781  if ( !t ) {
782  fclose( f );
783  return PAPI_ESYS;
784  }
785 
786  *t = '\0';
787  strcpy( hw_info->model_string, s + 2 );
788 
789  fclose( f );
790 
791  /*
792  if ( sparc_sysfs_cpu_attr( "clock_tick", &s ) == -1 )
793  return PAPI_ESYS;
794 
795  sscanf( s, "%llu", &cycles_per_second );
796  free( s );
797 
798  hw_info->mhz = cycles_per_second / 1000000;
799  hw_info->clock_mhz = hw_info->mhz;
800  */
801 
802  /* Now fetch the cache info */
803  hw_info->mem_hierarchy.levels = 3;
804 
805  level = &hw_info->mem_hierarchy.level[0];
806 
807  sparc_cpu_attr( "l1_icache_size", &cache_size );
808  sparc_cpu_attr( "l1_icache_line_size", &cache_line_size );
809  level[0].cache[0].type = PAPI_MH_TYPE_INST;
810  level[0].cache[0].size = cache_size;
811  level[0].cache[0].line_size = cache_line_size;
812  level[0].cache[0].num_lines = cache_size / cache_line_size;
813  level[0].cache[0].associativity = 1;
814 
815  sparc_cpu_attr( "l1_dcache_size", &cache_size );
816  sparc_cpu_attr( "l1_dcache_line_size", &cache_line_size );
818  level[0].cache[1].size = cache_size;
819  level[0].cache[1].line_size = cache_line_size;
820  level[0].cache[1].num_lines = cache_size / cache_line_size;
821  level[0].cache[1].associativity = 1;
822 
823  sparc_cpu_attr( "l2_cache_size", &cache_size );
824  sparc_cpu_attr( "l2_cache_line_size", &cache_line_size );
826  level[1].cache[0].size = cache_size;
827  level[1].cache[0].line_size = cache_line_size;
828  level[1].cache[0].num_lines = cache_size / cache_line_size;
829  level[1].cache[0].associativity = 1;
830 
831 #if 0
832  tlb = &hw_info->mem_hierarchy.level[0].tlb[0];
833  switch ( _perfmon2_pfm_pmu_type ) {
834  case PFMLIB_SPARC_ULTRA12_PMU:
836  tlb[0].num_entries = 64;
837  tlb[0].associativity = SHRT_MAX;
839  tlb[1].num_entries = 64;
840  tlb[1].associativity = SHRT_MAX;
841  break;
842 
843  case PFMLIB_SPARC_ULTRA3_PMU:
844  case PFMLIB_SPARC_ULTRA3I_PMU:
845  case PFMLIB_SPARC_ULTRA3PLUS_PMU:
846  case PFMLIB_SPARC_ULTRA4PLUS_PMU:
847  level[0].cache[0].associativity = 4;
848  level[0].cache[1].associativity = 4;
849  level[1].cache[0].associativity = 4;
850 
852  tlb[0].num_entries = 16;
853  tlb[0].associativity = SHRT_MAX;
855  tlb[1].num_entries = 16;
856  tlb[1].associativity = SHRT_MAX;
857  tlb[2].type = PAPI_MH_TYPE_DATA;
858  tlb[2].num_entries = 1024;
859  tlb[2].associativity = 2;
860  tlb[3].type = PAPI_MH_TYPE_INST;
861  tlb[3].num_entries = 128;
862  tlb[3].associativity = 2;
863  break;
864 
865  case PFMLIB_SPARC_NIAGARA1:
866  level[0].cache[0].associativity = 4;
867  level[0].cache[1].associativity = 4;
868  level[1].cache[0].associativity = 12;
869 
871  tlb[0].num_entries = 64;
872  tlb[0].associativity = SHRT_MAX;
874  tlb[1].num_entries = 64;
875  tlb[1].associativity = SHRT_MAX;
876  break;
877 
878  case PFMLIB_SPARC_NIAGARA2:
879  level[0].cache[0].associativity = 8;
880  level[0].cache[1].associativity = 4;
881  level[1].cache[0].associativity = 16;
882 
884  tlb[0].num_entries = 64;
885  tlb[0].associativity = SHRT_MAX;
887  tlb[1].num_entries = 128;
888  tlb[1].associativity = SHRT_MAX;
889  break;
890  }
891 #endif
892  return 0;
893 }
894 #endif
895 
896 /* FIXME: have code read the /sys/ cpu files to gather cache info */
897 /* in cases where we can't otherwise get cache size data */
898 
899 int
901 {
902 
903 
904  /* Now fetch the cache info */
905  hw_info->mem_hierarchy.levels = 0;
906 
907  return 0;
908 }
909 
910 
911 int
912 _linux_get_memory_info( PAPI_hw_info_t * hwinfo, int cpu_type )
913 {
914  ( void ) cpu_type; /*unused */
915  int retval = PAPI_OK;
916 
917 #if defined(__i386__)||defined(__x86_64__)
918  x86_get_memory_info( hwinfo );
919 #elif defined(__ia64__)
920  ia64_get_memory_info( hwinfo );
921 #elif defined(__powerpc__)
922  ppc64_get_memory_info( hwinfo );
923 #elif defined(__sparc__)
924  sparc_get_memory_info( hwinfo );
925 #elif defined(__arm__)
926  #warning "WARNING! linux_get_memory_info() does nothing on ARM!"
927  generic_get_memory_info (hwinfo);
928 #else
929  generic_get_memory_info (hwinfo);
930 #endif
931 
932  return retval;
933 }
934 
935 int
937 {
938 
939  char fname[PAPI_HUGE_STR_LEN];
940  unsigned long t_index = 0, d_index = 0, b_index = 0, counting = 1;
941  char buf[PAPI_HUGE_STR_LEN + PAPI_HUGE_STR_LEN], perm[5], dev[16];
942  char mapname[PAPI_HUGE_STR_LEN], lastmapname[PAPI_HUGE_STR_LEN];
943  unsigned long begin = 0, end = 0, size = 0, inode = 0, foo = 0;
944  PAPI_address_map_t *tmp = NULL;
945  FILE *f;
946 
947  memset( fname, 0x0, sizeof ( fname ) );
948  memset( buf, 0x0, sizeof ( buf ) );
949  memset( perm, 0x0, sizeof ( perm ) );
950  memset( dev, 0x0, sizeof ( dev ) );
951  memset( mapname, 0x0, sizeof ( mapname ) );
952  memset( lastmapname, 0x0, sizeof ( lastmapname ) );
953 
954  sprintf( fname, "/proc/%ld/maps", ( long ) mdi->pid );
955  f = fopen( fname, "r" );
956 
957  if ( !f ) {
958  PAPIERROR( "fopen(%s) returned < 0", fname );
959  return PAPI_OK;
960  }
961 
962  again:
963  while ( !feof( f ) ) {
964  begin = end = size = inode = foo = 0;
965  if ( fgets( buf, sizeof ( buf ), f ) == 0 )
966  break;
967  /* If mapname is null in the string to be scanned, we need to detect that */
968  if ( strlen( mapname ) )
969  strcpy( lastmapname, mapname );
970  else
971  lastmapname[0] = '\0';
972  /* If mapname is null in the string to be scanned, we need to detect that */
973  mapname[0] = '\0';
974  sscanf( buf, "%lx-%lx %4s %lx %s %ld %s", &begin, &end, perm, &foo, dev,
975  &inode, mapname );
976  size = end - begin;
977 
978  /* the permission string looks like "rwxp", where each character can
979  * be either the letter, or a hyphen. The final character is either
980  * p for private or s for shared. */
981 
982  if ( counting ) {
983  if ( ( perm[2] == 'x' ) && ( perm[0] == 'r' ) && ( inode != 0 ) ) {
984  if ( strcmp( mdi->exe_info.fullname, mapname )
985  == 0 ) {
987  ( caddr_t ) begin;
989  ( caddr_t ) ( begin + size );
990  }
991  t_index++;
992  } else if ( ( perm[0] == 'r' ) && ( perm[1] == 'w' ) &&
993  ( inode != 0 )
994  &&
995  ( strcmp
996  ( mdi->exe_info.fullname,
997  mapname ) == 0 ) ) {
999  ( caddr_t ) begin;
1001  ( caddr_t ) ( begin + size );
1002  d_index++;
1003  } else if ( ( perm[0] == 'r' ) && ( perm[1] == 'w' ) &&
1004  ( inode == 0 )
1005  &&
1006  ( strcmp
1007  ( mdi->exe_info.fullname,
1008  lastmapname ) == 0 ) ) {
1010  ( caddr_t ) begin;
1012  ( caddr_t ) ( begin + size );
1013  b_index++;
1014  }
1015  } else if ( !counting ) {
1016  if ( ( perm[2] == 'x' ) && ( perm[0] == 'r' ) && ( inode != 0 ) ) {
1017  if ( strcmp( mdi->exe_info.fullname, mapname )
1018  != 0 ) {
1019  t_index++;
1020  tmp[t_index - 1].text_start = ( caddr_t ) begin;
1021  tmp[t_index - 1].text_end = ( caddr_t ) ( begin + size );
1022  strncpy( tmp[t_index - 1].name, mapname, PAPI_MAX_STR_LEN );
1023  }
1024  } else if ( ( perm[0] == 'r' ) && ( perm[1] == 'w' ) &&
1025  ( inode != 0 ) ) {
1026  if ( ( strcmp
1027  ( mdi->exe_info.fullname,
1028  mapname ) != 0 )
1029  && ( t_index > 0 ) &&
1030  ( tmp[t_index - 1].data_start == 0 ) ) {
1031  tmp[t_index - 1].data_start = ( caddr_t ) begin;
1032  tmp[t_index - 1].data_end = ( caddr_t ) ( begin + size );
1033  }
1034  } else if ( ( perm[0] == 'r' ) && ( perm[1] == 'w' ) &&
1035  ( inode == 0 ) ) {
1036  if ( ( t_index > 0 ) && ( tmp[t_index - 1].bss_start == 0 ) ) {
1037  tmp[t_index - 1].bss_start = ( caddr_t ) begin;
1038  tmp[t_index - 1].bss_end = ( caddr_t ) ( begin + size );
1039  }
1040  }
1041  }
1042  }
1043 
1044  if ( counting ) {
1045  /* When we get here, we have counted the number of entries in the map
1046  for us to allocate */
1047 
1048  tmp =
1049  ( PAPI_address_map_t * ) papi_calloc( t_index,
1050  sizeof
1051  ( PAPI_address_map_t ) );
1052  if ( tmp == NULL ) {
1053  PAPIERROR( "Error allocating shared library address map" );
1054  fclose(f);
1055  return PAPI_ENOMEM;
1056  }
1057  t_index = 0;
1058  rewind( f );
1059  counting = 0;
1060  goto again;
1061  } else {
1062  if ( mdi->shlib_info.map )
1063  papi_free( mdi->shlib_info.map );
1064  mdi->shlib_info.map = tmp;
1065  mdi->shlib_info.count = t_index;
1066 
1067  fclose( f );
1068  }
1069 
1070  return PAPI_OK;
1071 }
#define PAPI_HUGE_STR_LEN
Definition: fpapi.h:42
sprintf(splash[splash_line++],"\tIozone: Performance Test of File I/O\n")
int atoi()
ssize_t read(int fd, void *buf, size_t count)
Definition: appio.c:225
memset(eventId, 0, size)
unsigned long cache_line_size
Definition: iozone.c:1376
int val
Definition: libbif.c:235
int errno
int close(int fd)
Definition: appio.c:175
double f(double a)
Definition: cpi.c:23
#define PAPI_ENOMEM
Definition: fpapi.h:107
int levels
Definition: papi.h:769
#define PAPI_VENDOR_SUN
Definition: papi.h:350
#define PAPI_ENOIMPL
Definition: fpapi.h:124
Hardware info structure.
Definition: papi.h:775
#define PAPI_MH_TYPE_INST
Definition: papi.h:725
#define papi_free(a)
Definition: papi_memory.h:35
caddr_t text_end
Definition: papi.h:693
PAPI_mh_info_t mem_hierarchy
Definition: papi.h:794
#define PAPI_MAX_STR_LEN
Definition: fpapi.h:43
cpu
Definition: iozone.c:3872
static char * search_cpu_info(FILE *f, char *search_str, char *line)
#define PAPI_MH_TYPE_WB
Definition: papi.h:732
int fd
Definition: iozone.c:1291
static int _perfmon2_pfm_pmu_type
Definition: perfmon.c:50
int associativity
Definition: papi.h:748
return PAPI_OK
Definition: linux-nvml.c:458
caddr_t bss_start
Definition: papi.h:696
PAPI_exe_info_t exe_info
#define PAPI_MH_TYPE_PSEUDO_LRU
Definition: papi.h:736
long long heap
Definition: papi.h:874
fclose(thread_wqfd)
void
Definition: iozone.c:18627
double c
Definition: multiplex.c:22
#define PAPI_MH_TYPE_LRU
Definition: papi.h:735
PAPI_shlib_info_t shlib_info
Return codes and api definitions.
#define PAPI_MH_TYPE_DATA
Definition: papi.h:726
long long ret
Definition: iozone.c:1346
int _linux_update_shlib_info(papi_mdi_t *mdi)
Definition: linux-memory.c:936
t
Definition: iozone.c:23562
int open(const char *pathname, int flags, mode_t mode)
Definition: appio.c:184
PAPI_mh_cache_info_t cache[PAPI_MH_MAX_LEVELS]
Definition: papi.h:763
int i
Definition: fileop.c:140
long long resident
Definition: papi.h:869
int _x86_cache_info(PAPI_mh_info_t *mh_info)
char buf[200]
Definition: iozone.c:19609
int _linux_get_memory_info(PAPI_hw_info_t *hwinfo, int cpu_type)
Definition: linux-memory.c:912
A pointer to the following is passed to PAPI_get_dmem_info()
Definition: papi.h:866
char *long long size
Definition: iozone.c:12023
free(dummyfile[xx])
caddr_t text_start
Definition: papi.h:692
PAPI_mh_level_t level[PAPI_MAX_MEM_HIERARCHY_LEVELS]
Definition: papi.h:770
PAPI_address_map_t address_info
Definition: papi.h:704
long long pagesize
Definition: papi.h:877
void int num
Definition: iozone.c:22151
PAPI_mh_tlb_info_t tlb[PAPI_MH_MAX_LEVELS]
Definition: papi.h:762
pthread_attr_t foo
Definition: iozone.c:18592
get the executable&#39;s address space info
Definition: papi.h:690
s
Definition: iozone.c:20289
long long locked
Definition: papi.h:875
static FILE * fp
void PAPIERROR(char *format,...)
int _linux_get_dmem_info(PAPI_dmem_info_t *d)
Definition: linux-memory.c:48
long long library
Definition: papi.h:873
strcat(command, mountname)
mh for mem hierarchy maybe?
Definition: papi.h:768
#define PAPI_ESYS
Definition: fpapi.h:108
char vendor_string[PAPI_MAX_STR_LEN]
Definition: papi.h:783
strcpy(filename, default_filename)
#define PAPI_VENDOR_INTEL
Definition: papi.h:346
caddr_t data_start
Definition: papi.h:694
int vendor
Definition: papi.h:782
long long shared
Definition: papi.h:871
#define PAPI_EBUG
Definition: fpapi.h:111
sscanf(mnc->m_child_port,"%d",&mc.m_child_port)
#define PATH_MAX
Definition: fileop.c:68
char * name
Definition: iozone.c:23648
PAPI_address_map_t * map
Definition: papi.h:709
caddr_t bss_end
Definition: papi.h:697
int generic_get_memory_info(PAPI_hw_info_t *hw_info)
Definition: linux-memory.c:900
long long text
Definition: papi.h:872
long long stack
Definition: papi.h:876
caddr_t data_end
Definition: papi.h:695
#define PAPI_MH_TYPE_UNIFIED
Definition: papi.h:729
char model_string[PAPI_MAX_STR_LEN]
Definition: papi.h:785
char fullname[PAPI_HUGE_STR_LEN]
Definition: papi.h:703
#define PAPI_MH_TYPE_EMPTY
Definition: papi.h:724
#define PAPI_MH_TYPE_WT
Definition: papi.h:731
long j
Definition: iozone.c:19135
ssize_t retval
Definition: libasync.c:338
long long tmp
Definition: iozone.c:12031
static const PAPI_hw_info_t * hw_info
Definition: byte_profile.c:23
long long size
Definition: papi.h:868
#define PAPI_MH_MAX_LEVELS
Definition: fpapi.h:87
rewind(w_traj_fd)
#define papi_calloc(a, b)
Definition: papi_memory.h:37
void begin()
unsigned long cache_size
Definition: iozone.c:1375
#define PAPI_VENDOR_AMD
Definition: papi.h:347
long long high_water_mark
Definition: papi.h:870
int sz
Definition: fileop.c:80