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