* 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:
parent
f5251d5b60
commit
a49ed9ad76
@ -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);
|
||||
}
|
||||
|
@ -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*);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user