* Completing the condition variable subsystem. Thanks to ingo for the heads

up.
* Removed the cv_waiters structure member as it is nowhere used in the network
  subsytem by FreeBSD either.
* Removing the sleepqueue dummy functions completely, as Haiku's condition
  variable subsystem is well suited for this purpose.
* This fixes the build, too, as it introduces the new implementation of pause
  and _pause.
* Implementing the msleep and wakeup functions based on the condition variable
  implementation.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34395 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Colin Günther
2009-11-30 22:27:02 +00:00
parent 73bade369c
commit cb89b085e3
7 changed files with 79 additions and 113 deletions
+51 -22
View File
@@ -20,7 +20,7 @@ extern "C" {
#include "device.h" #include "device.h"
#define ticks_to_usecs(t) (1000000*(t) / hz) #define ticks_to_usecs(t) (1000000*((bigtime_t)t) / hz)
static const int kConditionVariableHashSize = 32; static const int kConditionVariableHashSize = 32;
@@ -57,10 +57,14 @@ void
uninit_condition_variables() uninit_condition_variables()
{ {
InterruptsSpinLocker _(sConditionVariablesLock); InterruptsSpinLocker _(sConditionVariablesLock);
ConditionVariableHash::Iterator it = sConditionVariableHash.GetIterator(); ConditionVariableHashDefinition definition;
while (ConditionVariable* variable = it.Next()) { ConditionVariable* variable = sConditionVariableHash.Clear(true);
while (variable != NULL) {
ConditionVariable* next = definition.GetLink(variable);
variable->Unpublish(); variable->Unpublish();
free(variable); delete variable;
variable = next;
} }
} }
@@ -68,38 +72,49 @@ uninit_condition_variables()
void void
_cv_init(struct cv* conditionVariablePointer, const char* description) _cv_init(const void* object, const char* description)
{ {
ConditionVariable* conditionVariable ConditionVariable* conditionVariable
= new(std::nothrow) ConditionVariable(); = new(std::nothrow) ConditionVariable();
if (conditionVariable == NULL) if (conditionVariable == NULL)
panic("No memory left."); panic("No memory left.");
conditionVariablePointer->cv_waiters = 0;
conditionVariable->Init(conditionVariablePointer, description);
InterruptsSpinLocker _(sConditionVariablesLock); InterruptsSpinLocker _(sConditionVariablesLock);
conditionVariable->Publish(object, description);
sConditionVariableHash.Insert(conditionVariable); sConditionVariableHash.Insert(conditionVariable);
} }
void void
_cv_wait_unlocked(struct cv* conditionVariablePointer) _cv_destroy(const void* object)
{ {
InterruptsSpinLocker _(sConditionVariablesLock); InterruptsSpinLocker _(sConditionVariablesLock);
ConditionVariable* conditionVariable ConditionVariable* conditionVariable
= sConditionVariableHash.Lookup(conditionVariablePointer); = sConditionVariableHash.Lookup(object);
conditionVariablePointer->cv_waiters++; if (conditionVariable == NULL)
conditionVariable->Wait(); 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(struct cv* conditionVariablePointer, int timeout) _cv_timedwait_unlocked(const void* object, int timeout)
{ {
InterruptsSpinLocker _(sConditionVariablesLock); ConditionVariableEntry conditionVariableEntry;
ConditionVariable* conditionVariable
= sConditionVariableHash.Lookup(conditionVariablePointer); status_t status = conditionVariableEntry.Wait(object, B_ABSOLUTE_TIMEOUT,
conditionVariablePointer->cv_waiters++;
status_t status = conditionVariable->Wait(B_ABSOLUTE_TIMEOUT,
ticks_to_usecs(timeout)); ticks_to_usecs(timeout));
if (status == B_OK) if (status == B_OK)
@@ -110,12 +125,26 @@ _cv_timedwait_unlocked(struct cv* conditionVariablePointer, int timeout)
void void
_cv_signal(struct cv* conditionVariablePointer) _cv_signal(const void* object)
{ {
InterruptsSpinLocker _(sConditionVariablesLock); InterruptsSpinLocker _(sConditionVariablesLock);
ConditionVariable* conditionVariable ConditionVariable* conditionVariable
= sConditionVariableHash.Lookup(conditionVariablePointer); = sConditionVariableHash.Lookup(object);
if (conditionVariablePointer->cv_waiters > 0) if (conditionVariable == NULL)
conditionVariablePointer->cv_waiters--; return;
conditionVariable->NotifyOne(); conditionVariable->NotifyOne();
} }
void
_cv_broadcast(const void* object)
{
InterruptsSpinLocker _(sConditionVariablesLock);
ConditionVariable* conditionVariable
= sConditionVariableHash.Lookup(object);
if (conditionVariable == NULL)
return;
conditionVariable->NotifyAll();
}
-1
View File
@@ -33,7 +33,6 @@ KernelStaticLibrary libfreebsd_network.a :
mii.c mii.c
mutex.c mutex.c
priv.c priv.c
sleepqueue.c
synch.c synch.c
taskqueue.c taskqueue.c
timeout.c timeout.c
@@ -10,7 +10,7 @@
struct cv { struct cv {
int cv_waiters; int dummy;
}; };
@@ -1,16 +0,0 @@
/*
* Copyright 2009, Colin Günther, [email protected]
* All Rights Reserved. Distributed under the terms of the MIT License.
*/
#ifndef _FBSD_COMPAT_SYS_SLEEPQUEUE_H_
#define _FBSD_COMPAT_SYS_SLEEPQUEUE_H_
void sleepq_add(void*, struct mtx*, const char*, int, int);
int sleepq_broadcast(void*, int, int, int);
void sleepq_lock(void*);
void sleepq_release(void*);
void sleepq_remove(struct thread*, void*);
int sleepq_timedwait(void*, int);
#endif /* _FBSD_COMPAT_SYS_SLEEPQUEUE_H_ */
+6 -4
View File
@@ -10,10 +10,12 @@
extern "C" { extern "C" {
#endif #endif
void _cv_init(struct cv*, const char*); void _cv_init(const void*, const char*);
void _cv_wait_unlocked(struct cv *); void _cv_destroy(const void*);
int _cv_timedwait_unlocked(struct cv*, int); void _cv_wait_unlocked(const void*);
void _cv_signal(struct cv*); int _cv_timedwait_unlocked(const void*, int);
void _cv_signal(const void*);
void _cv_broadcast(const void*);
#ifdef __cplusplus #ifdef __cplusplus
} }
@@ -1,51 +0,0 @@
/*
* Copyright 2009 Colin Günther, [email protected]
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include <compat/sys/systm.h>
#include <compat/sys/sleepqueue.h>
void
sleepq_add(void* identifier, struct mtx* mutex, const char* description,
int flags, int queue)
{
}
int
sleepq_broadcast(void* identifier, int flags, int priority, int queue)
{
return 0;
}
void
sleepq_lock(void* identifier)
{
}
void
sleepq_release(void* identifier)
{
}
void
sleepq_remove(struct thread* thread, void* identifier)
{
}
int
sleepq_timedwait(void* identifier, int priority)
{
return 0;
}
+21 -18
View File
@@ -6,10 +6,12 @@
#include <compat/sys/systm.h> #include <compat/sys/systm.h>
#include <compat/sys/kernel.h> #include <compat/sys/kernel.h>
#include <compat/sys/sleepqueue.h> #include <compat/sys/mutex.h>
#include "condvar.h"
#define ticks_to_msecs(t) (1000 * (t) / hz) static int sPauseWaitChannel;
int int
@@ -18,19 +20,13 @@ msleep(void* identifier, struct mtx* mutex, int priority,
{ {
int status; int status;
// TODO can be removed once the sleepq functions are implemented. _cv_init(identifier, description);
status = snooze(ticks_to_msecs(timeout));
mtx_unlock(mutex);
sleepq_lock(identifier); status = _cv_timedwait_unlocked(identifier, timeout);
sleepq_add(identifier, mutex, description, 0, 0); mtx_lock(mutex);
sleepq_release(identifier);
_cv_destroy(identifier);
status = sleepq_timedwait(identifier, timeout);
sleepq_lock(identifier);
sleepq_remove(NULL, identifier);
sleepq_release(identifier);
return status; return status;
} }
@@ -38,7 +34,14 @@ msleep(void* identifier, struct mtx* mutex, int priority,
void void
wakeup(void* identifier) wakeup(void* identifier)
{ {
sleepq_lock(identifier); _cv_broadcast(identifier);
sleepq_broadcast(identifier, 0, 0, 0); }
sleepq_release(identifier);
int
_pause(const char* waitMessage, int timeout)
{
KASSERT(timeout != 0, ("pause: timeout required"));
return tsleep(&sPauseWaitChannel, 0, waitMessage, timeout);
} }