Exemplo n.º 1
0
/***
* The thread pool has the property that all the threads will keep running until signalled to quit.
* Each thread will call pthread_exit() once it has completed execution of it's current 'task_t'.
*/
void thread_pool_join_all( thread_pool_t *pool ) {
  dna_log(DEBUG, "Joining thread pool:");
  while ( !fifo_is_empty(pool->thread_queue) ) {
    dna_mutex_lock( pool->mutex );
    int threadsAreStillRunning = 0;
    while ( (threadsAreStillRunning = fifo_any( pool->thread_queue, &thread_context_is_running)) ) {
      dna_log(DEBUG, "Some threads are still running...%i", threadsAreStillRunning);
      dna_cond_wait( pool->wait, pool->mutex );
    }
    dna_thread_context_t *context = (dna_thread_context_t*) fifo_pop( pool->thread_queue );
    if (context->runstate == RUNNING) {
      dna_log(WARN, "context is still running, placing back in the queue.");
      fifo_push( pool->thread_queue, context );
    }
    else {
      // if the context is != RUNNING, it's either SHOULD_QUIT or HAS_QUIT
      // so we have to rely on the null work we pushed earlier to clear
      // any blocks
      dna_thread_context_join( context );
      dna_thread_context_destroy(context);
    }
    dna_mutex_unlock( pool->mutex );
  }
  dna_log(DEBUG, "Thread pool joined.");
}
Exemplo n.º 2
0
// test-helper: empty the fifo and see what we have in it
void fifo_check() {
  dna_log(DEBUG, "emptying result fifo...");
  int ctr = 0;
  while( !fifo_is_empty(fifo) )  {
    void *val = fifo_pop( fifo );
    if (val) {
      message_t *msg = (message_t *) val;
      if (msg) {
        free(msg);
      }
      ctr++;
    }
  }
  dna_log(INFO, "Counted %i elements popped from value queue", ctr);
}
Exemplo n.º 3
0
void test_empty_thread_pool() {
  dna_log(INFO,  "<-------------------- test_empty_thread_pool ---------------------");
  int i = 0;
  for (i = 0; i < 10 ; i++ ) {
    dna_log(INFO, ">> --- cycle %i --- <<", i+1);
    // global here, for all threads to share
    fifo = fifo_create("values", 0);
    dna_log(DEBUG, "starting thread pool");
    thread_pool_t *pool = thread_pool_create("main pool", 1);
    dna_log(DEBUG, "destroying thread pool");
    thread_pool_exit_all(pool);
    thread_pool_destroy(pool);
    fifo_check();
    fifo_destroy(fifo);
  }
}
Exemplo n.º 4
0
void test_fifo() {
  dna_log(INFO,  "<-------------------- test_fifo ---------------------");
  int j = 0;
  for (j = 0; j < 10; j++) {
    fifo_t *fifo = fifo_create("<test fifo>", 0);
    fifo_destroy(fifo);
  }
}
Exemplo n.º 5
0
void sleep_for( long seconds ) {
  dna_log(DEBUG, "Sleeping for %lu", seconds);
  struct timespec interval = {
      .tv_sec = (time_t) seconds,
      .tv_nsec = 0
  };
  nanosleep(&interval, NULL);
}

void test_empty_fifo() {
  dna_log(INFO,  "<-------------------- test_empty_fifo ---------------------");
  int j = 0;
  for (j = 0; j < 10; j++) {
    fifo_t *fifo = fifo_create(" <test fifo>", 0);
    fifo_destroy(fifo);
  }
}
Exemplo n.º 6
0
void test_busy_thread_pool() {
  dna_log(INFO,  "<-------------------- test_busy_thread_pool  ---------------------");
  fifo = fifo_create("<(busy_thread_pool) value fifo>", 0);
  thread_pool_t *pool = thread_pool_create("<busy thread pool>", 8); // should auto-determine thread count maybe?
  dna_log(DEBUG, "adding %i tasks to the queue...", ELEMS);
  int i = 0;
  for( i = 0; i < ELEMS; i++ ) {
    thread_pool_enqueue(pool, &fifo_fill, NULL);
  }
  dna_log(DEBUG, "waiting for threads to complete on their own...");
  thread_pool_exit_all(pool);
  thread_pool_join_all( pool );
  dna_log(DEBUG, "destroying thread pool...");
  thread_pool_destroy( pool );
  fifo_check();
  dna_log(DEBUG, "destroying global value fifo.");
  fifo_destroy( fifo );
}
Exemplo n.º 7
0
status_t semaphore_alarm (void * data)

/*
 * ARGUMENTS
 * * data : a thread_t element.
 *
 * RETURN
 * * DNA_BAD_ARGUMENT: the thread parameter is not valid
 * * DNA_ERROR: the thread is not a valid thread
 * * DNA_OK: the operation succeeded
 *
 * SOURCE
 */

{
  thread_t thread = data;
  status_t status = DNA_OK;

  watch (status_t)
  {
    ensure (thread != NULL, DNA_BAD_ARGUMENT);
    ensure (thread -> resource_queue != NULL, DNA_ERROR);
    ensure (thread -> info . status == DNA_THREAD_WAITING, DNA_ERROR);
    ensure (thread -> info . resource == DNA_RESOURCE_SEMAPHORE, DNA_ERROR);

    /*
     * Lock the thread's resource queue.
     * Extract the thread from the waiting list.
     */

    lock_acquire (& thread -> resource_queue -> lock);
    status = queue_extract (thread -> resource_queue, thread);
    lock_release (& thread -> resource_queue -> lock);

    /*
     * If the thread was waiting, we can dispatch it
     */

    if (status == DNA_OK)
    {
      lock_acquire (& thread -> lock);
 dna_log(VERBOSE_LEVEL, " %s DNA_NO_RESOURCE ", thread -> info . name);

      thread -> resource_queue = NULL;
      thread -> info . sem_tokens = 0;
      thread -> info . resource = DNA_NO_RESOURCE;
      thread -> info . resource_id = -1;

      thread -> info . status = DNA_THREAD_READY;
      status = scheduler_dispatch (thread);
    }

    return status;
  }
}
Exemplo n.º 8
0
void *fifo_fill( void *nothing ) {
  int i = 0;
  for (i = 0; i < ELEMS; i++) {
    fifo_push( fifo, NULL );
#ifdef VALUE_LOG
    dna_log(DEBUG, "<< added %i to value fifo", i);
#endif

  }
  return NULL;
}
Exemplo n.º 9
0
/**
* Until pthread_exit, pull a task_t out of the task queue and run it on our thread
*/
void *execute_task_thread_internal( void *args ) {
  execution_args_t *yargs = (execution_args_t*) args;
  fifo_t *tasks = yargs->task_list;
  dna_thread_context_t *context = yargs->thread_context;
  free( yargs );
  dna_log(DEBUG, "started execution of thread %lu", context->id);
  task_t *task = NULL;
  while ( !dna_thread_context_should_exit(context) &&
          (task = (task_t*) fifo_pop( tasks ) ) ) {

    if ( task->func ) { // thread_pool_destroy sends tasks which have NULL members in, don't bother executing it
      task_execute(task);
    }
    task_destroy( task );
    if (dna_thread_context_should_exit(context)) {
      break;
    }
  }
  dna_log(DEBUG, "Execution of thread %lu has finished.", context->id );
  return NULL;
}
Exemplo n.º 10
0
/* Actor system should be the only one repsonsible for
   creating, storing, retreiving or freeing messages */
message_t *message_create(void *data, int type, actor_t *from) {
  message_t *message = (message_t*) malloc( sizeof(message_t) );
  message->data = data;
  message->type = type;
  message->promise = NULL;
  message->from = from;
  message->id = ++messageId;
  if (message->id % 1000 == 0) {
    dna_log(DEBUG, "New message created. Reached new message id : %lu", message->id );
  }
  return message;
}
Exemplo n.º 11
0
void thread_pool_destroy( thread_pool_t *pool ) {
  dna_log(DEBUG, "Inside thread_pool_destroy()");
  if ( pool ) {
    dna_log(DEBUG, "Telling threads to exit...");
    thread_pool_join_all(pool);
    dna_log(DEBUG, "Destroying execution context fifo...");
    fifo_destroy( pool->thread_queue );
    pool->thread_queue = NULL;
    dna_log(DEBUG, "Destroying tasks in fifo...");
    while ( !fifo_is_empty( pool->tasks ) ) {
      task_t *task = (task_t*) fifo_pop( pool->tasks );
      task_destroy( task );
    }
    fifo_destroy( pool->tasks );
    pool->tasks = NULL;
    dna_log(DEBUG, "Freeing thread context pool \"%s\".", pool->name);
    dna_mutex_destroy( pool->mutex );
    dna_cond_destroy( pool->wait );
    free(pool->mutex);
    free(pool->wait);
    free( pool );
  }
}
Exemplo n.º 12
0
status_t block_device_control (void * handler, int32_t function,
    va_list arguments, int32_t * p_ret)
{
  interrupt_status_t it_status;
  block_device_control_t * block_device = (block_device_control_t *)handler;

  watch (status_t)
  {
    ensure (block_device != NULL, DNA_ERROR);

    it_status = cpu_trap_mask_and_backup ();

    switch (function)
    {
      case DNA_GET_DEVICE_SIZE:
        {
          int64_t * p_size = va_arg(arguments, int64_t *);
//          p_size = (int64_t *)arguments;
          ensure (p_size != NULL, DNA_ERROR);

          *p_size = block_device->block_count * block_device->block_size;

          *p_ret = 0;
          break;
        }

      case DNA_GET_INFO:
        {
          device_info_t * info = va_arg (arguments, device_info_t *);
          ensure (info != NULL, DNA_ERROR);

          dna_memset (info, 0, sizeof (device_info_t));
          info->type = DNA_DISK_DEVICE;

          *p_ret = 0;
          break;
        }

      default:
        {
          dna_log(INFO_LEVEL, "Unsupported control code 0x%x.", function);
          *p_ret = -1;
          break;
        }
    }

    cpu_trap_restore (it_status);
    return DNA_OK;
  }
}
Exemplo n.º 13
0
status_t semaphore_get_info (int32_t id, semaphore_info_t * info)

/*
 * ARGUMENTS
 * * id : the ID of the semaphore to get_info.
 * * sem_info : a pointer to a sem_info structure.
 *
 * RESULT
 * * DNA_BAD_SEM_ID: the id parameter is invalid
 * * DNA_BAD_ARGUMENT: the sem_info pointer is invalid
 * * DNA_OK: the operation succeeded
 *
 * SOURCE
 */

{
  semaphore_t sem = NULL;
  semaphore_id_t sid = { .raw = id };
  interrupt_status_t it_status = 0;
  status_t status = DNA_OK;

  watch (status_t)
  {
    ensure (info != NULL, DNA_BAD_ARGUMENT);
    ensure (sid . s . index < DNA_MAX_SEM, DNA_BAD_SEM_ID);

    it_status = cpu_trap_mask_and_backup();
    lock_acquire (& semaphore_pool . lock);

    /*
     * Look for the semaphore with ID id
     */

    sem = & semaphore_pool . data[sid . s . index];
    check (invalid_semaphore, sem != NULL, DNA_BAD_SEM_ID);
    DCACHE_INVAL(&sem->id.raw, sizeof(int32_t));
    check (invalid_semaphore, sem -> id . raw == sid . raw, DNA_BAD_SEM_ID);

    lock_acquire (& sem -> lock);
    lock_release (& semaphore_pool . lock);

    /*
     * Copy the semaphore information
     */
//    cpu_dcache_inv_addr(&sem -> info.tokens);

dna_log(VERBOSE_LEVEL, "ID(%d:%d) TOKEN(%d)",
        sem -> id . s . value, sem -> id . s . index, sem -> info . tokens);

    DCACHE_INVAL(&sem->info, sizeof(port_info_t));
    *info = sem -> info;
    DCACHE_FLUSH(info, sizeof(port_info_t));

    lock_release (& sem -> lock);
    cpu_trap_restore(it_status);

    return status;
  }

  rescue (invalid_semaphore)
  {
    lock_release (& semaphore_pool . lock);
    cpu_trap_restore(it_status);
    leave;
  }
}
Exemplo n.º 14
0
status_t file_put (int16_t fd)

/*
 * ARGUMENTS
 * * fd : the file descriptor.
 *
 * FUNCTION
 * Check if the fd entry exist in the current group pool. If it is the case,
 * decrements its usage counter, and delete the file when the counter reaches 0.
 *
 * RESULT
 * * DNA_INVALID_FD if fd is not a valid file
 * * DNA_OK if the operation succeed
 *
 * SOURCE
 */

{
  file_t file;
  int32_t tid;
  thread_info_t info;
  status_t status = DNA_OK;
  interrupt_status_t it_status = 0;
  vnode_t vnode = NULL;

  watch (status_t)
  {
    status = thread_find (NULL, & tid);
    ensure (status == DNA_OK, status);

    status = thread_get_info (tid, & info);
    ensure (status == DNA_OK, status);

    ensure (info . group >= 0, DNA_BAD_ARGUMENT);
    ensure (info . group < DNA_MAX_GROUP, DNA_BAD_ARGUMENT);

    /*
     * Look for the file in the pool.
     */

    it_status = cpu_trap_mask_and_backup();
    lock_acquire (& file_pool . lock);

    file = file_pool . file[info . group][fd];
    check (error, file != NULL, DNA_INVALID_FD);
    check (error, file -> usage_counter > 0, DNA_ERROR);

    atomic_add (& file -> usage_counter, -1);
 
    if (file -> usage_counter == 0 && file -> destroy)
    {
      file_pool . file[info . group][fd] = NULL;

      lock_release (& file_pool . lock);
      cpu_trap_restore(it_status);

      status =  file -> vnode -> volume -> cmd -> free
        (file -> vnode -> volume -> data, file -> vnode -> data, file -> data);
      panic (status != DNA_OK);

      vnode = file -> vnode;
      kernel_free (file);

      status = vnode_put (vnode -> volume -> id, vnode -> id);
      panic (status != DNA_OK);
    }
    else
    {
      lock_release (& file_pool . lock);
      cpu_trap_restore(it_status);
    }

    dna_log(VERBOSE_LEVEL, "Put FD %d.", fd);

    return DNA_OK;
  }

  rescue (error)
  {
    lock_release (& file_pool . lock);
    cpu_trap_restore(it_status);
    leave;
  }
}