示例#1
0
int spsc_trypush_slot_pass() {
  cqueue_spsc *q;
  int i;
  char data;
  char *p;

  q  = cqueue_spsc_new(26, sizeof(char));
  assert(q);

  // insert dummy data for testing
  for(i=0, data='A'; i < 26; i++, data++) {
    p = cqueue_spsc_trypush_slot(q);
    assert(p);
    *p = data;
    cqueue_spsc_push_slot_finish(q);
  }

  // check index, used flag, and data
  assert(q->push_idx == 26);
  void *offset = (char *)(q->array + 12*q->elem_size);
  size_t used = *(size_t *)offset;
  assert(used == 1);
  char *c = (char *)offset + sizeof(size_t);
  assert(*c == 'M');

  return 1;
}
示例#2
0
int spsc_trypop_slot_pass() {
  cqueue_spsc *q;
  int i;
  char data;
  char *p;

  q  = cqueue_spsc_new(26, sizeof(char));
  assert(q);

  // insert dummy data for testing
  for(i=0, data='A'; i < 26; i++, data++) {
    p = cqueue_spsc_trypush_slot(q);
    assert(p);
    *p = data;
    cqueue_spsc_push_slot_finish(q);
  }

  // pop some data so we're not at the start
  for(i=0; i < 13; i++) {
    p = cqueue_spsc_trypop_slot(q);
    assert(p);
    cqueue_spsc_pop_slot_finish(q);
  }

  // check index, used flag, and data
  assert(q->pop_idx == 13);
  void *offset = (char *)(q->array + 12*q->elem_size);
  size_t used = *(size_t *)offset;
  assert(used == 0);
  assert(*p == 'M');

  return 1;
}
示例#3
0
int spsc_new_fail() {
  cqueue_spsc *q;

  // fail on capacity
  q = cqueue_spsc_new(SIZE_MAX/2 + 2, sizeof(int));
  assert(!q);

  // fail on elem_size
  q = cqueue_spsc_new(32, 0);
  assert(!q);

  // fail on memory allocation
  q = cqueue_spsc_new(1, SIZE_MAX-sizeof(_Atomic size_t)-LEVEL1_DCACHE_LINESIZE);
  assert(!q);

  // fail on overflow of capacity * elem_size
  q = cqueue_spsc_new(SIZE_MAX/LEVEL1_DCACHE_LINESIZE, sizeof(int));
  assert(!q);

  return 1;
}
示例#4
0
int spsc_new_pass() {
  cqueue_spsc *q;
  ptrdiff_t d;

  q  = cqueue_spsc_new(26, LEVEL1_DCACHE_LINESIZE-sizeof(size_t));

  assert(q);
  assert(q->capacity == 32);  // round up to power of 2
  assert(q->elem_size == LEVEL1_DCACHE_LINESIZE);  // round up to cacheline

  // check initialization
  assert(q->push_idx == 0);
  assert(q->pop_idx == 0);
  for(size_t i=0; i < q->capacity; i++) {
    size_t used = *(size_t *)(q->array + i*q->elem_size);
    assert(used == 0);
  }

  // check struct layout
  d = ((char *)(void *)q - (char *)(void *)&q->capacity);
  assert(d == 0); // capacity is the first member

  d = (char *)(void *)&q->push_idx - (char*)(void *)&q->capacity;
  assert(d == LEVEL1_DCACHE_LINESIZE);  // should be 1 cacheline due to padding

  d = (char *)(void *)&q->pop_idx - (char *)(void *)&q->push_idx;
  assert(d == LEVEL1_DCACHE_LINESIZE); // should be 1 cacheline due to padding

  // check deletion
  cqueue_spsc_delete(&q);
  assert(!q);

  // check elem_size padding rounding up
  q  = cqueue_spsc_new(26, LEVEL1_DCACHE_LINESIZE-sizeof(size_t)+1);
  assert(q);
  assert(q->elem_size == 2*LEVEL1_DCACHE_LINESIZE);  // round up to 2 cachelines

  return 1;
}
示例#5
0
/*!
  Warning: this function relies on internal knowledge of cqueue_spsc
  to optimize num_actions
*/
tqueue *tqueue_new(size_t num_transactions, size_t num_actions) {
  tqueue *q;
  transaction *t;

  size_t transaction_size;

  if (!num_transactions)
    return NULL;

  if (!num_actions)
    return NULL;

  // check overflow
  if (num_actions > (SIZE_MAX - sizeof(transaction)) / sizeof (void *))
    return NULL;
  transaction_size = sizeof(transaction) + num_actions * sizeof(void *);

  q = malloc(sizeof(tqueue));
  if (!q)
    return NULL;

  q->transactions = cqueue_spsc_new(num_transactions, transaction_size);
  if (!q->transactions) {
    free(q);
    return NULL;
  }

  q->num_transactions = num_transactions;
  q->num_actions = (q->transactions->elem_size - sizeof(_Atomic size_t) 
                    - sizeof(transaction)) / sizeof(void *);

  // initialize the transactions
  while ((t = cqueue_spsc_trypush_slot(q->transactions)) != NULL) {
    t->write_idx = 0;
    t->read_idx = 0;
    cqueue_spsc_push_slot_finish(q->transactions);
  }

  while ((t = cqueue_spsc_trypop_slot(q->transactions)) != NULL) {
    cqueue_spsc_pop_slot_finish(q->transactions);
  }

  return q;
}
示例#6
0
/*! allocate and initialize queues, etc
  \param[in, out] context
  \returns 1 on success, 0 on failure
*/
int arpd_init(struct thread_context *context) {
  struct arpd_data *data;
  int rv;

  assert(context);
  data = context->data;

  context->msg_q = squeue_new(data->msg_q_capacity, data->msg_q_elem_size);
  if (!context->msg_q)
    return 0;

  context->pkt_xmit_q = cqueue_spsc_new(data->xmit_q_capacity,
                                        data->xmit_q_elem_size);
  if (!context->pkt_xmit_q) {
    squeue_delete(&context->msg_q);
    return 0;
  }

  rv = xmit_queue_init(context->pkt_xmit_q, &context->shared->inet_info->addr,
                        &context->shared->if_info->mac);
  if (!rv) {
    squeue_delete(&context->msg_q);
    return 0;
  }

  context->pkt_recv_q = tqueue_new(data->recv_q_transactions,
                                    data->recv_q_actions_per_transaction);
  if (!context->pkt_recv_q) {
    squeue_delete(&context->msg_q);
    cqueue_spsc_delete(&context->pkt_xmit_q);
    return 0;
  }

  data->arp_cache = arp_cache_new(context);
  if (!data->arp_cache) {
    squeue_delete(&context->msg_q);
    cqueue_spsc_delete(&context->pkt_xmit_q);
    tqueue_delete(&context->pkt_recv_q);
    return 0;
  }

  return 1;
}