PAPI  5.6.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[] = {
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  case 0x4e: /* POWER9 */
624  index = 4;
625  break;
626  default:
627  index = -1;
628  break;
629  }
630 
631  if ( index != -1 ) {
632  int cache_level;
633  PAPI_mh_info_t sys_mh_inf = sys_mem_info[index];
634  PAPI_mh_info_t *mh_inf = &hw_info->mem_hierarchy;
635  mh_inf->levels = sys_mh_inf.levels;
636  PAPI_mh_level_t *level = mh_inf->level;
637  PAPI_mh_level_t sys_mh_level;
638  for ( cache_level = 0; cache_level < sys_mh_inf.levels; cache_level++ ) {
639  sys_mh_level = sys_mh_inf.level[cache_level];
640  int cache_idx;
641  for ( cache_idx = 0; cache_idx < 2; cache_idx++ ) {
642  // process TLB info
643  PAPI_mh_tlb_info_t curr_tlb = sys_mh_level.tlb[cache_idx];
644  int type = curr_tlb.type;
645  if ( type != PAPI_MH_TYPE_EMPTY ) {
646  level[cache_level].tlb[cache_idx].type = type;
647  level[cache_level].tlb[cache_idx].associativity =
648  curr_tlb.associativity;
649  level[cache_level].tlb[cache_idx].num_entries =
650  curr_tlb.num_entries;
651  }
652  }
653  for ( cache_idx = 0; cache_idx < 2; cache_idx++ ) {
654  // process cache info
655  PAPI_mh_cache_info_t curr_cache = sys_mh_level.cache[cache_idx];
656  int type = curr_cache.type;
657  if ( type != PAPI_MH_TYPE_EMPTY ) {
658  level[cache_level].cache[cache_idx].type = type;
659  level[cache_level].cache[cache_idx].associativity =
660  curr_cache.associativity;
661  level[cache_level].cache[cache_idx].size = curr_cache.size;
662  level[cache_level].cache[cache_idx].line_size =
663  curr_cache.line_size;
664  level[cache_level].cache[cache_idx].num_lines =
665  curr_cache.num_lines;
666  }
667  }
668  }
669  }
670  return 0;
671 }
672 #endif
673 
674 
675 
676 #if defined(__sparc__)
677 static int
678 sparc_sysfs_cpu_attr( char *name, char **result )
679 {
680  const char *path_base = "/sys/devices/system/cpu/";
681  char path_buf[PATH_MAX];
682  char val_buf[32];
683  DIR *sys_cpu;
684 
685  sys_cpu = opendir( path_base );
686  if ( sys_cpu ) {
687  struct dirent *cpu;
688 
689  while ( ( cpu = readdir( sys_cpu ) ) != NULL ) {
690  int fd;
691 
692  if ( strncmp( "cpu", cpu->d_name, 3 ) )
693  continue;
694  strcpy( path_buf, path_base );
695  strcat( path_buf, cpu->d_name );
696  strcat( path_buf, "/" );
697  strcat( path_buf, name );
698 
699  fd = open( path_buf, O_RDONLY );
700  if ( fd < 0 )
701  continue;
702 
703  if ( read( fd, val_buf, 32 ) < 0 )
704  continue;
705  close( fd );
706 
707  *result = strdup( val_buf );
708  return 0;
709  }
710  }
711  closedir( sys_cpu );
712  return -1;
713 }
714 
715 static int
716 sparc_cpu_attr( char *name, unsigned long long *val )
717 {
718  char *buf;
719  int r;
720 
721  r = sparc_sysfs_cpu_attr( name, &buf );
722  if ( r == -1 )
723  return -1;
724 
725  sscanf( buf, "%llu", val );
726 
727  free( buf );
728 
729  return 0;
730 }
731 
732 static char *
733 search_cpu_info( FILE * f, char *search_str, char *line )
734 {
735  /* This code courtesy of our friends in Germany. Thanks Rudolph Berrend\
736  orf! */
737  /* See the home page for the German version of PAPI. */
738 
739  char *s;
740 
741  while ( fgets( line, 256, f ) != NULL ) {
742  if ( strstr( line, search_str ) != NULL ) {
743  /* ignore all characters in line up to : */
744  for ( s = line; *s && ( *s != ':' ); ++s );
745  if ( *s )
746  return s;
747  }
748  }
749  return NULL;
750 
751  /* End stolen code */
752 }
753 
754 
755 static int
756 sparc_get_memory_info( PAPI_hw_info_t * hw_info )
757 {
758  unsigned long long cache_size, cache_line_size;
759  /* unsigned long long cycles_per_second; */
760  char maxargs[PAPI_HUGE_STR_LEN];
761  /* PAPI_mh_tlb_info_t *tlb; */
762  PAPI_mh_level_t *level;
763  char *s, *t;
764  FILE *f;
765 
766  /* First, fix up the cpu vendor/model/etc. values */
767  strcpy( hw_info->vendor_string, "Sun" );
768  hw_info->vendor = PAPI_VENDOR_SUN;
769 
770  f = fopen( "/proc/cpuinfo", "r" );
771  if ( !f )
772  return PAPI_ESYS;
773 
774  rewind( f );
775  s = search_cpu_info( f, "cpu", maxargs );
776  if ( !s ) {
777  fclose( f );
778  return PAPI_ESYS;
779  }
780 
781  t = strchr( s + 2, '\n' );
782  if ( !t ) {
783  fclose( f );
784  return PAPI_ESYS;
785  }
786 
787  *t = '\0';
788  strcpy( hw_info->model_string, s + 2 );
789 
790  fclose( f );
791 
792  /*
793  if ( sparc_sysfs_cpu_attr( "clock_tick", &s ) == -1 )
794  return PAPI_ESYS;
795 
796  sscanf( s, "%llu", &cycles_per_second );
797  free( s );
798 
799  hw_info->mhz = cycles_per_second / 1000000;
800  hw_info->clock_mhz = hw_info->mhz;
801  */
802 
803  /* Now fetch the cache info */
804  hw_info->mem_hierarchy.levels = 3;
805 
806  level = &hw_info->mem_hierarchy.level[0];
807 
808  sparc_cpu_attr( "l1_icache_size", &cache_size );
809  sparc_cpu_attr( "l1_icache_line_size", &cache_line_size );
810  level[0].cache[0].type = PAPI_MH_TYPE_INST;
811  level[0].cache[0].size = cache_size;
812  level[0].cache[0].line_size = cache_line_size;
813  level[0].cache[0].num_lines = cache_size / cache_line_size;
814  level[0].cache[0].associativity = 1;
815 
816  sparc_cpu_attr( "l1_dcache_size", &cache_size );
817  sparc_cpu_attr( "l1_dcache_line_size", &cache_line_size );
819  level[0].cache[1].size = cache_size;
820  level[0].cache[1].line_size = cache_line_size;
821  level[0].cache[1].num_lines = cache_size / cache_line_size;
822  level[0].cache[1].associativity = 1;
823 
824  sparc_cpu_attr( "l2_cache_size", &cache_size );
825  sparc_cpu_attr( "l2_cache_line_size", &cache_line_size );
827  level[1].cache[0].size = cache_size;
828  level[1].cache[0].line_size = cache_line_size;
829  level[1].cache[0].num_lines = cache_size / cache_line_size;
830  level[1].cache[0].associativity = 1;
831 
832 #if 0
833  tlb = &hw_info->mem_hierarchy.level[0].tlb[0];
834  switch ( _perfmon2_pfm_pmu_type ) {
835  case PFMLIB_SPARC_ULTRA12_PMU:
837  tlb[0].num_entries = 64;
838  tlb[0].associativity = SHRT_MAX;
840  tlb[1].num_entries = 64;
841  tlb[1].associativity = SHRT_MAX;
842  break;
843 
844  case PFMLIB_SPARC_ULTRA3_PMU:
845  case PFMLIB_SPARC_ULTRA3I_PMU:
846  case PFMLIB_SPARC_ULTRA3PLUS_PMU:
847  case PFMLIB_SPARC_ULTRA4PLUS_PMU:
848  level[0].cache[0].associativity = 4;
849  level[0].cache[1].associativity = 4;
850  level[1].cache[0].associativity = 4;
851 
853  tlb[0].num_entries = 16;
854  tlb[0].associativity = SHRT_MAX;
856  tlb[1].num_entries = 16;
857  tlb[1].associativity = SHRT_MAX;
858  tlb[2].type = PAPI_MH_TYPE_DATA;
859  tlb[2].num_entries = 1024;
860  tlb[2].associativity = 2;
861  tlb[3].type = PAPI_MH_TYPE_INST;
862  tlb[3].num_entries = 128;
863  tlb[3].associativity = 2;
864  break;
865 
866  case PFMLIB_SPARC_NIAGARA1:
867  level[0].cache[0].associativity = 4;
868  level[0].cache[1].associativity = 4;
869  level[1].cache[0].associativity = 12;
870 
872  tlb[0].num_entries = 64;
873  tlb[0].associativity = SHRT_MAX;
875  tlb[1].num_entries = 64;
876  tlb[1].associativity = SHRT_MAX;
877  break;
878 
879  case PFMLIB_SPARC_NIAGARA2:
880  level[0].cache[0].associativity = 8;
881  level[0].cache[1].associativity = 4;
882  level[1].cache[0].associativity = 16;
883 
885  tlb[0].num_entries = 64;
886  tlb[0].associativity = SHRT_MAX;
888  tlb[1].num_entries = 128;
889  tlb[1].associativity = SHRT_MAX;
890  break;
891  }
892 #endif
893  return 0;
894 }
895 #endif
896 
897 
898 /* Fallback Linux code to read the cache info from /sys */
899 int
901 {
902 
903  int type=0,level,result;
904  int size,line_size,associativity,sets;
905  DIR *dir;
906  FILE *fff;
907  char filename[BUFSIZ],type_string[BUFSIZ];
908  struct dirent *d;
909  int max_level=0;
910  int level_count=0,last_level=-1,level_index=0;
911 
912  PAPI_mh_level_t *L = hw_info->mem_hierarchy.level;
913 
914  /* open Linux cache dir */
915  /* assume all CPUs same as cpu0. */
916  /* Not necessarily a good assumption */
917 
918  dir=opendir("/sys/devices/system/cpu/cpu0/cache");
919  if (dir==NULL) {
920  goto unrecoverable_error;
921  }
922 
923  while(1) {
924  d = readdir(dir);
925  if (d==NULL) break;
926 
927  if (strncmp(d->d_name, "index", 5)) continue;
928 
929  MEMDBG("Found %s\n",d->d_name);
930 
931  /*************/
932  /* Get level */
933  /*************/
934  sprintf(filename,
935  "/sys/devices/system/cpu/cpu0/cache/%s/level",
936  d->d_name);
937  fff=fopen(filename,"r");
938  if (fff==NULL) {
939  MEMDBG("Cannot open level.\n");
940  goto unrecoverable_error;
941  }
942 
943  result=fscanf(fff,"%d",&level);
944  fclose(fff);
945  if (result!=1) {
946  MEMDBG("Could not read cache level\n");
947  goto unrecoverable_error;
948  }
949 
950  /* Index arrays from 0 */
951  level_index=level-1;
952 
953  if (level!=last_level) {
954  level_count=0;
955  last_level=level;
956  } else {
957  level_count++;
958  }
959 
960  if (level_count>=PAPI_MH_MAX_LEVELS) {
961  MEMDBG("Exceeded maximum levels %d\n",
962  PAPI_MH_MAX_LEVELS);
963  break;
964  }
965 
966  /************/
967  /* Get type */
968  /************/
969  sprintf(filename,
970  "/sys/devices/system/cpu/cpu0/cache/%s/type",d->d_name);
971  fff=fopen(filename,"r");
972  if (fff==NULL) {
973  MEMDBG("Cannot open type\n");
974  goto unrecoverable_error;
975  }
976  result=fscanf(fff,"%s",type_string);
977  fclose(fff);
978  if (result!=1) {
979  MEMDBG("Could not read cache type\n");
980  goto unrecoverable_error;
981  }
982  if (!strcmp(type_string,"Data")) {
983  type=PAPI_MH_TYPE_DATA;
984  }
985  if (!strcmp(type_string,"Instruction")) {
986  type=PAPI_MH_TYPE_INST;
987  }
988  if (!strcmp(type_string,"Unified")) {
990  }
991  L[level_index].cache[level_count].type=type;
992 
993  /*************/
994  /* Get Size */
995  /*************/
996  sprintf(filename,
997  "/sys/devices/system/cpu/cpu0/cache/%s/size",d->d_name);
998  fff=fopen(filename,"r");
999  if (fff==NULL) {
1000  MEMDBG("Cannot open size\n");
1001  goto unrecoverable_error;
1002  }
1003  result=fscanf(fff,"%d",&size);
1004  fclose(fff);
1005  if (result!=1) {
1006  MEMDBG("Could not read cache size\n");
1007  goto unrecoverable_error;
1008  }
1009 
1010  /* Linux reports in kB, PAPI expects in Bytes */
1011  L[level_index].cache[level_count].size=size*1024;
1012 
1013  /*************/
1014  /* Line Size */
1015  /*************/
1016  sprintf(filename,
1017  "/sys/devices/system/cpu/cpu0/cache/%s/coherency_line_size",
1018  d->d_name);
1019  fff=fopen(filename,"r");
1020  if (fff==NULL) {
1021  MEMDBG("Cannot open linesize\n");
1022  goto unrecoverable_error;
1023  }
1024  result=fscanf(fff,"%d",&line_size);
1025  fclose(fff);
1026  if (result!=1) {
1027  MEMDBG("Could not read cache line-size\n");
1028  goto unrecoverable_error;
1029  }
1030  L[level_index].cache[level_count].line_size=line_size;
1031 
1032 
1033  /*********************/
1034  /* Get Associativity */
1035  /*********************/
1036  sprintf(filename,
1037  "/sys/devices/system/cpu/cpu0/cache/%s/ways_of_associativity",
1038  d->d_name);
1039  fff=fopen(filename,"r");
1040  if (fff==NULL) {
1041  MEMDBG("Cannot open associativity\n");
1042  goto unrecoverable_error;
1043  }
1044  result=fscanf(fff,"%d",&associativity);
1045  fclose(fff);
1046  if (result!=1) {
1047  MEMDBG("Could not read cache associativity\n");
1048  goto unrecoverable_error;
1049  }
1050  L[level_index].cache[level_count].associativity=associativity;
1051 
1052  /************/
1053  /* Get Sets */
1054  /************/
1055  sprintf(filename,
1056  "/sys/devices/system/cpu/cpu0/cache/%s/number_of_sets",
1057  d->d_name);
1058  fff=fopen(filename,"r");
1059  if (fff==NULL) {
1060  MEMDBG("Cannot open sets\n");
1061  goto unrecoverable_error;
1062  }
1063  result=fscanf(fff,"%d",&sets);
1064  fclose(fff);
1065 
1066  if (result!=1) {
1067  MEMDBG("Could not read cache sets\n");
1068  goto unrecoverable_error;
1069  }
1070  L[level_index].cache[level_count].num_lines=sets;
1071 
1072 
1073  if (((size*1024)/line_size/associativity)!=sets) {
1074  MEMDBG("Warning! sets %d != expected %d\n",
1075  sets,((size*1024)/line_size/associativity));
1076  }
1077 
1078  MEMDBG("\tL%d %s cache\n",level,type_string);
1079  MEMDBG("\t%d kilobytes\n",size);
1080  MEMDBG("\t%d byte linesize\n",line_size);
1081  MEMDBG("\t%d-way associative\n",associativity);
1082  MEMDBG("\t%d lines\n",sets);
1083  MEMDBG("\tUnknown inclusivity\n");
1084  MEMDBG("\tUnknown replacement algorithm\n");
1085  MEMDBG("\tUnknown if victim cache\n");
1086 
1087  if (level>max_level) max_level=level;
1088 
1089  if (level>=PAPI_MAX_MEM_HIERARCHY_LEVELS) {
1090  MEMDBG("Exceeded maximum cache level %d\n",
1092  break;
1093  }
1094  }
1095 
1096  hw_info->mem_hierarchy.levels = max_level;
1097 
1098  return 0;
1099 
1100 unrecoverable_error:
1101 
1102  /* Just say we have no cache */
1103  hw_info->mem_hierarchy.levels = 0;
1104 
1105  return 0;
1106 }
1107 
1108 
1109 int
1110 _linux_get_memory_info( PAPI_hw_info_t * hwinfo, int cpu_type )
1111 {
1112  ( void ) cpu_type; /*unused */
1113  int retval = PAPI_OK;
1114 
1115 #if defined(__i386__)||defined(__x86_64__)
1116  x86_get_memory_info( hwinfo );
1117 #elif defined(__ia64__)
1118  ia64_get_memory_info( hwinfo );
1119 #elif defined(__powerpc__)
1120  ppc64_get_memory_info( hwinfo );
1121 #elif defined(__sparc__)
1122  sparc_get_memory_info( hwinfo );
1123 #elif defined(__arm__)
1124  #warning "WARNING! linux_get_memory_info() does nothing on ARM32!"
1125  generic_get_memory_info (hwinfo);
1126 #else
1127  generic_get_memory_info (hwinfo);
1128 #endif
1129 
1130  return retval;
1131 }
1132 
1133 int
1135 {
1136 
1137  char fname[PAPI_HUGE_STR_LEN];
1138  unsigned long t_index = 0, d_index = 0, b_index = 0, counting = 1;
1139  char buf[PAPI_HUGE_STR_LEN + PAPI_HUGE_STR_LEN], perm[5], dev[16];
1140  char mapname[PAPI_HUGE_STR_LEN], lastmapname[PAPI_HUGE_STR_LEN];
1141  unsigned long begin = 0, end = 0, size = 0, inode = 0, foo = 0;
1142  PAPI_address_map_t *tmp = NULL;
1143  FILE *f;
1144 
1145  memset( fname, 0x0, sizeof ( fname ) );
1146  memset( buf, 0x0, sizeof ( buf ) );
1147  memset( perm, 0x0, sizeof ( perm ) );
1148  memset( dev, 0x0, sizeof ( dev ) );
1149  memset( mapname, 0x0, sizeof ( mapname ) );
1150  memset( lastmapname, 0x0, sizeof ( lastmapname ) );
1151 
1152  sprintf( fname, "/proc/%ld/maps", ( long ) mdi->pid );
1153  f = fopen( fname, "r" );
1154 
1155  if ( !f ) {
1156  PAPIERROR( "fopen(%s) returned < 0", fname );
1157  return PAPI_OK;
1158  }
1159 
1160  again:
1161  while ( !feof( f ) ) {
1162  begin = end = size = inode = foo = 0;
1163  if ( fgets( buf, sizeof ( buf ), f ) == 0 )
1164  break;
1165  /* If mapname is null in the string to be scanned, we need to detect that */
1166  if ( strlen( mapname ) )
1167  strcpy( lastmapname, mapname );
1168  else
1169  lastmapname[0] = '\0';
1170  /* If mapname is null in the string to be scanned, we need to detect that */
1171  mapname[0] = '\0';
1172  sscanf( buf, "%lx-%lx %4s %lx %s %ld %s", &begin, &end, perm, &foo, dev,
1173  &inode, mapname );
1174  size = end - begin;
1175 
1176  /* the permission string looks like "rwxp", where each character can
1177  * be either the letter, or a hyphen. The final character is either
1178  * p for private or s for shared. */
1179 
1180  if ( counting ) {
1181  if ( ( perm[2] == 'x' ) && ( perm[0] == 'r' ) && ( inode != 0 ) ) {
1182  if ( strcmp( mdi->exe_info.fullname, mapname )
1183  == 0 ) {
1185  ( caddr_t ) begin;
1187  ( caddr_t ) ( begin + size );
1188  }
1189  t_index++;
1190  } else if ( ( perm[0] == 'r' ) && ( perm[1] == 'w' ) &&
1191  ( inode != 0 )
1192  &&
1193  ( strcmp
1194  ( mdi->exe_info.fullname,
1195  mapname ) == 0 ) ) {
1197  ( caddr_t ) begin;
1199  ( caddr_t ) ( begin + size );
1200  d_index++;
1201  } else if ( ( perm[0] == 'r' ) && ( perm[1] == 'w' ) &&
1202  ( inode == 0 )
1203  &&
1204  ( strcmp
1205  ( mdi->exe_info.fullname,
1206  lastmapname ) == 0 ) ) {
1208  ( caddr_t ) begin;
1210  ( caddr_t ) ( begin + size );
1211  b_index++;
1212  }
1213  } else if ( !counting ) {
1214  if ( ( perm[2] == 'x' ) && ( perm[0] == 'r' ) && ( inode != 0 ) ) {
1215  if ( strcmp( mdi->exe_info.fullname, mapname )
1216  != 0 ) {
1217  t_index++;
1218  tmp[t_index - 1].text_start = ( caddr_t ) begin;
1219  tmp[t_index - 1].text_end = ( caddr_t ) ( begin + size );
1220  strncpy( tmp[t_index - 1].name, mapname, PAPI_MAX_STR_LEN );
1221  }
1222  } else if ( ( perm[0] == 'r' ) && ( perm[1] == 'w' ) &&
1223  ( inode != 0 ) ) {
1224  if ( ( strcmp
1225  ( mdi->exe_info.fullname,
1226  mapname ) != 0 )
1227  && ( t_index > 0 ) &&
1228  ( tmp[t_index - 1].data_start == 0 ) ) {
1229  tmp[t_index - 1].data_start = ( caddr_t ) begin;
1230  tmp[t_index - 1].data_end = ( caddr_t ) ( begin + size );
1231  }
1232  } else if ( ( perm[0] == 'r' ) && ( perm[1] == 'w' ) &&
1233  ( inode == 0 ) ) {
1234  if ( ( t_index > 0 ) && ( tmp[t_index - 1].bss_start == 0 ) ) {
1235  tmp[t_index - 1].bss_start = ( caddr_t ) begin;
1236  tmp[t_index - 1].bss_end = ( caddr_t ) ( begin + size );
1237  }
1238  }
1239  }
1240  }
1241 
1242  if ( counting ) {
1243  /* When we get here, we have counted the number of entries in the map
1244  for us to allocate */
1245 
1246  tmp =
1247  ( PAPI_address_map_t * ) papi_calloc( t_index,
1248  sizeof
1249  ( PAPI_address_map_t ) );
1250  if ( tmp == NULL ) {
1251  PAPIERROR( "Error allocating shared library address map" );
1252  fclose(f);
1253  return PAPI_ENOMEM;
1254  }
1255  t_index = 0;
1256  rewind( f );
1257  counting = 0;
1258  goto again;
1259  } else {
1260  if ( mdi->shlib_info.map )
1261  papi_free( mdi->shlib_info.map );
1262  mdi->shlib_info.map = tmp;
1263  mdi->shlib_info.count = t_index;
1264 
1265  fclose( f );
1266  }
1267 
1268  return PAPI_OK;
1269 }
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
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
int levels
Definition: papi.h:774
#define PAPI_VENDOR_SUN
Definition: papi.h:352
Hardware info structure.
Definition: papi.h:780
#define PAPI_MH_TYPE_INST
Definition: papi.h:730
#define papi_free(a)
Definition: papi_memory.h:35
caddr_t text_end
Definition: papi.h:698
PAPI_mh_info_t mem_hierarchy
Definition: papi.h:799
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:737
int fd
Definition: iozone.c:1291
static int _perfmon2_pfm_pmu_type
Definition: perfmon.c:50
#define PAPI_EBUG
Definition: papi.h:259
int associativity
Definition: papi.h:753
return PAPI_OK
Definition: linux-nvml.c:497
caddr_t bss_start
Definition: papi.h:701
char filename[MAXNAMESIZE]
Definition: iozone.c:1360
PAPI_exe_info_t exe_info
#define PAPI_MH_TYPE_PSEUDO_LRU
Definition: papi.h:741
long long heap
Definition: papi.h:879
fclose(thread_wqfd)
void
Definition: iozone.c:18627
static FILE * fp
double c
Definition: multiplex.c:22
#define PAPI_MH_TYPE_LRU
Definition: papi.h:740
#define PAPI_HUGE_STR_LEN
Definition: papi.h:467
PAPI_shlib_info_t shlib_info
Return codes and api definitions.
FILE * fff[MAX_EVENTS]
#define PAPI_MH_TYPE_DATA
Definition: papi.h:731
long long ret
Definition: iozone.c:1346
int _linux_update_shlib_info(papi_mdi_t *mdi)
t
Definition: iozone.c:23562
#define PAPI_MH_MAX_LEVELS
Definition: papi.h:745
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:768
int i
Definition: fileop.c:140
long long resident
Definition: papi.h:874
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)
A pointer to the following is passed to PAPI_get_dmem_info()
Definition: papi.h:871
char *long long size
Definition: iozone.c:12023
free(dummyfile[xx])
caddr_t text_start
Definition: papi.h:697
PAPI_mh_level_t level[PAPI_MAX_MEM_HIERARCHY_LEVELS]
Definition: papi.h:775
PAPI_address_map_t address_info
Definition: papi.h:709
long long pagesize
Definition: papi.h:882
void int num
Definition: iozone.c:22151
PAPI_mh_tlb_info_t tlb[PAPI_MH_MAX_LEVELS]
Definition: papi.h:767
#define PAPI_ESYS
Definition: papi.h:255
pthread_attr_t foo
Definition: iozone.c:18592
get the executable&#39;s address space info
Definition: papi.h:695
s
Definition: iozone.c:20289
long long locked
Definition: papi.h:880
void PAPIERROR(char *format,...)
#define MEMDBG(format, args...)
Definition: papi_debug.h:70
int _linux_get_dmem_info(PAPI_dmem_info_t *d)
Definition: linux-memory.c:48
long long library
Definition: papi.h:878
strcat(command, mountname)
mh for mem hierarchy maybe?
Definition: papi.h:773
#define PAPI_ENOMEM
Definition: papi.h:254
#define PAPI_ENOIMPL
Definition: papi.h:272
char vendor_string[PAPI_MAX_STR_LEN]
Definition: papi.h:788
strcpy(filename, default_filename)
#define PAPI_VENDOR_INTEL
Definition: papi.h:348
caddr_t data_start
Definition: papi.h:699
int vendor
Definition: papi.h:787
long long shared
Definition: papi.h:876
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:714
caddr_t bss_end
Definition: papi.h:702
int generic_get_memory_info(PAPI_hw_info_t *hw_info)
Definition: linux-memory.c:900
long long text
Definition: papi.h:877
long long stack
Definition: papi.h:881
caddr_t data_end
Definition: papi.h:700
#define PAPI_MH_TYPE_UNIFIED
Definition: papi.h:734
#define PAPI_MAX_STR_LEN
Definition: papi.h:465
char model_string[PAPI_MAX_STR_LEN]
Definition: papi.h:790
char fullname[PAPI_HUGE_STR_LEN]
Definition: papi.h:708
#define PAPI_MH_TYPE_EMPTY
Definition: papi.h:729
#define PAPI_MH_TYPE_WT
Definition: papi.h:736
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:28
long long size
Definition: papi.h:873
rewind(w_traj_fd)
#define papi_calloc(a, b)
Definition: papi_memory.h:37
void begin()
#define PAPI_MAX_MEM_HIERARCHY_LEVELS
Definition: papi.h:746
unsigned long cache_size
Definition: iozone.c:1375
#define PAPI_VENDOR_AMD
Definition: papi.h:349
long long high_water_mark
Definition: papi.h:875
int sz
Definition: fileop.c:80