* Refactoring the condition variable and synchronization subsystem of the

freebsd compat layer.
* Renaming functions where their names aren't preset by FreeBSD to stick
  to the coding style guidelines.
* Making use of static Notify functions of Haiku's ConditionalVariable
  implementation.
* Removing management of used ConditionalVariables within the compat layer.
  This should also fix #5072.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34461 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Colin Günther
2009-12-03 12:50:14 +00:00
parent f5251d5b60
commit a49ed9ad76
5 changed files with 65 additions and 115 deletions
+30 -81
View File
@@ -4,8 +4,6 @@
*/ */
#include "condvar.h"
extern "C" { extern "C" {
#include <compat/sys/condvar.h> #include <compat/sys/condvar.h>
#include <compat/sys/kernel.h> #include <compat/sys/kernel.h>
@@ -14,125 +12,76 @@ extern "C" {
#include <new> #include <new>
#include <condition_variable.h> #include <condition_variable.h>
#include <util/AutoLock.h>
#include "condvar.h"
#include "device.h" #include "device.h"
#define ticks_to_usecs(t) (1000000*((bigtime_t)t) / hz) #define ticks_to_usecs(t) (1000000*((bigtime_t)t) / hz)
static const int kConditionVariableHashSize = 32;
struct ConditionVariableHashDefinition {
typedef const void* KeyType;
typedef ConditionVariable ValueType;
size_t HashKey(const void* key) const
{ return (size_t)key; }
size_t Hash(ConditionVariable* variable) const
{ return (size_t)variable->fObject; }
bool Compare(const void* key, ConditionVariable* variable) const
{ return key == variable->fObject; }
ConditionVariable*& GetLink(ConditionVariable* variable) const
{ return variable->fNext; }
};
typedef BOpenHashTable<ConditionVariableHashDefinition> ConditionVariableHash;
static ConditionVariableHash sConditionVariableHash;
static spinlock sConditionVariablesLock;
extern "C" {
status_t status_t
init_condition_variables() init_condition_variables()
{ {
return sConditionVariableHash.Init(kConditionVariableHashSize); return B_OK;
} }
void void
uninit_condition_variables() {} uninit_condition_variables() {}
} /* extern "C" */
void void
_cv_init(const void* object, const char* description) conditionPublish(struct cv* variable, const void* waitChannel,
const char* description)
{ {
ConditionVariable* conditionVariable variable->waitChannel = waitChannel;
= new(std::nothrow) ConditionVariable(); variable->description = description;
if (conditionVariable == NULL) variable->condition = new(std::nothrow) ConditionVariable();
panic("No memory left."); variable->condition->Publish(waitChannel, description);
InterruptsSpinLocker _(sConditionVariablesLock);
conditionVariable->Publish(object, description);
sConditionVariableHash.Insert(conditionVariable);
} }
void void
_cv_destroy(const void* object) conditionUnpublish(const struct cv* variable)
{ {
InterruptsSpinLocker hashLocker(sConditionVariablesLock); variable->condition->Unpublish();
ConditionVariable* conditionVariable delete variable->condition;
= sConditionVariableHash.Lookup(object);
hashLocker.Unlock();
if (conditionVariable == NULL)
return;
conditionVariable->Unpublish();
sConditionVariableHash.RemoveUnchecked(conditionVariable);
delete conditionVariable;
}
void
_cv_wait_unlocked(const void* object)
{
ConditionVariableEntry conditionVariableEntry;
conditionVariableEntry.Wait(object);
} }
int int
_cv_timedwait_unlocked(const void* object, int timeout) conditionTimedWait(const struct cv* variable, const int timeout)
{ {
ConditionVariableEntry conditionVariableEntry; ConditionVariableEntry variableEntry;
status_t status = conditionVariableEntry.Wait(object, B_RELATIVE_TIMEOUT, status_t status = variableEntry.Wait(variable->waitChannel,
ticks_to_usecs(timeout)); B_RELATIVE_TIMEOUT, ticks_to_usecs(timeout));
if (status == B_OK) if (status != B_OK)
return ENOERR; status = EWOULDBLOCK;
else return status;
return EWOULDBLOCK;
} }
void void
_cv_signal(const void* object) conditionWait(const struct cv* variable)
{ {
InterruptsSpinLocker _(sConditionVariablesLock); ConditionVariableEntry variableEntry;
ConditionVariable* conditionVariable
= sConditionVariableHash.Lookup(object);
if (conditionVariable == NULL)
return;
conditionVariable->NotifyOne(); variableEntry.Wait(variable->waitChannel);
} }
void void
_cv_broadcast(const void* object) conditionNotifyOne(const void* waitChannel)
{ {
InterruptsSpinLocker _(sConditionVariablesLock); ConditionVariable::NotifyOne(waitChannel);
ConditionVariable* conditionVariable }
= sConditionVariableHash.Lookup(object);
if (conditionVariable == NULL)
return; void
conditionNotifyAll(const void* waitChannel)
conditionVariable->NotifyAll(); {
ConditionVariable::NotifyAll(waitChannel);
} }
@@ -10,11 +10,14 @@
struct cv { struct cv {
struct ConditionVariable* condition;
const char* description; const char* description;
const void* waitChannel;
}; };
void cv_init(struct cv*, const char*); void cv_init(struct cv*, const char*);
void cv_destroy(struct cv*);
void cv_wait(struct cv*, struct mtx*); void cv_wait(struct cv*, struct mtx*);
int cv_timedwait(struct cv*, struct mtx*, int); int cv_timedwait(struct cv*, struct mtx*, int);
void cv_signal(struct cv*); void cv_signal(struct cv*);
+14 -16
View File
@@ -10,41 +10,39 @@
#include "condvar.h" #include "condvar.h"
void cv_init(struct cv* conditionVariable, const char* description) void cv_init(struct cv* variable, const char* description)
{ {
conditionVariable->description = description; conditionPublish(variable, variable, description);
} }
void cv_signal(struct cv* conditionVariable) void cv_destroy(struct cv* variable)
{ {
_cv_signal(conditionVariable); conditionUnpublish(variable);
} }
int cv_timedwait(struct cv* conditionVariable, struct mtx* mutex, int timeout) void cv_signal(struct cv* variable)
{
conditionNotifyOne(variable);
}
int cv_timedwait(struct cv* variable, struct mtx* mutex, int timeout)
{ {
int status; int status;
_cv_init(conditionVariable, conditionVariable->description);
mtx_unlock(mutex); mtx_unlock(mutex);
status = _cv_timedwait_unlocked(conditionVariable, timeout); status = conditionTimedWait(variable, timeout);
mtx_lock(mutex); mtx_lock(mutex);
_cv_destroy(conditionVariable);
return status; return status;
} }
void cv_wait(struct cv* conditionVariable, struct mtx* mutex) void cv_wait(struct cv* variable, struct mtx* mutex)
{ {
_cv_init(conditionVariable, conditionVariable->description);
mtx_unlock(mutex); mtx_unlock(mutex);
_cv_wait_unlocked(conditionVariable); conditionWait(variable);
mtx_lock(mutex); mtx_lock(mutex);
_cv_destroy(conditionVariable);
} }
+6 -6
View File
@@ -10,12 +10,12 @@
extern "C" { extern "C" {
#endif #endif
void _cv_init(const void*, const char*); void conditionPublish(struct cv*, const void*, const char*);
void _cv_destroy(const void*); void conditionUnpublish(const struct cv*);
void _cv_wait_unlocked(const void*); void conditionNotifyOne(const void*);
int _cv_timedwait_unlocked(const void*, int); void conditionNotifyAll(const void*);
void _cv_signal(const void*); int conditionTimedWait(const struct cv*, const int);
void _cv_broadcast(const void*); void conditionWait(const struct cv*);
#ifdef __cplusplus #ifdef __cplusplus
} }
+9 -9
View File
@@ -7,26 +7,26 @@
#include <compat/sys/systm.h> #include <compat/sys/systm.h>
#include <compat/sys/kernel.h> #include <compat/sys/kernel.h>
#include <compat/sys/mutex.h> #include <compat/sys/mutex.h>
#include <compat/sys/condvar.h>
#include "condvar.h" #include "condvar.h"
static int sPauseWaitChannel;
int int
msleep(void* identifier, struct mtx* mutex, int priority, msleep(void* identifier, struct mtx* mutex, int priority,
const char* description, int timeout) const char* description, int timeout)
{ {
int status; int status;
struct cv sleep;
_cv_init(identifier, description); conditionPublish(&sleep, identifier, description);
mtx_unlock(mutex); mtx_unlock(mutex);
status = _cv_timedwait_unlocked(identifier, timeout); status = conditionTimedWait(&sleep, timeout);
mtx_lock(mutex); mtx_lock(mutex);
_cv_destroy(identifier); conditionUnpublish(&sleep);
return status; return status;
} }
@@ -34,14 +34,14 @@ msleep(void* identifier, struct mtx* mutex, int priority,
void void
wakeup(void* identifier) wakeup(void* identifier)
{ {
_cv_broadcast(identifier); conditionNotifyAll(identifier);
} }
int int
_pause(const char* waitMessage, int timeout) _pause(const char* waitMessage, int timeout)
{ {
int waitChannel;
KASSERT(timeout != 0, ("pause: timeout required")); KASSERT(timeout != 0, ("pause: timeout required"));
return tsleep(&sPauseWaitChannel, 0, waitMessage, timeout); return tsleep(&waitChannel, 0, waitMessage, timeout);
} }