static void * _thr_rtld_lock_create(void) { struct rtld_kse_lock *l; if ((l = malloc(sizeof(struct rtld_kse_lock))) != NULL) { _lock_init(&l->lck, LCK_ADAPTIVE, _kse_lock_wait, _kse_lock_wakeup, calloc); l->owner = NULL; l->count = 0; l->write = 0; } return (l); }
int _lock_reinit(struct lock *lck, enum lock_type ltype, lock_handler_t *waitfunc, lock_handler_t *wakeupfunc) { if (lck == NULL) return (-1); else if (lck->l_head == NULL) return (_lock_init(lck, ltype, waitfunc, wakeupfunc, calloc)); else { lck->l_head->lr_locked = 0; lck->l_head->lr_watcher = NULL; lck->l_head->lr_owner = NULL; lck->l_head->lr_active = 1; lck->l_tail = lck->l_head; } return (0); }
static int thr_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutex_attr, void *(calloc_cb)(size_t, size_t)) { struct pthread_mutex *pmutex; enum pthread_mutextype type; int protocol; int ceiling; int flags; int ret = 0; if (mutex == NULL) ret = EINVAL; /* Check if default mutex attributes: */ else if (mutex_attr == NULL || *mutex_attr == NULL) { /* Default to a (error checking) POSIX mutex: */ type = PTHREAD_MUTEX_ERRORCHECK; protocol = PTHREAD_PRIO_NONE; ceiling = THR_MAX_PRIORITY; flags = 0; } /* Check mutex type: */ else if (((*mutex_attr)->m_type < PTHREAD_MUTEX_ERRORCHECK) || ((*mutex_attr)->m_type >= PTHREAD_MUTEX_TYPE_MAX)) /* Return an invalid argument error: */ ret = EINVAL; /* Check mutex protocol: */ else if (((*mutex_attr)->m_protocol < PTHREAD_PRIO_NONE) || ((*mutex_attr)->m_protocol > PTHREAD_MUTEX_RECURSIVE)) /* Return an invalid argument error: */ ret = EINVAL; else { /* Use the requested mutex type and protocol: */ type = (*mutex_attr)->m_type; protocol = (*mutex_attr)->m_protocol; ceiling = (*mutex_attr)->m_ceiling; flags = (*mutex_attr)->m_flags; } /* Check no errors so far: */ if (ret == 0) { if ((pmutex = (pthread_mutex_t) calloc_cb(1, sizeof(struct pthread_mutex))) == NULL) ret = ENOMEM; else if (_lock_init(&pmutex->m_lock, LCK_ADAPTIVE, _thr_lock_wait, _thr_lock_wakeup, calloc_cb) != 0) { free(pmutex); *mutex = NULL; ret = ENOMEM; } else { /* Set the mutex flags: */ pmutex->m_flags = flags; /* Process according to mutex type: */ switch (type) { /* case PTHREAD_MUTEX_DEFAULT: */ case PTHREAD_MUTEX_ERRORCHECK: case PTHREAD_MUTEX_NORMAL: case PTHREAD_MUTEX_ADAPTIVE_NP: /* Nothing to do here. */ break; /* Single UNIX Spec 2 recursive mutex: */ case PTHREAD_MUTEX_RECURSIVE: /* Reset the mutex count: */ pmutex->m_count = 0; break; /* Trap invalid mutex types: */ default: /* Return an invalid argument error: */ ret = EINVAL; break; } if (ret == 0) { /* Initialise the rest of the mutex: */ TAILQ_INIT(&pmutex->m_queue); pmutex->m_flags |= MUTEX_FLAGS_INITED; pmutex->m_owner = NULL; pmutex->m_type = type; pmutex->m_protocol = protocol; pmutex->m_refcount = 0; if (protocol == PTHREAD_PRIO_PROTECT) pmutex->m_prio = ceiling; else pmutex->m_prio = -1; pmutex->m_saved_prio = 0; MUTEX_INIT_LINK(pmutex); *mutex = pmutex; } else { /* Free the mutex lock structure: */ MUTEX_DESTROY(pmutex); *mutex = NULL; } } } /* Return the completion status: */ return (ret); }
static void init_private(void) { struct clockinfo clockinfo; size_t len; int mib[2]; /* * Avoid reinitializing some things if they don't need to be, * e.g. after a fork(). */ if (init_once == 0) { /* Find the stack top */ mib[0] = CTL_KERN; mib[1] = KERN_USRSTACK; len = sizeof (_usrstack); if (sysctl(mib, 2, &_usrstack, &len, NULL, 0) == -1) PANIC("Cannot get kern.usrstack from sysctl"); /* Get the kernel clockrate: */ mib[0] = CTL_KERN; mib[1] = KERN_CLOCKRATE; len = sizeof (struct clockinfo); if (sysctl(mib, 2, &clockinfo, &len, NULL, 0) == 0) _clock_res_usec = 1000000 / clockinfo.stathz; else _clock_res_usec = CLOCK_RES_USEC; _thr_page_size = getpagesize(); _thr_guard_default = _thr_page_size; if (sizeof(void *) == 8) { _thr_stack_default = THR_STACK64_DEFAULT; _thr_stack_initial = THR_STACK64_INITIAL; } else { _thr_stack_default = THR_STACK32_DEFAULT; _thr_stack_initial = THR_STACK32_INITIAL; } _pthread_attr_default.guardsize_attr = _thr_guard_default; _pthread_attr_default.stacksize_attr = _thr_stack_default; TAILQ_INIT(&_thr_atfork_list); init_once = 1; /* Don't do this again. */ } else { /* * Destroy the locks before creating them. We don't * know what state they are in so it is better to just * recreate them. */ _lock_destroy(&_thread_signal_lock); _lock_destroy(&_mutex_static_lock); _lock_destroy(&_rwlock_static_lock); _lock_destroy(&_keytable_lock); } /* Initialize everything else. */ TAILQ_INIT(&_thread_list); TAILQ_INIT(&_thread_gc_list); _pthread_mutex_init(&_thr_atfork_mutex, NULL); /* * Initialize the lock for temporary installation of signal * handlers (to support sigwait() semantics) and for the * process signal mask and pending signal sets. */ if (_lock_init(&_thread_signal_lock, LCK_ADAPTIVE, _kse_lock_wait, _kse_lock_wakeup, calloc) != 0) PANIC("Cannot initialize _thread_signal_lock"); if (_lock_init(&_mutex_static_lock, LCK_ADAPTIVE, _thr_lock_wait, _thr_lock_wakeup, calloc) != 0) PANIC("Cannot initialize mutex static init lock"); if (_lock_init(&_rwlock_static_lock, LCK_ADAPTIVE, _thr_lock_wait, _thr_lock_wakeup, calloc) != 0) PANIC("Cannot initialize rwlock static init lock"); if (_lock_init(&_keytable_lock, LCK_ADAPTIVE, _thr_lock_wait, _thr_lock_wakeup, calloc) != 0) PANIC("Cannot initialize thread specific keytable lock"); _thr_spinlock_init(); /* Clear pending signals and get the process signal mask. */ SIGEMPTYSET(_thr_proc_sigpending); /* Are we in M:N mode (default) or 1:1 mode? */ #ifdef SYSTEM_SCOPE_ONLY _thread_scope_system = 1; #else if (getenv("LIBPTHREAD_SYSTEM_SCOPE") != NULL) _thread_scope_system = 1; else if (getenv("LIBPTHREAD_PROCESS_SCOPE") != NULL) _thread_scope_system = -1; #endif if (getenv("LIBPTHREAD_DEBUG") != NULL) _thr_debug_flags |= DBG_INFO_DUMP; /* * _thread_list_lock and _kse_count are initialized * by _kse_init() */ }
int _pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr) { enum pthread_cond_type type; pthread_cond_t pcond; int flags; int rval = 0; if (cond == NULL) rval = EINVAL; else { /* * Check if a pointer to a condition variable attribute * structure was passed by the caller: */ if (cond_attr != NULL && *cond_attr != NULL) { /* Default to a fast condition variable: */ type = (*cond_attr)->c_type; flags = (*cond_attr)->c_flags; } else { /* Default to a fast condition variable: */ type = COND_TYPE_FAST; flags = 0; } /* Process according to condition variable type: */ switch (type) { /* Fast condition variable: */ case COND_TYPE_FAST: /* Nothing to do here. */ break; /* Trap invalid condition variable types: */ default: /* Return an invalid argument error: */ rval = EINVAL; break; } /* Check for no errors: */ if (rval == 0) { if ((pcond = (pthread_cond_t) malloc(sizeof(struct pthread_cond))) == NULL) { rval = ENOMEM; } else if (_lock_init(&pcond->c_lock, LCK_ADAPTIVE, _thr_lock_wait, _thr_lock_wakeup, calloc) != 0) { free(pcond); rval = ENOMEM; } else { /* * Initialise the condition variable * structure: */ TAILQ_INIT(&pcond->c_queue); pcond->c_flags = COND_FLAGS_INITED; pcond->c_type = type; pcond->c_mutex = NULL; pcond->c_seqno = 0; *cond = pcond; } } } /* Return the completion status: */ return (rval); }