fix 64 bits
[lttv.git] / attic / usertrace-attic / 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
6f269e8f 26/*
27 * Notes :
28 *
29 * ltt_update :
30 *
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.
34 */
35
36
9d45fe0f 37/* TLS for the trace info
38 * http://www.dis.com/gnu/gcc/C--98-Thread-Local-Edits.html
78d75b00 39 *
40 * Add after paragraph 4
41 *
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
45 * initialization.
46 * GCC extention permits init of a range.
47 */
92f441a7 48
78d75b00 49static __thread struct lttng_trace_info lttng_trace_info[MAX_TRACES] =
50{ [ 0 ... MAX_TRACES-1 ].active = 0,
9d45fe0f 51 [ 0 ... MAX_TRACES-1 ].filter = 0,
29a3ac12 52 [ 0 ... MAX_TRACES-1 ].destroy = 0,
0166aeb5 53 [ 0 ... MAX_TRACES-1 ].nesting = ATOMIC_INIT(0),
78d75b00 54 [ 0 ... MAX_TRACES-1 ].channel =
55 { NULL,
0166aeb5 56 0,
78d75b00 57 ATOMIC_INIT(0),
58 ATOMIC_INIT(0),
59 ATOMIC_INIT(0),
60 ATOMIC_INIT(0),
61 ATOMIC_INIT(0)
62 }
63};
92f441a7 64
9d45fe0f 65
0166aeb5 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.
69 *
70 * Writers should always check if the trace must be destroyed when they
71 * finish writing and the nesting level is 0.
72 */
73void lttng_free_trace_info(struct lttng_trace_info *info)
74{
75 int ret;
76
77 if(info->active) {
78 printf(
79 "LTTng ERROR : lttng_free_trace_info should be called on inactive trace\n");
80 exit(1);
81 }
82 if(!info->destroy) {
83 printf(
84 "LTTng ERROR : lttng_free_trace_info should be called on destroyed trace\n");
85 exit(1);
86 }
87 if(atomic_read(&info->nesting) > 0) {
88 printf(
89 "LTTng ERROR : lttng_free_trace_info should not be nested on tracing\n");
90 exit(1);
91 }
92
93 /* Remove the maps */
94 ret = munmap(info->channel.cpu.start, info->channel.cpu.length);
95 if(ret) {
96 perror("LTTNG : error in munmap");
97 }
98 ret = munmap(info->channel.facilities.start, info->channel.facilities.length);
99 if(ret) {
100 perror("LTTNG : error in munmap");
101 }
102
103 /* Zero the structure */
104 memset(info, 0, sizeof(struct lttng_trace_info));
105}
106
107
6f269e8f 108static struct lttng_trace_info* find_info(unsigned long cpu_addr,
109 unsigned long fac_addr, unsigned int *first_empty)
110{
111 struct lttng_trace_info *found = NULL;
112 unsigned int i;
113
114 *first_empty = MAX_TRACES;
115
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) {
124 /* Found */
125 found = &lttng_trace_info[i];
126 break;
127 }
128 }
129 return found;
130}
131
132
9d45fe0f 133static void lttng_get_new_info(void)
134{
135 unsigned long cpu_addr, fac_addr;
136 unsigned int i, first_empty;
0166aeb5 137 int active, filter, destroy;
9d45fe0f 138 int ret;
6f269e8f 139 struct lttng_trace_info *info;
140 sigset_t set, oldset;
141
142 /* Disable signals */
143 ret = sigfillset(&set);
144 if(ret) {
145 printf("Error in sigfillset\n");
146 exit(1);
147 }
148
149 ret = pthread_sigmask(SIG_BLOCK, &set, &oldset);
150 if(ret) {
151 printf("Error in sigprocmask\n");
152 exit(1);
153 }
9d45fe0f 154
155 /* Get all the new traces */
156 while(1) {
157 cpu_addr = fac_addr = 0;
0166aeb5 158 active = filter = destroy = 0;
159 ret = ltt_update(&cpu_addr, &fac_addr, &active, &filter, &destroy);
9d45fe0f 160 if(ret) {
161 printf("LTTng : error in ltt_update\n");
162 exit(1);
163 }
164
165 if(!cpu_addr || !fac_addr) break;
166
6f269e8f 167 info = find_info(cpu_addr, fac_addr, &first_empty);
168 if(info) {
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);
174 } else {
9d45fe0f 175 /* Not found. Must take an empty slot */
176 if(first_empty == MAX_TRACES) {
177 printf(
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);
181
182 } else {
6f269e8f 183 info = &lttng_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);
9d45fe0f 193 }
194 }
195 }
6f269e8f 196
197 /* Enable signals */
198 ret = pthread_sigmask(SIG_SETMASK, &oldset, NULL);
199 if(ret) {
200 printf("Error in sigprocmask\n");
201 exit(1);
202 }
9d45fe0f 203}
204
205
b8b00688 206/* signal handler */
207void __lttng_sig_trace_handler(int signo)
208{
1a1e2a8c 209 printf("LTTng signal handler : thread id : %lu, pid %lu\n", pthread_self(), getpid());
6f269e8f 210 lttng_get_new_info();
b8b00688 211}
212
213
1a1e2a8c 214static void thread_init(void)
b8b00688 215{
b8b00688 216 int err;
6f269e8f 217 lttng_get_new_info();
b8b00688 218
92f441a7 219 /* Make some ltt_switch syscalls */
220 err = ltt_switch((unsigned long)NULL);
221 if(err) {
222 printf("Error in ltt_switch system call\n");
223 exit(1);
224 }
1a1e2a8c 225}
226
227void __attribute__((constructor)) __lttng_user_init(void)
228{
229 static struct sigaction act;
230 int err;
231
232 printf("LTTng user init\n");
233
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");
92f441a7 242
1a1e2a8c 243 thread_init();
244}
92f441a7 245
246
1a1e2a8c 247void lttng_thread_init(void)
248{
249 thread_init();
b8b00688 250}
1a1e2a8c 251
252
This page took 0.033982 seconds and 4 git commands to generate.