#ifdef LTT_TRACE_FAST
#include <errno.h>
-#include <asm/atomic.h>
#include <pthread.h>
#include <stdint.h>
#include <syscall.h>
-#include <asm/timex.h>
#include <semaphore.h>
#include <signal.h>
#include <ltt/ltt-facility-id-user_generic.h>
-#include <ltt/ltt-generic.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
#ifndef LTT_N_SUBBUFS
#define LTT_N_SUBBUFS 2
#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))
+#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new))
#endif //atomic_cmpxchg
-typedef unsigned int ltt_facility_t;
-
struct ltt_trace_header {
uint32_t magic_number;
uint32_t arch_type;
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));
* for every trace).
*/
static inline unsigned int __attribute__((no_instrument_function))
- ltt_get_index_from_facility(ltt_facility_t fID,
+ ltt_get_index_from_facility(uint8_t fID,
uint8_t eID)
{
return GET_CHANNEL_INDEX(process);
static inline unsigned char __attribute__((no_instrument_function))
ltt_get_header_size(struct ltt_trace_info *trace,
void *address,
- size_t *before_hdr_pad,
- size_t *after_hdr_pad,
- size_t *header_size)
+ size_t data_size,
+ size_t *before_hdr_pad)
{
unsigned int padding;
unsigned int header;
+ size_t after_hdr_pad;
header = sizeof(struct ltt_event_header_nohb);
/* Padding after header, considering header aligned on ltt_align.
* Calculated statically if header size if known. */
- *after_hdr_pad = ltt_align(header, sizeof(void*));
- padding += *after_hdr_pad;
-
- *header_size = header;
+ after_hdr_pad = ltt_align(header, sizeof(void*));
+ padding += after_hdr_pad;
return header+padding;
}
* @fID : facility ID
* @eID : event ID
* @event_size : size of the event, excluding the event header.
- * @offset : offset of the beginning of the header, for alignment.
- * Calculated by ltt_get_event_header_size.
* @tsc : time stamp counter.
*/
-static inline void __attribute__((no_instrument_function))
+static inline char *__attribute__((no_instrument_function))
ltt_write_event_header(
struct ltt_trace_info *trace, struct ltt_buf *buf,
- void *ptr, ltt_facility_t fID, uint32_t eID, size_t event_size,
- size_t offset, uint64_t tsc)
+ void *ptr, uint8_t fID, uint32_t eID, size_t event_size,
+ uint64_t tsc)
{
+ size_t after_hdr_pad;
struct ltt_event_header_nohb *nohb;
event_size = min(event_size, 0xFFFFU);
- nohb = (struct ltt_event_header_nohb *)(ptr+offset);
+ nohb = (struct ltt_event_header_nohb *)(ptr);
nohb->timestamp = (uint64_t)tsc;
nohb->facility_id = fID;
nohb->event_id = eID;
nohb->event_size = (uint16_t)event_size;
+ after_hdr_pad = ltt_align(sizeof(*nohb), sizeof(void*));
+ return ptr + sizeof(*nohb) + after_hdr_pad;
}
header->arch_variant = 0; //FIXME LTT_ARCH_VARIANT;
header->flight_recorder = 0;
header->has_heartbeat = 0;
+ header->tsc_lsb_truncate = 0;
+ header->tscbits = 0;
#ifndef LTT_PACK
header->has_alignment = sizeof(void*);
struct ltt_trace_info *trace,
struct ltt_buf *ltt_buf,
unsigned int data_size,
- unsigned int *slot_size,
- uint64_t *tsc,
- size_t *before_hdr_pad,
- size_t *after_hdr_pad,
- size_t *header_size)
+ size_t *slot_size,
+ uint64_t *tsc)
{
int offset_begin, offset_end, offset_old;
//int has_switch;
int begin_switch, end_switch_current, end_switch_old;
int reserve_commit_diff = 0;
unsigned int size;
+ size_t before_hdr_pad;
int consumed_old, consumed_new;
int commit_count, reserve_count;
int ret;
+ sigset_t oldset, set;
do {
offset_old = atomic_read(<t_buf->offset);
begin_switch = 1; /* For offset_begin */
} else {
size = ltt_get_header_size(trace, ltt_buf->start + offset_begin,
- before_hdr_pad, after_hdr_pad, header_size)
+ data_size, &before_hdr_pad)
+ data_size;
if((SUBBUF_OFFSET(offset_begin, ltt_buf)+size)>ltt_buf->subbuf_size) {
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 {
} 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;
+ data_size, &before_hdr_pad) + data_size;
if((SUBBUF_OFFSET(offset_begin,ltt_buf)+size)>ltt_buf->subbuf_size) {
/* 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
} 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);
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);
}
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. */
//BUG_ON(*slot_size != (data_size + *before_hdr_pad + *after_hdr_pad + *header_size));
//BUG_ON(*slot_size != (offset_end - offset_begin));
- return ltt_buf->start + BUFFER_OFFSET(offset_begin, ltt_buf);
+ return ltt_buf->start + BUFFER_OFFSET(offset_begin, ltt_buf) + before_hdr_pad;
}
* Parameters:
*
* @buf : the buffer to commit to.
- * @reserved : address of the beginnig of the reserved slot.
+ * @reserved : address of the end of the event header.
* @slot_size : size of the reserved slot.
*
*/
void *reserved,
unsigned int slot_size)
{
- unsigned int offset_begin = reserved - ltt_buf->start;
+ unsigned int offset_end = reserved - ltt_buf->start;
int commit_count;
commit_count = atomic_add_return(slot_size,
- <t_buf->commit_count[SUBBUF_INDEX(offset_begin,
+ <t_buf->commit_count[SUBBUF_INDEX(offset_end-1,
ltt_buf)]);
/* Check if all commits have been done */
if(commit_count ==
- atomic_read(<t_buf->reserve_count[SUBBUF_INDEX(offset_begin, ltt_buf)])) {
- ltt_deliver_callback(ltt_buf, SUBBUF_INDEX(offset_begin, ltt_buf), NULL);
+ atomic_read(<t_buf->reserve_count[SUBBUF_INDEX(offset_end-1, ltt_buf)])) {
+ ltt_deliver_callback(ltt_buf, SUBBUF_INDEX(offset_end-1, ltt_buf), NULL);
}
}
-
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
#endif //LTT_TRACE_FAST
#endif //LTT_TRACE