* Basically reimplemented the conditional variable support, so that it is now
easier to a) cleanup on driver unloading and b) to implement the msleep and wakeup functions. This is facilitated by keeping track of used conditional variables in a hash table. Also this table can be used to get the conditional variable belonging to a hash, which isn't supported by Haiku's conditional variable support at the moment. All network drivers are compiling and linking but it needs to be tested, whether executing rises any issues. * Minor coding style cleanup in condvar.h regarding intersection spacing. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34375 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -11,9 +11,11 @@ extern "C" {
|
||||
#include <compat/sys/kernel.h>
|
||||
}
|
||||
|
||||
#include <condition_variable.h>
|
||||
#include <new>
|
||||
|
||||
#include <condition_variable.h>
|
||||
#include <slab/Slab.h>
|
||||
#include <util/AutoLock.h>
|
||||
|
||||
#include "device.h"
|
||||
|
||||
@@ -21,53 +23,83 @@ extern "C" {
|
||||
#define ticks_to_usecs(t) (1000000*(t) / hz)
|
||||
|
||||
|
||||
extern "C" {
|
||||
static object_cache* sConditionVariableCache;
|
||||
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()
|
||||
{
|
||||
sConditionVariableCache = create_object_cache("condition variables",
|
||||
sizeof (ConditionVariable), 0, NULL, NULL, NULL);
|
||||
if (sConditionVariableCache == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
return B_OK;
|
||||
return sConditionVariableHash.Init(kConditionVariableHashSize);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
uninit_condition_variables()
|
||||
{
|
||||
delete_object_cache(sConditionVariableCache);
|
||||
InterruptsSpinLocker _(sConditionVariablesLock);
|
||||
ConditionVariableHash::Iterator it = sConditionVariableHash.GetIterator();
|
||||
while (ConditionVariable* variable = it.Next()) {
|
||||
variable->Unpublish();
|
||||
free(variable);
|
||||
}
|
||||
}
|
||||
|
||||
} /* extern "C" */
|
||||
|
||||
|
||||
void
|
||||
_cv_init(struct cv* conditionVariable, const char* description)
|
||||
_cv_init(struct cv* conditionVariablePointer, const char* description)
|
||||
{
|
||||
conditionVariable->condVar
|
||||
= (ConditionVariable*)object_cache_alloc(sConditionVariableCache, 0);
|
||||
conditionVariable->condVar->Init(NULL, description);
|
||||
ConditionVariable* conditionVariable
|
||||
= new(std::nothrow) ConditionVariable();
|
||||
if (conditionVariable == NULL)
|
||||
panic("No memory left.");
|
||||
conditionVariablePointer->cv_waiters = 0;
|
||||
conditionVariable->Init(conditionVariablePointer, description);
|
||||
InterruptsSpinLocker _(sConditionVariablesLock);
|
||||
sConditionVariableHash.Insert(conditionVariable);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_cv_wait_unlocked(struct cv* conditionVariable)
|
||||
_cv_wait_unlocked(struct cv* conditionVariablePointer)
|
||||
{
|
||||
conditionVariable->condVar->Wait();
|
||||
InterruptsSpinLocker _(sConditionVariablesLock);
|
||||
ConditionVariable* conditionVariable
|
||||
= sConditionVariableHash.Lookup(conditionVariablePointer);
|
||||
conditionVariablePointer->cv_waiters++;
|
||||
conditionVariable->Wait();
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
_cv_timedwait_unlocked(struct cv* conditionVariable, int timeout)
|
||||
_cv_timedwait_unlocked(struct cv* conditionVariablePointer, int timeout)
|
||||
{
|
||||
status_t status;
|
||||
|
||||
status = conditionVariable->condVar->Wait(B_ABSOLUTE_TIMEOUT,
|
||||
InterruptsSpinLocker _(sConditionVariablesLock);
|
||||
ConditionVariable* conditionVariable
|
||||
= sConditionVariableHash.Lookup(conditionVariablePointer);
|
||||
conditionVariablePointer->cv_waiters++;
|
||||
status_t status = conditionVariable->Wait(B_ABSOLUTE_TIMEOUT,
|
||||
ticks_to_usecs(timeout));
|
||||
|
||||
if (status == B_OK)
|
||||
@@ -78,7 +110,12 @@ _cv_timedwait_unlocked(struct cv* conditionVariable, int timeout)
|
||||
|
||||
|
||||
void
|
||||
_cv_signal(struct cv* conditionVariable)
|
||||
_cv_signal(struct cv* conditionVariablePointer)
|
||||
{
|
||||
conditionVariable->condVar->NotifyOne();
|
||||
InterruptsSpinLocker _(sConditionVariablesLock);
|
||||
ConditionVariable* conditionVariable
|
||||
= sConditionVariableHash.Lookup(conditionVariablePointer);
|
||||
if (conditionVariablePointer->cv_waiters > 0)
|
||||
conditionVariablePointer->cv_waiters--;
|
||||
conditionVariable->NotifyOne();
|
||||
}
|
||||
|
||||
@@ -8,13 +8,15 @@
|
||||
|
||||
#include <sys/queue.h>
|
||||
|
||||
|
||||
struct cv {
|
||||
struct ConditionVariable* condVar;
|
||||
int cv_waiters;
|
||||
};
|
||||
|
||||
|
||||
void cv_init(struct cv*, const char*);
|
||||
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*);
|
||||
|
||||
#endif /* _FBSD_COMPAT_SYS_CONDVAR_H_ */
|
||||
|
||||
Reference in New Issue
Block a user