static void * _thread_boot (void *arg) { thread_t *thr = (thread_t *) arg; int rc; rc = pthread_setspecific (_key_current, thr); CKRET (rc); /* Store the context so we can easily restart a dead thread */ setjmp (thr->thr_init_context); thr->thr_status = RUNNING; _thread_init_attributes (thr); thr->thr_stack_base = (void *) &arg; rc = (*thr->thr_initial_function) (thr->thr_initial_argument); /* thread died, put it on the dead queue */ thread_exit (rc); /* We should never come here */ GPF_T; failed: return (void *) 1L; }
thread_t * thread_create ( thread_init_func initial_function, unsigned long stack_size, void *init_arg) { thread_t *thr; assert (_main_thread != NULL); if (stack_size == 0) stack_size = THREAD_STACK_SIZE; #if (SIZEOF_VOID_P == 8) stack_size *= 2; #endif #if defined (__x86_64 ) && defined (SOLARIS) /*GK: the LDAP on that platform requires that */ stack_size *= 2; #endif /* Any free threads with the right stack size? */ for (thr = (thread_t *) _deadq.thq_head.thr_next; thr != (thread_t *) &_deadq.thq_head; thr = (thread_t *) thr->thr_hdr.thr_next) { if (thr->thr_stack_size >= stack_size) break; } if (thr == (thread_t *) &_deadq.thq_head) { /* No free fiber, create a new one */ thr = thread_allocate (); _fiber_for_thread (thr, stack_size); _thread_num_total++; } else { /* Set new context for the thread */ memcpy (thr->thr_context, thr->thr_init_context, sizeof (jmp_buf)); } thr->thr_initial_function = initial_function; thr->thr_initial_argument = init_arg; thread_set_priority (thr, NORMAL_PRIORITY); _thread_init_attributes (thr); _fiber_status (thr, RUNNABLE); return thr; }
/* * The main thread must call this function to convert itself into a thread. */ thread_t * thread_initial (unsigned long stack_size) { if (_main_thread) return _main_thread; else { NEW_VARZ (thread_t, thr); _main_thread = thr; thr->thr_status = RUNNING; thr->thr_sem = semaphore_allocate (0); thr->thr_schedule_sem = semaphore_allocate (0); _thread_init_attributes (thr); thread_set_priority (thr, NORMAL_PRIORITY); return thr; } }
/* * The main thread must call this function to convert itself into a fiber. */ thread_t * thread_initial (unsigned long stack_size) { static unsigned int marker = THREAD_STACK_MARKER; if (_current_fiber) return _current_fiber; else { NEW_VARZ (thread_t, thr); assert (_current_fiber == NULL); _main_thread = _current_fiber = thr; _sched_init (); if (stack_size == 0) stack_size = MAIN_STACK_SIZE; #if (SIZEOF_VOID_P == 8) stack_size *= 2; #endif #if defined (__x86_64 ) && defined (SOLARIS) /*GK: the LDAP on that platform requires that */ stack_size *= 2; #endif thr->thr_stack_marker = ▮ thr->thr_sem = semaphore_allocate (0); thr->thr_schedule_sem = semaphore_allocate (0); thread_set_priority (thr, NORMAL_PRIORITY); _thread_init_attributes (thr); _fiber_for_thread (thr, stack_size); _fiber_status (thr, RUNNING); return thr; } }
thread_t * thread_attach (void) { thread_t *thr; int rc; thr = thread_alloc (); thr->thr_stack_size = (unsigned long) -1; thr->thr_attached = 1; if (thr->thr_cv == NULL) goto failed; *((pthread_t *) thr->thr_handle) = pthread_self (); rc = pthread_setspecific (_key_current, thr); CKRET (rc); /* Store the context so we can easily restart a dead thread */ setjmp (thr->thr_init_context); thr->thr_status = RUNNING; _thread_init_attributes (thr); thr->thr_stack_base = 0; return thr; failed: if (thr->thr_sem) semaphore_free (thr->thr_sem); if (thr->thr_schedule_sem) semaphore_free (thr->thr_schedule_sem); if (thr->thr_handle) dk_free (thr->thr_handle, sizeof (pthread_t)); dk_free (thr, sizeof (thread_t)); return NULL; }
/* * The main thread must call this function to convert itself into a thread. */ thread_t * thread_initial (unsigned long stack_size) { int rc; thread_t *thr = NULL; if (_main_thread) return _main_thread; /* * Initialize pthread key */ #ifndef OLD_PTHREADS rc = pthread_key_create (&_key_current, NULL); #else rc = pthread_keycreate (&_key_current, NULL); #endif CKRET (rc); /* * Start off with a value of NULL */ rc = pthread_setspecific (_key_current, NULL); CKRET (rc); /* * Initialize default thread/mutex attributes */ #ifndef OLD_PTHREADS /* attribute for thread creation */ rc = pthread_attr_init (&_thread_attr); CKRET (rc); /* attribute for mutex creation */ rc = pthread_mutexattr_init (&_mutex_attr); CKRET (rc); #else rc = pthread_attr_create (&_thread_attr); CKRET (rc); rc = pthread_mutexattr_create (&_mutex_attr); CKRET (rc); #endif #if defined (PTHREAD_PROCESS_PRIVATE) && !defined(oldlinux) && !defined(__FreeBSD__) rc = pthread_mutexattr_setpshared (&_mutex_attr, PTHREAD_PROCESS_PRIVATE); CKRET (rc); #endif #if defined (MUTEX_FAST_NP) && !defined (_AIX) rc = pthread_mutexattr_setkind_np (&_mutex_attr, MUTEX_FAST_NP); CKRET (rc); #endif #ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP rc = pthread_mutexattr_settype (&_mutex_attr, PTHREAD_MUTEX_ADAPTIVE_NP); CKRET (rc); #endif /* * Allocate a thread structure */ thr = (thread_t *) dk_alloc (sizeof (thread_t)); memset (thr, 0, sizeof (thread_t)); assert (_main_thread == NULL); _main_thread = thr; _sched_init (); if (stack_size == 0) stack_size = MAIN_STACK_SIZE; #if (SIZEOF_VOID_P == 8) stack_size *= 2; #endif #if defined (__x86_64 ) && defined (SOLARIS) /*GK: the LDAP on that platform requires that */ stack_size *= 2; #endif stack_size = ((stack_size / 8192) + 1) * 8192; thr->thr_stack_size = stack_size; thr->thr_status = RUNNING; thr->thr_cv = _alloc_cv (); thr->thr_sem = semaphore_allocate (0); thr->thr_schedule_sem = semaphore_allocate (0); if (thr->thr_cv == NULL) goto failed; _thread_init_attributes (thr); thread_set_priority (thr, NORMAL_PRIORITY); rc = pthread_setspecific (_key_current, thr); CKRET (rc); return thr; failed: if (thr) { _thread_free_attributes (thr); dk_free (thr, sizeof (thread_t)); } return NULL; }