commit 1e20abdd9e025312024b3d1d6987f923ce23b0a9 Author: Cedric Roux Date: Mon Mar 14 18:02:12 2016 +0100 Initial commit of the T! diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000..06315e4585 --- /dev/null +++ b/Makefile @@ -0,0 +1,33 @@ +CC=gcc +CFLAGS=-Wall -g -pthread + +#comment those two lines to NOT use shared memory +CFLAGS += -DT_USE_SHARED_MEMORY +LIBS += -lrt + +PROG=t +OBJS=main.o T.o + +GENIDS=genids +GENIDS_OBJS=genids.o + +ALL=$(PROG) $(GENIDS) + +all : $(ALL) + +$(GENIDS): $(GENIDS_OBJS) + $(CC) $(CFLAGS) -o $(GENIDS) $(GENIDS_OBJS) + +$(PROG): $(OBJS) + $(CC) $(CFLAGS) -o $(PROG) $(OBJS) $(LIBS) + +%.o: %.c + $(CC) $(CFLAGS) -c -o $@ $< + +T_IDs.h: $(GENIDS) T_messages.txt + ./$(GENIDS) T_messages.txt T_IDs.h + +main.o: T.h T_IDs.h + +clean: + rm -f *.o $(PROG) $(GENIDS) core T_IDs.h diff --git a/T.c b/T.c new file mode 100644 index 0000000000..a33d1e90b6 --- /dev/null +++ b/T.c @@ -0,0 +1,140 @@ +#include "T.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* array used to activate/disactivate a log */ +static int T_IDs[T_NUMBER_OF_IDS]; +int *T_active = T_IDs; + +static int T_socket; + +/* T_cache + * - the T macro picks up the head of freelist and marks it busy + * - the T sender thread periodically wakes up and sends what's to be sent + */ +volatile int _T_freelist_head; +volatile int *T_freelist_head = &_T_freelist_head; +int T_busylist_head; +T_cache_t _T_cache[T_CACHE_SIZE]; +T_cache_t *T_cache = _T_cache; + +static void get_message(int s) +{ + char t; + int l; + int id; + + if (read(s, &t, 1) != 1) abort(); +printf("got mess %d\n", t); + switch (t) { + case 0: + /* toggle all those IDs */ + /* optimze? (too much syscalls) */ + if (read(s, &l, sizeof(int)) != sizeof(int)) abort(); + while (l) { + if (read(s, &id, sizeof(int)) != sizeof(int)) abort(); + T_IDs[id] = 1 - T_IDs[id]; + l--; + } + break; + } +} + +#ifndef T_USE_SHARED_MEMORY + +static void *T_send_thread(void *_) +{ + while (1) { + usleep(5000); + while (T_cache[T_busylist_head].busy) { + char *b = T_cache[T_busylist_head].buffer; + int l = T_cache[T_busylist_head].length; + while (l) { + int done = write(T_socket, b, l); + if (done <= 0) { + printf("%s:%d:%s: error sending to socket\n", + __FILE__, __LINE__, __FUNCTION__); + abort(); + } + b += done; + l -= done; + } + T_cache[T_busylist_head].busy = 0; + T_busylist_head++; + T_busylist_head &= T_CACHE_SIZE - 1; + } + } + return NULL; +} + +#endif /* T_USE_SHARED_MEMORY */ + +static void *T_receive_thread(void *_) +{ + while (1) get_message(T_socket); + return NULL; +} + +static void new_thread(void *(*f)(void *), void *data) +{ + pthread_t t; + pthread_attr_t att; + + if (pthread_attr_init(&att)) + { fprintf(stderr, "pthread_attr_init err\n"); exit(1); } + if (pthread_attr_setdetachstate(&att, PTHREAD_CREATE_DETACHED)) + { fprintf(stderr, "pthread_attr_setdetachstate err\n"); exit(1); } + if (pthread_create(&t, &att, f, data)) + { fprintf(stderr, "pthread_create err\n"); exit(1); } + if (pthread_attr_destroy(&att)) + { fprintf(stderr, "pthread_attr_destroy err\n"); exit(1); } +} + +void T_connect_to_tracer(char *addr, int port) +{ + struct sockaddr_in a; + int s; +#ifdef T_USE_SHARED_MEMORY + int T_shm_fd; +#endif + + s = socket(AF_INET, SOCK_STREAM, 0); + if (s == -1) { perror("socket"); exit(1); } + + a.sin_family = AF_INET; + a.sin_port = htons(port); + a.sin_addr.s_addr = inet_addr(addr); + + if (connect(s, (struct sockaddr *)&a, sizeof(a)) == -1) + { perror("connect"); exit(1); } + + /* wait for first message - initial list of active T events */ + get_message(s); + + T_socket = s; + +#ifdef T_USE_SHARED_MEMORY + /* setup shared memory */ + T_shm_fd = shm_open(T_SHM_FILENAME, O_RDWR, 0666); + shm_unlink(T_SHM_FILENAME); + if (T_shm_fd == -1) { perror(T_SHM_FILENAME); abort(); } + T_cache = mmap(NULL, T_CACHE_SIZE * sizeof(T_cache_t), + PROT_READ | PROT_WRITE, MAP_SHARED, T_shm_fd, 0); + if (T_cache == NULL) + { perror(T_SHM_FILENAME); abort(); } + close(T_shm_fd); +#endif + +#ifndef T_USE_SHARED_MEMORY + new_thread(T_send_thread, NULL); +#endif + new_thread(T_receive_thread, NULL); +} diff --git a/T.h b/T.h new file mode 100644 index 0000000000..884a9b6f89 --- /dev/null +++ b/T.h @@ -0,0 +1,506 @@ +#ifndef _T_T_T_ +#define _T_T_T_ + +#include + +#include "T_defs.h" + +/* T message IDs */ +#include "T_IDs.h" + +/* known type - this is where you add new types */ + +#define T_INT(x) int, (x) +#define T_FLOAT(x) float, (x) +#define T_BUFFER(x, len) buffer, ((T_buffer){addr:(x), length:(len)}) +#define T_STRING(x) string, (x) +#define T_PRINTF(...) printf, (__VA_ARGS__) + +/* for each known type a T_PUT_XX macro is defined */ + +#define T_PUT_int(argnum, val) \ + do { \ + int T_PUT_var = (val); \ + T_CHECK_SIZE(sizeof(int), argnum); \ + memcpy(T_LOCAL_buf + T_LOCAL_size, &T_PUT_var, sizeof(int)); \ + T_LOCAL_size += sizeof(int); \ + } while (0) + +#define T_PUT_float(argnum, val) \ + do { \ + float T_PUT_var = (val); \ + T_CHECK_SIZE(sizeof(float), argnum); \ + memcpy(T_LOCAL_buf + T_LOCAL_size, &T_PUT_var, sizeof(float)); \ + T_LOCAL_size += sizeof(float); \ + } while (0) + +#define T_PUT_buffer(argnum, val) \ + do { \ + T_buffer T_PUT_var = (val); \ + T_CHECK_SIZE(T_PUT_var.length, argnum); \ + memcpy(T_LOCAL_buf + T_LOCAL_size, T_PUT_var.addr, T_PUT_var.length); \ + T_LOCAL_size += T_PUT_var.length; \ + } while (0) + +#define T_PUT_string(argnum, val) \ + do { \ + char *T_PUT_var = (val); \ + int T_PUT_len = strlen(T_PUT_var) + 1; \ + T_CHECK_SIZE(T_PUT_len, argnum); \ + memcpy(T_LOCAL_buf + T_LOCAL_size, T_PUT_var, T_PUT_len); \ + T_LOCAL_size += T_PUT_len; \ + } while (0) + +#define T_PUT_printf_deref(...) __VA_ARGS__ + +#define T_PUT_printf(argnum, x) \ + do { \ + int T_PUT_len = snprintf(T_LOCAL_buf + T_LOCAL_size, \ + T_BUFFER_MAX - T_LOCAL_size, T_PUT_printf_deref x); \ + if (T_PUT_len < 0) { \ + printf("%s:%d:%s: you can't read this, or can you?", \ + __FILE__, __LINE__, __FUNCTION__); \ + abort(); \ + } \ + if (T_PUT_len >= T_BUFFER_MAX - T_LOCAL_size) { \ + printf("%s:%d:%s: cannot put argument %d in T macro, not enough space" \ + ", consider increasing T_BUFFER_MAX (%d)\n", \ + __FILE__, __LINE__, __FUNCTION__, argnum, T_BUFFER_MAX); \ + abort(); \ + } \ + T_LOCAL_size += T_PUT_len + 1; \ + } while (0) + +/* structure type to detect that you pass a known type as first arg of T */ +struct T_header; + +/* to define message ID */ +#define T_ID(x) ((struct T_header *)(uintptr_t)(x)) + +/* T macro tricks */ + +#define TN(...) TN_N(__VA_ARGS__,33,32,31,30,29,28,27,26,25,24,23,22,21,\ + 20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)(__VA_ARGS__) +#define TN_N(n0,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,n13,n14,n15,n16,n17,\ + n18,n19,n20,n21,n22,n23,n24,n25,n26,n27,n28,n29,n30,n31,n32,n,...) T##n +#define T(...) TN(__VA_ARGS__) + +/* type used to send arbitrary buffer data */ +typedef struct { + void *addr; + int length; +} T_buffer; + +extern volatile int *T_freelist_head; +extern T_cache_t *T_cache; + +/* used at header of Tn, allocates buffer */ +#define T_LOCAL_DATA \ + char *T_LOCAL_buf; \ + int T_LOCAL_size = 0; \ + int T_LOCAL_slot; \ + T_LOCAL_slot = __sync_fetch_and_add(T_freelist_head, 1) \ + & (T_CACHE_SIZE - 1); \ + (void)__sync_fetch_and_and(T_freelist_head, T_CACHE_SIZE - 1); \ + if (T_cache[T_LOCAL_slot].busy) { \ + printf("%s:%d:%s: T cache is full - consider increasing its size\n", \ + __FILE__, __LINE__, __FUNCTION__); \ + abort(); \ + } \ + T_LOCAL_buf = T_cache[T_LOCAL_slot].buffer; + +#define T_ACTIVE(x) T_active[(intptr_t)x] + +#define T_SEND() \ + T_cache[T_LOCAL_slot].busy = 1; \ + T_cache[T_LOCAL_slot].length = T_LOCAL_size; \ + T_send(T_LOCAL_buf, T_LOCAL_size) + +#define T_CHECK_SIZE(len, argnum) \ + if (T_LOCAL_size + len > T_BUFFER_MAX) { \ + printf("%s:%d:%s: cannot put argument %d in T macro, not enough space" \ + ", consider increasing T_BUFFER_MAX (%d)\n", \ + __FILE__, __LINE__, __FUNCTION__, argnum, T_BUFFER_MAX); \ + abort(); \ + } + +#if 0 +#define T_PUT(type, var, argnum) \ + do { \ + if (T_LOCAL_size + sizeof(var) > T_BUFFER_MAX) { \ + printf("%s:%d:%s: cannot put argument %d in T macro, not enough space" \ + ", consider increasing T_BUFFER_MAX (%d)\n", \ + __FILE__, __LINE__, __FUNCTION__, argnum, T_BUFFER_MAX); \ + abort(); \ + } \ + memcpy(T_LOCAL_buf + T_LOCAL_size, &var, sizeof(var)); \ + T_LOCAL_size += sizeof(var); \ + } while (0) +#endif + +#if 0 +#define T_PROCESS(x, argnum) \ + do { \ + T_PUT(typeof(x), x, argnum); \ + } while (0) +#endif + +#if 0 +#define T_PROCESS(x, argnum) \ + do { \ + if (__builtin_types_compatible_p(typeof(x), int)) \ + { T_PUT(int, (intptr_t)(x), argnum); printf("int\n"); } \ + else if (__builtin_types_compatible_p(typeof(x), short)) \ + { T_PUT(short, (intptr_t)(x), argnum); printf("short\n"); } \ + else if (__builtin_types_compatible_p(typeof(x), float)) \ + { T_PUT(float, (x), argnum); printf("float\n"); } \ + else if (__builtin_types_compatible_p(typeof(x), char *)) \ + { T_PUT(char *, (char *)(intptr_t)(x), argnum); printf("char *\n"); } \ + else if (__builtin_types_compatible_p(typeof(x), float *)) \ + { T_PUT(float *, (float *)(intptr_t)(x), argnum); printf("float *\n"); } \ + else if (__builtin_types_compatible_p(typeof(x), void *)) \ + { T_PUT(void *, (void *)(intptr_t)(x), argnum); printf("void *\n"); } \ + else { \ + printf("%s:%d:%s: unsupported type for argument %d in T macro\n", \ + __FILE__, __LINE__, __FUNCTION__, argnum); \ + abort(); \ + } \ + } while (0) +#endif + +#define T_HEADER(x) \ + do { \ + if (!__builtin_types_compatible_p(typeof(x), struct T_header *)) { \ + printf("%s:%d:%s: " \ + "bad use of T, pass a message ID as first parameter\n", \ + __FILE__, __LINE__, __FUNCTION__); \ + abort(); \ + } \ + T_PUT_int(1, (int)(uintptr_t)(x)); \ + } while (0) + +#define T1(t) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_SEND(); \ + } \ + } while (0) + +#define T3(t,t0,x0) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_SEND(); \ + } \ + } while (0) + +#define T5(t,t0,x0,t1,x1) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_PUT_##t1(3, x1); \ + T_SEND(); \ + } \ + } while (0) + +#define T7(t,t0,x0,t1,x1,t2,x2) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_PUT_##t1(3, x1); \ + T_PUT_##t2(4, x2); \ + T_SEND(); \ + } \ + } while (0) + +#define T9(t,t0,x0,t1,x1,t2,x2,t3,x3) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_PUT_##t1(3, x1); \ + T_PUT_##t2(4, x2); \ + T_PUT_##t3(5, x3); \ + T_SEND(); \ + } \ + } while (0) + +#define T11(t,t0,x0,t1,x1,t2,x2,t3,x3) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_PUT_##t1(3, x1); \ + T_PUT_##t2(4, x2); \ + T_PUT_##t3(5, x3); \ + T_SEND(); \ + } \ + } while (0) + +#define T13(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_PUT_##t1(3, x1); \ + T_PUT_##t2(4, x2); \ + T_PUT_##t3(5, x3); \ + T_PUT_##t4(6, x4); \ + T_SEND(); \ + } \ + } while (0) + +#define T15(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_PUT_##t1(3, x1); \ + T_PUT_##t2(4, x2); \ + T_PUT_##t3(5, x3); \ + T_PUT_##t4(6, x4); \ + T_PUT_##t5(7, x5); \ + T_SEND(); \ + } \ + } while (0) + +#define T17(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_PUT_##t1(3, x1); \ + T_PUT_##t2(4, x2); \ + T_PUT_##t3(5, x3); \ + T_PUT_##t4(6, x4); \ + T_PUT_##t5(7, x5); \ + T_PUT_##t6(8, x6); \ + T_SEND(); \ + } \ + } while (0) + +#define T19(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_PUT_##t1(3, x1); \ + T_PUT_##t2(4, x2); \ + T_PUT_##t3(5, x3); \ + T_PUT_##t4(6, x4); \ + T_PUT_##t5(7, x5); \ + T_PUT_##t6(8, x6); \ + T_PUT_##t7(9, x7); \ + T_SEND(); \ + } \ + } while (0) + +#define T21(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_PUT_##t1(3, x1); \ + T_PUT_##t2(4, x2); \ + T_PUT_##t3(5, x3); \ + T_PUT_##t4(6, x4); \ + T_PUT_##t5(7, x5); \ + T_PUT_##t6(8, x6); \ + T_PUT_##t7(9, x7); \ + T_PUT_##t8(10, x8); \ + T_SEND(); \ + } \ + } while (0) + +#define T23(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_PUT_##t1(3, x1); \ + T_PUT_##t2(4, x2); \ + T_PUT_##t3(5, x3); \ + T_PUT_##t4(6, x4); \ + T_PUT_##t5(7, x5); \ + T_PUT_##t6(8, x6); \ + T_PUT_##t7(9, x7); \ + T_PUT_##t8(10, x8); \ + T_PUT_##t9(11, x9); \ + T_SEND(); \ + } \ + } while (0) + +#define T25(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,t10,x10) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_PUT_##t1(3, x1); \ + T_PUT_##t2(4, x2); \ + T_PUT_##t3(5, x3); \ + T_PUT_##t4(6, x4); \ + T_PUT_##t5(7, x5); \ + T_PUT_##t6(8, x6); \ + T_PUT_##t7(9, x7); \ + T_PUT_##t8(10, x8); \ + T_PUT_##t9(11, x9); \ + T_PUT_##t10(12, x10); \ + T_SEND(); \ + } \ + } while (0) + +#define T27(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,t10,x10,t11,x11) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_PUT_##t1(3, x1); \ + T_PUT_##t2(4, x2); \ + T_PUT_##t3(5, x3); \ + T_PUT_##t4(6, x4); \ + T_PUT_##t5(7, x5); \ + T_PUT_##t6(8, x6); \ + T_PUT_##t7(9, x7); \ + T_PUT_##t8(10, x8); \ + T_PUT_##t9(11, x9); \ + T_PUT_##t10(12, x10); \ + T_PUT_##t11(13, x11); \ + T_SEND(); \ + } \ + } while (0) + +#define T29(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,t10,x10,t11,x11,t12,x12) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_PUT_##t1(3, x1); \ + T_PUT_##t2(4, x2); \ + T_PUT_##t3(5, x3); \ + T_PUT_##t4(6, x4); \ + T_PUT_##t5(7, x5); \ + T_PUT_##t6(8, x6); \ + T_PUT_##t7(9, x7); \ + T_PUT_##t8(10, x8); \ + T_PUT_##t9(11, x9); \ + T_PUT_##t10(12, x10); \ + T_PUT_##t11(13, x11); \ + T_PUT_##t12(14, x12); \ + T_SEND(); \ + } \ + } while (0) + +#define T31(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,t10,x10,t11,x11,t12,x12,t13,x13) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_PUT_##t1(3, x1); \ + T_PUT_##t2(4, x2); \ + T_PUT_##t3(5, x3); \ + T_PUT_##t4(6, x4); \ + T_PUT_##t5(7, x5); \ + T_PUT_##t6(8, x6); \ + T_PUT_##t7(9, x7); \ + T_PUT_##t8(10, x8); \ + T_PUT_##t9(11, x9); \ + T_PUT_##t10(12, x10); \ + T_PUT_##t11(13, x11); \ + T_PUT_##t12(14, x12); \ + T_PUT_##t13(15, x13); \ + T_SEND(); \ + } \ + } while (0) + +#define T33(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,t10,x10,t11,x11,t12,x12,t13,x13,t14,x14) \ + do { \ + if (T_ACTIVE(t)) { \ + T_LOCAL_DATA \ + T_HEADER(t); \ + T_PUT_##t0(2, x0); \ + T_PUT_##t1(3, x1); \ + T_PUT_##t2(4, x2); \ + T_PUT_##t3(5, x3); \ + T_PUT_##t4(6, x4); \ + T_PUT_##t5(7, x5); \ + T_PUT_##t6(8, x6); \ + T_PUT_##t7(9, x7); \ + T_PUT_##t8(10, x8); \ + T_PUT_##t9(11, x9); \ + T_PUT_##t10(12, x10); \ + T_PUT_##t11(13, x11); \ + T_PUT_##t12(14, x12); \ + T_PUT_##t13(15, x13); \ + T_PUT_##t14(16, x14); \ + T_SEND(); \ + } \ + } while (0) + +#define T_CALL_ERROR \ + do { \ + printf("%s:%d:%s: error calling T, you have to use T_INT() or T_XX()\n", \ + __FILE__, __LINE__, __FUNCTION__); \ + } while (0) + +#define T2(...) T_CALL_ERROR +#define T4(...) T_CALL_ERROR +#define T6(...) T_CALL_ERROR +#define T8(...) T_CALL_ERROR +#define T10(...) T_CALL_ERROR +#define T12(...) T_CALL_ERROR +#define T14(...) T_CALL_ERROR +#define T16(...) T_CALL_ERROR +#define T18(...) T_CALL_ERROR +#define T20(...) T_CALL_ERROR +#define T22(...) T_CALL_ERROR +#define T24(...) T_CALL_ERROR +#define T26(...) T_CALL_ERROR +#define T28(...) T_CALL_ERROR +#define T30(...) T_CALL_ERROR +#define T32(...) T_CALL_ERROR + +#ifndef T_USE_SHARED_MEMORY + +#include + +static inline void T_send(char *buf, int size) +{ + int i; +return; + printf("sending %d bytes", size); + for (i = 0; i < size; i++) + printf("%s%2.2x", i?" ":"\n", (unsigned char)buf[i]); + printf("\n"); +} + +#else /* T_USE_SHARED_MEMORY */ + +#define T_send(...) /**/ + +#endif /* T_USE_SHARED_MEMORY */ + +extern int *T_active; + +void T_connect_to_tracer(char *addr, int port); + +#endif /* _T_T_T_ */ diff --git a/T_defs.h b/T_defs.h new file mode 100644 index 0000000000..1d01ea7415 --- /dev/null +++ b/T_defs.h @@ -0,0 +1,18 @@ +#ifndef _T_defs_H_ +#define _T_defs_H_ + +/* maximum size of a message - increase if needed */ +#define T_BUFFER_MAX 1024 + +/* size of the local cache for messages (must be pow(2,something)) */ +#define T_CACHE_SIZE (65536 * 2) + +typedef struct { + volatile int busy; + char buffer[T_BUFFER_MAX]; + int length; +} T_cache_t; + +#define T_SHM_FILENAME "/T_shm_segment" + +#endif /* _T_defs_H_ */ diff --git a/T_messages.txt b/T_messages.txt new file mode 100644 index 0000000000..b0e6cb00ed --- /dev/null +++ b/T_messages.txt @@ -0,0 +1,140 @@ +#legacy logs +ID = LEGACY_MAC_INFO + DESC = MAC legacy logs + GROUP = MAC:INFO:LEGACY +ID = LEGACY_MAC_ERROR +ID = LEGACY_MAC_WARNING +ID = LEGACY_MAC_DEBUG +ID = LEGACY_MAC_TRACE + +ID = LEGACY_PHY_INFO +ID = LEGACY_PHY_ERROR +ID = LEGACY_PHY_WARNING +ID = LEGACY_PHY_DEBUG +ID = LEGACY_PHY_TRACE + +ID = LEGACY_S1AP_INFO +ID = LEGACY_S1AP_ERROR +ID = LEGACY_S1AP_WARNING +ID = LEGACY_S1AP_DEBUG +ID = LEGACY_S1AP_TRACE + +ID = LEGACY_RRC_INFO +ID = LEGACY_RRC_ERROR +ID = LEGACY_RRC_WARNING +ID = LEGACY_RRC_DEBUG +ID = LEGACY_RRC_TRACE + +ID = LEGACY_RLC_INFO +ID = LEGACY_RLC_ERROR +ID = LEGACY_RLC_WARNING +ID = LEGACY_RLC_DEBUG +ID = LEGACY_RLC_TRACE + +ID = LEGACY_PDCP_INFO +ID = LEGACY_PDCP_ERROR +ID = LEGACY_PDCP_WARNING +ID = LEGACY_PDCP_DEBUG +ID = LEGACY_PDCP_TRACE + +ID = LEGACY_ENB_APP_INFO +ID = LEGACY_ENB_APP_ERROR +ID = LEGACY_ENB_APP_WARNING +ID = LEGACY_ENB_APP_DEBUG +ID = LEGACY_ENB_APP_TRACE + +ID = LEGACY_SCTP_INFO +ID = LEGACY_SCTP_ERROR +ID = LEGACY_SCTP_WARNING +ID = LEGACY_SCTP_DEBUG +ID = LEGACY_SCTP_TRACE + +ID = LEGACY_UDP__INFO +ID = LEGACY_UDP__ERROR +ID = LEGACY_UDP__WARNING +ID = LEGACY_UDP__DEBUG +ID = LEGACY_UDP__TRACE + +ID = LEGACY_NAS_INFO +ID = LEGACY_NAS_ERROR +ID = LEGACY_NAS_WARNING +ID = LEGACY_NAS_DEBUG +ID = LEGACY_NAS_TRACE + +ID = LEGACY_HW_INFO +ID = LEGACY_HW_ERROR +ID = LEGACY_HW_WARNING +ID = LEGACY_HW_DEBUG +ID = LEGACY_HW_TRACE + +ID = LEGACY_EMU_INFO +ID = LEGACY_EMU_ERROR +ID = LEGACY_EMU_WARNING +ID = LEGACY_EMU_DEBUG +ID = LEGACY_EMU_TRACE + +ID = LEGACY_OTG_INFO +ID = LEGACY_OTG_ERROR +ID = LEGACY_OTG_WARNING +ID = LEGACY_OTG_DEBUG +ID = LEGACY_OTG_TRACE + +ID = LEGACY_OCG_INFO +ID = LEGACY_OCG_ERROR +ID = LEGACY_OCG_WARNING +ID = LEGACY_OCG_DEBUG +ID = LEGACY_OCG_TRACE + +ID = LEGACY_OMG_INFO +ID = LEGACY_OMG_ERROR +ID = LEGACY_OMG_WARNING +ID = LEGACY_OMG_DEBUG +ID = LEGACY_OMG_TRACE + +ID = LEGACY_OPT_INFO +ID = LEGACY_OPT_ERROR +ID = LEGACY_OPT_WARNING +ID = LEGACY_OPT_DEBUG +ID = LEGACY_OPT_TRACE + +ID = LEGACY_GTPU_INFO +ID = LEGACY_GTPU_ERROR +ID = LEGACY_GTPU_WARNING +ID = LEGACY_GTPU_DEBUG +ID = LEGACY_GTPU_TRACE + +ID = LEGACY_TMR_INFO +ID = LEGACY_TMR_ERROR +ID = LEGACY_TMR_WARNING +ID = LEGACY_TMR_DEBUG +ID = LEGACY_TMR_TRACE + +ID = LEGACY_OSA_INFO +ID = LEGACY_OSA_ERROR +ID = LEGACY_OSA_WARNING +ID = LEGACY_OSA_DEBUG +ID = LEGACY_OSA_TRACE + +# this is a bad hack but I won't fix (function util_print_hex_octets +# in openairinterface5g/openair2/LAYER2/PDCP_v10.1.0/pdcp_util.c +# does funky things with the LOG_x macros but we work on the C pre-processor +# level and this funkyness is not easily dealable with, so be it...) +ID = LEGACY_component_INFO +ID = LEGACY_component_ERROR +ID = LEGACY_component_WARNING +ID = LEGACY_component_DEBUG +ID = LEGACY_component_TRACE +ID = LEGACY_componentP_INFO +ID = LEGACY_componentP_ERROR +ID = LEGACY_componentP_WARNING +ID = LEGACY_componentP_DEBUG +ID = LEGACY_componentP_TRACE + +#needed? +ID = LEGACY_CLI_INFO +ID = LEGACY_CLI_ERROR +ID = LEGACY_CLI_WARNING +ID = LEGACY_CLI_DEBUG +ID = LEGACY_CLI_TRACE + +ID = first diff --git a/generate_Txx.c b/generate_Txx.c new file mode 100644 index 0000000000..6e803aac50 --- /dev/null +++ b/generate_Txx.c @@ -0,0 +1,25 @@ +#include + +void print(int n) +{ + int i; + printf("#define T%d(t", n); + for(i=0; i<(n-3)/2; i++) printf(",t%d,x%d", i, i); + printf(") \\\n"); + printf(" do { \\\n"); + printf(" if (T_ACTIVE(t)) { \\\n"); + printf(" T_LOCAL_DATA \\\n"); + printf(" T_HEADER(t); \\\n"); + for(i=0; i<(n-3)/2; i++) printf(" T_PUT_##t%d(%d, x%d); \\\n", i, i+2, i); + printf(" T_SEND(); \\\n"); + printf(" } \\\n"); + printf(" } while (0)\n"); + printf("\n"); +} + +int main(void) +{ + int i; + for (i = 11; i <= 33; i+=2) print(i); + return 0; +} diff --git a/genids.c b/genids.c new file mode 100644 index 0000000000..47383eccf3 --- /dev/null +++ b/genids.c @@ -0,0 +1,150 @@ +#include +#include +#include +#include +#include + +char **unique_ids; +int unique_ids_size; +int unique_ids_maxsize; + +int cmp(const void *p1, const void *p2) +{ + return strcmp(*(char * const *)p1, *(char * const *)p2); +} + +/* return 1 if s was not already known, 0 if it was */ +int new_unique_id(char *s) +{ + if (unique_ids_size) + if (bsearch(&s, unique_ids, unique_ids_size, sizeof(char *), cmp) != NULL) { + printf("FATAL: ID %s is not unique\n", s); + return 0; + } + if (unique_ids_size == unique_ids_maxsize) { + unique_ids_maxsize += 256; + unique_ids = realloc(unique_ids, unique_ids_maxsize * sizeof(char *)); + if (unique_ids == NULL) { printf("out of memory\n"); abort(); } + } + unique_ids[unique_ids_size] = strdup(s); + if (unique_ids[unique_ids_size] == NULL) + { printf("out of memory\n"); abort(); } + unique_ids_size++; + qsort(unique_ids, unique_ids_size, sizeof(char *), cmp); + return 1; +} + +char *bufname; +int bufname_size; +int bufname_maxsize; + +void putname(int c) +{ + if (bufname_size == bufname_maxsize) { + bufname_maxsize += 256; + bufname = realloc(bufname, bufname_maxsize); + if (bufname == NULL) { printf("memory allocation error\n"); exit(1); } + } + bufname[bufname_size] = c; + bufname_size++; +} + +char *bufvalue; +int bufvalue_size; +int bufvalue_maxsize; + +void putvalue(int c) +{ + if (bufvalue_size == bufvalue_maxsize) { + bufvalue_maxsize += 256; + bufvalue = realloc(bufvalue, bufvalue_maxsize); + if (bufvalue == NULL) { printf("memory allocation error\n"); exit(1); } + } + bufvalue[bufvalue_size] = c; + bufvalue_size++; +} + +void smash_spaces(FILE *f) +{ + int c; + while (1) { + c = fgetc(f); + if (isspace(c)) continue; + if (c == ' ') continue; + if (c == '\t') continue; + if (c == '\n') continue; + if (c == 10 || c == 13) continue; + if (c == '#') { + while (1) { + c = fgetc(f); + if (c == '\n' || c == EOF) break; + } + continue; + } + break; + } + if (c != EOF) ungetc(c, f); +} + +void get_line(FILE *f, char **name, char **value) +{ + int c; + bufname_size = 0; + bufvalue_size = 0; + *name = NULL; + *value = NULL; + smash_spaces(f); + c = fgetc(f); + while (!(c == '=' || isspace(c) || c == EOF)) { putname(c); c = fgetc(f); } + if (c == EOF) return; + putname(0); + while (!(c == EOF || c == '=')) c = fgetc(f); + if (c == EOF) return; + smash_spaces(f); + c = fgetc(f); + while (!(c == 10 || c == 13 || c == EOF)) { putvalue(c); c = fgetc(f); } + putvalue(0); + if (bufname_size <= 1) return; + if (bufvalue_size <= 1) return; + *name = bufname; + *value = bufvalue; +} + +int main(int n, char **v) +{ + FILE *in; + FILE *out; + char *name; + char *value; + char *in_name; + char *out_name; + + if (n != 3) { printf("gimme \n"); exit(1); } + + n = 0; + + in_name = v[1]; + out_name = v[2]; + + in = fopen(in_name, "r"); if (in == NULL) { perror(in_name); exit(1); } + out = fopen(out_name, "w"); if (out == NULL) { perror(out_name); exit(1); } + + fprintf(out, "/* generated file, do not edit by hand */\n\n"); + + while (1) { + get_line(in, &name, &value); + if (name == NULL) break; + printf("name '%s' value '%s'\n", name, value); + if (!strcmp(name, "ID")) { + if (!new_unique_id(value)) { unlink(out_name); exit(1); } + fprintf(out, "#define T_%s T_ID(%d)\n", value, n); + n++; + } + } + fprintf(out, "#define T_NUMBER_OF_IDS %d\n", n); + + fclose(in); + fclose(out); + + return 0; +} diff --git a/main.c b/main.c new file mode 100644 index 0000000000..50b1d9339c --- /dev/null +++ b/main.c @@ -0,0 +1,19 @@ +#include "T.h" +#include +#include +#include +#include +#include + +int main(void) +{ + T_connect_to_tracer("127.0.0.1", 2020); + printf("after connect\n"); + while (1) { + T(T_first, T_PRINTF("hello world %s!\n", "yo")); + //usleep(1); + } + while (1) pause(); + + return 0; +} diff --git a/tracer/Makefile b/tracer/Makefile new file mode 100644 index 0000000000..156700812e --- /dev/null +++ b/tracer/Makefile @@ -0,0 +1,20 @@ +CC=gcc +CFLAGS=-Wall -g -O3 + +#comment those two lines to NOT use shared memory +CFLAGS += -DT_USE_SHARED_MEMORY +LIBS += -lrt + +PROG=tracer +OBJS=main.o + +$(PROG): $(OBJS) + $(CC) $(CFLAGS) -o $(PROG) $(OBJS) $(LIBS) + +%.o: %.c + $(CC) $(CFLAGS) -c -o $@ $< + +main.o: ../T_IDs.h ../T_defs.h + +clean: + rm -f *.o $(PROG) core diff --git a/tracer/main.c b/tracer/main.c new file mode 100644 index 0000000000..fa19a6237b --- /dev/null +++ b/tracer/main.c @@ -0,0 +1,254 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define T_ID(x) x +#include "../T_IDs.h" +#include "../T_defs.h" + +#ifdef T_USE_SHARED_MEMORY + +T_cache_t *T_cache; +int T_busylist_head; +int T_pos; + +static inline int GET(int s, void *out, int count) +{ + if (count == 1) { + *(char *)out = T_cache[T_busylist_head].buffer[T_pos]; + T_pos++; + return 1; + } + memcpy(out, T_cache[T_busylist_head].buffer + T_pos, count); + T_pos += count; + return count; +} + +#else /* T_USE_SHARED_MEMORY */ + +#define GET read + +#endif /* T_USE_SHARED_MEMORY */ + +int get_connection(char *addr, int port) +{ + struct sockaddr_in a; + socklen_t alen; + int s, t; + + s = socket(AF_INET, SOCK_STREAM, 0); + if (s == -1) { perror("socket"); exit(1); } + t = 1; + if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &t, sizeof(int))) + { perror("setsockopt"); exit(1); } + + a.sin_family = AF_INET; + a.sin_port = htons(port); + a.sin_addr.s_addr = inet_addr(addr); + + if (bind(s, (struct sockaddr *)&a, sizeof(a))) { perror("bind"); exit(1); } + if (listen(s, 5)) { perror("bind"); exit(1); } + alen = sizeof(a); + t = accept(s, (struct sockaddr *)&a, &alen); + if (t == -1) { perror("accept"); exit(1); } + close(s); + return t; +} + +void get_string(int s, char *out) +{ + while (1) { + if (GET(s, out, 1) != 1) abort(); + if (*out == 0) break; + out++; + } +} + +void get_message(int s) +{ +#define S(x, y) do { \ + char str[1024]; \ + get_string(s, str); \ + printf("["x"]["y"] %s", str); \ + } while (0) + + int m; +#ifdef T_USE_SHARED_MEMORY + T_pos = 0; +#endif + if (GET(s, &m, sizeof(int)) != sizeof(int)) abort(); + switch (m) { + case T_first: { + char str[1024]; + get_string(s, str); + printf("%s", str); + break; + } + case T_LEGACY_MAC_INFO: S("MAC", "INFO"); break; + case T_LEGACY_MAC_ERROR: S("MAC", "ERROR"); break; + case T_LEGACY_MAC_WARNING: S("MAC", "WARNING"); break; + case T_LEGACY_MAC_DEBUG: S("MAC", "DEBUG"); break; + case T_LEGACY_MAC_TRACE: S("MAC", "TRACE"); break; + case T_LEGACY_PHY_INFO: S("PHY", "INFO"); break; + case T_LEGACY_PHY_ERROR: S("PHY", "ERROR"); break; + case T_LEGACY_PHY_WARNING: S("PHY", "WARNING"); break; + case T_LEGACY_PHY_DEBUG: S("PHY", "DEBUG"); break; + case T_LEGACY_PHY_TRACE: S("PHY", "TRACE"); break; + case T_LEGACY_S1AP_INFO: S("S1AP", "INFO"); break; + case T_LEGACY_S1AP_ERROR: S("S1AP", "ERROR"); break; + case T_LEGACY_S1AP_WARNING: S("S1AP", "WARNING"); break; + case T_LEGACY_S1AP_DEBUG: S("S1AP", "DEBUG"); break; + case T_LEGACY_S1AP_TRACE: S("S1AP", "TRACE"); break; + case T_LEGACY_RRC_INFO: S("RRC", "INFO"); break; + case T_LEGACY_RRC_ERROR: S("RRC", "ERROR"); break; + case T_LEGACY_RRC_WARNING: S("RRC", "WARNING"); break; + case T_LEGACY_RRC_DEBUG: S("RRC", "DEBUG"); break; + case T_LEGACY_RRC_TRACE: S("RRC", "TRACE"); break; + case T_LEGACY_RLC_INFO: S("RLC", "INFO"); break; + case T_LEGACY_RLC_ERROR: S("RLC", "ERROR"); break; + case T_LEGACY_RLC_WARNING: S("RLC", "WARNING"); break; + case T_LEGACY_RLC_DEBUG: S("RLC", "DEBUG"); break; + case T_LEGACY_RLC_TRACE: S("RLC", "TRACE"); break; + case T_LEGACY_PDCP_INFO: S("PDCP", "INFO"); break; + case T_LEGACY_PDCP_ERROR: S("PDCP", "ERROR"); break; + case T_LEGACY_PDCP_WARNING: S("PDCP", "WARNING"); break; + case T_LEGACY_PDCP_DEBUG: S("PDCP", "DEBUG"); break; + case T_LEGACY_PDCP_TRACE: S("PDCP", "TRACE"); break; + case T_LEGACY_ENB_APP_INFO: S("ENB_APP", "INFO"); break; + case T_LEGACY_ENB_APP_ERROR: S("ENB_APP", "ERROR"); break; + case T_LEGACY_ENB_APP_WARNING: S("ENB_APP", "WARNING"); break; + case T_LEGACY_ENB_APP_DEBUG: S("ENB_APP", "DEBUG"); break; + case T_LEGACY_ENB_APP_TRACE: S("ENB_APP", "TRACE"); break; + case T_LEGACY_SCTP_INFO: S("SCTP", "INFO"); break; + case T_LEGACY_SCTP_ERROR: S("SCTP", "ERROR"); break; + case T_LEGACY_SCTP_WARNING: S("SCTP", "WARNING"); break; + case T_LEGACY_SCTP_DEBUG: S("SCTP", "DEBUG"); break; + case T_LEGACY_SCTP_TRACE: S("SCTP", "TRACE"); break; + case T_LEGACY_UDP__INFO: S("UDP", "INFO"); break; + case T_LEGACY_UDP__ERROR: S("UDP", "ERROR"); break; + case T_LEGACY_UDP__WARNING: S("UDP", "WARNING"); break; + case T_LEGACY_UDP__DEBUG: S("UDP", "DEBUG"); break; + case T_LEGACY_UDP__TRACE: S("UDP", "TRACE"); break; + case T_LEGACY_NAS_INFO: S("NAS", "INFO"); break; + case T_LEGACY_NAS_ERROR: S("NAS", "ERROR"); break; + case T_LEGACY_NAS_WARNING: S("NAS", "WARNING"); break; + case T_LEGACY_NAS_DEBUG: S("NAS", "DEBUG"); break; + case T_LEGACY_NAS_TRACE: S("NAS", "TRACE"); break; + case T_LEGACY_HW_INFO: S("HW", "INFO"); break; + case T_LEGACY_HW_ERROR: S("HW", "ERROR"); break; + case T_LEGACY_HW_WARNING: S("HW", "WARNING"); break; + case T_LEGACY_HW_DEBUG: S("HW", "DEBUG"); break; + case T_LEGACY_HW_TRACE: S("HW", "TRACE"); break; + case T_LEGACY_EMU_INFO: S("EMU", "INFO"); break; + case T_LEGACY_EMU_ERROR: S("EMU", "ERROR"); break; + case T_LEGACY_EMU_WARNING: S("EMU", "WARNING"); break; + case T_LEGACY_EMU_DEBUG: S("EMU", "DEBUG"); break; + case T_LEGACY_EMU_TRACE: S("EMU", "TRACE"); break; + case T_LEGACY_OTG_INFO: S("OTG", "INFO"); break; + case T_LEGACY_OTG_ERROR: S("OTG", "ERROR"); break; + case T_LEGACY_OTG_WARNING: S("OTG", "WARNING"); break; + case T_LEGACY_OTG_DEBUG: S("OTG", "DEBUG"); break; + case T_LEGACY_OTG_TRACE: S("OTG", "TRACE"); break; + case T_LEGACY_OCG_INFO: S("OCG", "INFO"); break; + case T_LEGACY_OCG_ERROR: S("OCG", "ERROR"); break; + case T_LEGACY_OCG_WARNING: S("OCG", "WARNING"); break; + case T_LEGACY_OCG_DEBUG: S("OCG", "DEBUG"); break; + case T_LEGACY_OCG_TRACE: S("OCG", "TRACE"); break; + case T_LEGACY_OMG_INFO: S("OMG", "INFO"); break; + case T_LEGACY_OMG_ERROR: S("OMG", "ERROR"); break; + case T_LEGACY_OMG_WARNING: S("OMG", "WARNING"); break; + case T_LEGACY_OMG_DEBUG: S("OMG", "DEBUG"); break; + case T_LEGACY_OMG_TRACE: S("OMG", "TRACE"); break; + case T_LEGACY_GTPU_INFO: S("GTPU", "INFO"); break; + case T_LEGACY_GTPU_ERROR: S("GTPU", "ERROR"); break; + case T_LEGACY_GTPU_WARNING: S("GTPU", "WARNING"); break; + case T_LEGACY_GTPU_DEBUG: S("GTPU", "DEBUG"); break; + case T_LEGACY_GTPU_TRACE: S("GTPU", "TRACE"); break; + case T_LEGACY_TMR_INFO: S("TMR", "INFO"); break; + case T_LEGACY_TMR_ERROR: S("TMR", "ERROR"); break; + case T_LEGACY_TMR_WARNING: S("TMR", "WARNING"); break; + case T_LEGACY_TMR_DEBUG: S("TMR", "DEBUG"); break; + case T_LEGACY_TMR_TRACE: S("TMR", "TRACE"); break; + case T_LEGACY_OSA_INFO: S("OSA", "INFO"); break; + case T_LEGACY_OSA_ERROR: S("OSA", "ERROR"); break; + case T_LEGACY_OSA_WARNING: S("OSA", "WARNING"); break; + case T_LEGACY_OSA_DEBUG: S("OSA", "DEBUG"); break; + case T_LEGACY_OSA_TRACE: S("OSA", "TRACE"); break; + case T_LEGACY_component_INFO: S("XXX", "INFO"); break; + case T_LEGACY_component_ERROR: S("XXX", "ERROR"); break; + case T_LEGACY_component_WARNING: S("XXX", "WARNING"); break; + case T_LEGACY_component_DEBUG: S("XXX", "DEBUG"); break; + case T_LEGACY_component_TRACE: S("XXX", "TRACE"); break; + case T_LEGACY_componentP_INFO: S("XXX", "INFO"); break; + case T_LEGACY_componentP_ERROR: S("XXX", "ERROR"); break; + case T_LEGACY_componentP_WARNING: S("XXX", "WARNING"); break; + case T_LEGACY_componentP_DEBUG: S("XXX", "DEBUG"); break; + case T_LEGACY_componentP_TRACE: S("XXX", "TRACE"); break; + case T_LEGACY_CLI_INFO: S("CLI", "INFO"); break; + case T_LEGACY_CLI_ERROR: S("CLI", "ERROR"); break; + case T_LEGACY_CLI_WARNING: S("CLI", "WARNING"); break; + case T_LEGACY_CLI_DEBUG: S("CLI", "DEBUG"); break; + case T_LEGACY_CLI_TRACE: S("CLI", "TRACE"); break; + default: printf("unkown message type %d\n", m); abort(); + } + +#ifdef T_USE_SHARED_MEMORY + T_cache[T_busylist_head].busy = 0; + T_busylist_head++; + T_busylist_head &= T_CACHE_SIZE - 1; +#endif +} + +#ifdef T_USE_SHARED_MEMORY + +void wait_message(void) +{ + while (T_cache[T_busylist_head].busy == 0) usleep(1000); +} + +void init_shm(void) +{ + int s = shm_open(T_SHM_FILENAME, O_RDWR | O_CREAT, 0666); + if (s == -1) { perror(T_SHM_FILENAME); abort(); } + if (ftruncate(s, T_CACHE_SIZE * sizeof(T_cache_t))) + { perror(T_SHM_FILENAME); abort(); } + T_cache = mmap(NULL, T_CACHE_SIZE * sizeof(T_cache_t), + PROT_READ | PROT_WRITE, MAP_SHARED, s, 0); + if (T_cache == NULL) + { perror(T_SHM_FILENAME); abort(); } + close(s); +} + +#endif /* T_USE_SHARED_MEMORY */ + +int main(void) +{ + int s; + int l; + char t; +#ifdef T_USE_SHARED_MEMORY + init_shm(); +#endif + s = get_connection("127.0.0.1", 2020); + /* send the first message - activate all traces */ + t = 0; + if (write(s, &t, 1) != 1) abort(); + l = T_NUMBER_OF_IDS; + if (write(s, &l, sizeof(int)) != sizeof(int)) abort(); + for (l = 0; l < T_NUMBER_OF_IDS; l++) + if (write(s, &l, sizeof(int)) != sizeof(int)) abort(); + /* read messages */ + while (1) { +#ifdef T_USE_SHARED_MEMORY + wait_message(); +#endif + get_message(s); + } + return 0; +}