summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/pthread.h2
-rw-r--r--lib/libkse/thread/thr_mutex.c3
-rw-r--r--lib/libthr/thread/thr_mutex.c29
3 files changed, 34 insertions, 0 deletions
diff --git a/include/pthread.h b/include/pthread.h
index ee864fd..361b45c 100644
--- a/include/pthread.h
+++ b/include/pthread.h
@@ -98,6 +98,7 @@
* Static initialization values.
*/
#define PTHREAD_MUTEX_INITIALIZER NULL
+#define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP NULL
#define PTHREAD_COND_INITIALIZER NULL
#define PTHREAD_RWLOCK_INITIALIZER NULL
@@ -128,6 +129,7 @@ enum pthread_mutextype {
PTHREAD_MUTEX_ERRORCHECK = 1, /* Default POSIX mutex */
PTHREAD_MUTEX_RECURSIVE = 2, /* Recursive mutex */
PTHREAD_MUTEX_NORMAL = 3, /* No error checking */
+ PTHREAD_MUTEX_ADAPTIVE_NP = 4, /* Adaptive mutex, spins briefly before blocking on lock */
PTHREAD_MUTEX_TYPE_MAX
};
diff --git a/lib/libkse/thread/thr_mutex.c b/lib/libkse/thread/thr_mutex.c
index 564bc20..264e01e 100644
--- a/lib/libkse/thread/thr_mutex.c
+++ b/lib/libkse/thread/thr_mutex.c
@@ -179,6 +179,7 @@ __pthread_mutex_init(pthread_mutex_t *mutex,
/* case PTHREAD_MUTEX_DEFAULT: */
case PTHREAD_MUTEX_ERRORCHECK:
case PTHREAD_MUTEX_NORMAL:
+ case PTHREAD_MUTEX_ADAPTIVE_NP:
/* Nothing to do here. */
break;
@@ -971,6 +972,7 @@ mutex_self_trylock(struct pthread *curthread, pthread_mutex_t m)
/* case PTHREAD_MUTEX_DEFAULT: */
case PTHREAD_MUTEX_ERRORCHECK:
case PTHREAD_MUTEX_NORMAL:
+ case PTHREAD_MUTEX_ADAPTIVE_NP:
ret = EBUSY;
break;
@@ -1002,6 +1004,7 @@ mutex_self_lock(struct pthread *curthread, pthread_mutex_t m)
switch (m->m_type) {
/* case PTHREAD_MUTEX_DEFAULT: */
case PTHREAD_MUTEX_ERRORCHECK:
+ case PTHREAD_MUTEX_ADAPTIVE_NP:
/*
* POSIX specifies that mutexes should return EDEADLK if a
* recursive lock is detected.
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