diff --git a/src/lam/threads/Makefile.am b/src/lam/threads/Makefile.am index c88e90a7b5..2977d315f4 100644 --- a/src/lam/threads/Makefile.am +++ b/src/lam/threads/Makefile.am @@ -10,14 +10,25 @@ noinst_LTLIBRARIES = libthreads.la # Source code files headers = \ + condition.h \ + condition_pthread.h \ + condition_spinlock.h \ + condition_spinwait.h \ mutex.h \ + mutex_pthread.h \ mutex_spinlock.h \ mutex_spinwait.h \ thread.h libthreads_la_SOURCES = \ $(headers) \ - mutex.c \ + condition_pthread.c \ + condition_spinlock.c \ + condition_spinwait.c \ + mutex.c \ + mutex_pthread.c \ + mutex_spinlock.c \ + mutex_spinwait.c \ thread.c # Conditionally install the header files diff --git a/src/lam/threads/condition.h b/src/lam/threads/condition.h new file mode 100644 index 0000000000..dd373476ce --- /dev/null +++ b/src/lam/threads/condition.h @@ -0,0 +1,20 @@ +/* + * $HEADER$ + */ +#ifndef LAM_CONDITION_H +#define LAM_CONDITION_H + +#include "lam_config.h" +#include "lam/threads/mutex.h" + +#if defined(LAM_USE_SPINLOCK) +#include "condition_spinlock.h" +#elif defined(LAM_USE_SPINWAIT) +#include "condition_spinwait.h" +#elif defined(LAM_USE_PTHREADS) +#include "condition_pthread.h" +#else +#error "concurrency model not configured" +#endif + +#endif diff --git a/src/lam/threads/condition_pthread.c b/src/lam/threads/condition_pthread.c new file mode 100644 index 0000000000..290e828481 --- /dev/null +++ b/src/lam/threads/condition_pthread.c @@ -0,0 +1,27 @@ +/* + * $HEADER$ + */ + +#include "mutex.h" +#include "condition.h" +#if defined(LAM_USE_PTHREADS) + +static void lam_condition_construct(lam_condition_t* c) +{ + pthread_cond_init(&c->c_cond, NULL); +} + +static void lam_condition_destruct(lam_condition_t* c) +{ + pthread_cond_destroy(&c->c_cond); +} + +OBJ_CLASS_INSTANCE( + lam_condition_t, + lam_object_t, + lam_condition_construct, + lam_condition_destruct +); + +#endif + diff --git a/src/lam/threads/condition_pthread.h b/src/lam/threads/condition_pthread.h new file mode 100644 index 0000000000..3ce097fb37 --- /dev/null +++ b/src/lam/threads/condition_pthread.h @@ -0,0 +1,41 @@ +/* + * $HEADER$ + */ +#ifndef LAM_CONDITION_PTHREAD_H +#define LAM_CONDITION_PTHREAD_H + +#include +#include "lam/threads/mutex.h" + + +struct lam_condition_t { + lam_object_t super; + pthread_cond_t c_cond; +}; +typedef struct lam_condition_t lam_condition_t; + +OBJ_CLASS_DECLARATION(lam_condition_t); + + +static inline int lam_condition_wait(lam_condition_t* c, lam_mutex_t* m) +{ + return pthread_cond_wait(&c->c_cond, &m->m_lock); +} + +static inline int lam_condition_timedwait(lam_condition_t* c, lam_mutex_t* m, const struct timespec *abstime) +{ + return pthread_cond_timedwait(&c->c_cond, &m->m_lock, abstime); +} + +static inline int lam_condition_signal(lam_condition_t* c) +{ + return pthread_cond_signal(&c->c_cond); +} + +static inline int lam_condition_broadcast(lam_condition_t* c) +{ + return pthread_cond_broadcast(&c->c_cond); +} + +#endif + diff --git a/src/lam/threads/condition_spinlock.c b/src/lam/threads/condition_spinlock.c new file mode 100644 index 0000000000..9ff4bdee8e --- /dev/null +++ b/src/lam/threads/condition_spinlock.c @@ -0,0 +1,30 @@ +/* + * $HEADER$ + */ + +#include "mutex.h" +#include "condition.h" + +#if defined(LAM_USE_SPINLOCK) + + +static void lam_condition_construct(lam_condition_t* c) +{ +} + + +static void lam_condition_destruct(lam_condition_t* c) +{ +} + + +OBJ_CLASS_INSTANCE( + lam_condition_t, + lam_object_t, + lam_condition_construct, + lam_condition_destruct +); + + +#endif + diff --git a/src/lam/threads/condition_spinlock.h b/src/lam/threads/condition_spinlock.h new file mode 100644 index 0000000000..b917fd9063 --- /dev/null +++ b/src/lam/threads/condition_spinlock.h @@ -0,0 +1,39 @@ +/* + * $HEADER$ + */ +#ifndef LAM_CONDITION_SPINLOCK_H +#define LAM_CONDITION_SPINLOCK_H + +#include "lam/threads/condition.h" + + +struct lam_condition_t { + volatile int c_waiting; +}; +typedef struct lam_condition_t lam_condition_t; + +OBJ_CLASS_DECLARATION(lam_condition_t); + + +static inline int lam_condition_wait(lam_condition_t* c, lam_mutex_t* m) +{ + return 0; +} + +static inline int lam_condition_timedwait(lam_condition_t* c, lam_mutex_t* m, const struct timespec *abstime) +{ + return 0; +} + +static inline int lam_condition_signal(lam_condition_t* c) +{ + return 0; +} + +static inline int lam_condition_broadcast(lam_condition_t* c) +{ + return 0; +} + +#endif + diff --git a/src/lam/threads/condition_spinwait.c b/src/lam/threads/condition_spinwait.c new file mode 100644 index 0000000000..ae821f9d3a --- /dev/null +++ b/src/lam/threads/condition_spinwait.c @@ -0,0 +1,29 @@ +/* + * $HEADER$ + */ + +#include "mutex.h" +#include "condition.h" + +#if defined(LAM_USE_SPINWAIT) + + +static void lam_condition_construct(lam_condition_t* c) +{ + pthread_cond_init(&c->c_cond, NULL); +} + +static void lam_condition_destruct(lam_condition_t* c) +{ + pthread_cond_destroy(&c->c_cond); +} + +OBJ_CLASS_INSTANCE( + lam_condition_t, + lam_object_t, + lam_condition_construct, + lam_condition_destruct +); + +#endif + diff --git a/src/lam/threads/condition_spinwait.h b/src/lam/threads/condition_spinwait.h new file mode 100644 index 0000000000..979b5fb804 --- /dev/null +++ b/src/lam/threads/condition_spinwait.h @@ -0,0 +1,58 @@ +/* + * $HEADER$ + */ +#ifndef LAM_CONDITION_SPINWAIT_H +#define LAM_CONDITION_SPINWAIT_H + +#include +#include "lam/threads/mutex.h" + + +struct lam_condition_t { + lam_object_t super; + pthread_cond_t c_cond; +}; +typedef struct lam_condition_t lam_condition_t; + +OBJ_CLASS_DECLARATION(lam_condition_t); + + +static inline int lam_condition_wait(lam_condition_t* c, lam_mutex_t* m) +{ + + int rc; + pthread_mutex_lock(&m->m_lock); + /* release the spinlock */ + fetchNset(&m->m_spinlock, 0); + if(m->m_waiting) + pthread_cond_signal(&m->m_cond); + rc = pthread_cond_wait(&c->c_cond, &m->m_lock); + fetchNset(&m->m_spinlock, 1); + return rc; +} + +static inline int lam_condition_timedwait(lam_condition_t* c, lam_mutex_t* m, const struct timespec *abstime) +{ + int rc; + pthread_mutex_lock(&m->m_lock); + /* release the spinlock */ + fetchNset(&m->m_spinlock, 0); + if(m->m_waiting) + pthread_cond_signal(&m->m_cond); + rc = pthread_cond_timedwait(&c->c_cond, &m->m_lock, abstime); + fetchNset(&m->m_spinlock, 1); + return rc; +} + +static inline int lam_condition_signal(lam_condition_t* c) +{ + return pthread_cond_signal(&c->c_cond); +} + +static inline int lam_condition_broadcast(lam_condition_t* c) +{ + return pthread_cond_broadcast(&c->c_cond); +} + +#endif + diff --git a/src/lam/threads/mutex.h b/src/lam/threads/mutex.h index 6884240737..42070484d3 100644 --- a/src/lam/threads/mutex.h +++ b/src/lam/threads/mutex.h @@ -8,11 +8,17 @@ #define LAM_MUTEX_H_ #include "lam_config.h" +#define LAM_USE_PTHREADS -#if defined(USE_SPINWAIT) -#include "lam/threads/mutex_spinwait.h" -#else + +#if defined(LAM_USE_SPINLOCK) #include "lam/threads/mutex_spinlock.h" +#elif defined(LAM_USE_SPINWAIT) +#include "lam/threads/mutex_spinwait.h" +#elif defined(LAM_USE_PTHREADS) +#include "lam/threads/mutex_pthread.h" +#else +#error "concurrency model not configured" #endif /** diff --git a/src/lam/threads/mutex_pthread.c b/src/lam/threads/mutex_pthread.c new file mode 100644 index 0000000000..d4ce50300f --- /dev/null +++ b/src/lam/threads/mutex_pthread.c @@ -0,0 +1,25 @@ +/* + * $HEADER$ + */ +#include "lam/threads/mutex.h" +#if defined(LAM_USE_PTHREADS) + +static void lam_mutex_construct(lam_mutex_t* m) +{ + pthread_mutex_init(&m->m_lock, 0); +} + +static void lam_mutex_destruct(lam_mutex_t* m) +{ + pthread_mutex_destroy(&m->m_lock); +} + +OBJ_CLASS_INSTANCE( + lam_mutex_t, + lam_object_t, + lam_mutex_construct, + lam_mutex_destruct +); + +#endif + diff --git a/src/lam/threads/mutex_pthread.h b/src/lam/threads/mutex_pthread.h new file mode 100644 index 0000000000..7ccbcc8eb0 --- /dev/null +++ b/src/lam/threads/mutex_pthread.h @@ -0,0 +1,40 @@ +/* + * $HEADER$ + */ + +#ifndef _LAM_MUTEX_PTHREAD_ +#define _LAM_MUTEX_PTHREAD_ + +#include +#include "lam/lfc/lam_object.h" +#include "lam/os/atomic.h" + + +struct lam_mutex_t { + lam_object_t super; + pthread_mutex_t m_lock; +}; +typedef struct lam_mutex_t lam_mutex_t; + +OBJ_CLASS_DECLARATION(lam_mutex_t); + + + +static inline void lam_mutex_lock(lam_mutex_t* m) +{ + pthread_mutex_lock(&m->m_lock); +} + + +static inline int lam_mutex_trylock(lam_mutex_t* m) +{ + return pthread_mutex_trylock(&m->m_lock); +} + + +static inline void lam_mutex_unlock(lam_mutex_t* m) +{ + pthread_mutex_unlock(&m->m_lock); +} + +#endif diff --git a/src/lam/threads/mutex_spinlock.c b/src/lam/threads/mutex_spinlock.c new file mode 100644 index 0000000000..591d332a1f --- /dev/null +++ b/src/lam/threads/mutex_spinlock.c @@ -0,0 +1,27 @@ +/* + * $HEADER$ + */ + +#include "mutex.h" +#if defined(LAM_USE_SPINLOCK) + +static void lam_mutex_construct(lam_mutex_t* m) +{ + spinunlock(&m->m_lock); +} + + +static void lam_mutex_destruct(lam_mutex_t* m) +{ +} + + +OBJ_CLASS_INSTANCE( + lam_mutex_t, + lam_object_t, + lam_mutex_construct, + lam_mutex_destruct +); + +#endif + diff --git a/src/lam/threads/mutex_spinlock.h b/src/lam/threads/mutex_spinlock.h index 1ce5fdc90b..1be18ea699 100644 --- a/src/lam/threads/mutex_spinlock.h +++ b/src/lam/threads/mutex_spinlock.h @@ -5,13 +5,34 @@ #ifndef LAM_MUTEX_SPINLOCK_ #define LAM_MUTEX_SPINLOCK_ +#include "lam/lfc/lam_object.h" #include "lam/os/atomic.h" -typedef lam_lock_data_t lam_mutex_t; -#define lam_mutex_init(m) spinunlock(m) -#define lam_mutex_destroy(m) -#define lam_mutex_lock(m) spinlock(m) -#define lam_mutex_trylock(m) spintrylock(m) -#define lam_mutex_unlock(m) spinunlock(m) + +struct lam_mutex_t { + lam_object_t super; + lam_lock_data_t m_lock; + +}; +typedef struct lam_mutex_t lam_mutex_t; + + +OBJ_CLASS_DECLARATION(lam_mutex_t); + + +static inline void lam_mutex_lock(lam_mutex_t* m) +{ + spinlock(&m->m_lock); +} + +static inline int lam_mutex_trylock(lam_mutex_t* m) +{ + return spintrylock(&m->m_lock); +} + +static inline void lam_mutex_unlock(lam_mutex_t* m) +{ + spinunlock(&m->m_lock); +} #endif diff --git a/src/lam/threads/mutex_spinwait.c b/src/lam/threads/mutex_spinwait.c new file mode 100644 index 0000000000..cedd0ad5cd --- /dev/null +++ b/src/lam/threads/mutex_spinwait.c @@ -0,0 +1,27 @@ +#include "lam/threads/mutex.h" +#if defined(LAM_USE_SPINWAIT) + + +static void lam_mutex_construct(lam_mutex_t* m) +{ + m->m_spinlock = 0; + m->m_waiting = 0; + pthread_mutex_init(&m->m_lock, 0); + pthread_cond_init(&m->m_cond, 0); +} + +static void lam_mutex_destruct(lam_mutex_t* m) +{ + pthread_mutex_destroy(&m->m_lock); + pthread_cond_destroy(&m->m_cond); +} + +OBJ_CLASS_INSTANCE( + lam_mutex_t, + lam_object_t, + lam_mutex_construct, + lam_mutex_destruct +); + +#endif + diff --git a/src/lam/threads/mutex_spinwait.h b/src/lam/threads/mutex_spinwait.h index f4d5645bfa..a37eba2c7d 100644 --- a/src/lam/threads/mutex_spinwait.h +++ b/src/lam/threads/mutex_spinwait.h @@ -6,7 +6,8 @@ #define LAM_MUTEX_SPINWAIT_ #include -#include "os/atomic.h" +#include "lam/lfc/lam_object.h" +#include "lam/os/atomic.h" #ifndef MUTEX_SPINWAIT #define MUTEX_SPINWAIT 10000 @@ -14,58 +15,49 @@ struct lam_mutex_t { - volatile int mutex_spinlock; - volatile int mutex_waiting; - pthread_mutex_t mutex_lock; - pthread_cond_t mutex_cond; + lam_object_t super; + volatile int m_spinlock; + volatile int m_waiting; + pthread_mutex_t m_lock; + pthread_cond_t m_cond; }; -struct lam_mutex_t lam_mutex_t; +typedef struct lam_mutex_t lam_mutex_t; +OBJ_CLASS_DECLARATION(lam_mutex_t); -static inline void lam_mutex_init(lam_mutex_t* m) -{ - m->mutex_spinlock = 0; - m->mutex_waiting = 0; - pthread_mutex_init(&m->mutex_lock, 0); - pthread_cond_init(&m->mutex_cond, 0); -} - -static inline void lam_mutex_destroy(lam_mutex_t* m) -{ - -} static inline void lam_mutex_lock(lam_mutex_t* m) { - unsigned long cnt = 0; - int locked; - - fetchNadd(&m->mutex_waiting, 1); - while( ((locked = fetchNset(&m->mutex_spinlock, 1)) == 1) - && (cnt++ < MUTEX_SPINWAIT) ) - ; - if(locked) { - pthread_mutex_lock(&m->mutex_lock); - while(fetchNset(&m->mutex_spinlock, 1) == 1) - pthread_cond_wait(&m->mutex_cond, &m->mutex_lock); - pthread_mutex_unlock(&m->mutex_lock); + if(fetchNset(&m->m_spinlock, 1) == 1) { + unsigned long cnt = 0; + int locked; + fetchNadd(&m->m_waiting, 1); + while( ((locked = fetchNset(&m->m_spinlock, 1)) == 1) + && (cnt++ < MUTEX_SPINWAIT) ) + ; + if(locked) { + pthread_mutex_lock(&m->m_lock); + while(fetchNset(&m->m_spinlock, 1) == 1) + pthread_cond_wait(&m->m_cond, &m->m_lock); + pthread_mutex_unlock(&m->m_lock); + } + fetchNadd(&m->m_waiting, -1); } - fetchNadd(&m->mutex_waiting, -1); } static inline int lam_mutex_trylock(lam_mutex_t* m) { - return (fetchNset(&m->mutex_spinlock, 1) == 0); + return (fetchNset(&m->m_spinlock, 1) == 0); } static inline void lam_mutex_unlock(lam_mutex_t* m) { - fetchNset(&m->mutex_spinlock, 0); - if(m->mutex_waiting) { - pthread_cond_signal(&m->mutex_cond); + fetchNset(&m->m_spinlock, 0); + if(m->m_waiting) { + pthread_cond_signal(&m->m_cond); } } diff --git a/src/lam/threads/thread.c b/src/lam/threads/thread.c index c101887856..1071093829 100644 --- a/src/lam/threads/thread.c +++ b/src/lam/threads/thread.c @@ -2,5 +2,46 @@ * $HEADER$ */ +#include "lam/constants.h" #include "lam/threads/thread.h" + +static void lam_thread_construct(lam_thread_t* t) +{ + t->t_run = 0; + t->t_handle = -1; +} + + +static void lam_thread_destruct(lam_thread_t* t) +{ +} + + +OBJ_CLASS_INSTANCE( + lam_thread_t, + lam_object_t, + lam_thread_construct, + lam_thread_destruct +); + +typedef void* (*pthread_start_fn_t)(void*); + + +int lam_thread_start(lam_thread_t* t) +{ + int rc; +#if LAM_ENABLE_DEBUG + if(NULL == t->t_run || t->t_handle != -1) + return LAM_ERR_BAD_PARAM; +#endif + rc = pthread_create(&t->t_handle, NULL, (pthread_start_fn_t)t->t_run, t); + return (rc == 0) ? LAM_SUCCESS: LAM_ERROR; +} + +int lam_thread_join(lam_thread_t* t, void** thr_return) +{ + int rc = pthread_join(t->t_handle, thr_return); + return (rc == 0) ? LAM_SUCCESS: LAM_ERROR; +} + diff --git a/src/lam/threads/thread.h b/src/lam/threads/thread.h index 15cf65d5f7..634a511572 100644 --- a/src/lam/threads/thread.h +++ b/src/lam/threads/thread.h @@ -5,16 +5,25 @@ #ifndef LAM_THREAD_H #define LAM_THREAD_H +#include #include "lam/lfc/lam_object.h" -typedef struct lam_thread +typedef void* (*lam_thread_fn_t)(lam_object_t*); + + +struct lam_thread_t { lam_object_t super; - void (*thr_run)(lam_object_t*); -} lam_thread_t; + lam_thread_fn_t t_run; + pthread_t t_handle; +}; +typedef struct lam_thread_t lam_thread_t; -void lam_thr_construct(lam_thread_t *a_thread); -lam_thread_t *lam_thr_create(lam_object_t *arg); +OBJ_CLASS_DECLARATION(lam_thread_t); + + +int lam_thread_start(lam_thread_t*); +int lam_thread_join(lam_thread_t*, void** thread_return); #endif /* LAM_THREAD_H */