int _lock_init(struct lock *lck, enum lock_type ltype, lock_handler_t *waitfunc, lock_handler_t *wakeupfunc, void *(calloc_cb)(size_t, size_t)) { if (lck == NULL) return (-1); else if ((lck->l_head = calloc_cb(1, sizeof(struct lockreq))) == NULL) return (-1); else { lck->l_type = ltype; lck->l_wait = waitfunc; lck->l_wakeup = wakeupfunc; 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); }