* 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:
@@ -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();
|
||||||
|
}
|
||||||
|
|||||||
@@ -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_ */
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user