On May 30, 10:33am, charles.cui1...@gmail.com (Charles Cui) wrote: -- Subject: Re: pthread library related
Inline comments. christos diff --git a/lib/libpthread/pthread.h b/lib/libpthread/pthread.h index 5970378..ed16d7c 100644 --- a/lib/libpthread/pthread.h +++ b/lib/libpthread/pthread.h @@ -94,6 +94,9 @@ int pthread_mutex_destroy(pthread_mutex_t *); int pthread_mutex_lock(pthread_mutex_t *); int pthread_mutex_trylock(pthread_mutex_t *); int pthread_mutex_unlock(pthread_mutex_t *); +int pthread_mutex_timedlock(pthread_mutex_t *, const struct timespec*__restrict); +int pthread_mutex_getprioceiling(const pthread_mutex_t *__restrict, int*__restrict); +int pthread_mutex_setprioceiling(pthread_mutex_t* __restrict, int, int*__restrict); Wrap lines, whitespace "const struct timespec *__restrict" etc. (space after the type name) +int pthread_mutexattr_getprotocol(const pthread_mutexattr_t * __restrict, int*__restrict); +int pthread_mutexattr_setprotocol(pthread_mutexattr_t* , int); +int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *__restrict,int*__restrict); +int pthread_mutexattr_setprioceiling(pthread_mutexattr_t*, int); Again int pthread_cond_init(pthread_cond_t * __restrict, const pthread_condattr_t * __restrict); int pthread_cond_destroy(pthread_cond_t *); @@ -116,7 +122,7 @@ int pthread_cond_broadcast(pthread_cond_t *); int pthread_condattr_init(pthread_condattr_t *); #if defined(_NETBSD_SOURCE) int pthread_condattr_setclock(pthread_condattr_t *, clockid_t); -int pthread_condattr_getclock(pthread_condattr_t *); +int pthread_condattr_getclock(const pthread_condattr_t *__restrict attr, clockid_t *__restrict clock_id); Again (wrap) int -pthread_condattr_getclock(pthread_condattr_t *attr) +pthread_condattr_getclock(const pthread_condattr_t *__restrict attr, clockid_t *__restrict clock_id) Wrap { if (attr == NULL || attr->ptca_private == NULL) return EINVAL; - return *(int *)attr->ptca_private; + *clock_id = *(clockid_t*)attr->ptca_private; Whitespace before * + return 0; } int diff --git a/lib/libpthread/pthread_mutex.c b/lib/libpthread/pthread_mutex.c index e755ade..ec46070 100644 --- a/lib/libpthread/pthread_mutex.c +++ b/lib/libpthread/pthread_mutex.c @@ -51,6 +51,7 @@ __RCSID("$NetBSD: pthread_mutex.c,v 1.59 2014/02/03 15:51:01 rmind Exp $"); #include <sys/types.h> #include <sys/lwpctl.h> +#include <sys/sched.h> #include <sys/lock.h> #include <errno.h> @@ -67,10 +68,12 @@ __RCSID("$NetBSD: pthread_mutex.c,v 1.59 2014/02/03 15:51:01 rmind Exp $"); #define MUTEX_WAITERS_BIT ((uintptr_t)0x01) #define MUTEX_RECURSIVE_BIT ((uintptr_t)0x02) #define MUTEX_DEFERRED_BIT ((uintptr_t)0x04) +#define MUTEX_PROTECT_BIT ((uintptr_t)0x08) #define MUTEX_THREAD ((uintptr_t)-16L) #define MUTEX_HAS_WAITERS(x) ((uintptr_t)(x) & MUTEX_WAITERS_BIT) #define MUTEX_RECURSIVE(x) ((uintptr_t)(x) & MUTEX_RECURSIVE_BIT) +#define MUTEX_PROTECT(x) ((uintptr_t)(x) & MUTEX_PROTECT_BIT) #define MUTEX_OWNER(x) ((uintptr_t)(x) & MUTEX_THREAD) #if __GNUC_PREREQ__(3, 0) @@ -80,7 +83,7 @@ __RCSID("$NetBSD: pthread_mutex.c,v 1.59 2014/02/03 15:51:01 rmind Exp $"); #endif static void pthread__mutex_wakeup(pthread_t, pthread_mutex_t *); -static int pthread__mutex_lock_slow(pthread_mutex_t *); +static int pthread__mutex_lock_slow(pthread_mutex_t *, const struct timespec*); wrap and space static int pthread__mutex_unlock_slow(pthread_mutex_t *); static void pthread__mutex_pause(void); @@ -103,16 +106,21 @@ __strong_alias(__libc_mutexattr_settype,pthread_mutexattr_settype) int pthread_mutex_init(pthread_mutex_t *ptm, const pthread_mutexattr_t *attr) { - intptr_t type; + uintptr_t type, proto, val, ceil; if (__predict_false(__uselibcstub)) return __libc_mutex_init_stub(ptm, attr); - if (attr == NULL) + if (attr == NULL) { type = PTHREAD_MUTEX_NORMAL; - else - type = (intptr_t)attr->ptma_private; - + proto = PTHREAD_PRIO_NONE; + ceil = 0; + } else { + val = (uintptr_t)attr->ptma_private; + type = val & 0xff; + proto = (val & 0xff00) >> 8; + ceil = (val & 0xff0000) >> 16; + } switch (type) { case PTHREAD_MUTEX_ERRORCHECK: __cpu_simple_lock_set(&ptm->ptm_errorcheck); @@ -127,10 +135,17 @@ pthread_mutex_init(pthread_mutex_t *ptm, const pthread_mutexattr_t *attr) ptm->ptm_owner = NULL; break; } - + switch (proto) { + case PTHREAD_PRIO_PROTECT: + val = (uintptr_t)ptm->ptm_owner; + val |= MUTEX_PROTECT_BIT; + ptm->ptm_owner = (void*)val; space + break; + } ptm->ptm_magic = _PT_MUTEX_MAGIC; ptm->ptm_waiters = NULL; ptm->ptm_recursed = 0; + ptm->ptm_ceiling = (unsigned char)ceil; return 0; } @@ -168,7 +183,24 @@ pthread_mutex_lock(pthread_mutex_t *ptm) #endif return 0; } - return pthread__mutex_lock_slow(ptm); + return pthread__mutex_lock_slow(ptm, NULL); +} + +int +pthread_mutex_timedlock(pthread_mutex_t* ptm, const struct timespec *ts) +{ + pthread_t self; + void *val; + + self = pthread__self(); + val = atomic_cas_ptr(&ptm->ptm_owner, NULL, self); + if (__predict_true(val == NULL)) { +#ifndef PTHREAD__ATOMIC_IS_MEMBAR + membar_enter(); +#endif + return 0; + } + return pthread__mutex_lock_slow(ptm, ts); } /* We want function call overhead. */ @@ -258,11 +290,12 @@ again: } NOINLINE static int -pthread__mutex_lock_slow(pthread_mutex_t *ptm) +pthread__mutex_lock_slow(pthread_mutex_t *ptm, const struct timespec *ts) { void *waiters, *new, *owner, *next; pthread_t self; int serrno; + int error; pthread__error(EINVAL, "Invalid mutex", ptm->ptm_magic == _PT_MUTEX_MAGIC); @@ -282,6 +315,10 @@ pthread__mutex_lock_slow(pthread_mutex_t *ptm) return EDEADLK; } + /*priority protect*/ + if (MUTEX_PROTECT(owner) && _sched_protect(ptm->ptm_ceiling) == -1) { + return errno; + } serrno = errno; for (;; owner = ptm->ptm_owner) { /* Spin while the owner is running. */ @@ -339,12 +376,23 @@ pthread__mutex_lock_slow(pthread_mutex_t *ptm) */ while (self->pt_mutexwait) { self->pt_blocking++; - (void)_lwp_park(CLOCK_REALTIME, TIMER_ABSTIME, NULL, + error = _lwp_park(CLOCK_REALTIME, TIMER_ABSTIME, ts, self->pt_unpark, __UNVOLATILE(&ptm->ptm_waiters), __UNVOLATILE(&ptm->ptm_waiters)); self->pt_unpark = 0; self->pt_blocking--; membar_sync(); + if (__predict_true(error != -1)) { + continue; + } + if (errno == ETIMEDOUT && self->pt_mutexwait) { + /*Remove self from waiters list*/ + pthread__mutex_wakeup(self, ptm); + /*priority protect*/ + if (MUTEX_PROTECT(owner)) + (void)_sched_protect(-1); + return ETIMEDOUT; + } } } } @@ -460,6 +508,10 @@ pthread__mutex_unlock_slow(pthread_mutex_t *ptm) */ if (new != owner) { owner = atomic_swap_ptr(&ptm->ptm_owner, new); + if (__predict_false(MUTEX_PROTECT(owner))) { + /*restore elevated priority*/ + (void)_sched_protect(-1); + } if (MUTEX_HAS_WAITERS(owner) != 0) { pthread__mutex_wakeup(self, ptm); return 0; @@ -591,16 +643,21 @@ pthread_mutexattr_destroy(pthread_mutexattr_t *attr) int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *typep) { + uintptr_t val; + pthread__error(EINVAL, "Invalid mutex attribute", attr->ptma_magic == _PT_MUTEXATTR_MAGIC); - *typep = (int)(intptr_t)attr->ptma_private; + val = (uintptr_t)attr->ptma_private & ~0x00ffL; + *typep = (int)val; I'd use a constant for 0x00ff, instead of repeating it everywhere. In fact I'd define and use accessor macros for fields setting and getting return 0; } int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) { + uintptr_t val; + if (__predict_false(__uselibcstub)) return __libc_mutexattr_settype_stub(attr, type); @@ -611,7 +668,8 @@ pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) case PTHREAD_MUTEX_NORMAL: case PTHREAD_MUTEX_ERRORCHECK: case PTHREAD_MUTEX_RECURSIVE: - attr->ptma_private = (void *)(intptr_t)type; + val = (uintptr_t)attr->ptma_private & ~0x00ffL; + attr->ptma_private = (void*)(val | type); return 0; default: return EINVAL; @@ -619,6 +677,67 @@ pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) } int +pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr, int*proto) +{ + uintptr_t val; + + pthread__error(EINVAL, "Invalid mutex attribute", + attr->ptma_magic == _PT_MUTEXATTR_MAGIC); + + val = (uintptr_t)attr->ptma_private & ~0xff00L; + *proto = (int)(val >> 8); + return 0; +} + +int +pthread_mutexattr_setprotocol(pthread_mutexattr_t* attr, int proto) +{ + uintptr_t val; + + pthread__error(EINVAL, "Invalid mutex attribute", + attr->ptma_magic == _PT_MUTEXATTR_MAGIC); + + switch (proto) { + case PTHREAD_PRIO_NONE: + case PTHREAD_PRIO_PROTECT: + val = (uintptr_t)attr->ptma_private & ~0xff00L; + attr->ptma_private = (void *)(val | (proto << 8)); + return 0; + case PTHREAD_PRIO_INHERIT: + return ENOTSUP; + default: + return EINVAL; + } +} + +int +pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *attr, int *ceil) +{ + uintptr_t val; + + pthread__error(EINVAL, "Invalid mutex attribute", + attr->ptma_magic == _PT_MUTEXATTR_MAGIC); + + val = (uintptr_t)attr->ptma_private & ~0xff0000L; + *ceil = (int)(val >> 16); + return 0; +} + +int +pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr, int ceil) +{ + uintptr_t val; + + pthread__error(EINVAL, "Invalid mutex attribute", + attr->ptma_magic == _PT_MUTEXATTR_MAGIC); Indent, second level indent is 4 spaces + + /*check range*/ + val = (uintptr_t)attr->ptma_private & ~0xff0000L; + attr->ptma_private = (void*)(val | (ceil << 16)); + return 0; +} + +int pthread_mutexattr_getpshared(const pthread_mutexattr_t *__restrict attr, int* __restrict pshared) { *pshared = PTHREAD_PROCESS_PRIVATE; return 0; @@ -662,6 +781,28 @@ pthread__mutex_deferwake(pthread_t self, pthread_mutex_t *ptm) } int +pthread_mutex_getprioceiling(const pthread_mutex_t *ptm, int*ceil) +{ + *ceil = (unsigned int)ptm->ptm_ceiling; + return 0; +} + +int +pthread_mutex_setprioceiling(pthread_mutex_t *ptm, int ceil, int *old_ceil) +{ + int error; + + error = pthread_mutex_lock(ptm); + if (error == 0) { + *old_ceil = (unsigned int)ptm->ptm_ceiling; + /*check range*/ + ptm->ptm_ceiling = (unsigned char)ceil; + pthread_mutex_unlock(ptm); + } + return error; +} + +int _pthread_mutex_held_np(pthread_mutex_t *ptm) { diff --git a/lib/libpthread/pthread_types.h b/lib/libpthread/pthread_types.h index a25be8e..7981348 100644 --- a/lib/libpthread/pthread_types.h +++ b/lib/libpthread/pthread_types.h @@ -115,7 +115,7 @@ struct __pthread_mutex_st { #ifdef __CPU_SIMPLE_LOCK_PAD uint8_t ptm_pad1[3]; #endif - __pthread_spin_t ptm_interlock; /* unused - backwards compat */ + __pthread_spin_t ptm_ceiling; #ifdef __CPU_SIMPLE_LOCK_PAD uint8_t ptm_pad2[3]; #endif @@ -130,14 +130,14 @@ struct __pthread_mutex_st { #ifdef __CPU_SIMPLE_LOCK_PAD #define _PTHREAD_MUTEX_INITIALIZER { _PT_MUTEX_MAGIC, \ - __SIMPLELOCK_UNLOCKED, { 0, 0, 0 }, \ + __SIMPLELOCK_UNLOCKED, { 0, 0, 0 }, \ __SIMPLELOCK_UNLOCKED, { 0, 0, 0 }, \ NULL, NULL, 0, NULL \ } #else #define _PTHREAD_MUTEX_INITIALIZER { _PT_MUTEX_MAGIC, \ - __SIMPLELOCK_UNLOCKED, \ - __SIMPLELOCK_UNLOCKED, \ + __SIMPLELOCK_UNLOCKED, \ + __SIMPLELOCK_UNLOCKED, \ NULL, NULL, 0, NULL \ } These were not changed, why are there whitespace diffs? christos