| 1 | #include <stdio.h> |
| 2 | #include <unistd.h> |
| 3 | #include <sys/mman.h> |
| 4 | #include <stdarg.h> |
| 5 | #include <sys/types.h> |
| 6 | #include <sys/stat.h> |
| 7 | #include <fcntl.h> |
| 8 | |
| 9 | #include "../libmarkers/marker.h" |
| 10 | #include "usterr.h" |
| 11 | #include "tracer.h" |
| 12 | #include "marker-control.h" |
| 13 | #include "relay.h" |
| 14 | |
| 15 | |
| 16 | char consumer_stack[10000]; |
| 17 | char trace_name[] = "theusttrace"; |
| 18 | char trace_type[] = "ustrelay"; |
| 19 | |
| 20 | #define CPRINTF(fmt, args...) safe_printf(fmt "\n", ## args) |
| 21 | |
| 22 | int safe_printf(const char *fmt, ...) |
| 23 | { |
| 24 | static char buf[500]; |
| 25 | va_list ap; |
| 26 | int n; |
| 27 | |
| 28 | va_start(ap, fmt); |
| 29 | |
| 30 | n = vsnprintf(buf, sizeof(buf), fmt, ap); |
| 31 | |
| 32 | write(STDOUT_FILENO, buf, n); |
| 33 | |
| 34 | va_end(ap); |
| 35 | } |
| 36 | |
| 37 | struct consumer_channel { |
| 38 | int fd; |
| 39 | struct ltt_channel_struct *chan; |
| 40 | }; |
| 41 | |
| 42 | int consumer(void *arg) |
| 43 | { |
| 44 | int result; |
| 45 | int fd; |
| 46 | char str[] = "Hello, this is the consumer.\n"; |
| 47 | struct ltt_trace_struct *trace; |
| 48 | struct consumer_channel *consumer_channels; |
| 49 | int i; |
| 50 | |
| 51 | ltt_lock_traces(); |
| 52 | trace = _ltt_trace_find(trace_name); |
| 53 | ltt_unlock_traces(); |
| 54 | |
| 55 | if(trace == NULL) { |
| 56 | CPRINTF("cannot find trace!"); |
| 57 | return 1; |
| 58 | } |
| 59 | |
| 60 | consumer_channels = (struct consumer_channel *) malloc(trace->nr_channels * sizeof(struct consumer_channel)); |
| 61 | if(consumer_channels == NULL) { |
| 62 | ERR("malloc returned NULL"); |
| 63 | return 1; |
| 64 | } |
| 65 | |
| 66 | CPRINTF("opening trace files"); |
| 67 | for(i=0; i<trace->nr_channels; i++) { |
| 68 | char tmp[100]; |
| 69 | struct ltt_channel_struct *chan = &trace->channels[i]; |
| 70 | |
| 71 | consumer_channels[i].chan = chan; |
| 72 | |
| 73 | snprintf(tmp, sizeof(tmp), "trace/%s", chan->channel_name); |
| 74 | result = consumer_channels[i].fd = open(tmp, O_WRONLY | O_CREAT | O_TRUNC, 00644); |
| 75 | if(result == -1) { |
| 76 | perror("open"); |
| 77 | return -1; |
| 78 | } |
| 79 | CPRINTF("\topened trace file %s", tmp); |
| 80 | |
| 81 | } |
| 82 | CPRINTF("done opening trace files"); |
| 83 | |
| 84 | for(;;) { |
| 85 | /*wait*/ |
| 86 | |
| 87 | for(i=0; i<trace->nr_channels; i++) { |
| 88 | struct rchan *rchan = consumer_channels[i].chan->trans_channel_data; |
| 89 | struct rchan_buf *rbuf = rchan->buf; |
| 90 | struct ltt_channel_buf_struct *lttbuf = consumer_channels[i].chan->buf; |
| 91 | long consumed_old; |
| 92 | |
| 93 | result = ltt_do_get_subbuf(rbuf, lttbuf, &consumed_old); |
| 94 | if(result < 0) { |
| 95 | CPRINTF("ltt_do_get_subbuf: error: %s", strerror(-result)); |
| 96 | } |
| 97 | else { |
| 98 | CPRINTF("success!"); |
| 99 | |
| 100 | result = write(consumer_channels[i].fd, rbuf->buf_data + (consumed_old & (2 * 4096-1)), 4096); |
| 101 | ltt_do_put_subbuf(rbuf, lttbuf, consumed_old); |
| 102 | } |
| 103 | } |
| 104 | |
| 105 | sleep(1); |
| 106 | } |
| 107 | |
| 108 | // CPRINTF("consumer: got a trace: %s with %d channels\n", trace_name, trace->nr_channels); |
| 109 | // |
| 110 | // struct ltt_channel_struct *chan = &trace->channels[0]; |
| 111 | // |
| 112 | // CPRINTF("channel 1 (%s) active=%u", chan->channel_name, chan->active & 1); |
| 113 | |
| 114 | // struct rchan *rchan = chan->trans_channel_data; |
| 115 | // struct rchan_buf *rbuf = rchan->buf; |
| 116 | // struct ltt_channel_buf_struct *lttbuf = chan->buf; |
| 117 | // long consumed_old; |
| 118 | // |
| 119 | // result = fd = open("trace.out", O_WRONLY | O_CREAT | O_TRUNC, 00644); |
| 120 | // if(result == -1) { |
| 121 | // perror("open"); |
| 122 | // return -1; |
| 123 | // } |
| 124 | |
| 125 | // for(;;) { |
| 126 | // write(STDOUT_FILENO, str, sizeof(str)); |
| 127 | // |
| 128 | // result = ltt_do_get_subbuf(rbuf, lttbuf, &consumed_old); |
| 129 | // if(result < 0) { |
| 130 | // CPRINTF("ltt_do_get_subbuf: error: %s", strerror(-result)); |
| 131 | // } |
| 132 | // else { |
| 133 | // CPRINTF("success!"); |
| 134 | // |
| 135 | // result = write(fd, rbuf->buf_data + (consumed_old & (2 * 4096-1)), 4096); |
| 136 | // ltt_do_put_subbuf(rbuf, lttbuf, consumed_old); |
| 137 | // } |
| 138 | // |
| 139 | // //CPRINTF("There seems to be %ld bytes available", SUBBUF_TRUNC(local_read(<tbuf->offset), rbuf->chan) - consumed_old); |
| 140 | // CPRINTF("Commit count %ld", local_read(<tbuf->commit_count[0])); |
| 141 | // |
| 142 | // |
| 143 | // sleep(1); |
| 144 | // } |
| 145 | } |
| 146 | |
| 147 | void start_consumer(void) |
| 148 | { |
| 149 | int result; |
| 150 | |
| 151 | result = clone(consumer, consumer_stack+sizeof(consumer_stack)-1, CLONE_FS | CLONE_FILES | CLONE_VM, NULL); |
| 152 | if(result == -1) { |
| 153 | perror("clone"); |
| 154 | } |
| 155 | } |
| 156 | |
| 157 | void probe(const struct marker *mdata, |
| 158 | void *probe_private, void *call_private, |
| 159 | const char *fmt, va_list *args) |
| 160 | { |
| 161 | printf("In probe\n"); |
| 162 | } |
| 163 | |
| 164 | void inthandler(int sig) |
| 165 | { |
| 166 | printf("in handler\n"); |
| 167 | exit(0); |
| 168 | } |
| 169 | |
| 170 | int init_int_handler(void) |
| 171 | { |
| 172 | int result; |
| 173 | struct sigaction act; |
| 174 | |
| 175 | result = sigemptyset(&act.sa_mask); |
| 176 | if(result == -1) { |
| 177 | PERROR("sigemptyset"); |
| 178 | return -1; |
| 179 | } |
| 180 | |
| 181 | act.sa_handler = inthandler; |
| 182 | act.sa_flags = SA_RESTART; |
| 183 | |
| 184 | /* Only defer ourselves. Also, try to restart interrupted |
| 185 | * syscalls to disturb the traced program as little as possible. |
| 186 | */ |
| 187 | result = sigaction(SIGINT, &act, NULL); |
| 188 | if(result == -1) { |
| 189 | PERROR("sigaction"); |
| 190 | return -1; |
| 191 | } |
| 192 | |
| 193 | return 0; |
| 194 | } |
| 195 | |
| 196 | int main() |
| 197 | { |
| 198 | int result; |
| 199 | int i; |
| 200 | |
| 201 | init_int_handler(); |
| 202 | |
| 203 | init_ustrelay_transport(); |
| 204 | |
| 205 | printf("page size is %d\n", sysconf(_SC_PAGE_SIZE)); |
| 206 | |
| 207 | // extern struct marker __start___markers[] __attribute__((visibility("hidden"))); |
| 208 | // extern struct marker __stop___markers[] __attribute__((visibility("hidden"))); |
| 209 | // |
| 210 | // printf("the executable's markers start at %lx and end at %lx, the size of a marker is %d\n", __start___markers, __stop___markers, sizeof(struct marker)); |
| 211 | |
| 212 | marker_control_init(); |
| 213 | |
| 214 | //marker_probe_register("abc", "testmark", "", probe, NULL); |
| 215 | //ust// marker_probe_register("metadata", "core_marker_id", "channel %s name %s event_id %hu int #1u%zu long #1u%zu pointer #1u%zu size_t #1u%zu alignment #1u%u", probe, NULL); |
| 216 | //ust// result = ltt_probe_register(&default_probe); |
| 217 | //ust// if(result) |
| 218 | //ust// ERR("ltt_probe_register"); |
| 219 | |
| 220 | //result = ltt_marker_connect("metadata", "testev", "default"); |
| 221 | //if(result) |
| 222 | // ERR("ltt_marker_connect"); |
| 223 | result = ltt_marker_connect("foo", "bar", "default"); |
| 224 | if(result) |
| 225 | ERR("ltt_marker_connect"); |
| 226 | |
| 227 | result = ltt_trace_setup(trace_name); |
| 228 | if(result < 0) { |
| 229 | ERR("ltt_trace_setup failed"); |
| 230 | return 1; |
| 231 | } |
| 232 | |
| 233 | result = ltt_trace_set_type(trace_name, trace_type); |
| 234 | if(result < 0) { |
| 235 | ERR("ltt_trace_set_type failed"); |
| 236 | return 1; |
| 237 | } |
| 238 | |
| 239 | result = ltt_trace_alloc(trace_name); |
| 240 | if(result < 0) { |
| 241 | ERR("ltt_trace_alloc failed"); |
| 242 | return 1; |
| 243 | } |
| 244 | |
| 245 | result = ltt_trace_start(trace_name); |
| 246 | if(result < 0) { |
| 247 | ERR("ltt_trace_start failed"); |
| 248 | return 1; |
| 249 | } |
| 250 | |
| 251 | start_consumer(); |
| 252 | printf("Hello, World!\n"); |
| 253 | |
| 254 | sleep(1); |
| 255 | for(i=0; i<50; i++) { |
| 256 | //trace_mark(abc, testmark, "", MARK_NOARGS); |
| 257 | //trace_mark(metadata, testev, "", MARK_NOARGS); |
| 258 | trace_mark(foo, bar, "%s", "FOOBAZ"); |
| 259 | //trace_mark(metadata, core_marker_id, |
| 260 | // "channel %s name %s event_id %hu " |
| 261 | // "int #1u%zu long #1u%zu pointer #1u%zu " |
| 262 | // "size_t #1u%zu alignment #1u%u", |
| 263 | // "abc", "def", (unsigned short)1000, |
| 264 | // sizeof(int), sizeof(long), sizeof(void *), |
| 265 | // sizeof(size_t), ltt_get_alignment()); |
| 266 | usleep(100000); |
| 267 | } |
| 268 | |
| 269 | ltt_trace_stop(trace_name); |
| 270 | ltt_trace_destroy(trace_name); |
| 271 | |
| 272 | scanf("%*s"); |
| 273 | |
| 274 | return 0; |
| 275 | } |
| 276 | |
| 277 | MARKER_LIB |