* 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:
@@ -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,
|
|
||||||
ticks_to_usecs(timeout));
|
|
||||||
|
|
||||||
if (status == B_OK)
|
status_t status = variableEntry.Wait(variable->waitChannel,
|
||||||
return ENOERR;
|
B_RELATIVE_TIMEOUT, ticks_to_usecs(timeout));
|
||||||
else
|
|
||||||
return EWOULDBLOCK;
|
if (status != B_OK)
|
||||||
|
status = EWOULDBLOCK;
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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*);
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
conditionPublish(&sleep, identifier, description);
|
||||||
|
|
||||||
_cv_init(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);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user