summaryrefslogtreecommitdiffstats
path: root/lib/libthr/thread/thr_mutex.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libthr/thread/thr_mutex.c')
-rw-r--r--lib/libthr/thread/thr_mutex.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/lib/libthr/thread/thr_mutex.c b/lib/libthr/thread/thr_mutex.c
index c08ee81..b1e6d0c 100644
--- a/lib/libthr/thread/thr_mutex.c
+++ b/lib/libthr/thread/thr_mutex.c
@@ -39,6 +39,8 @@
#include <string.h>
#include <sys/param.h>
#include <sys/queue.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
#include <pthread.h>
#include "un-namespace.h"
@@ -65,6 +67,12 @@
#endif
/*
+ * For adaptive mutexes, how many times to spin doing trylock2
+ * before entering the kernel to block
+ */
+#define MUTEX_ADAPTIVE_SPINS 200
+
+/*
* Prototypes
*/
int __pthread_mutex_init(pthread_mutex_t *mutex,
@@ -355,6 +363,25 @@ mutex_lock_common(struct pthread *curthread, pthread_mutex_t *mutex,
} else if (m->m_owner == curthread) {
ret = mutex_self_lock(m, abstime);
} else {
+ /*
+ * For adaptive mutexes, spin for a bit in the expectation
+ * that if the application requests this mutex type then
+ * the lock is likely to be released quickly and it is
+ * faster than entering the kernel
+ */
+ if (m->m_type == PTHREAD_MUTEX_ADAPTIVE_NP) {
+ int count = MUTEX_ADAPTIVE_SPINS;
+
+ while (count--) {
+ ret = _thr_umutex_trylock2(&m->m_lock, id);
+ if (ret == 0)
+ break;
+ cpu_spinwait();
+ }
+ }
+ if (ret == 0)
+ goto done;
+
if (abstime == NULL) {
ret = __thr_umutex_lock(&m->m_lock);
} else if (__predict_false(
@@ -372,6 +399,7 @@ mutex_lock_common(struct pthread *curthread, pthread_mutex_t *mutex,
if (ret == EINTR)
ret = ETIMEDOUT;
}
+done:
if (ret == 0) {
m->m_owner = curthread;
/* Add to the list of owned mutexes: */
@@ -501,6 +529,7 @@ mutex_self_trylock(pthread_mutex_t m)
switch (m->m_type) {
case PTHREAD_MUTEX_ERRORCHECK:
case PTHREAD_MUTEX_NORMAL:
+ case PTHREAD_MUTEX_ADAPTIVE_NP:
ret = EBUSY;
break;
OpenPOWER on IntegriCloud