X-Git-Url: http://git.lttng.org./?a=blobdiff_plain;f=usertrace%2Flttng_usertrace.c;h=5e32b0cd4e640df69e2fe66b62de04fd1d4da1bf;hb=2d6c6b76f73668703e823a0638e7a67262668aee;hp=7f1039f44eb01e7c8909e7ec8cccd26fba495bc4;hpb=78d75b00afc8370df37409e0150a0649ce29c981;p=lttv.git diff --git a/usertrace/lttng_usertrace.c b/usertrace/lttng_usertrace.c index 7f1039f4..5e32b0cd 100644 --- a/usertrace/lttng_usertrace.c +++ b/usertrace/lttng_usertrace.c @@ -18,31 +18,24 @@ #include #include -#include #include "lttng_usertrace.h" #define MAX_TRACES 16 -struct ltt_buf { - void *start; - atomic_t offset; - atomic_t reserve_count; - atomic_t commit_count; - atomic_t events_lost; -}; - -struct lttng_trace_info { - int active:1; - struct { - struct ltt_buf facilities; - struct ltt_buf cpu; - } channel; -}; +/* + * Notes : + * + * ltt_update : + * + * it should send the information on the traces that has their status MODIFIED. + * It's a necessary assumption to have a correct lttng_free_trace_info, which + * would not be reentrant otherwise. + */ -/* TLS for the trace info */ -/* http://www.dis.com/gnu/gcc/C--98-Thread-Local-Edits.html +/* TLS for the trace info + * http://www.dis.com/gnu/gcc/C--98-Thread-Local-Edits.html * * Add after paragraph 4 * @@ -55,8 +48,12 @@ struct lttng_trace_info { static __thread struct lttng_trace_info lttng_trace_info[MAX_TRACES] = { [ 0 ... MAX_TRACES-1 ].active = 0, + [ 0 ... MAX_TRACES-1 ].filter = 0, + [ 0 ... MAX_TRACES-1 ].destroy = 0, + [ 0 ... MAX_TRACES-1 ].nesting = ATOMIC_INIT(0), [ 0 ... MAX_TRACES-1 ].channel = { NULL, + 0, ATOMIC_INIT(0), ATOMIC_INIT(0), ATOMIC_INIT(0), @@ -65,13 +62,82 @@ static __thread struct lttng_trace_info lttng_trace_info[MAX_TRACES] = } }; -/* signal handler */ -void __lttng_sig_trace_handler(int signo) + +/* Must be called we sure nobody else is using the info. + * It implies that the trace should have been previously stopped + * and that every writer has finished. + * + * Writers should always check if the trace must be destroyed when they + * finish writing and the nesting level is 0. + */ +void lttng_free_trace_info(struct lttng_trace_info *info) { int ret; - sigset_t set, oldset; - printf("LTTng Sig handler : pid : %lu\n", getpid()); + if(info->active) { + printf( + "LTTng ERROR : lttng_free_trace_info should be called on inactive trace\n"); + exit(1); + } + if(!info->destroy) { + printf( + "LTTng ERROR : lttng_free_trace_info should be called on destroyed trace\n"); + exit(1); + } + if(atomic_read(&info->nesting) > 0) { + printf( + "LTTng ERROR : lttng_free_trace_info should not be nested on tracing\n"); + exit(1); + } + + /* Remove the maps */ + ret = munmap(info->channel.cpu.start, info->channel.cpu.length); + if(ret) { + perror("LTTNG : error in munmap"); + } + ret = munmap(info->channel.facilities.start, info->channel.facilities.length); + if(ret) { + perror("LTTNG : error in munmap"); + } + + /* Zero the structure */ + memset(info, 0, sizeof(struct lttng_trace_info)); +} + + +static struct lttng_trace_info* find_info(unsigned long cpu_addr, + unsigned long fac_addr, unsigned int *first_empty) +{ + struct lttng_trace_info *found = NULL; + unsigned int i; + + *first_empty = MAX_TRACES; + + /* Try to find the trace */ + for(i=0;ifilter = filter; + info->active = active; + info->destroy = destroy; + if(destroy && !atomic_read(&info->nesting)) + lttng_free_trace_info(info); + } else { + /* Not found. Must take an empty slot */ + if(first_empty == MAX_TRACES) { + printf( + "LTTng WARNING : too many traces requested for pid %d by the kernel.\n" + " Compilation defined maximum is %u\n", + getpid(), MAX_TRACES); + + } else { + info = <tng_trace_info[first_empty]; + info->channel.cpu.start = (void*)cpu_addr; + info->channel.cpu.length = PAGE_SIZE; + info->channel.facilities.start = (void*)fac_addr; + info->channel.facilities.length = PAGE_SIZE; + info->filter = filter; + info->active = active; + info->destroy = destroy; + if(destroy && !atomic_read(&info->nesting)) + lttng_free_trace_info(info); + } + } + } + /* Enable signals */ - ret = sigprocmask(SIG_SETMASK, &oldset, NULL); + ret = pthread_sigmask(SIG_SETMASK, &oldset, NULL); if(ret) { printf("Error in sigprocmask\n"); exit(1); } - } -void __lttng_init_trace_info(void) +/* signal handler */ +void __lttng_sig_trace_handler(int signo) +{ + printf("LTTng signal handler : thread id : %lu, pid %lu\n", pthread_self(), getpid()); + lttng_get_new_info(); +} + + +static void thread_init(void) { - memset(<tng_trace_info, 0, MAX_TRACES*sizeof(struct lttng_trace_info)); + int err; + lttng_get_new_info(); + + /* Make some ltt_switch syscalls */ + err = ltt_switch((unsigned long)NULL); + if(err) { + printf("Error in ltt_switch system call\n"); + exit(1); + } } void __attribute__((constructor)) __lttng_user_init(void) @@ -121,9 +231,6 @@ void __attribute__((constructor)) __lttng_user_init(void) printf("LTTng user init\n"); - /* Init trace info */ - __lttng_init_trace_info(); - /* Activate the signal */ act.sa_handler = __lttng_sig_trace_handler; err = sigemptyset(&(act.sa_mask)); @@ -133,27 +240,13 @@ void __attribute__((constructor)) __lttng_user_init(void) err = sigaction(SIGRTMIN+3, &act, NULL); if(err) perror("Error with sigaction"); - /* TEST */ - err = ltt_switch((unsigned long)NULL); - if(err) { - printf("Error in ltt_switch system call\n"); - exit(1); - } + thread_init(); +} - /* Make the first ltt_update system call */ - err = ltt_update(1, NULL, NULL); - if(err) { - printf("Error in ltt_update system call\n"); - exit(1); - } - - /* Make some ltt_switch syscalls */ - err = ltt_switch((unsigned long)NULL); - if(err) { - printf("Error in ltt_switch system call\n"); - exit(1); - } +void lttng_thread_init(void) +{ + thread_init(); +} -}