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, ¶m )) 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, ¶m ); 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; }
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, ¶m )) 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, ¶m ); return DR_OK; }