* 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

View File

@ -4,8 +4,6 @@
*/
#include "condvar.h"
extern "C" {
#include <compat/sys/condvar.h>
#include <compat/sys/kernel.h>
@ -14,125 +12,76 @@ extern "C" {
#include <new>
#include <condition_variable.h>
#include <util/AutoLock.h>
#include "condvar.h"
#include "device.h"
#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
init_condition_variables()
{
return sConditionVariableHash.Init(kConditionVariableHashSize);
return B_OK;
}
void
uninit_condition_variables() {}
} /* extern "C" */
void
_cv_init(const void* object, const char* description)
conditionPublish(struct cv* variable, const void* waitChannel,
const char* description)
{
ConditionVariable* conditionVariable
= new(std::nothrow) ConditionVariable();
if (conditionVariable == NULL)
panic("No memory left.");
InterruptsSpinLocker _(sConditionVariablesLock);
conditionVariable->Publish(object, description);
sConditionVariableHash.Insert(conditionVariable);
variable->waitChannel = waitChannel;
variable->description = description;
variable->condition = new(std::nothrow) ConditionVariable();
variable->condition->Publish(waitChannel, description);
}
void
_cv_destroy(const void* object)
conditionUnpublish(const struct cv* variable)
{
InterruptsSpinLocker hashLocker(sConditionVariablesLock);
ConditionVariable* conditionVariable
= 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);
variable->condition->Unpublish();
delete variable->condition;
}
int
_cv_timedwait_unlocked(const void* object, int timeout)
conditionTimedWait(const struct cv* variable, const int timeout)
{
ConditionVariableEntry conditionVariableEntry;
status_t status = conditionVariableEntry.Wait(object, B_RELATIVE_TIMEOUT,
ticks_to_usecs(timeout));
ConditionVariableEntry variableEntry;
if (status == B_OK)
return ENOERR;
else
return EWOULDBLOCK;
status_t status = variableEntry.Wait(variable->waitChannel,
B_RELATIVE_TIMEOUT, ticks_to_usecs(timeout));
if (status != B_OK)
status = EWOULDBLOCK;
return status;
}
void
_cv_signal(const void* object)
conditionWait(const struct cv* variable)
{
InterruptsSpinLocker _(sConditionVariablesLock);
ConditionVariable* conditionVariable
= sConditionVariableHash.Lookup(object);
if (conditionVariable == NULL)
return;
ConditionVariableEntry variableEntry;
conditionVariable->NotifyOne();
variableEntry.Wait(variable->waitChannel);
}
void
_cv_broadcast(const void* object)
conditionNotifyOne(const void* waitChannel)
{
InterruptsSpinLocker _(sConditionVariablesLock);
ConditionVariable* conditionVariable
= sConditionVariableHash.Lookup(object);
if (conditionVariable == NULL)
return;
conditionVariable->NotifyAll();
ConditionVariable::NotifyOne(waitChannel);
}
void
conditionNotifyAll(const void* waitChannel)
{
ConditionVariable::NotifyAll(waitChannel);
}

View File

@ -10,11 +10,14 @@
struct cv {
struct ConditionVariable* condition;
const char* description;
const void* waitChannel;
};
void cv_init(struct cv*, const char*);
void cv_destroy(struct cv*);
void cv_wait(struct cv*, struct mtx*);
int cv_timedwait(struct cv*, struct mtx*, int);
void cv_signal(struct cv*);

View File

@ -10,41 +10,39 @@
#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;
_cv_init(conditionVariable, conditionVariable->description);
mtx_unlock(mutex);
status = _cv_timedwait_unlocked(conditionVariable, timeout);
status = conditionTimedWait(variable, timeout);
mtx_lock(mutex);
_cv_destroy(conditionVariable);
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);
_cv_wait_unlocked(conditionVariable);
conditionWait(variable);
mtx_lock(mutex);
_cv_destroy(conditionVariable);
}

View File

@ -10,12 +10,12 @@
extern "C" {
#endif
void _cv_init(const void*, const char*);
void _cv_destroy(const void*);
void _cv_wait_unlocked(const void*);
int _cv_timedwait_unlocked(const void*, int);
void _cv_signal(const void*);
void _cv_broadcast(const void*);
void conditionPublish(struct cv*, const void*, const char*);
void conditionUnpublish(const struct cv*);
void conditionNotifyOne(const void*);
void conditionNotifyAll(const void*);
int conditionTimedWait(const struct cv*, const int);
void conditionWait(const struct cv*);
#ifdef __cplusplus
}

View File

@ -7,26 +7,26 @@
#include <compat/sys/systm.h>
#include <compat/sys/kernel.h>
#include <compat/sys/mutex.h>
#include <compat/sys/condvar.h>
#include "condvar.h"
static int sPauseWaitChannel;
int
msleep(void* identifier, struct mtx* mutex, int priority,
const char* description, int timeout)
{
int status;
struct cv sleep;
conditionPublish(&sleep, identifier, description);
_cv_init(identifier, description);
mtx_unlock(mutex);
status = _cv_timedwait_unlocked(identifier, timeout);
status = conditionTimedWait(&sleep, timeout);
mtx_lock(mutex);
_cv_destroy(identifier);
conditionUnpublish(&sleep);
return status;
}
@ -34,14 +34,14 @@ msleep(void* identifier, struct mtx* mutex, int priority,
void
wakeup(void* identifier)
{
_cv_broadcast(identifier);
conditionNotifyAll(identifier);
}
int
_pause(const char* waitMessage, int timeout)
{
int waitChannel;
KASSERT(timeout != 0, ("pause: timeout required"));
return tsleep(&sPauseWaitChannel, 0, waitMessage, timeout);
return tsleep(&waitChannel, 0, waitMessage, timeout);
}