T.c 3.53 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 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 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
#include "T.h"
#include <string.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>

/* 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);
    __sync_synchronize();
    while (T_cache[T_busylist_head].busy) {
      char *b;
      int l;
      /* TODO: be sure about those memory barriers - in doubt one is
       * put here too
       */
      __sync_synchronize();
      b = T_cache[T_busylist_head].buffer;
      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 /*| O_SYNC*/, 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);
}