/TIMING/t_initialize.c

https://gitlab.com/martinsingh/SAM · C · 292 lines · 167 code · 75 blank · 50 comment · 40 complexity · 5ba458684d060ba6a1c3d3d941d25cc9 MD5 · raw file

  1. #include <stdlib.h> /* malloc */
  2. #include <unistd.h> /* sysconf */
  3. #include <gpt.h>
  4. /*
  5. ** Array (1 per thread) of linked lists of timers, and last timer in each list
  6. */
  7. struct node **timers = NULL;
  8. struct node **last = NULL;
  9. long ticks_per_sec;
  10. /*
  11. ** Define lock arrays depending upon the type of threading done
  12. */
  13. #if ( defined THREADED_OMP )
  14. omp_lock_t lock;
  15. #elif ( defined THREADED_PTHREADS )
  16. pthread_mutex_t t_mutex = PTHREAD_MUTEX_INITIALIZER;
  17. pthread_t *threadid;
  18. #endif
  19. float *overhead; /* wallclock estimate of timer overhead */
  20. int *max_indent_level; /* maximum indentation level */
  21. int numthreads = 1; /* number of threads. 1 is for no threading */
  22. Boolean t_initialized = false; /* whether t_initialize has been called */
  23. Boolean wallenabled = false; /* wallclock timer stats enabled */
  24. Boolean usrsysenabled = false; /* usr & sys timer stats enabled */
  25. Boolean pclenabled = false; /* enable PCL library */
  26. Boolean pcl_cyclesenabled = false; /* enable PCL cycle count */
  27. int pcl_cyclesindex = -1; /* index for PCL cycle count */
  28. struct PossibleEvent possible_event[] = {
  29. {usrsys, true, "Usr Sys "},
  30. {wall, true, "Wallclock "},
  31. #ifdef HAVE_PCL
  32. {pcl_start, false, " "}, /* bracket PCL entries */
  33. {pcl_l1dcache_miss, false, "l1 D miss "},
  34. {pcl_l2cache_miss, false, "L2 miss "},
  35. {pcl_cycles, false, "Cycles "},
  36. {pcl_elapsed_cycles, false, "E-Cycles "},
  37. {pcl_fp_instr, false, "FP instr "},
  38. {pcl_loadstore_instr, false, "L/S instr "},
  39. {pcl_instr, false, "Instruct "},
  40. {pcl_stall, false, "Stall "},
  41. {pcl_end, false, " "}, /* bracket PCL entries */
  42. #endif
  43. };
  44. struct Event **event = NULL;
  45. int nevent = 0;
  46. int npossible = sizeof (possible_event) / sizeof (struct PossibleEvent);
  47. /*
  48. ** Needed by PCL library: otherwise unused
  49. */
  50. PCL_DESCR_TYPE *descr;
  51. int counter_list[PCL_COUNTER_MAX];
  52. int ncounter = 0; /* number of PCL counters */
  53. PCL_CNT_TYPE *overhead_pcl; /* overhead counter (cycles) */
  54. /*
  55. ** t_initialize (): Initialization routine must be called from single-threaded
  56. ** region before any other timing routines may be called. The need for this
  57. ** routine could be eliminated if not targetting timing library for threaded
  58. ** capability.
  59. **
  60. ** return value: 0 (success) or -1 (failure)
  61. */
  62. int t_initialize ()
  63. {
  64. int n; /* index */
  65. int nbytes; /* number of bytes for malloc */
  66. /* int ret; */ /* return code */
  67. /*
  68. ** Determine number of ticks per second for conversion use by other t_pr(), t_stamp()
  69. */
  70. if ((ticks_per_sec = sysconf (_SC_CLK_TCK)) == -1)
  71. return t_error ("t_initialize: token _SC_CLK_TCK is not defined\n");
  72. #if ( ! defined DISABLE_TIMERS )
  73. if (t_initialized)
  74. return t_error ("t_initialize has already been called\n");
  75. #if ( defined THREADED_OMP )
  76. /*
  77. ** OMP: must call init_lock before using the lock (get_thread_num())
  78. */
  79. omp_init_lock (&lock);
  80. numthreads = omp_get_max_threads();
  81. #elif ( defined THREADED_PTHREADS )
  82. numthreads = MAX_THREADS;
  83. #endif
  84. /*
  85. ** Allocate space for global arrays
  86. */
  87. nbytes = numthreads * sizeof (struct node *);
  88. if ((timers = (struct node **) malloc (nbytes)) == 0)
  89. return t_error ("malloc failure: %d items\n", numthreads);
  90. if ((last = (struct node **) malloc (nbytes)) == 0)
  91. return t_error ("malloc failure: %d items\n", numthreads);
  92. nbytes = numthreads * sizeof (float);
  93. if ((overhead = (float *) malloc (nbytes)) == 0)
  94. return t_error ("malloc failure: %d items\n", numthreads);
  95. nbytes = numthreads * sizeof (PCL_CNT_TYPE);
  96. if ((overhead_pcl = (PCL_CNT_TYPE *) malloc (nbytes)) == 0)
  97. return t_error ("malloc failure: %d items\n", numthreads);
  98. nbytes = numthreads * sizeof (int);
  99. if ((max_indent_level = (int *) malloc (nbytes)) == 0)
  100. return t_error ("malloc failure for %d items\n", numthreads);
  101. /*
  102. ** Initialize array values
  103. */
  104. for (n = 0; n < numthreads; n++) {
  105. timers[n] = 0;
  106. last[n] = 0;
  107. overhead[n] = 0.;
  108. overhead_pcl[n] = 0;
  109. max_indent_level[n] = 0;
  110. }
  111. #ifdef THREADED_PTHREADS
  112. /*
  113. ** In the pthreads case, we must manage the threadid array which maps
  114. ** physical thread id's to logical id's
  115. */
  116. nbytes = numthreads * sizeof (pthread_t);
  117. if ((threadid = (pthread_t *) malloc (nbytes)) == 0)
  118. return t_error ("malloc failure for %d items\n", numthreads);
  119. /*
  120. ** Reset numthreads to 1 and define the threadid array now that initialization
  121. ** is done.
  122. */
  123. threadid[0] = pthread_self ();
  124. numthreads = 1;
  125. #endif
  126. if (get_thread_num () > 0)
  127. return t_error ("t_initialize: should only be called by master thread\n");
  128. for (n = 0; n < npossible; n++) {
  129. if (possible_event[n].enabled) {
  130. if (possible_event[n].name == usrsys)
  131. usrsysenabled = true;
  132. if (possible_event[n].name == wall)
  133. wallenabled = true;
  134. if ((event = realloc (event, (nevent+1) * sizeof (struct Event *))) == NULL)
  135. return t_error ("realloc failure\n");
  136. if ((event[nevent] = malloc (sizeof (struct Event))) == NULL)
  137. return t_error ("realloc failure\n");
  138. event[nevent]->name = possible_event[n].name;
  139. strcpy (event[nevent]->string, possible_event[n].string);
  140. #ifdef HAVE_PCL
  141. /*
  142. ** Set up PCL stuff based on what t_setoption has provided.
  143. */
  144. if (event[nevent]->name > pcl_start && event[nevent]->name < pcl_end) {
  145. pclenabled = true;
  146. event[nevent]->index = ncounter;
  147. switch (possible_event[n].name) {
  148. case pcl_l1dcache_miss:
  149. counter_list[ncounter++] = PCL_L1DCACHE_MISS;
  150. break;
  151. case pcl_l2cache_miss:
  152. counter_list[ncounter++] = PCL_L2CACHE_MISS;
  153. break;
  154. case pcl_cycles:
  155. pcl_cyclesindex = ncounter;
  156. pcl_cyclesenabled = true;
  157. counter_list[ncounter++] = PCL_CYCLES;
  158. break;
  159. case pcl_elapsed_cycles:
  160. counter_list[ncounter++] = PCL_ELAPSED_CYCLES;
  161. break;
  162. case pcl_fp_instr:
  163. counter_list[ncounter++] = PCL_FP_INSTR;
  164. break;
  165. case pcl_loadstore_instr:
  166. counter_list[ncounter++] = PCL_LOADSTORE_INSTR;
  167. break;
  168. case pcl_instr:
  169. counter_list[ncounter++] = PCL_INSTR;
  170. break;
  171. case pcl_stall:
  172. counter_list[ncounter++] = PCL_STALL;
  173. break;
  174. default:
  175. break;
  176. }
  177. }
  178. #endif
  179. ++nevent;
  180. }
  181. }
  182. #ifdef HAVE_PCL
  183. if (ncounter > 0) {
  184. int thread; /* thread number */
  185. nbytes = numthreads * sizeof (PCL_DESCR_TYPE);
  186. if ((descr = (PCL_DESCR_TYPE *) malloc (nbytes)) == 0)
  187. return t_error ("malloc failure: %d items\n", numthreads);
  188. /*
  189. ** PCLinit must be called on a per-thread basis. Therefore must make the call here
  190. ** rather than in t_initialize. null timer list flags not initialized.
  191. ** Also, the critical section is necessary because PCLstart appears not to be
  192. ** thread-safe.
  193. */
  194. #pragma omp parallel for
  195. for (thread = 0; thread < numthreads; thread++) {
  196. unsigned int flags; /* mode flags needed by PCL */
  197. #pragma omp critical
  198. {
  199. if ((ret = PCLinit (&descr[thread])) != PCL_SUCCESS)
  200. return t_error ("unable to allocate PCL handle for thread %d. %s\n",
  201. thread, t_pclstr (ret));
  202. /*
  203. ** Always count user mode only
  204. */
  205. flags = PCL_MODE_USER;
  206. if ((ret = PCLquery (descr[thread], counter_list, ncounter, flags)) != PCL_SUCCESS)
  207. return t_error ("Bad return from PCLquery thread %d: %s\n", thread, t_pclstr (ret));
  208. if ((ret = PCLstart (descr[thread], counter_list, ncounter, flags)) != PCL_SUCCESS)
  209. return t_error ("PCLstart failed thread=%d: %s\n", thread, t_pclstr (ret));
  210. }
  211. }
  212. }
  213. #endif
  214. t_initialized = true;
  215. #endif
  216. return 0;
  217. }