Exemplo n.º 1
0
//__attribute__((noinline))
STATIC tcb_x86* thread_create(ac_size_t stack_size, ac_uptr flags,
    void*(*entry)(void*), void* entry_arg) {
  ac_uint sv_flags = disable_intr();
  tcb_x86* ptcb = AC_NULL;
  ac_u8* pstack = AC_NULL;
  int error = 0;

  // Allocate a stack
  if (stack_size <= 0) {
    stack_size = AC_THREAD_STACK_MIN;
  }
  if (stack_size < AC_THREAD_STACK_MIN) {
    error = 1;
    goto done;
  }
  stack_size = (stack_size + 0xff) & ~0xff;

  pstack = ac_malloc(stack_size);
  if (pstack == AC_NULL) {
    ac_printf("thread_create: could not allocate stack\n");
    error = 1; // TODO: add AC_STATUS_OOM
    goto done;
  }
  ac_debug_assert(((ac_uptr)pstack & 0xf) == 0);

  // Get the tcb and initialize the stack frame
  ptcb = get_tcb(entry, entry_arg);
  if (ptcb == AC_NULL) {
    ac_printf("thread_create: no tcb's available\n");
    error = 1; // TODO: add AC_STATUS_TO_MANY_THREADS
    goto done;
  }
  ptcb->pstack = pstack;
  init_stack_frame(pstack, stack_size, flags, entry_trampoline, ptcb,
      &ptcb->sp, &ptcb->ss);

  // Add this after pready
  add_tcb_after(ptcb, pready);

done:
  if (error != 0) {
    if (pstack != AC_NULL) {
      ac_free(pstack);
    }
  }

#if AC_FALSE
  ac_printf("thread_create: pstack=0x%x stack_size=0x%x tos=0x%x rl=%d\n",
      pstack, stack_size, pstack + stack_size, get_ready_length());
  ac_printf("thread_create:-ptcb=0x%x ready: ", ptcb);
  print_tcb_list(AC_NULL, pready);
#endif

  restore_intr(sv_flags);
  return ptcb;
}
Exemplo n.º 2
0
/**
 * Allocate num_members * size bytes and initialize to 0.
 *
 * @param: count is number of items of size to create
 * @param: size is the number of bytes in each item
 *
 * @return: pointer to the items
 */
void* ac_calloc(ac_size_t count, ac_size_t size) {
  ac_size_t total_size = count * size;
  if (total_size == 0) {
    // Standard C99 implementations may return AC_NULL or other value
    // but its undefined behavior if the returned value is used.
    // Therefore we require ac_calloc(0) to always return AC_NULL
    return AC_NULL;
  } else {
    void* p = ac_malloc(total_size);
    ac_memset(p, 0, total_size);
    return p;
  }
}
Exemplo n.º 3
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;
  }
}
Exemplo n.º 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);
}
Exemplo n.º 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;
}
Exemplo n.º 6
0
int main(void) {
  ac_bool error = AC_FALSE;

  // Must return AC_NULL although according to C99 standard a
  // malloc(0) may return either but undefined behavior happens
  // if the pointer is used. Therefore we'll defined it as always
  // returning AC_NULL
  error |= AC_TEST(ac_malloc(0) == AC_NULL);

  // Test conditions which attempt allocate too much memory
  error |= AC_TEST(ac_malloc(((ac_size_t)0) - 1) == AC_NULL);

  error |= AC_TEST(ac_malloc(((ac_size_t)0) - 2) == AC_NULL);

  error |= AC_TEST(ac_malloc(((ac_size_t)0) - 63) == AC_NULL);

  error |= AC_TEST(ac_malloc(((ac_size_t)0) - 64) == AC_NULL);

  error |= AC_TEST(ac_malloc(((ac_size_t)0) - 65) == AC_NULL);

  error |= AC_TEST(ac_malloc(((ac_size_t)0) - 66) == AC_NULL);

  // Test conditions which must succeed as we expect at
  // least being able to do a few small allocations
  void* p1 = ac_malloc(1);
  error |= AC_TEST(ac_malloc(1) != AC_NULL);
  ac_free(p1);

  void* p2 = ac_malloc(2);
  error |= AC_TEST(p2 != AC_NULL);
  ac_free(p2);

  void* p63 = ac_malloc(63);
  error |= AC_TEST(p63 != AC_NULL);
  ac_free(p63);

  void* p64 = ac_malloc(64);
  error |= AC_TEST(p64 != AC_NULL);
  ac_free(p64);

  void* p65 = ac_malloc(1);
  error |= AC_TEST(p65 != AC_NULL);
  ac_free(p65);

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

  return error;
}