litl  0.1.9
litl_write.c
Go to the documentation of this file.
1 /* -*- c-file-style: "GNU" -*- */
2 /*
3  * Copyright © Télécom SudParis.
4  * See COPYING in top-level directory.
5  */
6 
7 #define _GNU_SOURCE
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <math.h>
12 #include <pthread.h>
13 #include <sys/utsname.h>
14 #include <fcntl.h>
15 #include <unistd.h>
16 #include <errno.h>
17 #include <assert.h>
18 #include <sys/mman.h>
19 
20 #include "litl_timer.h"
21 #include "litl_tools.h"
22 #include "litl_write.h"
23 
24 /*
25  * Adds a header to the trace file with the information regarding:
26  * - OS
27  * - Processor type
28  * - Version of LiTL
29  */
30 static void __litl_write_add_trace_header(litl_write_trace_t* trace) {
31  struct utsname uts;
32 
33  // allocate memory for the trace header
34  trace->header_ptr = (litl_buffer_t) malloc(trace->header_size);
35  if (!trace->header_ptr) {
36  perror("Could not allocate memory for the trace header!");
37  exit(EXIT_FAILURE);
38  }
39  trace->header = trace->header_ptr;
40  memset(trace->header_ptr, 0, trace->header_size);
41  if (uname(&uts) < 0)
42  perror("Could not use uname()!");
43 
44  // add a general header
45  // version of LiTL
46  sprintf((char*) ((litl_general_header_t *) trace->header)->litl_ver, "%s",
47  VERSION);
48  // system information
49  sprintf((char*) ((litl_general_header_t *) trace->header)->sysinfo,
50  "%s %s %s %s %s", uts.sysname, uts.nodename, uts.release, uts.version,
51  uts.machine);
52  // a number of processes
53  ((litl_general_header_t *) trace->header)->nb_processes = 1;
54  // move pointer
55  trace->header += sizeof(litl_general_header_t);
56 
57  // add a process-specific header
58  // by default one trace file contains events only of one process
59  char* filename = strrchr(trace->filename, '/');
60  filename++;
61  sprintf((char*) ((litl_process_header_t *) trace->header)->process_name, "%s",
62  filename);
63  ((litl_process_header_t *) trace->header)->nb_threads = trace->nb_threads;
64  ((litl_process_header_t *) trace->header)->header_nb_threads =
65  trace->nb_threads;
66  ((litl_process_header_t *) trace->header)->buffer_size = trace->buffer_size;
67  ((litl_process_header_t *) trace->header)->trace_size = 0;
68  ((litl_process_header_t *) trace->header)->offset =
70 
71  // header_size stores the position of nb_threads in the trace file
72  trace->header_size = sizeof(litl_general_header_t)
73  + 256 * sizeof(litl_data_t);
74  // move pointer
75  trace->header += sizeof(litl_process_header_t);
76 }
77 
78 /*
79  * Initializes the trace buffer
80  */
83  litl_write_trace_t* trace;
84 
85  trace = (litl_write_trace_t*) malloc(sizeof(litl_write_trace_t));
86  if (!trace) {
87  perror("Could not allocate memory for the trace!");
88  exit(EXIT_FAILURE);
89  }
90 
91  // set variables
92  trace->filename = NULL;
93  trace->general_offset = 0;
94  trace->is_header_flushed = 0;
95 
96  // set the buffer size using the environment variable.
97  // If the variable is not specified, use the provided value
98  char* str = getenv("LITL_BUFFER_SIZE");
99  if (str != NULL )
100  trace->buffer_size = atoi(str);
101  else
102  trace->buffer_size = buf_size;
103 
104  trace->is_buffer_full = 0;
105  trace->nb_allocated_buffers = 256;
106  trace->buffers = malloc(
107  sizeof(litl_write_buffer_t*) * trace->nb_allocated_buffers);
108  if (!trace->buffers) {
109  perror("Could not allocate memory for the threads!");
110  exit(EXIT_FAILURE);
111  }
112 
113  for (i = 0; i < trace->nb_allocated_buffers; i++) {
114  // initialize the array already_flushed
115  trace->buffers[i] = malloc(sizeof(litl_write_buffer_t));
116  if (!trace->buffers[i]) {
117  perror("Could not allocate memory for a thread\n");
118  exit(EXIT_FAILURE);
119  }
120  trace->buffers[i]->already_flushed = 0;
121 
122  // initialize tids by zeros; this is needed for __is_tid and __find_slot
123  trace->buffers[i]->tid = 0;
124  }
125  trace->nb_threads = 0;
126 
127  // initialize the timing mechanism
129 
130  assert(pthread_key_create(&trace->index, NULL ) == 0);
131 
132  // set trace->allow_buffer_flush using the environment variable.
133  // By default the buffer flushing is disabled
135  str = getenv("LITL_BUFFER_FLUSH");
136  if (str) {
137  if(strcmp(str, "0") == 0)
139  else
141  }
142 
143  // set trace->allow_thread_safety using the environment variable.
144  // By default thread safety is enabled
146  str = getenv("LITL_THREAD_SAFETY");
147  if (str && (strcmp(str, "0") == 0))
149 
150  if (trace->allow_thread_safety)
151  pthread_mutex_init(&trace->lock_litl_flush, NULL );
152  pthread_mutex_init(&trace->lock_buffer_init, NULL );
153 
154  // set trace->allow_tid_recording using the environment variable.
155  // By default tid recording is enabled
157  str = getenv("LITL_TID_RECORDING");
158  if (str && (strcmp(str, "0") == 0))
160 
161  trace->is_recording_paused = 0;
162  trace->is_litl_initialized = 1;
163 
164  return trace;
165 }
166 
167 /*
168  * Computes the size of data in the trace header
169  */
170 static litl_size_t __litl_write_get_header_size(litl_write_trace_t* trace) {
171  return (trace->header - trace->header_ptr);
172 }
173 
174 /*
175  * Computes the size of data in buffer
176  */
177 static litl_size_t __litl_write_get_buffer_size(litl_write_trace_t* trace,
178  litl_med_size_t pos) {
179  return (trace->buffers[pos]->buffer - trace->buffers[pos]->buffer_ptr);
180 }
181 
182 /*
183  * Activates buffer flush
184  */
186  trace->allow_buffer_flush = 1;
187 }
188 
189 /*
190  * Deactivates buffer flush. By default, it is activated
191  */
193  trace->allow_buffer_flush = 0;
194 }
195 
196 /*
197  * Activate thread safety. By default it is deactivated
198  */
200  trace->allow_thread_safety = 1;
201 }
202 
203 /*
204  * Deactivates thread safety
205  */
207  trace->allow_thread_safety = 0;
208 }
209 
210 /*
211  * Activates recording tid. By default it is deactivated
212  */
214  trace->allow_tid_recording = 1;
215 }
216 
217 /*
218  * Deactivates recording tid
219  */
221  trace->allow_tid_recording = 0;
222 }
223 
224 /*
225  * Pauses the event recording
226  */
228  if (trace)
229  trace->is_recording_paused = 1;
230 }
231 
232 /*
233  * Resumes the event recording
234  */
236  if (trace)
237  trace->is_recording_paused = 0;
238 }
239 
240 /*
241  * Sets a new name for the trace file
242  */
243 void litl_write_set_filename(litl_write_trace_t* trace, char* filename) {
244  if (trace->filename) {
245  if (trace->is_header_flushed)
246  fprintf(
247  stderr,
248  "Warning: changing the trace file name to %s after some events have been saved in file %s\n",
249  filename, trace->filename);
250  free(trace->filename);
251  }
252 
253  // check whether the file name was set. If no, set it by default trace name.
254  if (filename == NULL )
255  sprintf(filename, "/tmp/%s_%s", getenv("USER"), "litl_log_1");
256 
257  if (asprintf(&trace->filename, "%s", filename) == -1) {
258  perror("Error: Cannot set the filename for recording events!\n");
259  exit(EXIT_FAILURE);
260  }
261 }
262 
263 /*
264  * Records an event with offset only
265  */
266 static void __litl_write_probe_offset(litl_write_trace_t* trace,
267  litl_med_size_t index) {
268  if (!trace->is_litl_initialized || trace->is_recording_paused)
269  return;
270 
271  litl_t* cur_ptr = (litl_t *) trace->buffers[index]->buffer;
272  cur_ptr->time = 0;
273  cur_ptr->code = LITL_OFFSET_CODE;
274  cur_ptr->type = LITL_TYPE_REGULAR;
275  cur_ptr->parameters.offset.nb_params = 1;
276  cur_ptr->parameters.offset.offset = 0;
277 
278  trace->buffers[index]->buffer += __litl_get_gen_event_size(cur_ptr);
279 }
280 
281 /* Open the trace file. If the file already exists, delete it first
282  */
283 static void __litl_open_new_file(litl_write_trace_t* trace) {
284  /* if file exist. delete it first */
285  if ((trace->f_handle = open(trace->filename, O_WRONLY | O_CREAT | O_EXCL, 0644))
286  < 0) {
287 
288  if(errno == EEXIST) {
289  /* file already exist. Delete it and open it */
290  if(unlink(trace->filename) < 0 ){
291  perror("Cannot delete trace file");
292  exit(EXIT_FAILURE);
293  }
294  if ((trace->f_handle = open(trace->filename, O_WRONLY | O_CREAT | O_EXCL, 0644))
295  < 0) {
296  perror("Cannot open trace file");
297  exit(EXIT_FAILURE);
298  }
299  } else {
300  fprintf(stderr, "Cannot open %s\n", trace->filename);
301  exit(EXIT_FAILURE);
302  }
303  }
304 }
305 
306 /*
307  * Write the header on the disk
308  */
309 static void __litl_write_update_header(litl_write_trace_t* trace) {
310  // write the trace header to the trace file
311  assert(trace->f_handle >= 0);
312  lseek(trace->f_handle, 0, SEEK_SET);
313 
314  if (write(trace->f_handle, trace->header_ptr,
315  __litl_write_get_header_size(trace)) == -1) {
316  perror(
317  "Flushing the buffer. Could not write measured data to the trace file!");
318  exit(EXIT_FAILURE);
319  }
320 }
321 
322 /*
323  * Update the header and flush it to disk
324  */
325 static void __litl_write_flush_header(litl_write_trace_t* trace) {
326 
327  if (!trace->is_header_flushed) {
328  // open the trace file
329  __litl_open_new_file(trace);
330 
331  // add a header to the trace file
332  trace->header_size = sizeof(litl_general_header_t)
333  + sizeof(litl_process_header_t)
334  + (trace->nb_threads + 1) * sizeof(litl_thread_pair_t);
335  __litl_write_add_trace_header(trace);
336 
337  // add information about each working thread: (tid, offset)
338  litl_med_size_t i;
339  for (i = 0; i < trace->nb_threads; i++) {
340  ((litl_thread_pair_t *) trace->header)->tid = trace->buffers[i]->tid;
341  ((litl_thread_pair_t *) trace->header)->offset = 0;
342 
343  trace->header += sizeof(litl_thread_pair_t);
344 
345  // save the position of offset inside the trace file
346  trace->buffers[i]->offset = __litl_write_get_header_size(trace)
347  - sizeof(litl_offset_t);
348  trace->buffers[i]->already_flushed = 1;
349  }
350 
351  // offset indicates the position of offset to the next slot of
352  // pairs (tid, offset) within the trace file
353  trace->header_offset = __litl_write_get_header_size(trace);
354 
355  // specify the last slot of pairs (offset == 0)
356  litl_thread_pair_t *thread_pair = (litl_thread_pair_t *) trace->header;
357  trace->header += sizeof(litl_thread_pair_t);
358  thread_pair->tid = 0;
359  thread_pair->offset = 0;
360 
361  // write the trace header to the trace file
362  __litl_write_update_header(trace);
363 
364  trace->general_offset = __litl_write_get_header_size(trace);
365 
366  trace->header_nb_threads = trace->nb_threads;
367  trace->threads_offset = 0;
368  trace->nb_slots = 0;
369 
370  trace->is_header_flushed = 1;
371  }
372 }
373 
374 
375 /*
376  * Write the thread-specific header to disk
377  */
378 static void __litl_write_flush_thread_header(litl_write_trace_t* trace,
379  litl_med_size_t index,
380  litl_offset_t header_size) {
382  int res;
383  // when more buffers to store threads information is required
384  if (trace->nb_threads
385  > (trace->header_nb_threads + NBTHREADS * trace->nb_slots)) {
386 
387  // updated the offset from the previous slot
388  lseek(trace->f_handle, trace->header_offset + sizeof(litl_tid_t),
389  SEEK_SET);
390  offset = trace->general_offset - header_size;
391  res = write(trace->f_handle, &offset, sizeof(litl_offset_t));
392  assert(res>=0);
393 
394  // reserve a new slot for pairs (tid, offset)
395  trace->header_offset = trace->general_offset;
396  trace->threads_offset = trace->header_offset;
397  trace->general_offset += (NBTHREADS + 1) * sizeof(litl_thread_pair_t);
398 
399  trace->nb_slots++;
400  }
401 
402  // add a new pair (tid, offset)
403  lseek(trace->f_handle, trace->header_offset, SEEK_SET);
404  res = write(trace->f_handle, &trace->buffers[index]->tid,
405  sizeof(litl_tid_t));
406  assert(res >= 0);
407  offset = trace->general_offset - header_size;
408  res = write(trace->f_handle, &offset, sizeof(litl_offset_t));
409  assert(res >= 0);
410 
411  // add an indicator to specify the last slot of pairs (offset == 0)
412  // TODO: how to optimize this and write only once at the end of the slot
413  offset = 0;
414  res = write(trace->f_handle, &offset, sizeof(litl_tid_t));
415  assert(res >= 0);
416  res = write(trace->f_handle, &offset, sizeof(litl_offset_t));
417  assert(res >= 0);
418 
419  trace->header_offset += sizeof(litl_thread_pair_t);
420  trace->buffers[index]->already_flushed = 1;
421 
422  // updated the number of threads
423  // TODO: perform update only once 'cause there is duplication
424  lseek(trace->f_handle, trace->header_size, SEEK_SET);
425  res = write(trace->f_handle, &trace->nb_threads, sizeof(litl_med_size_t));
426  assert(res >= 0);
427 }
428 
429 /*
430  * Update the thread-specific header and write it to disk
431  */
432 static void __litl_write_update_thread_header(litl_write_trace_t* trace,
433  litl_med_size_t index,
434  litl_offset_t header_size) {
435  // update the previous offset of the current thread,
436  // updating the location in the file
437  lseek(trace->f_handle, trace->buffers[index]->offset, SEEK_SET);
438  litl_offset_t offset = trace->general_offset - header_size;
439  int res = write(trace->f_handle, &offset, sizeof(litl_offset_t));
440  assert(res >= 0);
441 }
442 
443 /*
444  * Writes the recorded events from the buffer to the trace file
445  */
446 static void __litl_write_flush_buffer(litl_write_trace_t* trace,
447  litl_med_size_t index) {
448  int res __attribute__ ((__unused__));
449  litl_offset_t header_size;
450  if (!trace->is_litl_initialized)
451  return;
452 
453  if (trace->allow_thread_safety)
454  pthread_mutex_lock(&trace->lock_litl_flush);
455 
456  if (!trace->is_header_flushed) {
457  /* flush the header to disk */
458  __litl_write_flush_header(trace);
459  }
460 
461  header_size = sizeof(litl_general_header_t) + sizeof(litl_process_header_t);
462  // handle the situation when some threads start after the header was flushed
463  if (!trace->buffers[index]->already_flushed) {
464  __litl_write_flush_thread_header(trace, index, header_size);
465  } else {
466  __litl_write_update_thread_header(trace, index, header_size);
467  }
468 
469  // add an event with offset
470  __litl_write_probe_offset(trace, index);
471  lseek(trace->f_handle, trace->general_offset, SEEK_SET);
472  if (write(trace->f_handle, trace->buffers[index]->buffer_ptr,
473  __litl_write_get_buffer_size(trace, index)) == -1) {
474  perror(
475  "Flushing the buffer. Could not write measured data to the trace file!");
476  exit(EXIT_FAILURE);
477  }
478 
479  // update the general_offset
480  trace->general_offset += __litl_write_get_buffer_size(trace, index);
481  // update the current offset of the thread
482  trace->buffers[index]->offset = trace->general_offset - sizeof(litl_offset_t);
483 
484  if (trace->allow_thread_safety)
485  pthread_mutex_unlock(&trace->lock_litl_flush);
486 
487  trace->buffers[index]->buffer = trace->buffers[index]->buffer_ptr;
488 }
489 
490 /*
491  * Checks whether the trace buffer was allocated. If no, then allocate
492  * the buffer and, for otherwise too, returns the position of
493  * the thread buffer in the array buffer_ptr/buffer.
494  */
495 static void __litl_write_allocate_buffer(litl_write_trace_t* trace) {
496  litl_med_size_t* pos;
497 
498  // thread safe region
499  pthread_mutex_lock(&trace->lock_buffer_init);
500 
501  pos = malloc(sizeof(litl_med_size_t));
502  *pos = trace->nb_threads;
503  int thread_id = *pos;
504  pthread_setspecific(trace->index, pos);
505  trace->nb_threads++;
506 
507  if (*pos >= trace->nb_allocated_buffers) {
508  // We need to allocate a bigger array of buffers
509  void* ptr = realloc(
510  trace->buffers,
511  trace->nb_allocated_buffers * 2 * sizeof(litl_write_buffer_t*));
512  if (!ptr) {
513  perror("LiTL failed to reallocate memory for threads!\n");
514  exit(EXIT_FAILURE);
515  }
516 
517  trace->buffers = ptr;
518  unsigned i;
519  for (i = trace->nb_allocated_buffers; i < 2 * trace->nb_allocated_buffers;
520  i++) {
521  trace->buffers[i] = malloc(sizeof(litl_write_buffer_t));
522  if (!trace->buffers[i]) {
523  perror("Could not allocate memory for a thread\n!");
524  exit(EXIT_FAILURE);
525  }
526  trace->buffers[i]->already_flushed = 0;
527  trace->buffers[i]->initialized = 0;
528  }
529  trace->nb_allocated_buffers *= 2;
530  }
531 
532  trace->buffers[thread_id]->tid = CUR_TID;
533  trace->buffers[thread_id]->already_flushed = 0;
534 
535  pthread_mutex_unlock(&trace->lock_buffer_init);
536 
537  /* use mmap instead of malloc so that we can use the MAP_POPULATE option
538  that makes sure the page table is populated. This way, the page faults
539  caused by litl are sensibly reduced.
540  */
541 #define USE_MMAP
542 #ifdef USE_MMAP
544 
545  trace->buffers[thread_id]->buffer_ptr = mmap(NULL,
546  length,
547  PROT_READ|PROT_WRITE,
548  MAP_SHARED|MAP_ANONYMOUS|MAP_POPULATE,
549  -1,
550  0);
551  if(trace->buffers[thread_id]->buffer_ptr == MAP_FAILED) {
552  perror("mmap");
553  }
554  /* touch the first pages */
555  if(length> 1024*1024)
556  length=1024*1024;
557  memset(trace->buffers[thread_id]->buffer_ptr, 0, length);
558 #else
560  trace->buffers[thread_id]->buffer_ptr = malloc(length);
561 #endif
562 
563  if (!trace->buffers[thread_id]->buffer_ptr) {
564  perror("Could not allocate memory buffer for the thread\n!");
565  exit(EXIT_FAILURE);
566  }
567 
568  // touch the memory so that it is allocated for real (otherwise, this may
569  // cause performance issues on NUMA machines)
570  memset(trace->buffers[thread_id]->buffer_ptr, 1, 1);
571  trace->buffers[thread_id]->buffer = trace->buffers[thread_id]->buffer_ptr;
572 
573  trace->buffers[thread_id]->initialized = 1;
574 }
575 
576 /*
577  * For internal use only.
578  * Allocates an event
579  */
581  litl_code_t code, int param_size) {
582  litl_med_size_t index = 0;
583  litl_t*retval = NULL;
584  litl_size_t event_size = __litl_get_event_size(type, param_size);
585 
586  if (trace && trace->is_litl_initialized && !trace->is_recording_paused
587  && !trace->is_buffer_full) {
588 
589  // find the thread index
590  litl_med_size_t *p_index = pthread_getspecific(trace->index);
591  if (!p_index) {
592  __litl_write_allocate_buffer(trace);
593  p_index = pthread_getspecific(trace->index);
594  if(!p_index)
595  return NULL;
596  }
597  index = *(litl_med_size_t *) p_index;
598 
599  if(trace->buffers[index]->initialized == 0)
600  return NULL;
601 
602  litl_write_buffer_t *p_buffer = trace->buffers[index];
603 
604  // is there enough space in the buffer?
605  litl_size_t used_memory= __litl_write_get_buffer_size(trace, index);
606 
607  if (used_memory+event_size < trace->buffer_size) {
608  // there is enough space for this event
609  litl_t* cur_ptr = (litl_t*) p_buffer->buffer;
610 
611  // fill the event
612  cur_ptr->time = litl_get_time();
613  cur_ptr->code = code;
614  cur_ptr->type = type;
615 
616  switch (type) {
617  case LITL_TYPE_REGULAR:
618  cur_ptr->parameters.regular.nb_params = (param_size) / sizeof(litl_param_t);
619  break;
620  case LITL_TYPE_RAW:
621  cur_ptr->parameters.raw.size = param_size;
622  break;
623  case LITL_TYPE_PACKED:
624  cur_ptr->parameters.packed.size = param_size;
625  break;
626  case LITL_TYPE_OFFSET:
627  cur_ptr->parameters.offset.nb_params = param_size;
628  break;
629  default:
630  fprintf(stderr, "Unknown event type %d\n", type);
631  abort();
632  }
633 
634  p_buffer->buffer += __litl_get_gen_event_size(cur_ptr);
635 
636  retval = cur_ptr;
637  goto out;
638  } else if (trace->allow_buffer_flush) {
639  // not enough space. flush the buffer and retry
640  __litl_write_flush_buffer(trace, index);
641  retval = __litl_write_get_event(trace, type, code, param_size);
642  goto out;
643  } else {
644  // not enough space, but flushing is disabled so just stop recording
645  trace->is_buffer_full = 1;
646  retval = NULL ;
647  goto out;
648  }
649  }
650 
651  out:
652  return retval;
653 }
654 
655 
656 /* Common function for recording a regular event.
657  * This function fills all the fiels except for the parameters
658  */
659 static litl_t* __litl_write_probe_reg_common(litl_write_trace_t* trace,
660  litl_code_t code,
661  unsigned nb_params) {
662  litl_t*retval = __litl_write_get_event(trace,
664  code,
665  nb_params);
666  return retval;
667 }
668 
669 /*
670  * Records a regular event without any arguments
671  */
673  litl_t *cur_ptr = __litl_write_probe_reg_common(trace, code, 0);
674  return cur_ptr;
675 }
676 
677 /*
678  * Records a regular event with one argument
679  */
681  litl_param_t param1) {
682  litl_t *cur_ptr = __litl_write_probe_reg_common(trace, code, 1);
683  if(cur_ptr) {
684  cur_ptr->parameters.regular.param[0] = param1;
685  }
686  return cur_ptr;
687 }
688 
689 /*
690  * Records a regular event with two arguments
691  */
693  litl_param_t param1, litl_param_t param2) {
694  litl_t *cur_ptr = __litl_write_probe_reg_common(trace, code, 2);
695  if(cur_ptr) {
696  cur_ptr->parameters.regular.param[0] = param1;
697  cur_ptr->parameters.regular.param[1] = param2;
698  }
699  return cur_ptr;
700 }
701 
702 /*
703  * Records a regular event with three arguments
704  */
706  litl_param_t param1, litl_param_t param2,
707  litl_param_t param3) {
708  litl_t *cur_ptr = __litl_write_probe_reg_common(trace, code, 3);
709  if(cur_ptr) {
710  cur_ptr->parameters.regular.param[0] = param1;
711  cur_ptr->parameters.regular.param[1] = param2;
712  cur_ptr->parameters.regular.param[2] = param3;
713  }
714  return cur_ptr;
715 }
716 
717 /*
718  * Records a regular event with four arguments
719  */
721  litl_param_t param1, litl_param_t param2,
722  litl_param_t param3, litl_param_t param4) {
723  litl_t *cur_ptr = __litl_write_probe_reg_common(trace, code, 4);
724  if(cur_ptr) {
725  cur_ptr->parameters.regular.param[0] = param1;
726  cur_ptr->parameters.regular.param[1] = param2;
727  cur_ptr->parameters.regular.param[2] = param3;
728  cur_ptr->parameters.regular.param[3] = param4;
729  }
730  return cur_ptr;
731 }
732 
733 /*
734  * Records a regular event with five arguments
735  */
737  litl_param_t param1, litl_param_t param2,
738  litl_param_t param3, litl_param_t param4,
739  litl_param_t param5) {
740  litl_t *cur_ptr = __litl_write_probe_reg_common(trace, code, 5);
741  if(cur_ptr) {
742  cur_ptr->parameters.regular.param[0] = param1;
743  cur_ptr->parameters.regular.param[1] = param2;
744  cur_ptr->parameters.regular.param[2] = param3;
745  cur_ptr->parameters.regular.param[3] = param4;
746  cur_ptr->parameters.regular.param[4] = param5;
747  }
748  return cur_ptr;
749 }
750 
751 /*
752  * Records a regular event with six arguments
753  */
755  litl_param_t param1, litl_param_t param2,
756  litl_param_t param3, litl_param_t param4,
757  litl_param_t param5, litl_param_t param6) {
758  litl_t *cur_ptr = __litl_write_probe_reg_common(trace, code, 6);
759  if(cur_ptr) {
760  cur_ptr->parameters.regular.param[0] = param1;
761  cur_ptr->parameters.regular.param[1] = param2;
762  cur_ptr->parameters.regular.param[2] = param3;
763  cur_ptr->parameters.regular.param[3] = param4;
764  cur_ptr->parameters.regular.param[4] = param5;
765  cur_ptr->parameters.regular.param[5] = param6;
766  }
767  return cur_ptr;
768 }
769 
770 /*
771  * Records a regular event with seven arguments
772  */
774  litl_param_t param1, litl_param_t param2,
775  litl_param_t param3, litl_param_t param4,
776  litl_param_t param5, litl_param_t param6,
777  litl_param_t param7) {
778  litl_t *cur_ptr = __litl_write_probe_reg_common(trace, code, 7);
779  if(cur_ptr) {
780  cur_ptr->parameters.regular.param[0] = param1;
781  cur_ptr->parameters.regular.param[1] = param2;
782  cur_ptr->parameters.regular.param[2] = param3;
783  cur_ptr->parameters.regular.param[3] = param4;
784  cur_ptr->parameters.regular.param[4] = param5;
785  cur_ptr->parameters.regular.param[5] = param6;
786  cur_ptr->parameters.regular.param[6] = param7;
787  }
788  return cur_ptr;
789 }
790 
791 /*
792  * Records a regular event with eight arguments
793  */
795  litl_param_t param1, litl_param_t param2,
796  litl_param_t param3, litl_param_t param4,
797  litl_param_t param5, litl_param_t param6,
798  litl_param_t param7, litl_param_t param8) {
799  litl_t *cur_ptr = __litl_write_probe_reg_common(trace, code, 8);
800  if(cur_ptr) {
801  cur_ptr->parameters.regular.param[0] = param1;
802  cur_ptr->parameters.regular.param[1] = param2;
803  cur_ptr->parameters.regular.param[2] = param3;
804  cur_ptr->parameters.regular.param[3] = param4;
805  cur_ptr->parameters.regular.param[4] = param5;
806  cur_ptr->parameters.regular.param[5] = param6;
807  cur_ptr->parameters.regular.param[6] = param7;
808  cur_ptr->parameters.regular.param[7] = param8;
809  }
810  return cur_ptr;
811 }
812 
813 /*
814  * Records a regular event with nine arguments
815  */
817  litl_param_t param1, litl_param_t param2,
818  litl_param_t param3, litl_param_t param4,
819  litl_param_t param5, litl_param_t param6,
820  litl_param_t param7, litl_param_t param8,
821  litl_param_t param9) {
822  litl_t *cur_ptr = __litl_write_probe_reg_common(trace, code, 9);
823  if(cur_ptr) {
824  cur_ptr->parameters.regular.param[0] = param1;
825  cur_ptr->parameters.regular.param[1] = param2;
826  cur_ptr->parameters.regular.param[2] = param3;
827  cur_ptr->parameters.regular.param[3] = param4;
828  cur_ptr->parameters.regular.param[4] = param5;
829  cur_ptr->parameters.regular.param[5] = param6;
830  cur_ptr->parameters.regular.param[6] = param7;
831  cur_ptr->parameters.regular.param[7] = param8;
832  cur_ptr->parameters.regular.param[8] = param9;
833  }
834  return cur_ptr;
835 }
836 
837 /*
838  * Records a regular event with ten arguments
839  */
841  litl_param_t param1, litl_param_t param2,
842  litl_param_t param3, litl_param_t param4,
843  litl_param_t param5, litl_param_t param6,
844  litl_param_t param7, litl_param_t param8,
845  litl_param_t param9, litl_param_t param10) {
846  litl_t *cur_ptr = __litl_write_probe_reg_common(trace, code, 10);
847  if(cur_ptr) {
848  cur_ptr->parameters.regular.param[0] = param1;
849  cur_ptr->parameters.regular.param[1] = param2;
850  cur_ptr->parameters.regular.param[2] = param3;
851  cur_ptr->parameters.regular.param[3] = param4;
852  cur_ptr->parameters.regular.param[4] = param5;
853  cur_ptr->parameters.regular.param[5] = param6;
854  cur_ptr->parameters.regular.param[6] = param7;
855  cur_ptr->parameters.regular.param[7] = param8;
856  cur_ptr->parameters.regular.param[8] = param9;
857  cur_ptr->parameters.regular.param[9] = param10;
858  }
859  return cur_ptr;
860 }
861 
862 /*
863  * Records an event in a raw state, where the size is #args in the void* array.
864  * That helps to discover places where the application has crashed
865  */
867  litl_size_t size, litl_data_t data[]) {
868  litl_t* retval = __litl_write_get_event(trace,
870  code,
871  size+1);
872  if(retval) {
873  litl_size_t i;
874  for (i = 0; i < size; i++) {
875  retval->parameters.raw.data[i] = data[i];
876  }
877  retval->parameters.raw.data[size]='\0';
878  }
879  return retval;
880 }
881 
882 /*
883  * This function finalizes the trace
884  */
886  litl_med_size_t i;
887  if(!trace)
888  return;
889 
890  for (i = 0; i < trace->nb_threads; i++) {
891  __litl_write_flush_buffer(trace, i);
892  }
893 
894  close(trace->f_handle);
895  trace->f_handle = -1;
896 
897  for (i = 0; i < trace->nb_allocated_buffers; i++) {
898  if (trace->buffers[i]->tid != 0) {
900 #ifdef USE_MMAP
901  int ret = munmap(trace->buffers[i]->buffer_ptr, length);
902  assert(ret==0);
903 #else
904  free(trace->buffers[i]->buffer_ptr);
905 #endif
906  trace->buffers[i]->buffer_ptr = NULL;
907  } else {
908  break;
909  }
910  }
911 
912  if (trace->allow_thread_safety) {
913  pthread_mutex_destroy(&trace->lock_litl_flush);
914  }
915  pthread_mutex_destroy(&trace->lock_buffer_init);
916 
917  free(trace->filename);
918  trace->filename = NULL;
919  trace->is_litl_initialized = 0;
920  trace->is_header_flushed = 0;
921  free(trace);
922 }
struct litl_t::@0::@1 regular
litl_t * litl_write_probe_reg_2(litl_write_trace_t *trace, litl_code_t code, litl_param_t param1, litl_param_t param2)
Records a regular event with 2 parameters.
Definition: litl_write.c:692
litl_buffer_t buffer_ptr
Definition: litl_types.h:293
litl_type_t
The enumeration of event types.
Definition: litl_types.h:180
struct litl_t::@0::@2 raw
litl_size_t buffer_size
Definition: litl_types.h:326
litl_data_t is_buffer_full
Definition: litl_types.h:327
#define LITL_MAX_PARAMS
Defines the maximum number of parameters.
Definition: litl_types.h:169
void litl_write_buffer_flush_on(litl_write_trace_t *trace)
Enable buffer flush. By default, it is disabled.
Definition: litl_write.c:185
Thread-specific buffer.
Definition: litl_types.h:292
litl_write_buffer_t ** buffers
Definition: litl_types.h:324
litl_data_t is_header_flushed
Definition: litl_types.h:318
uint64_t litl_param_t
A data type for the non-optimized storage of parameters.
Definition: litl_types.h:124
void litl_write_thread_safety_on(litl_write_trace_t *trace)
Enable thread safety.
Definition: litl_write.c:199
litl_t * litl_write_probe_reg_1(litl_write_trace_t *trace, litl_code_t code, litl_param_t param1)
Records a regular event with 1 parameter.
Definition: litl_write.c:680
litl_med_size_t nb_slots
Definition: litl_types.h:321
volatile litl_data_t is_recording_paused
Definition: litl_types.h:335
litl_t * litl_write_probe_reg_6(litl_write_trace_t *trace, litl_code_t code, litl_param_t param1, litl_param_t param2, litl_param_t param3, litl_param_t param4, litl_param_t param5, litl_param_t param6)
Records a regular event with 6 parameters.
Definition: litl_write.c:754
void litl_write_thread_safety_off(litl_write_trace_t *trace)
Disable thread safety. By default, it is enabled.
Definition: litl_write.c:206
#define NBTHREADS
Defines the maximum number of threads (pairs of tid and offset) stored in one data slot...
Definition: litl_types.h:242
litl_timing_method_t litl_get_time
Calls the selected timing method and get the current time in ns.
Definition: litl_timer.c:37
litl_t * litl_write_probe_reg_4(litl_write_trace_t *trace, litl_code_t code, litl_param_t param1, litl_param_t param2, litl_param_t param3, litl_param_t param4)
Records a regular event with 4 parameters.
Definition: litl_write.c:720
litl_buffer_t buffer
Definition: litl_types.h:294
litl_t * litl_write_probe_reg_9(litl_write_trace_t *trace, litl_code_t code, litl_param_t param1, litl_param_t param2, litl_param_t param3, litl_param_t param4, litl_param_t param5, litl_param_t param6, litl_param_t param7, litl_param_t param8, litl_param_t param9)
Records a regular event with 9 parameters.
Definition: litl_write.c:816
litl_size_t header_offset
Definition: litl_types.h:316
litl_time_t time
Definition: litl_types.h:193
litl_size_t nb_allocated_buffers
Definition: litl_types.h:325
A data structure for recording events.
Definition: litl_types.h:307
litl_data_t allow_thread_safety
Definition: litl_types.h:337
litl_t * litl_write_probe_raw(litl_write_trace_t *trace, litl_code_t code, litl_size_t size, litl_data_t data[])
Records an event with data in a string format.
Definition: litl_write.c:866
litl_data_t is_litl_initialized
Definition: litl_types.h:334
litl_write_trace_t * litl_write_init_trace(const litl_size_t buf_size)
Initializes the trace buffer.
Definition: litl_write.c:81
A general structure of LiTL event type.
Definition: litl_types.h:192
union litl_t::@0 parameters
litl_offset_t offset
Definition: litl_types.h:275
litl_t * litl_write_probe_reg_7(litl_write_trace_t *trace, litl_code_t code, litl_param_t param1, litl_param_t param2, litl_param_t param3, litl_param_t param4, litl_param_t param5, litl_param_t param6, litl_param_t param7)
Records a regular event with 7 parameters.
Definition: litl_write.c:773
A general data structure that corresponds to the header of a trace file.
Definition: litl_types.h:260
litl_med_size_t nb_threads
Definition: litl_types.h:320
litl_size_t __litl_get_reg_event_size(litl_data_t nb_params)
Returns the size of a regular event (in Bytes) depending on the number of its parameters.
Definition: litl_tools.c:18
litl_tid_t tid
Definition: litl_types.h:274
uint8_t * litl_buffer_t
A data type for storing sets of events.
Definition: litl_types.h:135
litl_data_t allow_tid_recording
Definition: litl_types.h:338
litl_param_t threads_offset
Definition: litl_types.h:322
void litl_write_tid_recording_off(litl_write_trace_t *trace)
Disable recording tid. By default, it is enabled.
Definition: litl_write.c:220
pthread_key_t index
Definition: litl_types.h:330
litl_buffer_t header
Definition: litl_types.h:314
litl_offset_t general_offset
Definition: litl_types.h:311
litl_size_t header_size
Definition: litl_types.h:315
void litl_write_finalize_trace(litl_write_trace_t *trace)
Finalizes the trace.
Definition: litl_write.c:885
#define CUR_TID
A current thread ID.
Definition: litl_types.h:68
litl_param_t offset
Definition: litl_types.h:231
litl_t * __litl_write_get_event(litl_write_trace_t *trace, litl_type_t type, litl_code_t code, int param_size)
For internal use only. Allocates an event.
Definition: litl_write.c:580
litl_t * litl_write_probe_reg_3(litl_write_trace_t *trace, litl_code_t code, litl_param_t param1, litl_param_t param2, litl_param_t param3)
Records a regular event with 3 parameters.
Definition: litl_write.c:705
uint16_t litl_med_size_t
An auxiliary data type for the optimized storage of data.
Definition: litl_types.h:152
pthread_mutex_t lock_buffer_init
Definition: litl_types.h:332
pthread_mutex_t lock_litl_flush
Definition: litl_types.h:331
litl_size_t __litl_get_event_size(litl_type_t type, int param_size)
Returns the size of an event (in Bytes) depending on the number or size of its parameters.
Definition: litl_tools.c:22
A data structure for pairs (tid, offset) stored in the trace header.
Definition: litl_types.h:273
uint64_t litl_tid_t
A data type for storing thread IDs.
Definition: litl_types.h:109
litl_buffer_t header_ptr
Definition: litl_types.h:313
An offset event.
litl_t * litl_write_probe_reg_8(litl_write_trace_t *trace, litl_code_t code, litl_param_t param1, litl_param_t param2, litl_param_t param3, litl_param_t param4, litl_param_t param5, litl_param_t param6, litl_param_t param7, litl_param_t param8)
Records a regular event with 8 parameters.
Definition: litl_write.c:794
#define LITL_OFFSET_CODE
Defines the code of an event of type offset.
Definition: litl_types.h:163
litl_med_size_t header_nb_threads
Definition: litl_types.h:317
litl_offset_t offset
Definition: litl_types.h:297
litl_size_t __litl_get_gen_event_size(litl_t *p_evt)
Returns the size of a general event (in Bytes) depending on its type and the number of its parameters...
Definition: litl_tools.c:42
uint8_t litl_data_t
A data type for the optimized storage of parameters.
Definition: litl_types.h:157
void litl_time_initialize()
Initializes the timing mechanism.
Definition: litl_timer.c:138
void litl_write_resume_recording(litl_write_trace_t *trace)
Resumes the event recording.
Definition: litl_write.c:235
struct litl_t::@0::@3 packed
uint32_t litl_size_t
An auxiliary data type for storing data.
Definition: litl_types.h:147
void litl_write_set_filename(litl_write_trace_t *trace, char *filename)
Sets a new name for the trace file.
Definition: litl_write.c:243
litl_t * litl_write_probe_reg_10(litl_write_trace_t *trace, litl_code_t code, litl_param_t param1, litl_param_t param2, litl_param_t param3, litl_param_t param4, litl_param_t param5, litl_param_t param6, litl_param_t param7, litl_param_t param8, litl_param_t param9, litl_param_t param10)
Records a regular event with 10 parameters.
Definition: litl_write.c:840
litl_t * litl_write_probe_reg_5(litl_write_trace_t *trace, litl_code_t code, litl_param_t param1, litl_param_t param2, litl_param_t param3, litl_param_t param4, litl_param_t param5)
Records a regular event with 5 parameters.
Definition: litl_write.c:736
litl_data_t already_flushed
Definition: litl_types.h:299
litl_data_t allow_buffer_flush
Definition: litl_types.h:336
uint64_t litl_offset_t
A data type for storing offsets.
Definition: litl_types.h:129
void litl_write_tid_recording_on(litl_write_trace_t *trace)
Enable recording tid.
Definition: litl_write.c:213
A general data structure that corresponds to the header of a trace file.
Definition: litl_types.h:249
void litl_write_buffer_flush_off(litl_write_trace_t *trace)
Disable buffer flush.
Definition: litl_write.c:192
litl_t * litl_write_probe_reg_0(litl_write_trace_t *trace, litl_code_t code)
Records a regular event without parameters.
Definition: litl_write.c:672
void litl_write_pause_recording(litl_write_trace_t *trace)
Pauses the event recording.
Definition: litl_write.c:227
uint32_t litl_code_t
A data type for storing events codes.
Definition: litl_types.h:142
litl_tools Provides a set of auxiliary functions
litl_type_t type
Definition: litl_types.h:195
litl_timer Provides a set of functions for measuring time
litl_write Provides a set of functions for recording events in a trace file
litl_code_t code
Definition: litl_types.h:194