From 8b0472932c1cb8cb2cc46322b21c0c4e21848522 Mon Sep 17 00:00:00 2001 From: Jens Gustedt Date: Sat, 6 Sep 2014 22:07:22 -0400 Subject: add C11 mutex functions --- src/thread/mtx_destroy.c | 5 +++++ src/thread/mtx_init.c | 10 ++++++++++ src/thread/mtx_lock.c | 12 ++++++++++++ src/thread/mtx_timedlock.c | 14 ++++++++++++++ src/thread/mtx_trylock.c | 17 +++++++++++++++++ src/thread/mtx_unlock.c | 11 +++++++++++ 6 files changed, 69 insertions(+) create mode 100644 src/thread/mtx_destroy.c create mode 100644 src/thread/mtx_init.c create mode 100644 src/thread/mtx_lock.c create mode 100644 src/thread/mtx_timedlock.c create mode 100644 src/thread/mtx_trylock.c create mode 100644 src/thread/mtx_unlock.c diff --git a/src/thread/mtx_destroy.c b/src/thread/mtx_destroy.c new file mode 100644 index 00000000..40a08999 --- /dev/null +++ b/src/thread/mtx_destroy.c @@ -0,0 +1,5 @@ +#include + +void mtx_destroy(mtx_t *mtx) +{ +} diff --git a/src/thread/mtx_init.c b/src/thread/mtx_init.c new file mode 100644 index 00000000..4826f76b --- /dev/null +++ b/src/thread/mtx_init.c @@ -0,0 +1,10 @@ +#include "pthread_impl.h" +#include + +int mtx_init(mtx_t *m, int type) +{ + *m = (mtx_t){ + ._m_type = ((type&mtx_recursive) ? PTHREAD_MUTEX_RECURSIVE : PTHREAD_MUTEX_NORMAL), + }; + return thrd_success; +} diff --git a/src/thread/mtx_lock.c b/src/thread/mtx_lock.c new file mode 100644 index 00000000..5c2415c1 --- /dev/null +++ b/src/thread/mtx_lock.c @@ -0,0 +1,12 @@ +#include "pthread_impl.h" +#include + +int mtx_lock(mtx_t *m) +{ + if (m->_m_type == PTHREAD_MUTEX_NORMAL && !a_cas(&m->_m_lock, 0, EBUSY)) + return thrd_success; + /* Calling mtx_timedlock with a null pointer is an extension. + * It is convenient, here to avoid duplication of the logic + * for return values. */ + return mtx_timedlock(m, 0); +} diff --git a/src/thread/mtx_timedlock.c b/src/thread/mtx_timedlock.c new file mode 100644 index 00000000..bcc152c5 --- /dev/null +++ b/src/thread/mtx_timedlock.c @@ -0,0 +1,14 @@ +#include +#include + +int __pthread_mutex_timedlock(mtx_t *restrict, const struct timespec *restrict); + +int mtx_timedlock(mtx_t *restrict m, const struct timespec *restrict ts) +{ + int ret = __pthread_mutex_timedlock(m, ts); + switch (ret) { + default: return thrd_error; + case 0: return thrd_success; + case ETIMEDOUT: return thrd_timedout; + } +} diff --git a/src/thread/mtx_trylock.c b/src/thread/mtx_trylock.c new file mode 100644 index 00000000..61e7694e --- /dev/null +++ b/src/thread/mtx_trylock.c @@ -0,0 +1,17 @@ +#include "pthread_impl.h" +#include + +int __pthread_mutex_trylock(mtx_t *); + +int mtx_trylock(mtx_t *m) +{ + if (m->_m_type == PTHREAD_MUTEX_NORMAL) + return (a_cas(&m->_m_lock, 0, EBUSY) & EBUSY) ? thrd_busy : thrd_success; + + int ret = __pthread_mutex_trylock(m); + switch (ret) { + default: return thrd_error; + case 0: return thrd_success; + case EBUSY: return thrd_busy; + } +} diff --git a/src/thread/mtx_unlock.c b/src/thread/mtx_unlock.c new file mode 100644 index 00000000..5033ace7 --- /dev/null +++ b/src/thread/mtx_unlock.c @@ -0,0 +1,11 @@ +#include + +int __pthread_mutex_unlock(mtx_t *); + +int mtx_unlock(mtx_t *mtx) +{ + /* The only cases where pthread_mutex_unlock can return an + * error are undefined behavior for C11 mtx_unlock, so we can + * assume it does not return an error and simply tail call. */ + return __pthread_mutex_unlock(mtx); +} -- cgit v1.2.1