update infos
[lttv.git] / usertrace / lttng_usertrace.c
CommitLineData
b8b00688 1
2/* LTTng user-space tracing code
3 *
4 * Copyright 2006 Mathieu Desnoyers
5 *
6 */
7
8
9#include <sys/types.h>
10#include <sys/wait.h>
11#include <unistd.h>
92f441a7 12#include <stdlib.h>
b8b00688 13#include <stdio.h>
14#include <signal.h>
15#include <syscall.h>
92f441a7 16#include <features.h>
17#include <pthread.h>
18#include <malloc.h>
19#include <string.h>
b8b00688 20
21#include "lttng_usertrace.h"
22
92f441a7 23#define MAX_TRACES 16
24
92f441a7 25
9d45fe0f 26/* TLS for the trace info
27 * http://www.dis.com/gnu/gcc/C--98-Thread-Local-Edits.html
78d75b00 28 *
29 * Add after paragraph 4
30 *
31 * The storage for an object of thread storage duration shall be statically
32 * initialized before the first statement of the thread startup function. An
33 * object of thread storage duration shall not require dynamic
34 * initialization.
35 * GCC extention permits init of a range.
36 */
92f441a7 37
78d75b00 38static __thread struct lttng_trace_info lttng_trace_info[MAX_TRACES] =
39{ [ 0 ... MAX_TRACES-1 ].active = 0,
9d45fe0f 40 [ 0 ... MAX_TRACES-1 ].filter = 0,
0166aeb5 41 [ 0 ... MAX_TRACES-1 ].nesting = ATOMIC_INIT(0),
78d75b00 42 [ 0 ... MAX_TRACES-1 ].channel =
43 { NULL,
0166aeb5 44 0,
78d75b00 45 ATOMIC_INIT(0),
46 ATOMIC_INIT(0),
47 ATOMIC_INIT(0),
48 ATOMIC_INIT(0),
49 ATOMIC_INIT(0)
50 }
51};
92f441a7 52
9d45fe0f 53
0166aeb5 54/* Must be called we sure nobody else is using the info.
55 * It implies that the trace should have been previously stopped
56 * and that every writer has finished.
57 *
58 * Writers should always check if the trace must be destroyed when they
59 * finish writing and the nesting level is 0.
60 */
61void lttng_free_trace_info(struct lttng_trace_info *info)
62{
63 int ret;
64
65 if(info->active) {
66 printf(
67 "LTTng ERROR : lttng_free_trace_info should be called on inactive trace\n");
68 exit(1);
69 }
70 if(!info->destroy) {
71 printf(
72 "LTTng ERROR : lttng_free_trace_info should be called on destroyed trace\n");
73 exit(1);
74 }
75 if(atomic_read(&info->nesting) > 0) {
76 printf(
77 "LTTng ERROR : lttng_free_trace_info should not be nested on tracing\n");
78 exit(1);
79 }
80
81 /* Remove the maps */
82 ret = munmap(info->channel.cpu.start, info->channel.cpu.length);
83 if(ret) {
84 perror("LTTNG : error in munmap");
85 }
86 ret = munmap(info->channel.facilities.start, info->channel.facilities.length);
87 if(ret) {
88 perror("LTTNG : error in munmap");
89 }
90
91 /* Zero the structure */
92 memset(info, 0, sizeof(struct lttng_trace_info));
93}
94
95
9d45fe0f 96static void lttng_get_new_info(void)
97{
98 unsigned long cpu_addr, fac_addr;
99 unsigned int i, first_empty;
0166aeb5 100 int active, filter, destroy;
9d45fe0f 101 int ret;
102
103 /* Get all the new traces */
104 while(1) {
105 cpu_addr = fac_addr = 0;
0166aeb5 106 active = filter = destroy = 0;
107 ret = ltt_update(&cpu_addr, &fac_addr, &active, &filter, &destroy);
9d45fe0f 108 if(ret) {
109 printf("LTTng : error in ltt_update\n");
110 exit(1);
111 }
112
113 if(!cpu_addr || !fac_addr) break;
114
115 first_empty = MAX_TRACES;
116 /* Try to find the trace */
117 for(i=0;i<MAX_TRACES;i++) {
118 if(i<first_empty && !lttng_trace_info[i].channel.cpu.start)
119 first_empty = i;
120 if(cpu_addr ==
121 (unsigned long)lttng_trace_info[i].channel.cpu.start &&
122 fac_addr ==
123 (unsigned long)lttng_trace_info[i].channel.facilities.start) {
0166aeb5 124 /* Found */
9d45fe0f 125 lttng_trace_info[i].filter = filter;
126 lttng_trace_info[i].active = active;
0166aeb5 127 lttng_trace_info[i].destroy = destroy;
128 if(destroy && !atomic_read(&lttng_trace_info[i].nesting)) {
129 lttng_free_trace_info(&lttng_trace_info[i]);
130 }
131 break;
9d45fe0f 132 }
133
134 }
135 if(i == MAX_TRACES) {
136 /* Not found. Must take an empty slot */
137 if(first_empty == MAX_TRACES) {
138 printf(
139 "LTTng WARNING : too many traces requested for pid %d by the kernel.\n"
140 " Compilation defined maximum is %u\n",
141 getpid(), MAX_TRACES);
142
143 } else {
144 lttng_trace_info[first_empty].channel.cpu.start = (void*)cpu_addr;
0166aeb5 145 lttng_trace_info[first_empty].channel.cpu.length = PAGE_SIZE;
9d45fe0f 146 lttng_trace_info[first_empty].channel.facilities.start =
147 (void*)fac_addr;
0166aeb5 148 lttng_trace_info[first_empty].channel.facilities.length = PAGE_SIZE;
9d45fe0f 149 lttng_trace_info[first_empty].filter = filter;
150 lttng_trace_info[first_empty].active = active;
151 }
152 }
153 }
154}
155
156
b8b00688 157/* signal handler */
158void __lttng_sig_trace_handler(int signo)
159{
92f441a7 160 int ret;
161 sigset_t set, oldset;
162
1a1e2a8c 163 printf("LTTng signal handler : thread id : %lu, pid %lu\n", pthread_self(), getpid());
164#if 0
92f441a7 165 /* Disable signals */
166 ret = sigfillset(&set);
167 if(ret) {
168 printf("Error in sigfillset\n");
169 exit(1);
170 }
171
172 ret = sigprocmask(SIG_BLOCK, &set, &oldset);
173 if(ret) {
174 printf("Error in sigprocmask\n");
175 exit(1);
176 }
1a1e2a8c 177#endif //0
1a1e2a8c 178#if 0
92f441a7 179 /* Enable signals */
180 ret = sigprocmask(SIG_SETMASK, &oldset, NULL);
181 if(ret) {
182 printf("Error in sigprocmask\n");
183 exit(1);
184 }
1a1e2a8c 185#endif //0
b8b00688 186}
187
188
1a1e2a8c 189static void thread_init(void)
b8b00688 190{
9d45fe0f 191 lttng_get_new_info();
b8b00688 192 int err;
193
92f441a7 194 /* Make some ltt_switch syscalls */
195 err = ltt_switch((unsigned long)NULL);
196 if(err) {
197 printf("Error in ltt_switch system call\n");
198 exit(1);
199 }
1a1e2a8c 200}
201
202void __attribute__((constructor)) __lttng_user_init(void)
203{
204 static struct sigaction act;
205 int err;
206
207 printf("LTTng user init\n");
208
209 /* Activate the signal */
210 act.sa_handler = __lttng_sig_trace_handler;
211 err = sigemptyset(&(act.sa_mask));
212 if(err) perror("Error with sigemptyset");
213 err = sigaddset(&(act.sa_mask), SIGRTMIN+3);
214 if(err) perror("Error with sigaddset");
215 err = sigaction(SIGRTMIN+3, &act, NULL);
216 if(err) perror("Error with sigaction");
92f441a7 217
1a1e2a8c 218 thread_init();
219}
92f441a7 220
221
1a1e2a8c 222void lttng_thread_init(void)
223{
224 thread_init();
b8b00688 225}
1a1e2a8c 226
227
228
229
230
This page took 0.03194 seconds and 4 git commands to generate.