summaryrefslogtreecommitdiffstats
path: root/lib/libthr
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libthr')
-rw-r--r--lib/libthr/thread/thr_private.h2
-rw-r--r--lib/libthr/thread/thr_umtx.h21
2 files changed, 18 insertions, 5 deletions
diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h
index 4b9219d..87af318 100644
--- a/lib/libthr/thread/thr_private.h
+++ b/lib/libthr/thread/thr_private.h
@@ -834,8 +834,6 @@ ssize_t __sys_write(int, const void *, size_t);
void __sys_exit(int);
#endif
-int _umtx_op_err(void *, int op, u_long, void *, void *) __hidden;
-
static inline int
_thr_isthreaded(void)
{
diff --git a/lib/libthr/thread/thr_umtx.h b/lib/libthr/thread/thr_umtx.h
index 61a74a8..d74cc81 100644
--- a/lib/libthr/thread/thr_umtx.h
+++ b/lib/libthr/thread/thr_umtx.h
@@ -35,6 +35,7 @@
#define DEFAULT_UMUTEX {0,0,{0,0},{0,0,0,0}}
#define DEFAULT_URWLOCK {0,0,0,0,{0,0,0,0}}
+int _umtx_op_err(void *, int op, u_long, void *, void *) __hidden;
int __thr_umutex_lock(struct umutex *mtx, uint32_t id) __hidden;
int __thr_umutex_lock_spin(struct umutex *mtx, uint32_t id) __hidden;
int __thr_umutex_timedlock(struct umutex *mtx, uint32_t id,
@@ -121,9 +122,23 @@ _thr_umutex_timedlock(struct umutex *mtx, uint32_t id,
static inline int
_thr_umutex_unlock(struct umutex *mtx, uint32_t id)
{
- if (atomic_cmpset_rel_32(&mtx->m_owner, id, UMUTEX_UNOWNED))
- return (0);
- return (__thr_umutex_unlock(mtx, id));
+ uint32_t flags = mtx->m_flags;
+
+ if ((flags & (UMUTEX_PRIO_PROTECT | UMUTEX_PRIO_INHERIT)) == 0) {
+ uint32_t owner;
+ do {
+ owner = mtx->m_owner;
+ if (__predict_false((owner & ~UMUTEX_CONTESTED) != id))
+ return (EPERM);
+ } while (__predict_false(!atomic_cmpset_rel_32(&mtx->m_owner,
+ owner, UMUTEX_UNOWNED)));
+ if ((owner & UMUTEX_CONTESTED))
+ (void)_umtx_op_err(mtx, UMTX_OP_MUTEX_WAKE2, flags, 0, 0);
+ return (0);
+ }
+ if (atomic_cmpset_rel_32(&mtx->m_owner, id, UMUTEX_UNOWNED))
+ return (0);
+ return (__thr_umutex_unlock(mtx, id));
}
static inline int
OpenPOWER on IntegriCloud