예제 #1
0
파일: test.c 프로젝트: winksaville/sadie
void TestComp_deinit(AcCompMgr* cm) {
  ac_debug_printf(LDR ":+cm=%p comp=%s\n", ldr, cm, test_comp.comp.name);

  AcReceptor_ret(test_comp.waiting);
  AcCompMgr_rmv_comp((AcComp*)&test_comp);

  ac_debug_printf(LDR ":-cm=%p comp=%s\n", ldr, cm, test_comp.comp.name);
}
예제 #2
0
파일: test.c 프로젝트: winksaville/sadie
/**
 * Test dispatching a message
 *
 * return AC_TRUE if an error.
 */
/*static*/ ac_bool test_dispatching() {
  ac_bool error = AC_FALSE;
  AcStatus status;
  ac_debug_printf("test_dispatching:+\n");

  // Get a dispatcher
  AcDispatcher* pd = AcDispatcher_get(1);
  error |= AC_TEST(pd != AC_NULL);

  Ac1Comp ac1 = {
    .comp = { .name=(ac_u8*)"ac1", .process_msg = &ac1_process_msg },
    .msg_count = 0,
    .ac_init_cmd_count = 0,
    .ac_deinit_cmd_count = 0,
    .error = 0
  };

  // Add an acq
  AcDispatchableComp* dc1;

  dc1 = AcDispatcher_add_comp(pd, &ac1.comp);
  error |= AC_TEST(dc1 != AC_NULL);

  // Initialize a msg pool
  AcMsgPool mp;
  status = AcMsgPool_init(&mp, 2, 0);
  error |= AC_TEST(status == AC_STATUS_OK);

  // Get a msg and dispatch it
  AcMsg* msg1;
  msg1 = AcMsgPool_get_msg(&mp);
  error |= AC_TEST(msg1 != AC_NULL);
  msg1->op = 1;
  AcDispatcher_send_msg(dc1, msg1);

  ac_debug_printf("test_dispatching: dispatch now\n");
  ac_bool processed_msgs = AcDispatcher_dispatch(pd);
  ac_debug_printf("test_dispatching: dispatch complete\n");
  error |= AC_TEST(processed_msgs == AC_TRUE);

  // Get a second message and dispatch it
  AcMsg* msg2;
  msg2 = AcMsgPool_get_msg(&mp);
  error |= AC_TEST(msg2 != AC_NULL);
  msg2->op = 1;
  AcDispatcher_send_msg(dc1, msg2);

  ac_debug_printf("test_dispatching: rmv_ac\n");
  error |= AC_TEST(AcDispatcher_rmv_comp(pd, &ac1.comp) == AC_STATUS_OK);
  error |= AC_TEST(ac1.error == 0);

  ac_debug_printf("test_dispatching:- error=%d\n", error);
  return error;
}
예제 #3
0
파일: test.c 프로젝트: winksaville/sadie
AcStatus TestComp_init(AcCompMgr* cm) {
  AcStatus status;
  ac_debug_printf(LDR ":+cm=%p comp=%s\n", ldr, cm, test_comp.comp.name);

  test_comp.cm = cm;
  test_comp.target_comp_name = (AcU8*)INET_LINK_COMP_IPV4_NAME;
  test_comp.waiting = AcReceptor_get();
  status = AcCompMgr_add_comp(cm, &test_comp.comp);

  ac_debug_printf(LDR ":-cm=%p comp=%s status=%u\n", ldr, cm, test_comp.comp.name, status);
  return status;
}
예제 #4
0
파일: test.c 프로젝트: winksaville/sadie
void* t1(void *param) {
  struct test_params* params = (struct test_params*)param;
  //ac_printf("t1:+params->loops=%d\n", params->loops);
  for(ac_uint i = 0; i < params->loops; i++) {
    __atomic_add_fetch(&params->counter, 1, __ATOMIC_RELEASE);

    //ac_thread_yield();

#ifdef NDEBUG
    // Wait to be signaled
    AcReceptor_wait(params->receptor);
#else
    if ((i % 1) == 0) {
      ac_printf("t1: i=%d flags=%x isr_counter=%d receptor.thdl=%x",
          i, get_flags(), get_timer_reschedule_isr_counter(), params->receptor->thdl);
      print_ready_list(" - ");
    }

    ac_printf("t1: waiting    thdl=%x flags=%x\n", ac_thread_get_cur_hdl(), get_flags());
    ac_u64 wait_start = ac_tscrd();
    AcReceptor_wait(params->receptor);
    ac_u64 ticks = ac_tscrd() - wait_start;
    ac_printf("t1: continuing wait time=%.9t\n", ticks);
#endif
  }

  ac_debug_printf("t1: signal done_receptor\n");
  AcReceptor_signal(params->done_receptor);
  return AC_NULL;
}
예제 #5
0
파일: test.c 프로젝트: winksaville/sadie
static ac_bool ac1_process_msg(AcComp* ac, AcMsg* msg) {
  Ac1Comp* this = (Ac1Comp*)ac;

  ac_debug_printf("ac1_process_msg:+ msg->arg1=%lx, msg->arg2=%lx\n",
      msg->arg1, msg->arg2);

  ac_debug_printf("ac1_process_msg:+\n");

  if (msg->op == AC_INIT_CMD) {
    ac_debug_printf("ac1_process_msg: AC_INIT_CMD\n");
    this->ac_init_cmd_count += 1;
    this->error |= AC_TEST(this->ac_init_cmd_count == 1);
    this->error |= AC_TEST(this->ac_deinit_cmd_count == 0);
  } else if (msg->op == AC_DEINIT_CMD) {
    ac_debug_printf("ac1_process_msg: AC_DEINIT_CMD\n");
    this->ac_deinit_cmd_count += 1;
    this->error |= AC_TEST(this->ac_init_cmd_count == 1);
    this->error |= AC_TEST(this->ac_deinit_cmd_count == 1);
  } else {
    ac_debug_printf("ac1_process_msg: OTHER msg->arg1=%lx, msg->arg2=%lx\n",
        msg->arg1, msg->arg2);
    this->msg_count += 1;
    this->error |= AC_TEST(msg->op == 1);
  }

  ac_debug_printf("ac1_process_msg: ret msg=%p\n", msg);
  AcMsgPool_ret_msg(msg);

  ac_debug_printf("ac1_process_msg:-error=%d\n", this->error);

  return AC_TRUE;
}
예제 #6
0
파일: test.c 프로젝트: winksaville/sadie
ac_bool work_state(AcComp* comp, AcMsg* msg) {
  TestComp* this = (TestComp*)comp;
  ac_debug_printf(LDR ":+msg->op=%lx\n", ldr, msg->op);

  switch (msg->op) {
    case SEND_ARP_REQ: {
      ac_printf(LDR "SEND_ARP_REQ\n", ldr);

      AcMsg* m = AcMsgPool_get_msg(&this->mp);
      m->op = AC_INET_SEND_ARP_CMD;
      AcInetSendArpExtra* send_arp_extra = (AcInetSendArpExtra*)m->extra;
      send_arp_extra->proto = AC_ETHER_PROTO_IPV4;
      send_arp_extra->proto_addr_len = AC_IPV4_ADDR_LEN;
      send_arp_extra->proto_addr[0] = 10;
      send_arp_extra->proto_addr[1] = 0;
      send_arp_extra->proto_addr[2] = 0;
      send_arp_extra->proto_addr[3] = 2;
      AcCompMgr_send_msg(this->target_comp, m);

      // Delay a 1/4 second to let it complete
      //ac_printf(LDR "SEND_ARP_REQ; waiting\n", ldr);
      ac_thread_wait_ns(250000000);
      //ac_printf(LDR "SEND_ARP_REQ; done waiting\n", ldr);

      AcReceptor_signal(this->waiting);
      break;
    }
    case DONE: {
      ac_printf(LDR "DONE\n", ldr);
      TRANS_TO(this, done_state);
      AcReceptor_signal(this->waiting);
      break;
    }
    default: {
      ac_printf(LDR "unregonized AC_OP=%lx\n", ldr, msg->op);
      TRANS_TO(this, done_state);
      break;
    }
  }

  ac_debug_printf(LDR ":-msg->op=%lx\n", ldr, msg->op);
  AcMsgPool_ret_msg(msg);
  return AC_TRUE;
}
예제 #7
0
/**
 * Allocate count elements each at least size long and each aligned
 * on the alignment value. The value in pRaw is the unaligned pointer
 * and is passed to ac_free. The value in pAligned is the address of
 * the first element.
 *
 * @param count is the number of elements to create
 * @param size is the minimum size of each element created
 * @param alignment is a value to align on, such as AC_MAX_CACHE_LINE_LEN
 * @param pRaw is the address to return the raw pointer passed to ac_free
 * @param pAligned is the address to return the aligned pointer of the frist element
 * @param pElemSize is length of each element which will be a multipel of alignment
 */
AcStatus ac_calloc_align(AcU32 count, AcU32 size, AcU32 alignment,
    void** pRaw, void** pAligned, AcU32* pElemSize) {
  ac_debug_printf("ac_calloc_align:+count=%u size=%u alignment=%u\n"
                  "                 pRaw=%p pAligned=%p pElemSize=%p\n",
                  count, size, alignment, pRaw, pAligned, pElemSize);
  AcStatus status;
  void* raw = AC_NULL;
  void* aligned = AC_NULL;
  AcU32 elem_size = 0;
  AcUptr mask = 0;

  if ((count == 0) | (size == 0) | (AC_COUNT_ONE_BITS(alignment) != 1)
      | (pRaw == AC_NULL) | (pAligned == AC_NULL) | (pElemSize == AC_NULL)) {
    ac_debug_printf("ac_calloc_align: BAD_PARAM\n");
    status = AC_STATUS_BAD_PARAM;
    goto done;
  }

  mask = ~((AcUptr)alignment - 1);
  elem_size = (size + alignment - 1) & mask;
  AcU64 allocation_size = (elem_size * count) + alignment - 1;
  raw = ac_calloc(1, allocation_size);
  if (raw == AC_NULL) {
    ac_debug_printf("ac_calloc_align: OUT_OF_MEMORY\n");
    status = AC_STATUS_OUT_OF_MEMORY;
    goto done;
  }
  aligned = (void*)((((AcUptr)raw) + alignment - 1) & mask);

  status = AC_STATUS_OK;

done:
  if (status != AC_STATUS_OK) {
    ac_free(raw);
  } else {
    *pRaw = raw;
    *pAligned = aligned;
    *pElemSize = elem_size;
  }

  ac_debug_printf("ac_calloc_align:-raw=%p aligned=%p elem_size=%u status=%u\n",
      raw, aligned, elem_size, status);
  return status;
}
예제 #8
0
파일: test.c 프로젝트: winksaville/sadie
ac_bool done_state(AcComp* comp, AcMsg* msg) {
  TestComp* this = (TestComp*)comp;
  ac_debug_printf(LDR ":+msg->op=%lx\n", ldr, msg->op);

  switch (msg->op) {
    case (AC_DEINIT_CMD): {
      ac_debug_printf(LDR "AC_DEINIT_CMD\n", ldr);
      break;
    }
    default: {
      ac_printf(LDR "unregonized AC_OP=%lx\n", ldr, msg->op);
      break;
    }
  }

  ac_debug_printf(LDR ":-msg->op=%lx\n", ldr, msg->op);
  AcMsgPool_ret_msg(msg);
  return AC_TRUE;
}
예제 #9
0
파일: test.c 프로젝트: cci-smoketests/sadie
/**
 * Indentify and clear source of interrupt.
 * After returning interrupts will be enabled
 * so we use __atomic operations on source.
 */
void periodic_iacs(ac_uptr param) {
  irq_param* pirq_param = (irq_param*)param;
  ac_u32 timer_ris = ac_timer_rd_ris(pirq_param->timer);
  if ((timer_ris & 0x1) != 0) {
    ac_bool* psource = &pirq_param->source;
    __atomic_store_n(psource, AC_TRUE, __ATOMIC_RELEASE);
    ac_timer_wr_int_clr(pirq_param->timer);
    ac_debug_printf("\n\nperiodic: %d cleared\n", pirq_param->timer);
  }
}
예제 #10
0
파일: test.c 프로젝트: winksaville/sadie
AcUint test_inet_link_impl(AcCompMgr* cm) {
  AcUint error = AC_FALSE;
  AcMsgPool mp;
  AcMsg* msg;

  ac_debug_printf(LDR ":+\n", ldr);

  // Create a message pool with extra space large enough
  // for AC_INET_LINK_PROTOCOL messages
  AcMsgPool_init(&mp, 8, AC_INET_LINK_PROTOCOL_EXTRA_MAX_LEN);

  // Initialize the test component
  TestComp_init(cm);
#if 0
  AcReceptor_wait(test_comp.waiting);
  if (test_comp.status != AC_STATUS_OK) {
    ac_debug_printf(LDR "Could not initialize test_comp\n", ldr);
    goto done;
  }
#endif

  // Send a ARP Request
  msg = AcMsgPool_get_msg(&mp);
  msg->op = SEND_ARP_REQ;
  AcCompMgr_send_msg(&test_comp.comp, msg);
  AcReceptor_wait(test_comp.waiting);

  // Send Done
  msg = AcMsgPool_get_msg(&mp);
  msg->op = DONE;
  AcCompMgr_send_msg(&test_comp.comp, msg);
  AcReceptor_wait(test_comp.waiting);

//done:
  // Deinitialize the test component
  TestComp_deinit(cm);

  AcMsgPool_deinit(&mp);

  ac_debug_printf(LDR ":-\n", ldr);
  return error;
}
예제 #11
0
파일: test.c 프로젝트: winksaville/sadie
ac_bool initial_state(AcComp* comp, AcMsg* msg) {
  AcStatus status;
  TestComp* this = (TestComp*)comp;
  ac_debug_printf(LDR ":+msg->op=%lx\n", ldr, msg->op);

  switch (msg->op) {
    case (AC_INIT_CMD): {
      ac_debug_printf(LDR "AC_INIT_CMD\n", ldr);

      // Create a message pool
      status = AcMsgPool_init(&this->mp, 8, AC_INET_LINK_PROTOCOL_EXTRA_MAX_LEN);
      if (status != AC_STATUS_OK) {
        ac_printf(LDR "AC_INIT_CMD could not allocates messages", ldr);
        this->status = status;
        TRANS_TO(this, done_state);
      }
      ac_debug_printf(LDR "AC_INIT_CMD mp initied\n", ldr);

      // Find the component we're going to test
      test_comp.target_comp = AcCompMgr_find_comp(this->cm, this->target_comp_name);
      if (test_comp.target_comp == AC_NULL) {
        ac_printf(LDR "AC_INIT_CMD could not find target_comp=%s", ldr, this->target_comp_name);
        this->status = status;
        TRANS_TO(this, done_state);
      }
      ac_debug_printf(LDR "AC_INIT_CMD found target comp\n", ldr);

      this->status = AC_STATUS_OK;
      AcReceptor_signal(this->waiting);
      TRANS_TO(this, work_state);
      break;
    }
    default: {
      ac_printf(LDR "unregonized AC_OP=%lx\n", ldr, msg->op);
      break;
    }
  }

  ac_debug_printf(LDR ":-msg->op=%lx\n", ldr, msg->op);
  AcMsgPool_ret_msg(msg);
  return AC_TRUE;
}
예제 #12
0
파일: test.c 프로젝트: cci-smoketests/sadie
/**
 * Handle the one_shot interrupt.
 *
 * NOTE: Interrupts are enabled so __atomic operations are used.
 */
void periodic_handler(ac_uptr param) {
  irq_param* pirq_param = (irq_param*)param;
  ac_bool ac_true = AC_TRUE;
  ac_bool* psource = &pirq_param->source;

  ac_bool ok = __atomic_compare_exchange_n(psource, &ac_true, AC_FALSE,
      AC_TRUE, __ATOMIC_RELEASE, __ATOMIC_ACQUIRE);
  if (ok) {
    __atomic_add_fetch(&periodic_counter, 1, __ATOMIC_RELEASE);
    ac_debug_printf("periodic: %d inc counter\n\n", pirq_param->timer);
  }
}
예제 #13
0
파일: _timer.c 프로젝트: winksaville/sadie
/**
 * Handle the periodic interrupt.
 *
 * NOTE: Interrupts are enabled so __atomic operations are used.
 */
static void periodic_handler(ac_uptr param) {
  irq_param* pirq_param = (irq_param*)param;

  // Test if pirq_param->source is AC_TRUE which means this did fire
  ac_bool ac_true = AC_TRUE;
  ac_bool* psource = &pirq_param->source;
  ac_bool ok = __atomic_compare_exchange_n(psource, &ac_true, AC_FALSE,
      AC_TRUE, __ATOMIC_RELEASE, __ATOMIC_ACQUIRE);
  if (ok) {
    // Yes, this interupt occurred.
    ac_debug_printf("periodic: %d handled\n", pirq_param->timer);
  }
}
예제 #14
0
파일: test.c 프로젝트: winksaville/sadie
void* t1(void *param) {
  struct test_params* params = (struct test_params*)param;
  //ac_printf("t1:+params->loops=%d\n", params->loops);
  for(ac_uint i = 0; i < params->loops; i++) {
    __atomic_add_fetch(&params->counter, 1, __ATOMIC_RELEASE);

    //ac_thread_yield();

    AcReceptor_wait(params->receptor);
  }

  ac_debug_printf("t1: signal done_receptor\n");
  AcReceptor_signal(params->done_receptor);
  return AC_NULL;
}
예제 #15
0
/**
 * Have the current thread wait for some number of ticks.
 */
static void thread_wait_timespec(struct timespec* ptime) {
  // Wait loop
  while (AC_TRUE) {
    int rslt = nanosleep(ptime, ptime);
    //ac_printf("ac_thread_wait: rslt=%d\n", rslt);
    switch (rslt) {
      case 0: return;
      case EINTR: break;
      default: {
        ac_debug_printf("ac_thread_wait: errno=%d\n", rslt);
        return;
        break;
      }
    }
  }
}
예제 #16
0
/**
 * @see ac_msg_pool.h
 */
AcStatus AcMsgPool_init(AcMsgPool* mp, AcU32 msg_count, AcU32 len_extra) {
  ac_debug_printf("AcMsgPool_init:+mp=%p msg_count=%u len_extra=%u\n",
      mp, msg_count, len_extra);
  AcStatus status;

  if (mp == AC_NULL) {
    status = AC_STATUS_BAD_PARAM;
    goto done;
  }
  mp->msgs_raw = AC_NULL;
  mp->next_ptrs_raw = AC_NULL;
  mp->msgs = AC_NULL;
  mp->len_extra = len_extra;
  
  // Allocate and align the messages
  AcU32 size_entry;
  status = ac_calloc_align(msg_count, sizeof(AcMsg) + len_extra, sizeof(AcU64),
      &mp->msgs_raw, (void**)&mp->msgs, &size_entry);
  ac_debug_printf("AcMsgPool_init: mp=%p msgs_raw=%p msgs=%p size_entry=%u status=%u\n",
      mp, mp->msgs_raw, mp->msgs, size_entry, status);
  if (status != AC_STATUS_OK) {
    goto done;
  }

  // Allocate and align the AcNextPtrs
  // BUG These AcNextPtrs need to be managed globally.
  AcU32 size_next_entry;
  status = ac_calloc_align(msg_count, sizeof(AcNextPtr), AC_MAX_CACHE_LINE_LEN,
      &mp->next_ptrs_raw, (void**)&mp->next_ptrs, &size_next_entry);
  ac_debug_printf("AcMsgPool_init: mp=%p next_ptrs_raw=%p next_ptrs=%p size_next_entry=%u status=%u\n",
      mp, mp->next_ptrs_raw, mp->msgs, size_next_entry, status);
  if (status != AC_STATUS_OK) {
    goto done;
  }

  // Init the ring buffer
  status = AcMpscRingBuff_init(&mp->rb, msg_count);
  if (status != AC_STATUS_OK) {
    goto done;
  }

  // Add messages
  void* base = mp->msgs;
  void* base_np = mp->next_ptrs;
  for (AcU32 i = 0; i < msg_count; i++) {
    AcMsg* msg = (AcMsg*)base;
    AcNextPtr* np = (AcNextPtr*)base_np;

    // Init next_ptr fields
    np->next = AC_NULL;
    np->msg = AC_NULL;

    // Init msg fields
    msg->mp = mp;
    msg->next_ptr = np;

    // Add msg to ring buffer
    if (!AcMpscRingBuff_add_mem(&mp->rb, msg)) {
      ac_fail("AcMsgPool_init: WTF should always be able to add msg");
      status = AC_STATUS_ERR;
      goto done;
    }

    // Advance to next entries
    base += size_entry;
    base_np += size_next_entry;
  }

done:
  if (status != AC_STATUS_OK && mp != AC_NULL) {
    ac_free(mp->msgs_raw);
    ac_free(mp->next_ptrs_raw);
  }
  ac_debug_printf("AcMsgPool_init:-mp=%p msg_count=%u len_extra=%u status=%d\n",
      mp, msg_count, len_extra, status);
  return status;
}
예제 #17
0
/**
 * Initialize this module
 */
void AcInetLink_init(AcCompMgr* cm) {
  ac_debug_printf("AcInetLink_init:# cm=%p\n", cm);
}
예제 #18
0
파일: test.c 프로젝트: winksaville/sadie
ac_uint test_receptor(void) {
  ac_printf("test_receptor:+\n");

  ac_uint error = AC_FALSE;
#if AC_PLATFORM == Posix || AC_PLATFORM == pc_x86_64
  struct test_params params;

  ac_printf("test_receptor: call AcReceptor_get\n");
  params.receptor = AcReceptor_get();
  params.done_receptor = AcReceptor_get();
  params.counter = 0;
#ifdef NDEBUG
  params.loops = 1000000;
#else
  params.loops = 10;
  ac_uint x = 0;
#endif

  ac_thread_rslt_t rslt = ac_thread_create(0, t1, (void*)&params);
  error |= AC_TEST(rslt.status == 0);

  ac_u64 start = ac_tscrd();

  ac_printf("test_receptor: loops=%ld\n", params.loops);
  for (ac_uint i = 0; i < params.loops; i++) {
#ifdef NDEBUG
    // Wait for params.counter to change, i.e. t1 and incremented the counter
    // and is waiting for the signal
    while (__atomic_load_n(&params.counter, __ATOMIC_ACQUIRE) <= i) {
    }
    AcReceptor_signal_yield_if_waiting(params.receptor);
#else
    // Wait for params.counter to change, i.e. t1 and incremented the counter
    // and is waiting for the signal
    while (__atomic_load_n(&params.counter, __ATOMIC_ACQUIRE) <= i) {
      if ((++x % 20000000) == 0) {
        ac_printf("test_receptor: waiting for counter i=%d x=%d\n", i, x);
      }

      //ac_printf("test_receptor: call ac_thread_yield\n");
      //ac_thread_yield();
    }
    ac_u64 wait_until = ac_tscrd() + (ac_tsc_freq() / 1);
    while (ac_tscrd() < wait_until) {
      if ((++x % 20000000) == 0) {
        ac_printf("test_receptor: wait until=%ld cur tsc=%ld i=%d x=%d\n", wait_until, ac_tscrd(), i, x);
      }
      //ac_thread_yield();
    }

    //ac_printf("test_receptor: signal\n");
    ac_u64 signal_start = ac_tscrd();
    AcReceptor_signal_yield_if_waiting(params.receptor);
    ac_u64 ticks = ac_tscrd() - signal_start;
    ac_printf("test_receptor: signal time=%.9t\n", ticks);
#endif
  }
  ac_debug_printf("test_receptor: wait on done_receptor x=%d\n", x);
  AcReceptor_wait(params.done_receptor);
  ac_debug_printf("test_receptor: continuing done_receptor\n");

  ac_u64 stop = ac_tscrd();
  ac_u64 ticks = stop - start;
  ac_printf("test_receptor: ticks=%ld %ld - %ld\n", ticks, stop, start);

  ac_u64 ticks_per_op = AC_U64_DIV_ROUND_UP(ticks, params.loops);
  ac_printf("test_receptor: ticks_per_op=%ld(%.9t)\n", ticks_per_op, ticks_per_op);

  ac_printf("test_receptor: time=%.9t\n", ticks);

  AcReceptor_ret(params.receptor);
#endif

  ac_printf("test_receptor:-error=%d\n", error);
  return error;
}