2 /* LTTng user-space tracing code
4 * Copyright 2006 Mathieu Desnoyers
21 #include "lttng_usertrace.h"
31 * it should send the information on the traces that has their status MODIFIED.
32 * It's a necessary assumption to have a correct lttng_free_trace_info, which
33 * would not be reentrant otherwise.
37 /* TLS for the trace info
38 * http://www.dis.com/gnu/gcc/C--98-Thread-Local-Edits.html
40 * Add after paragraph 4
42 * The storage for an object of thread storage duration shall be statically
43 * initialized before the first statement of the thread startup function. An
44 * object of thread storage duration shall not require dynamic
46 * GCC extention permits init of a range.
49 static __thread
struct lttng_trace_info lttng_trace_info
[MAX_TRACES
] =
50 { [ 0 ... MAX_TRACES
-1 ].active
= 0,
51 [ 0 ... MAX_TRACES
-1 ].filter
= 0,
52 [ 0 ... MAX_TRACES
-1 ].destroy
= 0,
53 [ 0 ... MAX_TRACES
-1 ].nesting
= ATOMIC_INIT(0),
54 [ 0 ... MAX_TRACES
-1 ].channel
=
66 /* Must be called we sure nobody else is using the info.
67 * It implies that the trace should have been previously stopped
68 * and that every writer has finished.
70 * Writers should always check if the trace must be destroyed when they
71 * finish writing and the nesting level is 0.
73 void lttng_free_trace_info(struct lttng_trace_info
*info
)
79 "LTTng ERROR : lttng_free_trace_info should be called on inactive trace\n");
84 "LTTng ERROR : lttng_free_trace_info should be called on destroyed trace\n");
87 if(atomic_read(&info
->nesting
) > 0) {
89 "LTTng ERROR : lttng_free_trace_info should not be nested on tracing\n");
94 ret
= munmap(info
->channel
.cpu
.start
, info
->channel
.cpu
.length
);
96 perror("LTTNG : error in munmap");
98 ret
= munmap(info
->channel
.facilities
.start
, info
->channel
.facilities
.length
);
100 perror("LTTNG : error in munmap");
103 /* Zero the structure */
104 memset(info
, 0, sizeof(struct lttng_trace_info
));
108 static struct lttng_trace_info
* find_info(unsigned long cpu_addr
,
109 unsigned long fac_addr
, unsigned int *first_empty
)
111 struct lttng_trace_info
*found
= NULL
;
114 *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
)
121 (unsigned long)lttng_trace_info
[i
].channel
.cpu
.start
&&
123 (unsigned long)lttng_trace_info
[i
].channel
.facilities
.start
) {
125 found
= <tng_trace_info
[i
];
133 static void lttng_get_new_info(void)
135 unsigned long cpu_addr
, fac_addr
;
136 unsigned int i
, first_empty
;
137 int active
, filter
, destroy
;
139 struct lttng_trace_info
*info
;
140 sigset_t set
, oldset
;
142 /* Disable signals */
143 ret
= sigfillset(&set
);
145 printf("Error in sigfillset\n");
149 ret
= pthread_sigmask(SIG_BLOCK
, &set
, &oldset
);
151 printf("Error in sigprocmask\n");
155 /* Get all the new traces */
157 cpu_addr
= fac_addr
= 0;
158 active
= filter
= destroy
= 0;
159 ret
= ltt_update(&cpu_addr
, &fac_addr
, &active
, &filter
, &destroy
);
161 printf("LTTng : error in ltt_update\n");
165 if(!cpu_addr
|| !fac_addr
) break;
167 info
= find_info(cpu_addr
, fac_addr
, &first_empty
);
169 info
->filter
= filter
;
170 info
->active
= active
;
171 info
->destroy
= destroy
;
172 if(destroy
&& !atomic_read(&info
->nesting
))
173 lttng_free_trace_info(info
);
175 /* Not found. Must take an empty slot */
176 if(first_empty
== MAX_TRACES
) {
178 "LTTng WARNING : too many traces requested for pid %d by the kernel.\n"
179 " Compilation defined maximum is %u\n",
180 getpid(), MAX_TRACES
);
183 info
= <tng_trace_info
[first_empty
];
184 info
->channel
.cpu
.start
= (void*)cpu_addr
;
185 info
->channel
.cpu
.length
= PAGE_SIZE
;
186 info
->channel
.facilities
.start
= (void*)fac_addr
;
187 info
->channel
.facilities
.length
= PAGE_SIZE
;
188 info
->filter
= filter
;
189 info
->active
= active
;
190 info
->destroy
= destroy
;
191 if(destroy
&& !atomic_read(&info
->nesting
))
192 lttng_free_trace_info(info
);
198 ret
= pthread_sigmask(SIG_SETMASK
, &oldset
, NULL
);
200 printf("Error in sigprocmask\n");
207 void __lttng_sig_trace_handler(int signo
)
209 printf("LTTng signal handler : thread id : %lu, pid %lu\n", pthread_self(), getpid());
210 lttng_get_new_info();
214 static void thread_init(void)
217 lttng_get_new_info();
219 /* Make some ltt_switch syscalls */
220 err
= ltt_switch((unsigned long)NULL
);
222 printf("Error in ltt_switch system call\n");
227 void __attribute__((constructor
)) __lttng_user_init(void)
229 static struct sigaction act
;
232 printf("LTTng user init\n");
234 /* Activate the signal */
235 act
.sa_handler
= __lttng_sig_trace_handler
;
236 err
= sigemptyset(&(act
.sa_mask
));
237 if(err
) perror("Error with sigemptyset");
238 err
= sigaddset(&(act
.sa_mask
), SIGRTMIN
+3);
239 if(err
) perror("Error with sigaddset");
240 err
= sigaction(SIGRTMIN
+3, &act
, NULL
);
241 if(err
) perror("Error with sigaction");
247 void lttng_thread_init(void)