T.c 5.18 KB
Newer Older
1 2 3 4 5 6 7 8 9
#include "T.h"
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
Cedric Roux's avatar
Cedric Roux committed
10
#include <sys/socket.h>
11

12 13
#include "common/config/config_userapi.h"

14
#define QUIT(x) do { \
15 16 17
    printf("T tracer: QUIT: %s\n", x); \
    exit(1); \
  } while (0)
18

19 20 21
/* array used to activate/disactivate a log */
static int T_IDs[T_NUMBER_OF_IDS];
int *T_active = T_IDs;
22

Cedric Roux's avatar
Cedric Roux committed
23
int T_stdout = 1;
24

25

26 27 28 29 30 31 32 33
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;
34
T_cache_t *T_cache;
35

Cedric Roux's avatar
Cedric Roux committed
36
#if BASIC_SIMULATOR
37 38 39
  /* global variables used by T_GET_SLOT, see in T.h */
  volatile uint64_t T_next_id;
  volatile uint64_t T_active_id;
Cedric Roux's avatar
Cedric Roux committed
40 41
#endif

42
static void get_message(int s) {
43 44 45
  char t;
  int l;
  int id;
Cedric Roux's avatar
Cedric Roux committed
46
  int is_on;
47

48
  if (read(s, &t, 1) != 1) QUIT("get_message fails");
49 50 51

  printf("T tracer: got mess %d\n", t);

52
  switch (t) {
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
    case 0:

      /* toggle all those IDs */
      /* optimze? (too much syscalls) */
      if (read(s, &l, sizeof(int)) != sizeof(int)) QUIT("get_message fails");

      while (l) {
        if (read(s, &id, sizeof(int)) != sizeof(int)) QUIT("get_message fails");

        T_IDs[id] = 1 - T_IDs[id];
        l--;
      }

      break;

    case 1:

      /* set IDs as given */
      /* optimize? */
      if (read(s, &l, sizeof(int)) != sizeof(int)) QUIT("get_message fails");

      id = 0;

      while (l) {
        if (read(s, &is_on, sizeof(int)) != sizeof(int))
          QUIT("get_message fails");

        T_IDs[id] = is_on;
        id++;
        l--;
      }

      break;

    case 2:
      break; /* do nothing, this message is to wait for local tracer */
89 90 91
  }
}

92
static void *T_receive_thread(void *_) {
93
  while (1) get_message(T_socket);
94

95 96 97
  return NULL;
}

98
static void new_thread(void *(*f)(void *), void *data) {
99 100 101
  pthread_t t;
  pthread_attr_t att;

102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
  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);
  }
121 122
}

Cedric Roux's avatar
Cedric Roux committed
123 124
/* defined in local_tracer.c */
void T_local_tracer_main(int remote_port, int wait_for_tracer,
125
                         int local_socket, void *shm_array);
Cedric Roux's avatar
Cedric Roux committed
126

127 128 129 130 131
/* We monitor the tracee and the local tracer processes.
 * When one dies we forcefully kill the other.
 */
#include <sys/types.h>
#include <sys/wait.h>
132
static void monitor_and_kill(int child1, int child2) {
133 134 135
  int child;
  int status;
  child = wait(&status);
136

137
  if (child == -1) perror("wait");
138

139 140 141 142 143
  kill(child1, SIGKILL);
  kill(child2, SIGKILL);
  exit(0);
}

144
void T_init(int remote_port, int wait_for_tracer, int dont_fork) {
Cedric Roux's avatar
Cedric Roux committed
145
  int socket_pair[2];
146
  int s;
147
  int child1, child2;
Cedric Roux's avatar
Cedric Roux committed
148
  int i;
149

150 151 152 153
  if (socketpair(AF_UNIX, SOCK_STREAM, 0, socket_pair)) {
    perror("socketpair");
    abort();
  }
154

Cedric Roux's avatar
Cedric Roux committed
155 156 157
  /* setup shared memory */
  T_cache = mmap(NULL, T_CACHE_SIZE * sizeof(T_cache_t),
                 PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
158 159 160 161 162

  if (T_cache == MAP_FAILED) {
    perror("mmap");
    abort();
  }
Cedric Roux's avatar
Cedric Roux committed
163 164 165 166 167

  /* let's garbage the memory to catch some potential problems
   * (think multiprocessor sync issues, barriers, etc.)
   */
  memset(T_cache, 0x55, T_CACHE_SIZE * sizeof(T_cache_t));
168

Cedric Roux's avatar
Cedric Roux committed
169 170
  for (i = 0; i < T_CACHE_SIZE; i++) T_cache[i].busy = 0;

171
  /* child1 runs the local tracer and child2 (or main) runs the tracee */
172 173 174
  child1 = fork();

  if (child1 == -1) abort();
175 176

  if (child1 == 0) {
Cedric Roux's avatar
Cedric Roux committed
177
    close(socket_pair[1]);
Cedric Roux's avatar
Cedric Roux committed
178
    T_local_tracer_main(remote_port, wait_for_tracer, socket_pair[0],
Cedric Roux's avatar
Cedric Roux committed
179
                        T_cache);
Cedric Roux's avatar
Cedric Roux committed
180
    exit(0);
181
  }
182

Cedric Roux's avatar
Cedric Roux committed
183
  close(socket_pair[0]);
184

185
  if (dont_fork == 0) {
186 187 188 189
    child2 = fork();

    if (child2 == -1) abort();

190 191
    if (child2 != 0) {
      close(socket_pair[1]);
Cedric Roux's avatar
Cedric Roux committed
192
      munmap(T_cache, T_CACHE_SIZE * sizeof(T_cache_t));
193 194
      monitor_and_kill(child1, child2);
    }
195 196
  }

Cedric Roux's avatar
Cedric Roux committed
197
  s = socket_pair[1];
198 199 200 201 202
  /* wait for first message - initial list of active T events */
  get_message(s);
  T_socket = s;
  new_thread(T_receive_thread, NULL);
}
203

204
void T_Config_Init(void) {
205 206 207
  int T_port=TTRACER_DEFAULT_PORTNUM; /* by default we wait for the tracer */
  int T_nowait=0;                     /* default port to listen to to wait for the tracer */
  int T_dont_fork=0;                  /* default is to fork, see 'T_init' to understand */
Cedric Roux's avatar
Cedric Roux committed
208 209 210 211 212 213 214 215 216 217 218
  paramdef_t ttraceparams[] = CMDLINE_TTRACEPARAMS_DESC;
  /* for a cleaner config file, TTracer params should be defined in a
   * specific section...
   */
  config_get(ttraceparams,
             sizeof(ttraceparams) / sizeof(paramdef_t),
             TTRACER_CONFIG_PREFIX);
  /* compatibility: look for TTracer command line options in root section */
  config_process_cmdline(ttraceparams,
                         sizeof(ttraceparams) / sizeof(paramdef_t),
                         NULL);
219

Cedric Roux's avatar
Cedric Roux committed
220
  if (T_stdout == 0)
221 222
    T_init(T_port, 1-T_nowait, T_dont_fork);
}