Beispiel #1
0
static void *
direct_thread_main( void *arg )
{
     void                    *ret;
     DirectThread            *thread = arg;

     prctl( PR_SET_NAME, thread->name, 0, 0, 0 );

     pthread_setspecific( thread_key, thread );


     D_DEBUG_AT( Direct_ThreadInit, "%s( %p )\n", __FUNCTION__, arg );

     D_DEBUG_AT( Direct_ThreadInit, "  -> starting...\n" );

     D_MAGIC_ASSERT( thread, DirectThread );

     pthread_cleanup_push( direct_thread_cleanup, thread );



     thread->tid = direct_gettid();

     D_DEBUG_AT( Direct_ThreadInit, " -> tid %d\n", thread->tid );


     __D_direct_thread_call_init_handlers( thread );


     /* Have all signals handled by the main thread. */
     if (direct_config->thread_block_signals)
          direct_signals_block_all();

     /* Lock the thread mutex. */
     D_DEBUG_AT( Direct_ThreadInit, "  -> locking...\n" );
     direct_mutex_lock( &thread->lock );

     /* Indicate that our initialization has completed. */
     D_ASSERT( !thread->init );
     thread->init = true;

     D_DEBUG_AT( Direct_ThreadInit, "  -> signalling...\n" );
     direct_waitqueue_signal( &thread->cond );

     /* Unlock the thread mutex. */
     D_DEBUG_AT( Direct_ThreadInit, "  -> unlocking...\n" );
     direct_mutex_unlock( &thread->lock );

     if (thread->joining) {
          D_DEBUG_AT( Direct_Thread, "  -> Being joined before entering main routine!\n" );
          return NULL;
     }

     D_MAGIC_ASSERT( thread, DirectThread );

     /* Call main routine. */
     D_DEBUG_AT( Direct_ThreadInit, "  -> running...\n" );
     ret = thread->main( thread, thread->arg );

     D_DEBUG_AT( Direct_Thread, "  -> Returning %p from '%s' (%s, %d)...\n",
                 ret, thread->name, direct_thread_type_name(thread->type), thread->tid );

     D_MAGIC_ASSERT( thread, DirectThread );

     pthread_cleanup_pop( 1 );

     return ret;
}
Beispiel #2
0
DirectThread *
direct_thread_create( DirectThreadType      thread_type,
                      DirectThreadMainFunc  thread_main,
                      void                 *arg,
                      const char           *name )
{
     DirectThread       *thread;
     pthread_attr_t      attr;
     struct sched_param  param;
     int                 policy;
     int                 priority;
     size_t              stack_size;

     D_ASSERT( thread_main != NULL );
     D_ASSERT( name != NULL );

     D_DEBUG_AT( Direct_Thread, "%s( %s, %p(%p), '%s' )\n", __FUNCTION__,
                 direct_thread_type_name(thread_type), thread_main, arg, name );

     /* Create the key for the TSD (thread specific data). */
     pthread_mutex_lock( &key_lock );

     if (thread_key == -1)
          pthread_key_create( &thread_key, NULL );

     pthread_mutex_unlock( &key_lock );

     /* Allocate thread structure. */
     thread = D_CALLOC( 1, sizeof(DirectThread) );
     if (!thread) {
          D_OOM();
          return NULL;
     }

     /* Write thread information to structure. */
     thread->name = D_STRDUP( name );
     thread->type = thread_type;
     thread->main = thread_main;
     thread->arg  = arg;

     /* Initialize to -1 for synchronization. */
     thread->thread = (pthread_t) -1;
     thread->tid    = (pid_t) -1;

     /* Initialize mutex and condition. */
     direct_util_recursive_pthread_mutex_init( &thread->lock );
     pthread_cond_init( &thread->cond, NULL );

     D_MAGIC_SET( thread, DirectThread );

     /* Initialize scheduling and other parameters. */
     pthread_attr_init( &attr );

     pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED );

     /* Select scheduler. */
     switch (direct_config->thread_scheduler) {
          case DCTS_FIFO:
               policy = SCHED_FIFO;
               break;

          case DCTS_RR:
               policy = SCHED_RR;
               break;

          default:
               policy = SCHED_OTHER;
               break;
     }

     if (pthread_attr_setschedpolicy( &attr, policy ))
          D_PERROR( "Direct/Thread: Could not set scheduling policy to %s!\n", direct_thread_policy_name(policy) );

     /* Read (back) value. */
     pthread_attr_getschedpolicy( &attr, &policy );

     /* Select priority. */
     switch (thread->type) {
          case DTT_CLEANUP:
          case DTT_INPUT:
          case DTT_OUTPUT:
          case DTT_MESSAGING:
          case DTT_CRITICAL:
               priority = thread->type * direct_config->thread_priority_scale / 100;
               break;

          default:
               priority = direct_config->thread_priority;
               break;
     }

     D_DEBUG_AT( Direct_ThreadInit, "  -> %s (%d) [%d;%d]\n", direct_thread_policy_name(policy), priority,
                 sched_get_priority_min( policy ), sched_get_priority_max( policy ) );

     if (priority < sched_get_priority_min( policy ))
          priority = sched_get_priority_min( policy );

     if (priority > sched_get_priority_max( policy ))
          priority = sched_get_priority_max( policy );

     param.sched_priority = priority;

     if (pthread_attr_setschedparam( &attr, &param ))
          D_PERROR( "Direct/Thread: Could not set scheduling priority to %d!\n", priority );

     /* Select stack size? */
     if (direct_config->thread_stack_size > 0) {
          if (pthread_attr_setstacksize( &attr, direct_config->thread_stack_size ))
               D_PERROR( "Direct/Thread: Could not set stack size to %d!\n", direct_config->thread_stack_size );
     }

     /* Read (back) value. */
     pthread_attr_getstacksize( &attr, &stack_size );

     /* Lock the thread mutex. */
     D_DEBUG_AT( Direct_ThreadInit, "  -> locking...\n" );
     pthread_mutex_lock( &thread->lock );

     /* Create and run the thread. */
     D_DEBUG_AT( Direct_ThreadInit, "  -> creating...\n" );
     pthread_create( &thread->thread, &attr, direct_thread_main, thread );

     pthread_attr_destroy( &attr );

     pthread_getschedparam( thread->thread, &policy, &param );

     D_INFO( "Direct/Thread: Started '%s' (%d) [%s %s/%s %d/%d] <%zu>...\n",
             name, thread->tid, direct_thread_type_name(thread_type),
             direct_thread_policy_name(policy), direct_thread_scheduler_name(direct_config->thread_scheduler),
             param.sched_priority, priority, stack_size );

#ifdef DIRECT_THREAD_WAIT_INIT
     /* Wait for completion of the thread's initialization. */
     while (!thread->init) {
          D_DEBUG_AT( Direct_ThreadInit, "  -> waiting...\n" );
          pthread_cond_wait( &thread->cond, &thread->lock );
     }

     D_DEBUG_AT( Direct_ThreadInit, "  -> ...thread is running.\n" );
#endif

     /* Unlock the thread mutex. */
     D_DEBUG_AT( Direct_ThreadInit, "  -> unlocking...\n" );
     pthread_mutex_unlock( &thread->lock );

     D_DEBUG_AT( Direct_ThreadInit, "  -> returning %p\n", thread );

     return thread;
}
Beispiel #3
0
static void *
direct_thread_main( void *arg )
{
     void                    *ret;
     DirectThread            *thread = arg;
     DirectThreadInitHandler *handler;
     pid_t                    tid;

     tid = direct_gettid();

     D_DEBUG_AT( Direct_ThreadInit, "%s( %p ) <- tid %d\n", __FUNCTION__, arg, tid );

     D_DEBUG_AT( Direct_ThreadInit, "  -> starting...\n" );

     D_MAGIC_ASSERT( thread, DirectThread );

     pthread_cleanup_push( direct_thread_cleanup, thread );


     pthread_setspecific( thread_key, thread );

     thread->tid = tid;


     /* Call all init handlers. */
     pthread_mutex_lock( &handler_lock );

     direct_list_foreach (handler, handlers)
          handler->func( thread, handler->arg );

     pthread_mutex_unlock( &handler_lock );


     /* Have all signals handled by the main thread. */
     if (direct_config->thread_block_signals)
          direct_signals_block_all();

     /* Lock the thread mutex. */
     D_DEBUG_AT( Direct_ThreadInit, "  -> locking...\n" );
     pthread_mutex_lock( &thread->lock );

     /* Indicate that our initialization has completed. */
     thread->init = true;

#ifdef DIRECT_THREAD_WAIT_INIT
     D_DEBUG_AT( Direct_ThreadInit, "  -> signalling...\n" );
     pthread_cond_signal( &thread->cond );
#endif

     /* Unlock the thread mutex. */
     D_DEBUG_AT( Direct_ThreadInit, "  -> unlocking...\n" );
     pthread_mutex_unlock( &thread->lock );

     if (thread->joining) {
          D_DEBUG_AT( Direct_Thread, "  -> Being joined before entering main routine!\n" );
          return NULL;
     }

     D_MAGIC_ASSERT( thread, DirectThread );

     /* Call main routine. */
     D_DEBUG_AT( Direct_ThreadInit, "  -> running...\n" );
     ret = thread->main( thread, thread->arg );

     D_DEBUG_AT( Direct_Thread, "  -> Returning %p from '%s' (%s, %d)...\n",
                 ret, thread->name, direct_thread_type_name(thread->type), thread->tid );

     D_MAGIC_ASSERT( thread, DirectThread );

     pthread_cleanup_pop( 1 );

     return ret;
}
Beispiel #4
0
DirectResult
direct_thread_init( DirectThread *thread )
{
     pthread_attr_t      attr;
     struct sched_param  param;
     int                 policy;
     int                 priority;
     size_t              stack_size;

     direct_once( &thread_init_once, init_once );

     /* Initialize scheduling and other parameters. */
     pthread_attr_init( &attr );

     pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED );

     /* Select scheduler. */
     switch (direct_config->thread_scheduler) {
          case DCTS_FIFO:
               policy = SCHED_FIFO;
               break;

          case DCTS_RR:
               policy = SCHED_RR;
               break;

          default:
               policy = SCHED_OTHER;
               break;
     }

     if (pthread_attr_setschedpolicy( &attr, policy ))
          D_PERROR( "Direct/Thread: Could not set scheduling policy to %s!\n", direct_thread_policy_name(policy) );

     /* Read (back) value. */
     pthread_attr_getschedpolicy( &attr, &policy );

     /* Select priority. */
     switch (thread->type) {
          case DTT_CLEANUP:
          case DTT_INPUT:
          case DTT_OUTPUT:
          case DTT_MESSAGING:
          case DTT_CRITICAL:
               priority = thread->type * direct_config->thread_priority_scale / 100;
               break;

          default:
               priority = direct_config->thread_priority;
               break;
     }

     D_DEBUG_AT( Direct_ThreadInit, "  -> %s (%d)\n", direct_thread_policy_name(policy), priority );

     param.sched_priority = priority;

     if (pthread_attr_setschedparam( &attr, &param ))
          D_PERROR( "Direct/Thread: Could not set scheduling priority to %d!\n", priority );

     /* Select stack size? */
     if (direct_config->thread_stack_size > 0) {
          if (pthread_attr_setstacksize( &attr, direct_config->thread_stack_size ))
               D_PERROR( "Direct/Thread: Could not set stack size to %d!\n", direct_config->thread_stack_size );
     }

     /* Read (back) value. */
     pthread_attr_getstacksize( &attr, &stack_size );


     if (pthread_create( &thread->handle.thread, &attr, direct_thread_main, thread ))
          return errno2result( errno );

     D_INFO( "Direct/Thread: Started '%s' (%d) [%s %s/%s %d/%d] <%zu>...\n",
             thread->name, thread->tid, direct_thread_type_name(thread->type),
             direct_thread_policy_name(policy), direct_thread_scheduler_name(direct_config->thread_scheduler),
             param.sched_priority, priority, stack_size );

     pthread_attr_destroy( &attr );

     pthread_getschedparam( thread->handle.thread, &policy, &param );

     return DR_OK;
}