* 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:
Colin Günther
2009-11-30 13:17:04 +00:00
parent 0eb45760a7
commit d0805bf47e
2 changed files with 63 additions and 24 deletions
+59 -22
View File
@@ -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_ */