Commit 1481a252 authored by Martin Karsten's avatar Martin Karsten

- added fast mutex based on MCS lock

parent a85c016a
......@@ -36,6 +36,7 @@ typedef cpuset_t cpu_set_t;
#define __LIBFIBRE__
#include "libfibre/fibre.h"
//#define FibreMutex FastMutex
#else /* VARIANT */
......
......@@ -23,16 +23,21 @@ struct _cfibre_mutex_t : public fibre_mutex_t {};
struct _cfibre_cond_t : public fibre_cond_t {};
struct _cfibre_rwlock_t : public fibre_rwlock_t {};
struct _cfibre_barrier_t : public fibre_barrier_t {};
struct _cfibre_cluster_t : public Cluster {};
struct _cfibre_sproc_t : public OsProcessor {
_cfibre_sproc_t(Cluster& c, funcvoid1_t func = nullptr, ptr_t arg = nullptr) : OsProcessor(c, func, arg) {}
};
struct _cfast_mutex_t : public fast_mutex_t {};
struct _cfast_cond_t : public fast_cond_t {};
struct _cfibre_attr_t : public fibre_attr_t {};
struct _cfibre_mutexattr_t : public fibre_mutexattr_t {};
struct _cfibre_condattr_t : public fibre_condattr_t {};
struct _cfibre_rwlockattr_t : public fibre_rwlockattr_t {};
struct _cfibre_barrierattr_t : public fibre_barrierattr_t {};
struct _cfast_mutexattr_t : public fast_mutexattr_t {};
struct _cfast_condattr_t : public fast_condattr_t {};
struct _cfibre_cluster_t : public Cluster {};
struct _cfibre_sproc_t : public OsProcessor {
_cfibre_sproc_t(Cluster& c, funcvoid1_t func = nullptr, ptr_t arg = nullptr) : OsProcessor(c, func, arg) {}
};
extern "C" int cfibre_cluster_create(cfibre_cluster_t* cluster) {
*cluster = new _cfibre_cluster_t;
......@@ -311,6 +316,58 @@ extern "C" int cfibre_barrier_wait(cfibre_barrier_t *barrier) {
return fibre_barrier_wait(*barrier);
}
extern "C" int cfast_mutex_init(cfast_mutex_t *restrict mutex, const cfast_mutexattr_t *restrict attr) {
*mutex = (cfast_mutex_t)new fast_mutex_t;
return fast_mutex_init(*mutex, (fast_mutexattr_t*)attr);
}
extern "C" int cfast_mutex_destroy(cfast_mutex_t *mutex) {
int ret = fast_mutex_destroy(*mutex);
delete *mutex;
*mutex = nullptr;
return ret;
}
extern "C" int cfast_mutex_lock(cfast_mutex_t *mutex) {
return fast_mutex_lock(*mutex);
}
extern "C" int cfast_mutex_trylock(cfast_mutex_t *mutex) {
return fast_mutex_trylock(*mutex);
}
extern "C" int cfast_mutex_unlock(cfast_mutex_t *mutex) {
return fast_mutex_unlock(*mutex);
}
extern "C" int cfast_cond_init(cfast_cond_t *restrict cond, const cfast_condattr_t *restrict attr) {
*cond = (cfast_cond_t)new fast_cond_t;
return fast_cond_init(*cond, (fast_condattr_t*)attr);
}
extern "C" int cfast_cond_destroy(cfast_cond_t *cond) {
int ret = fast_cond_destroy(*cond);
delete *cond;
*cond = nullptr;
return ret;
}
extern "C" int cfast_cond_wait(cfast_cond_t *restrict cond, cfast_mutex_t *restrict mutex) {
return fast_cond_wait(*cond, *mutex);
}
extern "C" int cfast_cond_timedwait(cfast_cond_t *restrict cond, cfast_mutex_t *restrict mutex, const struct timespec *restrict abstime) {
return fast_cond_timedwait(*cond, *mutex, abstime);
}
extern "C" int cfast_cond_signal(cfast_cond_t *cond) {
return fast_cond_signal(*cond);
}
extern "C" int cfast_cond_broadcast(cfast_cond_t *cond) {
return fast_cond_broadcast(*cond);
}
extern "C" int cfibre_socket(int domain, int type, int protocol) {
return lfSocket(domain, type, protocol);
}
......
......@@ -39,6 +39,11 @@ typedef struct _cfibre_condattr_t* cfibre_condattr_t;
typedef struct _cfibre_rwlockattr_t* cfibre_rwlockattr_t;
typedef struct _cfibre_barrierattr_t* cfibre_barrierattr_t;
typedef struct _cfast_mutex_t* cfast_mutex_t;
typedef struct _cfast_cond_t* cfast_cond_t;
typedef struct _cfast_mutexattr_t* cfast_mutexattr_t;
typedef struct _cfast_condattr_t* cfast_condattr_t;
typedef struct _cfibre_cluster_t* cfibre_cluster_t;
typedef struct _cfibre_sproc_t* cfibre_sproc_t;
......@@ -129,10 +134,18 @@ int cfibre_barrier_init(cfibre_barrier_t *restrict barrier, const cfibre_barrier
int cfibre_barrier_destroy(cfibre_barrier_t *barrier);
int cfibre_barrier_wait(cfibre_barrier_t *barrier);
/** @brief Sleep fibre. (`usleep`). */
int cfibre_usleep(useconds_t uses);
/** @brief Sleep fibre. (`sleep`). */
int cfibre_sleep(unsigned int secs);
int cfast_mutex_init(cfast_mutex_t *restrict mutex, const cfast_mutexattr_t *restrict attr);
int cfast_mutex_destroy(cfast_mutex_t *mutex);
int cfast_mutex_lock(cfast_mutex_t *mutex);
int cfast_mutex_trylock(cfast_mutex_t *mutex);
int cfast_mutex_unlock(cfast_mutex_t *mutex);
int cfast_cond_init(cfast_cond_t *restrict cond, const cfast_condattr_t *restrict attr);
int cfast_cond_destroy(cfast_cond_t *cond);
int cfast_cond_wait(cfast_cond_t *restrict cond, cfast_mutex_t *restrict mutex);
int cfast_cond_timedwait(cfast_cond_t *restrict cond, cfast_mutex_t *restrict mutex, const struct timespec *restrict abstime);
int cfast_cond_signal(cfast_cond_t *cond);
int cfast_cond_broadcast(cfast_cond_t *cond);
/** @brief Create socket. (`socket`). */
int cfibre_socket(int domain, int type, int protocol);
......@@ -172,6 +185,11 @@ void cfibre_suspendFD(int fd);
/** @brief resume event handling for FD */
void cfibre_resumeFD(int fd);
/** @brief Sleep fibre. (`usleep`). */
int cfibre_usleep(useconds_t uses);
/** @brief Sleep fibre. (`sleep`). */
int cfibre_sleep(unsigned int secs);
#ifdef __cplusplus
}
#endif
......
......@@ -42,6 +42,9 @@ typedef FibreSemaphore fibre_sem_t;
typedef FibreLockRW fibre_rwlock_t;
typedef FibreBarrier fibre_barrier_t;
typedef FastMutex fast_mutex_t;
typedef Condition<FastMutex> fast_cond_t;
struct fibre_attr_t {
size_t stackSize;
bool detached;
......@@ -60,6 +63,9 @@ struct fibre_condattr_t {};
struct fibre_rwlockattr_t {};
struct fibre_barrierattr_t {};
struct fast_mutexattr_t {};
struct fast_condattr_t {};
#ifdef __GNUC__
#define restrict __restrict__
#else
......@@ -341,6 +347,71 @@ inline int fibre_barrier_wait(fibre_barrier_t *barrier) {
return barrier->wait() ? PTHREAD_BARRIER_SERIAL_THREAD : 0;
}
/** @brief Initialize mutex lock. (`pthread_mutex_init`) */
inline int fast_mutex_init(fast_mutex_t *restrict mutex, const fast_mutexattr_t *restrict attr) {
RASSERT0(attr == nullptr);
return 0;
}
/** @brief Destroy mutex lock. (`pthread_mutex_destroy`) */
inline int fast_mutex_destroy(fast_mutex_t *mutex) {
return 0;
}
/** @brief Acquire mutex lock. Block, if necessary. (`pthread_mutex_lock`) */
inline int fast_mutex_lock(fast_mutex_t *mutex) {
mutex->acquire();
return 0;
}
/** @brief Perform non-blocking attempt to acquire mutex lock. (`pthread_mutex_trylock`) */
inline int fast_mutex_trylock(fast_mutex_t *mutex) {
return mutex->tryAcquire() ? 0 : EBUSY;
}
/** @brief Release mutex lock. Block, if necessary. (`pthread_mutex_unlock`) */
inline int fast_mutex_unlock(fast_mutex_t *mutex) {
mutex->release();
return 0;
}
/** @brief Initialize condition variable. (`pthread_cond_init`) */
inline int fast_cond_init(fast_cond_t *restrict cond, const fast_condattr_t *restrict attr) {
RASSERT0(attr == nullptr);
return 0;
}
/** @brief Destroy condition variable. (`pthread_cond_init`) */
inline int fast_cond_destroy(fast_cond_t *cond) {
return 0;
}
/** @brief Wait on condition variable. (`pthread_cond_wait`) */
inline int fast_cond_wait(fast_cond_t *restrict cond, fast_mutex_t *restrict mutex) {
cond->wait(*mutex);
mutex->acquire();
return 0;
}
/** @brief Perform wait attempt on condition variable with timeout. (`pthread_cond_timedwait`) */
inline int fast_cond_timedwait(fast_cond_t *restrict cond, fast_mutex_t *restrict mutex, const struct timespec *restrict abstime) {
int retcode = cond->wait(*mutex, *abstime) ? 0 : ETIMEDOUT;
mutex->acquire();
return retcode;
}
/** @brief Signal one waiting fibre on condition variable. (`pthread_cond_signal`) */
inline int fast_cond_signal(fast_cond_t *cond) {
cond->signal();
return 0;
}
/** @brief Signal all waiting fibres on condition variable. (`pthread_cond_broadcast`) */
inline int fast_cond_broadcast(fast_cond_t *cond) {
cond->signal<true>();
return 0;
}
#endif /* _fibre_h_ */
/**
......
......@@ -332,6 +332,29 @@ public:
void release() { return V(); }
};
class FastMutex : public BaseSuspender {
BlockStackMCS queue;
public:
bool acquire() {
StackContext* cs = Context::CurrStack();
if (!queue.push(*cs)) {
prepareSuspend();
doSuspend(*cs);
}
return true;
}
bool tryAcquire() {
StackContext* cs = Context::CurrStack();
return queue.tryPushEmpty(*cs);
}
void release() {
StackContext* cs = Context::CurrStack();
StackContext* next = queue.next(*cs);
BlockStackMCS::clear(*cs);
if (next) next->resume();
}
};
template<typename Lock, bool OwnerLock, bool Fifo, typename BQ = BlockingQueue>
class LockedMutex {
Lock lock;
......
......@@ -34,9 +34,9 @@ class KernelProcessor;
class Scheduler;
#if TESTING_ENABLE_DEBUGGING
static const size_t StackLinkCount = 2;
static const size_t StackLinkCount = 3;
#else
static const size_t StackLinkCount = 1;
static const size_t StackLinkCount = 2;
#endif
template <size_t NUM> class StackList :
......@@ -45,6 +45,9 @@ public IntrusiveList<StackContext,NUM,StackLinkCount,DoubleLink<StackContext,Sta
template <size_t NUM> class StackQueue :
public IntrusiveQueue<StackContext,NUM,StackLinkCount,DoubleLink<StackContext,StackLinkCount>> {};
template <size_t NUM> class StackMCS :
public IntrusiveQueueMCS<StackContext,NUM,StackLinkCount,DoubleLink<StackContext,StackLinkCount>> {};
template <size_t NUM> class StackMPSC :
#if TESTING_NEMESIS_READYQUEUE
public IntrusiveQueueNemesis<StackContext,NUM,StackLinkCount,DoubleLink<StackContext,StackLinkCount>> {};
......@@ -52,13 +55,16 @@ public IntrusiveQueueNemesis<StackContext,NUM,StackLinkCount,DoubleLink<StackCon
public IntrusiveQueueStub<StackContext,NUM,StackLinkCount,DoubleLink<StackContext,StackLinkCount>> {};
#endif
static const size_t ReadyQueueLink = 0;
typedef StackList<ReadyQueueLink> FlexStackList;
typedef StackQueue<ReadyQueueLink> FlexStackQueue;
typedef StackMPSC<ReadyQueueLink> FlexStackMPSC;
static const size_t FlexQueueLink = 0;
typedef StackList<FlexQueueLink> FlexStackList;
typedef StackQueue<FlexQueueLink> FlexStackQueue;
typedef StackMPSC<FlexQueueLink> FlexStackMPSC;
static const size_t BlockQueueLink = 1;
typedef StackMCS<BlockQueueLink> BlockStackMCS;
#if TESTING_ENABLE_DEBUGGING
static const size_t DebugListLink = 1;
static const size_t DebugListLink = 2;
typedef StackList<DebugListLink> GlobalStackList;
#endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment