Changeset View
Changeset View
Standalone View
Standalone View
head/lib/libthr/thread/thr_mutex.c
Show First 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | |||||
* For adaptive mutexes, how many times to spin doing trylock2 | * For adaptive mutexes, how many times to spin doing trylock2 | ||||
* before entering the kernel to block | * before entering the kernel to block | ||||
*/ | */ | ||||
#define MUTEX_ADAPTIVE_SPINS 2000 | #define MUTEX_ADAPTIVE_SPINS 2000 | ||||
/* | /* | ||||
* Prototypes | * Prototypes | ||||
*/ | */ | ||||
int __pthread_mutex_consistent(pthread_mutex_t *mutex); | |||||
int __pthread_mutex_init(pthread_mutex_t * __restrict mutex, | |||||
const pthread_mutexattr_t * __restrict mutex_attr); | |||||
int __pthread_mutex_trylock(pthread_mutex_t *mutex); | |||||
int __pthread_mutex_lock(pthread_mutex_t *mutex); | |||||
int __pthread_mutex_timedlock(pthread_mutex_t * __restrict mutex, | int __pthread_mutex_timedlock(pthread_mutex_t * __restrict mutex, | ||||
const struct timespec * __restrict abstime); | const struct timespec * __restrict abstime); | ||||
int _pthread_mutex_getspinloops_np(pthread_mutex_t *mutex, int *count); | int _pthread_mutex_getspinloops_np(pthread_mutex_t *mutex, int *count); | ||||
int _pthread_mutex_setspinloops_np(pthread_mutex_t *mutex, int count); | int _pthread_mutex_setspinloops_np(pthread_mutex_t *mutex, int count); | ||||
int __pthread_mutex_setspinloops_np(pthread_mutex_t *mutex, int count); | int __pthread_mutex_setspinloops_np(pthread_mutex_t *mutex, int count); | ||||
int _pthread_mutex_setyieldloops_np(pthread_mutex_t *mutex, int count); | int _pthread_mutex_setyieldloops_np(pthread_mutex_t *mutex, int count); | ||||
int _pthread_mutex_getyieldloops_np(pthread_mutex_t *mutex, int *count); | int _pthread_mutex_getyieldloops_np(pthread_mutex_t *mutex, int *count); | ||||
int __pthread_mutex_setyieldloops_np(pthread_mutex_t *mutex, int count); | int __pthread_mutex_setyieldloops_np(pthread_mutex_t *mutex, int count); | ||||
static int mutex_self_trylock(pthread_mutex_t); | static int mutex_self_trylock(pthread_mutex_t); | ||||
static int mutex_self_lock(pthread_mutex_t, | static int mutex_self_lock(pthread_mutex_t, | ||||
const struct timespec *abstime); | const struct timespec *abstime); | ||||
static int mutex_unlock_common(struct pthread_mutex *, bool, int *); | static int mutex_unlock_common(struct pthread_mutex *, bool, int *); | ||||
static int mutex_lock_sleep(struct pthread *, pthread_mutex_t, | static int mutex_lock_sleep(struct pthread *, pthread_mutex_t, | ||||
const struct timespec *); | const struct timespec *); | ||||
static void mutex_init_robust(struct pthread *curthread); | static void mutex_init_robust(struct pthread *curthread); | ||||
static int mutex_qidx(struct pthread_mutex *m); | static int mutex_qidx(struct pthread_mutex *m); | ||||
static bool is_robust_mutex(struct pthread_mutex *m); | static bool is_robust_mutex(struct pthread_mutex *m); | ||||
static bool is_pshared_mutex(struct pthread_mutex *m); | static bool is_pshared_mutex(struct pthread_mutex *m); | ||||
__weak_reference(__pthread_mutex_init, pthread_mutex_init); | __weak_reference(__Tthr_mutex_init, pthread_mutex_init); | ||||
__strong_reference(__pthread_mutex_init, _pthread_mutex_init); | __weak_reference(__Tthr_mutex_init, __pthread_mutex_init); | ||||
__weak_reference(__pthread_mutex_lock, pthread_mutex_lock); | __strong_reference(__Tthr_mutex_init, _pthread_mutex_init); | ||||
__strong_reference(__pthread_mutex_lock, _pthread_mutex_lock); | __weak_reference(__Tthr_mutex_lock, pthread_mutex_lock); | ||||
__weak_reference(__Tthr_mutex_lock, __pthread_mutex_lock); | |||||
__strong_reference(__Tthr_mutex_lock, _pthread_mutex_lock); | |||||
__weak_reference(__pthread_mutex_timedlock, pthread_mutex_timedlock); | __weak_reference(__pthread_mutex_timedlock, pthread_mutex_timedlock); | ||||
__strong_reference(__pthread_mutex_timedlock, _pthread_mutex_timedlock); | __strong_reference(__pthread_mutex_timedlock, _pthread_mutex_timedlock); | ||||
__weak_reference(__pthread_mutex_trylock, pthread_mutex_trylock); | __weak_reference(__Tthr_mutex_trylock, pthread_mutex_trylock); | ||||
__strong_reference(__pthread_mutex_trylock, _pthread_mutex_trylock); | __weak_reference(__Tthr_mutex_trylock, __pthread_mutex_trylock); | ||||
__weak_reference(_pthread_mutex_consistent, pthread_mutex_consistent); | __strong_reference(__Tthr_mutex_trylock, _pthread_mutex_trylock); | ||||
__strong_reference(_pthread_mutex_consistent, __pthread_mutex_consistent); | __weak_reference(_Tthr_mutex_consistent, pthread_mutex_consistent); | ||||
__weak_reference(_Tthr_mutex_consistent, _pthread_mutex_consistent); | |||||
__strong_reference(_Tthr_mutex_consistent, __pthread_mutex_consistent); | |||||
/* Single underscore versions provided for libc internal usage: */ | /* Single underscore versions provided for libc internal usage: */ | ||||
/* No difference between libc and application usage of these: */ | /* No difference between libc and application usage of these: */ | ||||
__weak_reference(_pthread_mutex_destroy, pthread_mutex_destroy); | __weak_reference(_thr_mutex_destroy, pthread_mutex_destroy); | ||||
__weak_reference(_pthread_mutex_unlock, pthread_mutex_unlock); | __weak_reference(_thr_mutex_destroy, _pthread_mutex_destroy); | ||||
__weak_reference(_thr_mutex_unlock, pthread_mutex_unlock); | |||||
__weak_reference(_thr_mutex_unlock, _pthread_mutex_unlock); | |||||
__weak_reference(_pthread_mutex_getprioceiling, pthread_mutex_getprioceiling); | __weak_reference(_pthread_mutex_getprioceiling, pthread_mutex_getprioceiling); | ||||
__weak_reference(_pthread_mutex_setprioceiling, pthread_mutex_setprioceiling); | __weak_reference(_pthread_mutex_setprioceiling, pthread_mutex_setprioceiling); | ||||
__weak_reference(__pthread_mutex_setspinloops_np, pthread_mutex_setspinloops_np); | __weak_reference(__pthread_mutex_setspinloops_np, pthread_mutex_setspinloops_np); | ||||
__strong_reference(__pthread_mutex_setspinloops_np, _pthread_mutex_setspinloops_np); | __strong_reference(__pthread_mutex_setspinloops_np, _pthread_mutex_setspinloops_np); | ||||
__weak_reference(_pthread_mutex_getspinloops_np, pthread_mutex_getspinloops_np); | __weak_reference(_pthread_mutex_getspinloops_np, pthread_mutex_getspinloops_np); | ||||
▲ Show 20 Lines • Show All 256 Lines • ▼ Show 20 Lines | for (done = false; !done;) { | ||||
default: | default: | ||||
PANIC("corrupted offpage"); | PANIC("corrupted offpage"); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
int | int | ||||
__pthread_mutex_init(pthread_mutex_t * __restrict mutex, | __Tthr_mutex_init(pthread_mutex_t * __restrict mutex, | ||||
const pthread_mutexattr_t * __restrict mutex_attr) | const pthread_mutexattr_t * __restrict mutex_attr) | ||||
{ | { | ||||
struct pthread_mutex *pmtx; | struct pthread_mutex *pmtx; | ||||
int ret; | int ret; | ||||
if (mutex_attr != NULL) { | if (mutex_attr != NULL) { | ||||
ret = mutex_check_attr(*mutex_attr); | ret = mutex_check_attr(*mutex_attr); | ||||
if (ret != 0) | if (ret != 0) | ||||
▲ Show 20 Lines • Show All 65 Lines • ▼ Show 20 Lines | _mutex_fork(struct pthread *curthread) | ||||
queue_fork(curthread, &curthread->mq[TMQ_NORM_PP], | queue_fork(curthread, &curthread->mq[TMQ_NORM_PP], | ||||
&curthread->mq[TMQ_NORM_PP_PRIV], UMUTEX_CONTESTED); | &curthread->mq[TMQ_NORM_PP_PRIV], UMUTEX_CONTESTED); | ||||
queue_fork(curthread, &curthread->mq[TMQ_ROBUST_PP], | queue_fork(curthread, &curthread->mq[TMQ_ROBUST_PP], | ||||
&curthread->mq[TMQ_ROBUST_PP_PRIV], UMUTEX_CONTESTED); | &curthread->mq[TMQ_ROBUST_PP_PRIV], UMUTEX_CONTESTED); | ||||
curthread->robust_list = 0; | curthread->robust_list = 0; | ||||
} | } | ||||
int | int | ||||
_pthread_mutex_destroy(pthread_mutex_t *mutex) | _thr_mutex_destroy(pthread_mutex_t *mutex) | ||||
{ | { | ||||
pthread_mutex_t m, m1; | pthread_mutex_t m, m1; | ||||
int ret; | int ret; | ||||
m = *mutex; | m = *mutex; | ||||
if (m < THR_MUTEX_DESTROYED) { | if (m < THR_MUTEX_DESTROYED) { | ||||
ret = 0; | ret = 0; | ||||
} else if (m == THR_MUTEX_DESTROYED) { | } else if (m == THR_MUTEX_DESTROYED) { | ||||
▲ Show 20 Lines • Show All 132 Lines • ▼ Show 20 Lines | if (*m == THR_MUTEX_DESTROYED) { | ||||
if (ret == 0) | if (ret == 0) | ||||
*m = *mutex; | *m = *mutex; | ||||
} | } | ||||
} | } | ||||
return (ret); | return (ret); | ||||
} | } | ||||
int | int | ||||
__pthread_mutex_trylock(pthread_mutex_t *mutex) | __Tthr_mutex_trylock(pthread_mutex_t *mutex) | ||||
{ | { | ||||
struct pthread *curthread; | struct pthread *curthread; | ||||
struct pthread_mutex *m; | struct pthread_mutex *m; | ||||
uint32_t id; | uint32_t id; | ||||
int ret, robust; | int ret, robust; | ||||
ret = check_and_init_mutex(mutex, &m); | ret = check_and_init_mutex(mutex, &m); | ||||
if (ret != 0) | if (ret != 0) | ||||
▲ Show 20 Lines • Show All 112 Lines • ▼ Show 20 Lines | if (!rb_onlist && robust) | ||||
_mutex_leave_robust(curthread, m); | _mutex_leave_robust(curthread, m); | ||||
if (ret != 0 && ret != EOWNERDEAD && | if (ret != 0 && ret != EOWNERDEAD && | ||||
(m->m_flags & PMUTEX_FLAG_PRIVATE) != 0 && !cvattach) | (m->m_flags & PMUTEX_FLAG_PRIVATE) != 0 && !cvattach) | ||||
THR_CRITICAL_LEAVE(curthread); | THR_CRITICAL_LEAVE(curthread); | ||||
return (ret); | return (ret); | ||||
} | } | ||||
int | int | ||||
__pthread_mutex_lock(pthread_mutex_t *mutex) | __Tthr_mutex_lock(pthread_mutex_t *mutex) | ||||
{ | { | ||||
struct pthread_mutex *m; | struct pthread_mutex *m; | ||||
int ret; | int ret; | ||||
_thr_check_init(); | _thr_check_init(); | ||||
ret = check_and_init_mutex(mutex, &m); | ret = check_and_init_mutex(mutex, &m); | ||||
if (ret == 0) | if (ret == 0) | ||||
ret = mutex_lock_common(m, NULL, false, false); | ret = mutex_lock_common(m, NULL, false, false); | ||||
Show All 10 Lines | __pthread_mutex_timedlock(pthread_mutex_t * __restrict mutex, | ||||
_thr_check_init(); | _thr_check_init(); | ||||
ret = check_and_init_mutex(mutex, &m); | ret = check_and_init_mutex(mutex, &m); | ||||
if (ret == 0) | if (ret == 0) | ||||
ret = mutex_lock_common(m, abstime, false, false); | ret = mutex_lock_common(m, abstime, false, false); | ||||
return (ret); | return (ret); | ||||
} | } | ||||
int | int | ||||
_pthread_mutex_unlock(pthread_mutex_t *mutex) | _thr_mutex_unlock(pthread_mutex_t *mutex) | ||||
{ | { | ||||
struct pthread_mutex *mp; | struct pthread_mutex *mp; | ||||
if (*mutex == THR_PSHARED_PTR) { | if (*mutex == THR_PSHARED_PTR) { | ||||
mp = __thr_pshared_offpage(mutex, 0); | mp = __thr_pshared_offpage(mutex, 0); | ||||
if (mp == NULL) | if (mp == NULL) | ||||
return (EINVAL); | return (EINVAL); | ||||
shared_mutex_init(mp, NULL); | shared_mutex_init(mp, NULL); | ||||
▲ Show 20 Lines • Show All 386 Lines • ▼ Show 20 Lines | if (__predict_false(mp <= THR_MUTEX_DESTROYED)) { | ||||
return (EPERM); | return (EPERM); | ||||
} | } | ||||
if (PMUTEX_OWNER_ID(mp) != TID(curthread)) | if (PMUTEX_OWNER_ID(mp) != TID(curthread)) | ||||
return (EPERM); | return (EPERM); | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
_pthread_mutex_consistent(pthread_mutex_t *mutex) | _Tthr_mutex_consistent(pthread_mutex_t *mutex) | ||||
{ | { | ||||
struct pthread_mutex *m; | struct pthread_mutex *m; | ||||
struct pthread *curthread; | struct pthread *curthread; | ||||
if (*mutex == THR_PSHARED_PTR) { | if (*mutex == THR_PSHARED_PTR) { | ||||
m = __thr_pshared_offpage(mutex, 0); | m = __thr_pshared_offpage(mutex, 0); | ||||
if (m == NULL) | if (m == NULL) | ||||
return (EINVAL); | return (EINVAL); | ||||
Show All 15 Lines |