Пример #1
0
int main(void) {
  volatile0 = 0;
  ac_bool error = AC_FALSE;

  /*
   * Manually test these runtime errors, enable one at a time
   * and compile and run, each statement should fail.
   */
  //ac_static_assert(1 == 0, "ac_static_assert(1 == 0), should always fail");
  //ac_static_assert(volatile0 == 0, "ac_static_assert(volatile0 == 0), should always fail");

  // Expect these asserts to fail, but since our ac_fail_impl
  // does not invoke "stop()" we can use AC_TEST to validate
  // that they failed (returned AC_TRUE) and PASS.
  ac_printf("Expect 5 failures vvvvvvvvvvvvvvvvvvvvvvv\n");
  error |= AC_TEST(ac_fail("failing"));
  error |= AC_TEST(ac_assert(0 == 1));
  error |= AC_TEST(ac_assert(volatile0 == 1));
  error |= AC_TEST(ac_debug_assert(1 == 2));
  error |= AC_TEST(ac_debug_assert(volatile0 == 2));
  ac_printf("Expect 5 failures ^^^^^^^^^^^^^^^^^^^^^^^\n");

  // These should never fail
  ac_static_assert(0 == 0, "ac_static_assert(0 == 0) should never fail");
  error |= AC_TEST(!ac_assert(0 == 0));
  error |= AC_TEST(!ac_assert(volatile0 == 0));

  if (!error) {
    // Succeeded
    ac_printf("OK\n");
  }

  return error;
}
Пример #2
0
/**
 * Initialize module
 */
void ac_thread_init(ac_u32 max_threads) {
  // Verify that pthread_t is <= sizeof(ac_uptr)
  ac_static_assert(sizeof(pthread_t) <= sizeof(ac_uptr),
      "Expect pthread_t to be the size of a pointer");

  ac_assert(max_threads > 0);

  ac_u32 size = sizeof(ac_threads) + (max_threads * sizeof(ac_tcb));
  pthreads = ac_malloc(size);
  ac_assert(pthreads != AC_NULL);

  pthreads->max_count = max_threads;
  for (ac_u32 i = 0; i < pthreads->max_count; i++) {
    pthreads->tcbs[i].thread_id = AC_THREAD_ID_EMPTY;
  }
}
Пример #3
0
/**
 * Create a thread and invoke the entry passing entry_arg. If
 * the entry routine returns the thread is considered dead
 * and will not be rescheduled and its stack is reclamined.
 * Any other global memory associated with the thread still
 * exists and is left untouched.
 *
 * @param stack_size is 0 a "default" stack size will be used.
 * @param entry is the routine to run
 * @param entry_arg is the argument passed to entry.
 *
 * @return a ac_thread_rslt contains a status and an opaque ac_thread_hdl_t.
 *         if rslt.status == 0 the thread was created and ac_thread_hdl_t
 *         is valid.
 */
ac_thread_rslt_t ac_thread_create(ac_size_t stack_size,
    void*(*entry)(void*), void* entry_arg) {
  ac_thread_rslt_t rslt;
  ac_tcb* pthe_tcb = AC_NULL;
  int error = 0;
  pthread_attr_t attr;
  pthread_attr_init(&attr);

  if (stack_size > 0) {
    error |= pthread_attr_setstacksize(&attr, (size_t)stack_size);
    if (error != 0) {
      goto done;
    }
  }

  // Find an empty slot
  for (ac_u32 i = 0; i < pthreads->max_count; i++) {
    pthread_t empty = AC_THREAD_ID_EMPTY;

    ac_tcb* pcur_tcb = &pthreads->tcbs[i];
    pthread_t* pthread_id = &pcur_tcb->thread_id;
    ac_bool ok = __atomic_compare_exchange_n(pthread_id, &empty,
        AC_THREAD_ID_NOT_EMPTY, AC_TRUE, __ATOMIC_RELEASE, __ATOMIC_ACQUIRE);
    if (ok) {
      pcur_tcb->entry = entry;
      pcur_tcb->entry_arg = entry_arg;
      error |= pthread_create((pthread_t *)pthread_id, &attr,
          entry_trampoline, pcur_tcb);
      ac_assert(*pthread_id != AC_THREAD_ID_EMPTY);
      ac_assert(*pthread_id != AC_THREAD_ID_NOT_EMPTY);
      if (error == 0) {
        pthe_tcb = pcur_tcb;
        break;
      } else {
        // Mark as empty and try again, although probably won't work
        __atomic_store_n(pthread_id, AC_THREAD_ID_EMPTY, __ATOMIC_RELEASE);
      }
    }
  }

  pthread_attr_destroy(&attr);

done:
  rslt.hdl = (ac_thread_hdl_t)pthe_tcb;
  rslt.status = (rslt.hdl != 0) ? 0 : 1;
  return (ac_thread_rslt_t)rslt;
}
Пример #4
0
/**
 * Initialize this module
 */
void ac_thread_init(ac_u32 max_threads) {
  ac_assert(max_threads > 0);

  max_threads += SYSTEM_THREAD_COUNT;

  ac_uint flags = disable_intr();
  if (max_threads > total_threads) {
    // Create array of the threads
    ac_u32 count = max_threads - total_threads;
    ac_u32 size = sizeof(ac_threads) + (count * sizeof(tcb_x86));
    ac_threads* pnew = ac_malloc(size);
    ac_assert(pnew != AC_NULL);
    pnew->max_count = count;

    // Initialize new entries to AC_THREAD_EMPTY
    for (ac_u32 i = 0; i < count; i++) {
      tcb_init(&pnew->tcbs[i], AC_THREAD_ID_EMPTY, AC_NULL, AC_NULL);
    }

    if (pthreads == AC_NULL) {
      // Add frist set of threads
      pnew->pnext = pnew;
      pnew->pprev = pnew;
      pthreads = pnew;
    } else {
      // Add these new ones to the beginning of the list
      // by adding after the pthreads then move pthreads
      ac_threads* ptmp = pthreads->pnext;
      pnew->pnext = ptmp;
      pnew->pprev = pthreads;
      ptmp->pprev = pnew;
      pthreads->pnext = pnew;

      // Point pthreads at pnew to make it head of the list
      pthreads = pnew;
    }
    total_threads += max_threads;

    // Gurantee all threads can wait simultaneously
    waiting_tcbs_update_max(total_threads);
  }
  restore_intr(flags);
}
Пример #5
0
/**
 * Initialize module
 */
void ac_thread_init(ac_u32 max_threads) {
  // Verify that pthread_t is <= sizeof(ac_uptr)
  ac_static_assert(sizeof(pthread_t) <= sizeof(ac_uptr),
      "Expect pthread_t to be the size of a pointer");

  ac_assert(max_threads > 0);

  // Add one for the "main" thread
  max_threads += 1;

  ac_u32 size = sizeof(ac_threads) + (max_threads * sizeof(ac_tcb));
  pthreads = ac_malloc(size);
  ac_assert(pthreads != AC_NULL);

  pthreads->max_count = max_threads;
  for (ac_u32 i = 0; i < pthreads->max_count; i++) {
    pthreads->tcbs[i].thread_id = AC_THREAD_ID_EMPTY;
  }

  // Initialize pthreads->tcb[0] as main thread
  pthreads->tcbs[0].thread_id = pthread_self();
  pthreads->tcbs[0].entry = AC_NULL;
  pthreads->tcbs[0].entry_arg = AC_NULL;
}
Пример #6
0
/**
 * Early initialization of this module
 */
void ac_thread_early_init() {
  // Initialize timer first, the main reason
  // is it set slice_default.
  init_timer();

  // Initialize reschedule isr
  set_intr_handler(RESCHEDULE_ISR_INTR, reschedule_isr);
  set_intr_handler(TIMER_RESCHEDULE_ISR_INTR, timer_reschedule_isr);

  // Allocate the initial array
  total_threads = 0;
  pthreads = AC_NULL;
  ac_thread_init(SYSTEM_THREAD_COUNT);
  ac_assert(pthreads != AC_NULL);

  pidle_tcb = &pthreads->tcbs[0];
  pmain_tcb = &pthreads->tcbs[1];

  // Initialize idle and main tcbs
  tcb_init(pidle_tcb, 0, idle, AC_NULL);
  tcb_init(pmain_tcb, 1, AC_NULL, AC_NULL);

  // Initialize idle's stack
  init_stack_frame(idle_stack, sizeof(idle_stack), DEFAULT_FLAGS, idle, pidle_tcb,
      &pidle_tcb->sp, &pidle_tcb->ss);

  // Add main as the initial pready list
  pmain_tcb->pnext_tcb = pmain_tcb;
  pmain_tcb->pprev_tcb = pmain_tcb;
  pready = pmain_tcb;
#ifdef SUPPORT_READY_LENGTH
  ready_length = 1;
#endif

  // Add idle to the pready list
  add_tcb_after(pidle_tcb, pready);

  // Initialize waiting tcbs data structures
  waiting_tcbs_init(SYSTEM_THREAD_COUNT);
  print_waiting_tcbs();

  ac_printf("ac_thread_early_init: pmain=0x%lx pidle=0x%lx rl=%d\n", pmain_tcb, pidle_tcb,
      get_ready_length());
  print_tcb_list("ac_thread_early_init:-ready: ", pready);
}