diff options
-rw-r--r-- | include/pthread.h | 2 | ||||
-rw-r--r-- | lib/libkse/thread/thr_mutex.c | 3 | ||||
-rw-r--r-- | lib/libthr/thread/thr_mutex.c | 29 |
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; |