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 ].nesting
= ATOMIC_INIT(0),
53 [ 0 ... MAX_TRACES
-1 ].channel
=
65 /* Must be called we sure nobody else is using the info.
66 * It implies that the trace should have been previously stopped
67 * and that every writer has finished.
69 * Writers should always check if the trace must be destroyed when they
70 * finish writing and the nesting level is 0.
72 void lttng_free_trace_info(struct lttng_trace_info
*info
)
78 "LTTng ERROR : lttng_free_trace_info should be called on inactive trace\n");
83 "LTTng ERROR : lttng_free_trace_info should be called on destroyed trace\n");
86 if(atomic_read(&info
->nesting
) > 0) {
88 "LTTng ERROR : lttng_free_trace_info should not be nested on tracing\n");
93 ret
= munmap(info
->channel
.cpu
.start
, info
->channel
.cpu
.length
);
95 perror("LTTNG : error in munmap");
97 ret
= munmap(info
->channel
.facilities
.start
, info
->channel
.facilities
.length
);
99 perror("LTTNG : error in munmap");
102 /* Zero the structure */
103 memset(info
, 0, sizeof(struct lttng_trace_info
));
107 static struct lttng_trace_info
* find_info(unsigned long cpu_addr
,
108 unsigned long fac_addr
, unsigned int *first_empty
)
110 struct lttng_trace_info
*found
= NULL
;
113 *first_empty
= MAX_TRACES
;
115 /* Try to find the trace */
116 for(i
=0;i
<MAX_TRACES
;i
++) {
117 if(i
<*first_empty
&& !lttng_trace_info
[i
].channel
.cpu
.start
)
120 (unsigned long)lttng_trace_info
[i
].channel
.cpu
.start
&&
122 (unsigned long)lttng_trace_info
[i
].channel
.facilities
.start
) {
124 found
= <tng_trace_info
[i
];
132 static void lttng_get_new_info(void)
134 unsigned long cpu_addr
, fac_addr
;
135 unsigned int i
, first_empty
;
136 int active
, filter
, destroy
;
138 struct lttng_trace_info
*info
;
139 sigset_t set
, oldset
;
141 /* Disable signals */
142 ret
= sigfillset(&set
);
144 printf("Error in sigfillset\n");
148 ret
= pthread_sigmask(SIG_BLOCK
, &set
, &oldset
);
150 printf("Error in sigprocmask\n");
154 /* Get all the new traces */
156 cpu_addr
= fac_addr
= 0;
157 active
= filter
= destroy
= 0;
158 ret
= ltt_update(&cpu_addr
, &fac_addr
, &active
, &filter
, &destroy
);
160 printf("LTTng : error in ltt_update\n");
164 if(!cpu_addr
|| !fac_addr
) break;
166 info
= find_info(cpu_addr
, fac_addr
, &first_empty
);
168 info
->filter
= filter
;
169 info
->active
= active
;
170 info
->destroy
= destroy
;
171 if(destroy
&& !atomic_read(&info
->nesting
))
172 lttng_free_trace_info(info
);
174 /* Not found. Must take an empty slot */
175 if(first_empty
== MAX_TRACES
) {
177 "LTTng WARNING : too many traces requested for pid %d by the kernel.\n"
178 " Compilation defined maximum is %u\n",
179 getpid(), MAX_TRACES
);
182 info
= <tng_trace_info
[first_empty
];
183 info
->channel
.cpu
.start
= (void*)cpu_addr
;
184 info
->channel
.cpu
.length
= PAGE_SIZE
;
185 info
->channel
.facilities
.start
= (void*)fac_addr
;
186 info
->channel
.facilities
.length
= PAGE_SIZE
;
187 info
->filter
= filter
;
188 info
->active
= active
;
189 info
->destroy
= destroy
;
190 if(destroy
&& !atomic_read(&info
->nesting
))
191 lttng_free_trace_info(info
);
197 ret
= pthread_sigmask(SIG_SETMASK
, &oldset
, NULL
);
199 printf("Error in sigprocmask\n");
206 void __lttng_sig_trace_handler(int signo
)
208 printf("LTTng signal handler : thread id : %lu, pid %lu\n", pthread_self(), getpid());
209 lttng_get_new_info();
213 static void thread_init(void)
216 lttng_get_new_info();
218 /* Make some ltt_switch syscalls */
219 err
= ltt_switch((unsigned long)NULL
);
221 printf("Error in ltt_switch system call\n");
226 void __attribute__((constructor
)) __lttng_user_init(void)
228 static struct sigaction act
;
231 printf("LTTng user init\n");
233 /* Activate the signal */
234 act
.sa_handler
= __lttng_sig_trace_handler
;
235 err
= sigemptyset(&(act
.sa_mask
));
236 if(err
) perror("Error with sigemptyset");
237 err
= sigaddset(&(act
.sa_mask
), SIGRTMIN
+3);
238 if(err
) perror("Error with sigaddset");
239 err
= sigaction(SIGRTMIN
+3, &act
, NULL
);
240 if(err
) perror("Error with sigaction");
246 void lttng_thread_init(void)