1
1

various flavors of condition variables/mutexes -- not all are complete -- for experimentation only

This commit was SVN r816.
Этот коммит содержится в:
Tim Woodall 2004-03-03 16:10:26 +00:00
родитель 2493a6c3ea
Коммит 366b325f24
17 изменённых файлов: 493 добавлений и 50 удалений

Просмотреть файл

@ -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

20
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

27
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

41
src/lam/threads/condition_pthread.h Обычный файл
Просмотреть файл

@ -0,0 +1,41 @@
/*
* $HEADER$
*/
#ifndef LAM_CONDITION_PTHREAD_H
#define LAM_CONDITION_PTHREAD_H
#include <pthread.h>
#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

30
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

39
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

29
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

58
src/lam/threads/condition_spinwait.h Обычный файл
Просмотреть файл

@ -0,0 +1,58 @@
/*
* $HEADER$
*/
#ifndef LAM_CONDITION_SPINWAIT_H
#define LAM_CONDITION_SPINWAIT_H
#include <pthread.h>
#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

Просмотреть файл

@ -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
/**

25
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

40
src/lam/threads/mutex_pthread.h Обычный файл
Просмотреть файл

@ -0,0 +1,40 @@
/*
* $HEADER$
*/
#ifndef _LAM_MUTEX_PTHREAD_
#define _LAM_MUTEX_PTHREAD_
#include <pthread.h>
#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

27
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

Просмотреть файл

@ -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

27
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

Просмотреть файл

@ -6,7 +6,8 @@
#define LAM_MUTEX_SPINWAIT_
#include <pthread.h>
#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);
}
}

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -5,16 +5,25 @@
#ifndef LAM_THREAD_H
#define LAM_THREAD_H
#include <pthread.h>
#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 */