X-Git-Url: http://git.lttng.org./?a=blobdiff_plain;f=ltt-usertrace%2Fltt%2Fltt-usertrace-fast.h;h=fb01893684259d7ab09bbab69610e792f25ed22b;hb=2786770231bafe751b79ee829519b6d74a4d7709;hp=b0d222f83bc0467da307bd1daa53d5780b06af11;hpb=976db1b3ea97f6714590ec9cf36ea30b9b6aa59b;p=lttv.git diff --git a/ltt-usertrace/ltt/ltt-usertrace-fast.h b/ltt-usertrace/ltt/ltt-usertrace-fast.h index b0d222f8..fb018936 100644 --- a/ltt-usertrace/ltt/ltt-usertrace-fast.h +++ b/ltt-usertrace/ltt/ltt-usertrace-fast.h @@ -12,16 +12,18 @@ #ifdef LTT_TRACE_FAST #include -#include #include #include #include -#include #include #include #include +#ifdef __cplusplus +extern "C" { +#endif + #ifndef LTT_N_SUBBUFS #define LTT_N_SUBBUFS 2 #endif //LTT_N_SUBBUFS @@ -51,7 +53,7 @@ #define LTT_TRACER_MAGIC_NUMBER 0x00D6B7ED #define LTT_TRACER_VERSION_MAJOR 0 -#define LTT_TRACER_VERSION_MINOR 7 +#define LTT_TRACER_VERSION_MINOR 8 #ifndef atomic_cmpxchg #define atomic_cmpxchg(v, old, new) ((int)cmpxchg(&((v)->counter), old, new)) @@ -69,12 +71,14 @@ struct ltt_trace_header { uint8_t flight_recorder; uint8_t has_heartbeat; uint8_t has_alignment; /* Event header alignment */ + uint8_t tsc_lsb_truncate; + uint8_t tscbits; uint32_t freq_scale; uint64_t start_freq; uint64_t start_tsc; uint64_t start_monotonic; - uint64_t start_time_sec; - uint64_t start_time_usec; + uint64_t start_time_sec; + uint64_t start_time_usec; } __attribute((packed)); @@ -350,7 +354,7 @@ static inline void * __attribute__((no_instrument_function)) ltt_reserve_slot( struct ltt_trace_info *trace, struct ltt_buf *ltt_buf, unsigned int data_size, - unsigned int *slot_size, + size_t *slot_size, uint64_t *tsc, size_t *before_hdr_pad, size_t *after_hdr_pad, @@ -364,6 +368,7 @@ static inline void * __attribute__((no_instrument_function)) ltt_reserve_slot( int consumed_old, consumed_new; int commit_count, reserve_count; int ret; + sigset_t oldset, set; do { offset_old = atomic_read(<t_buf->offset); @@ -404,29 +409,40 @@ static inline void * __attribute__((no_instrument_function)) ltt_reserve_slot( ltt_buf)]) - atomic_read(<t_buf->commit_count[SUBBUF_INDEX(offset_begin, ltt_buf)]); + if(reserve_commit_diff == 0) { /* Next buffer not corrupted. */ //if((SUBBUF_TRUNC(offset_begin, ltt_buf) // - SUBBUF_TRUNC(atomic_read(<t_buf->consumed), ltt_buf)) // >= ltt_buf->alloc_size) { - /* sem_wait is not signal safe. Disable signals around it. */ { - sigset_t oldset, set; - + /* sem_wait is not signal safe. Disable signals around it. + * Signals are kept disabled to make sure we win the cmpxchg. */ /* Disable signals */ ret = sigfillset(&set); if(ret) perror("LTT Error in sigfillset\n"); - + ret = pthread_sigmask(SIG_BLOCK, &set, &oldset); if(ret) perror("LTT Error in pthread_sigmask\n"); + /* We detect if a signal came between + * the offset read and signal disabling: + * if it is the case, then we restart + * the loop after reenabling signals. It + * means that it's a signal that has + * won the buffer switch.*/ + if(offset_old != atomic_read(<t_buf->offset)) { + ret = pthread_sigmask(SIG_SETMASK, &oldset, NULL); + if(ret) perror("LTT Error in pthread_sigmask\n"); + continue; + } + /* If the offset is still the same, then + * we can safely proceed to do the + * buffer switch without being + * interrupted by a signal. */ sem_wait(<t_buf->writer_sem); - /* Enable signals */ - ret = pthread_sigmask(SIG_SETMASK, &oldset, NULL); - if(ret) perror("LTT Error in pthread_sigmask\n"); } - /* go on with the write */ //} else { @@ -436,7 +452,8 @@ static inline void * __attribute__((no_instrument_function)) ltt_reserve_slot( } else { /* Next subbuffer corrupted. Force pushing reader even in normal * mode. It's safe to write in this new subbuffer. */ - sem_post(<t_buf->writer_sem); + /* No sem_post is required because we fall through without doing a + * sem_wait. */ } size = ltt_get_header_size(trace, ltt_buf->start + offset_begin, before_hdr_pad, after_hdr_pad, header_size) + data_size; @@ -444,6 +461,10 @@ static inline void * __attribute__((no_instrument_function)) ltt_reserve_slot( /* Event too big for subbuffers, report error, don't complete * the sub-buffer switch. */ atomic_inc(<t_buf->events_lost); + if(reserve_commit_diff == 0) { + ret = pthread_sigmask(SIG_SETMASK, &oldset, NULL); + if(ret) perror("LTT Error in pthread_sigmask\n"); + } return NULL; } else { /* We just made a successful buffer switch and the event fits in the @@ -464,7 +485,6 @@ static inline void * __attribute__((no_instrument_function)) ltt_reserve_slot( } while(atomic_cmpxchg(<t_buf->offset, offset_old, offset_end) != offset_old); - /* Push the reader if necessary */ do { consumed_old = atomic_read(<t_buf->consumed); @@ -476,7 +496,7 @@ static inline void * __attribute__((no_instrument_function)) ltt_reserve_slot( index in the buffer being the one which will win this loop. */ /* If the buffer is not in overwrite mode, pushing the reader only happen if a sub-buffer is corrupted */ - if((SUBBUF_TRUNC(offset_end, ltt_buf) + if((SUBBUF_TRUNC(offset_end-1, ltt_buf) - SUBBUF_TRUNC(consumed_old, ltt_buf)) >= ltt_buf->alloc_size) consumed_new = SUBBUF_ALIGN(consumed_old, ltt_buf); @@ -539,6 +559,14 @@ static inline void * __attribute__((no_instrument_function)) ltt_reserve_slot( } if(begin_switch) { + /* Enable signals : this is what guaranteed that same reserve which did the + * sem_wait does in fact win the cmpxchg for the offset. We only call + * these system calls on buffer boundaries because of their performance + * cost. */ + if(reserve_commit_diff == 0) { + ret = pthread_sigmask(SIG_SETMASK, &oldset, NULL); + if(ret) perror("LTT Error in pthread_sigmask\n"); + } /* New sub-buffer */ /* This code can be executed unordered : writers may already have written to the sub-buffer before this code gets executed, caution. */ @@ -624,7 +652,10 @@ static inline void __attribute__((no_instrument_function)) ltt_commit_slot( ltt_deliver_callback(ltt_buf, SUBBUF_INDEX(offset_begin, ltt_buf), NULL); } } - + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif #endif //LTT_TRACE_FAST #endif //LTT_TRACE