* 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"
#define ticks_to_usecs(t) (1000000*(t) / hz)
#define ticks_to_usecs(t) (1000000*((bigtime_t)t) / hz)
static const int kConditionVariableHashSize = 32;
@@ -57,10 +57,14 @@ void
uninit_condition_variables()
{
InterruptsSpinLocker _(sConditionVariablesLock);
ConditionVariableHash::Iterator it = sConditionVariableHash.GetIterator();
while (ConditionVariable* variable = it.Next()) {
ConditionVariableHashDefinition definition;
ConditionVariable* variable = sConditionVariableHash.Clear(true);
while (variable != NULL) {
ConditionVariable* next = definition.GetLink(variable);
variable->Unpublish();
free(variable);
delete variable;
variable = next;
}
}
@@ -68,38 +72,49 @@ uninit_condition_variables()
void
_cv_init(struct cv* conditionVariablePointer, const char* description)
_cv_init(const void* object, const char* description)
{
ConditionVariable* conditionVariable
= new(std::nothrow) ConditionVariable();
if (conditionVariable == NULL)
panic("No memory left.");
conditionVariablePointer->cv_waiters = 0;
conditionVariable->Init(conditionVariablePointer, description);
InterruptsSpinLocker _(sConditionVariablesLock);
conditionVariable->Publish(object, description);
sConditionVariableHash.Insert(conditionVariable);
}
void
_cv_wait_unlocked(struct cv* conditionVariablePointer)
_cv_destroy(const void* object)
{
InterruptsSpinLocker _(sConditionVariablesLock);
ConditionVariable* conditionVariable
= sConditionVariableHash.Lookup(conditionVariablePointer);
conditionVariablePointer->cv_waiters++;
conditionVariable->Wait();
ConditionVariable* conditionVariable
= sConditionVariableHash.Lookup(object);
if (conditionVariable == NULL)
return;
conditionVariable->Unpublish();
sConditionVariableHash.RemoveUnchecked(conditionVariable);
delete conditionVariable;
}
void
_cv_wait_unlocked(const void* object)
{
ConditionVariableEntry conditionVariableEntry;
conditionVariableEntry.Wait(object);
}
int
_cv_timedwait_unlocked(struct cv* conditionVariablePointer, int timeout)
_cv_timedwait_unlocked(const void* object, int timeout)
{
InterruptsSpinLocker _(sConditionVariablesLock);
ConditionVariable* conditionVariable
= sConditionVariableHash.Lookup(conditionVariablePointer);
conditionVariablePointer->cv_waiters++;
status_t status = conditionVariable->Wait(B_ABSOLUTE_TIMEOUT,
ConditionVariableEntry conditionVariableEntry;
status_t status = conditionVariableEntry.Wait(object, B_ABSOLUTE_TIMEOUT,
ticks_to_usecs(timeout));
if (status == B_OK)
@@ -110,12 +125,26 @@ _cv_timedwait_unlocked(struct cv* conditionVariablePointer, int timeout)
void
_cv_signal(struct cv* conditionVariablePointer)
_cv_signal(const void* object)
{
InterruptsSpinLocker _(sConditionVariablesLock);
ConditionVariable* conditionVariable
= sConditionVariableHash.Lookup(conditionVariablePointer);
if (conditionVariablePointer->cv_waiters > 0)
conditionVariablePointer->cv_waiters--;
= sConditionVariableHash.Lookup(object);
if (conditionVariable == NULL)
return;
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
mutex.c
priv.c
sleepqueue.c
synch.c
taskqueue.c
timeout.c
@@ -10,7 +10,7 @@
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" {
#endif
void _cv_init(struct cv*, const char*);
void _cv_wait_unlocked(struct cv *);
int _cv_timedwait_unlocked(struct cv*, int);
void _cv_signal(struct cv*);
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*);
#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/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
@@ -18,19 +20,13 @@ msleep(void* identifier, struct mtx* mutex, int priority,
{
int status;
// TODO can be removed once the sleepq functions are implemented.
status = snooze(ticks_to_msecs(timeout));
sleepq_lock(identifier);
sleepq_add(identifier, mutex, description, 0, 0);
sleepq_release(identifier);
status = sleepq_timedwait(identifier, timeout);
sleepq_lock(identifier);
sleepq_remove(NULL, identifier);
sleepq_release(identifier);
_cv_init(identifier, description);
mtx_unlock(mutex);
status = _cv_timedwait_unlocked(identifier, timeout);
mtx_lock(mutex);
_cv_destroy(identifier);
return status;
}
@@ -38,7 +34,14 @@ msleep(void* identifier, struct mtx* mutex, int priority,
void
wakeup(void* identifier)
{
sleepq_lock(identifier);
sleepq_broadcast(identifier, 0, 0, 0);
sleepq_release(identifier);
_cv_broadcast(identifier);
}
int
_pause(const char* waitMessage, int timeout)
{
KASSERT(timeout != 0, ("pause: timeout required"));
return tsleep(&sPauseWaitChannel, 0, waitMessage, timeout);
}