Fixed a few regressions that were introduced during the last months:
* device_attach() must not load the network stack. Besides being completely unbalanced, this was also one reason why the stack could not be unloaded anymore. Instead, it's now done in compat_open(), as before. * This also fixes network booting from FreeBSD drivers - the stack apparently could not be initialized that early. * Replaced the previous network stack based callout implementation with one that mostly copies its functionality, but has no dependencies. Furthermore, it runs at a higher priority (the one of the network timer should also be revisited, though). * Fixed mtx_owned() to work without KDEBUG as well. It's not a good idea to introduce code that behaves completely different based on debug settings. * Minor cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37580 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -14,7 +14,7 @@ SubDirCcFlags [ FDefines _KERNEL=1 ] ;
|
||||
|
||||
KernelStaticLibrary libfreebsd_network.a :
|
||||
bus.c
|
||||
callout.c
|
||||
callout.cpp
|
||||
clock.c
|
||||
compat.c
|
||||
compat_cpp.cpp
|
||||
@@ -40,7 +40,6 @@ KernelStaticLibrary libfreebsd_network.a :
|
||||
priv.c
|
||||
synch.c
|
||||
taskqueue.c
|
||||
timeout.c
|
||||
unit.c
|
||||
Unit.cpp
|
||||
;
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Copyright 2009, Colin Günther, [email protected].
|
||||
* Copyright 2007, Hugo Santos. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "device.h"
|
||||
|
||||
#include <compat/sys/callout.h>
|
||||
|
||||
|
||||
static void
|
||||
handle_callout(struct net_timer *timer, void *data)
|
||||
{
|
||||
struct callout *c = data;
|
||||
struct mtx *c_mtx = c->c_mtx;
|
||||
|
||||
if (c_mtx)
|
||||
mtx_lock(c_mtx);
|
||||
|
||||
/* FreeBSD 6.2 uses THREAD_NO_SLEEPING/THREAD_SLEEPING_OK when calling the
|
||||
* callback */
|
||||
|
||||
c->c_func(c->c_arg);
|
||||
|
||||
if (c_mtx)
|
||||
mtx_unlock(c_mtx);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
void
|
||||
callout_init_mtx(struct callout *c, struct mtx *mtx, int flags)
|
||||
{
|
||||
gStack->init_timer(&c->c_timer, handle_callout, c);
|
||||
|
||||
c->c_arg = NULL;
|
||||
c->c_func = NULL;
|
||||
c->c_mtx = mtx;
|
||||
c->c_flags = flags;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
callout_reset(struct callout *c, int when, void (*func)(void *), void *arg)
|
||||
{
|
||||
int canceled = gStack->cancel_timer(&c->c_timer) ? 1 : 0;
|
||||
|
||||
c->c_func = func;
|
||||
c->c_arg = arg;
|
||||
|
||||
gStack->set_timer(&c->c_timer, when);
|
||||
|
||||
return canceled;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
_callout_stop_safe(struct callout *c, int safe)
|
||||
{
|
||||
return gStack->cancel_timer(&c->c_timer) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
callout_pending(struct callout *c)
|
||||
{
|
||||
return gStack->is_timer_active(&c->c_timer);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
callout_active(struct callout *c)
|
||||
{
|
||||
return gStack->is_timer_running(&c->c_timer);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* Copyright 2010, Axel Dörfler, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "device.h"
|
||||
|
||||
#include <lock.h>
|
||||
#include <thread.h>
|
||||
|
||||
extern "C" {
|
||||
# include <sys/callout.h>
|
||||
# include <sys/mutex.h>
|
||||
}
|
||||
|
||||
#include <util/AutoLock.h>
|
||||
|
||||
|
||||
//#define TRACE_CALLOUT
|
||||
#ifdef TRACE_CALLOUT
|
||||
# define TRACE(x...) dprintf(x)
|
||||
#else
|
||||
# define TRACE(x...) ;
|
||||
#endif
|
||||
|
||||
|
||||
static struct list sTimers;
|
||||
static mutex sLock;
|
||||
static sem_id sWaitSem;
|
||||
static callout* sCurrentCallout;
|
||||
static thread_id sThread;
|
||||
static bigtime_t sTimeout;
|
||||
|
||||
|
||||
static status_t
|
||||
callout_thread(void* /*data*/)
|
||||
{
|
||||
status_t status = B_OK;
|
||||
|
||||
do {
|
||||
bigtime_t timeout = B_INFINITE_TIMEOUT;
|
||||
|
||||
if (status == B_TIMED_OUT || status == B_OK) {
|
||||
// scan timers for new timeout and/or execute a timer
|
||||
mutex_lock(&sLock);
|
||||
|
||||
while (true) {
|
||||
struct callout* c = (callout*)list_get_next_item(&sTimers, c);
|
||||
if (c == NULL)
|
||||
break;
|
||||
|
||||
if (c->due < system_time()) {
|
||||
struct mtx *mutex = c->c_mtx;
|
||||
|
||||
// execute timer
|
||||
list_remove_item(&sTimers, c);
|
||||
c->due = -1;
|
||||
sCurrentCallout = c;
|
||||
|
||||
mutex_unlock(&sLock);
|
||||
|
||||
if (mutex != NULL)
|
||||
mtx_lock(mutex);
|
||||
|
||||
c->c_func(c->c_arg);
|
||||
|
||||
if (mutex != NULL)
|
||||
mtx_unlock(mutex);
|
||||
|
||||
mutex_lock(&sLock);
|
||||
|
||||
sCurrentCallout = NULL;
|
||||
c = NULL;
|
||||
// restart scanning as we unlocked the list
|
||||
} else {
|
||||
// calculate new timeout
|
||||
if (c->due < timeout)
|
||||
timeout = c->due;
|
||||
}
|
||||
}
|
||||
|
||||
sTimeout = timeout;
|
||||
mutex_unlock(&sLock);
|
||||
}
|
||||
|
||||
status = acquire_sem_etc(sWaitSem, 1, B_ABSOLUTE_TIMEOUT, timeout);
|
||||
// the wait sem normally can't be acquired, so we
|
||||
// have to look at the status value the call returns:
|
||||
//
|
||||
// B_OK - a new timer has been added or canceled
|
||||
// B_TIMED_OUT - look for timers to be executed
|
||||
// B_BAD_SEM_ID - we are asked to quit
|
||||
} while (status != B_BAD_SEM_ID);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - private API
|
||||
|
||||
|
||||
status_t
|
||||
init_callout(void)
|
||||
{
|
||||
list_init(&sTimers);
|
||||
sTimeout = B_INFINITE_TIMEOUT;
|
||||
|
||||
status_t status = B_OK;
|
||||
mutex_init(&sLock, "fbsd callout");
|
||||
|
||||
sWaitSem = create_sem(0, "fbsd callout wait");
|
||||
if (sWaitSem < 0) {
|
||||
status = sWaitSem;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
sThread = spawn_kernel_thread(callout_thread, "fbsd callout",
|
||||
B_URGENT_DISPLAY_PRIORITY, NULL);
|
||||
if (sThread < 0) {
|
||||
status = sThread;
|
||||
goto err2;
|
||||
}
|
||||
|
||||
return resume_thread(sThread);
|
||||
|
||||
err1:
|
||||
mutex_destroy(&sLock);
|
||||
err2:
|
||||
delete_sem(sWaitSem);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
uninit_callout(void)
|
||||
{
|
||||
delete_sem(sWaitSem);
|
||||
mutex_lock(&sLock);
|
||||
|
||||
mutex_destroy(&sLock);
|
||||
|
||||
status_t status;
|
||||
wait_for_thread(sThread, &status);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - public API
|
||||
|
||||
|
||||
void
|
||||
callout_init(struct callout *callout, int mpsafe)
|
||||
{
|
||||
if (mpsafe)
|
||||
callout_init_mtx(callout, NULL, 0);
|
||||
else
|
||||
callout_init_mtx(callout, &Giant, 0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
callout_init_mtx(struct callout *c, struct mtx *mtx, int flags)
|
||||
{
|
||||
c->due = 0;
|
||||
c->flags = 0;
|
||||
|
||||
c->c_arg = NULL;
|
||||
c->c_func = NULL;
|
||||
c->c_mtx = mtx;
|
||||
c->c_flags = flags;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
callout_reset(struct callout *c, int when, void (*func)(void *), void *arg)
|
||||
{
|
||||
int canceled = callout_stop(c);
|
||||
|
||||
MutexLocker locker(sLock);
|
||||
|
||||
c->c_func = func;
|
||||
c->c_arg = arg;
|
||||
|
||||
TRACE("callout_reset %p, func %p, arg %p\n", c, c->c_func, c->c_arg);
|
||||
|
||||
if (when >= 0) {
|
||||
// reschedule or add this timer
|
||||
if (c->due <= 0)
|
||||
list_add_item(&sTimers, c);
|
||||
|
||||
c->due = system_time() + when;
|
||||
|
||||
// notify timer about the change if necessary
|
||||
if (sTimeout > c->due)
|
||||
release_sem(sWaitSem);
|
||||
}
|
||||
|
||||
return canceled;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
callout_schedule(struct callout *callout, int toTicks)
|
||||
{
|
||||
return callout_reset(callout, toTicks, callout->c_func, callout->c_arg);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
_callout_stop_safe(struct callout *c, int safe)
|
||||
{
|
||||
MutexLocker locker(sLock);
|
||||
|
||||
TRACE("_callout_stop_safe %p, func %p, arg %p\n", c, c->c_func, c->c_arg);
|
||||
|
||||
if (c->due <= 0)
|
||||
return 0;
|
||||
|
||||
// this timer is scheduled, cancel it
|
||||
list_remove_item(&sTimers, c);
|
||||
c->due = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
callout_pending(struct callout *c)
|
||||
{
|
||||
return c->due > 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
callout_active(struct callout *c)
|
||||
{
|
||||
return c == sCurrentCallout;
|
||||
}
|
||||
@@ -385,18 +385,13 @@ device_attach(device_t device)
|
||||
|| device->methods.attach == NULL)
|
||||
return B_ERROR;
|
||||
|
||||
if (get_module(NET_STACK_MODULE_NAME, (module_info **)&gStack) != B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
result = device->methods.attach(device);
|
||||
|
||||
if (result == 0) {
|
||||
if (result == 0)
|
||||
atomic_or(&device->flags, DEVICE_ATTACHED);
|
||||
}
|
||||
|
||||
if (result == 0) {
|
||||
if (result == 0)
|
||||
result = start_wlan(device);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -7,12 +7,18 @@
|
||||
#define _FBSD_COMPAT_SYS__MUTEX_H_
|
||||
|
||||
|
||||
#include <lock.h>
|
||||
|
||||
|
||||
struct mtx {
|
||||
int type;
|
||||
int type;
|
||||
union {
|
||||
mutex mutex;
|
||||
int32 spinlock;
|
||||
recursive_lock recursive;
|
||||
struct {
|
||||
mutex lock;
|
||||
thread_id owner;
|
||||
} mutex;
|
||||
int32 spinlock;
|
||||
recursive_lock recursive;
|
||||
} u;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010, Axel Dörfler, [email protected].
|
||||
* Copyright 2009, Colin Günther, [email protected].
|
||||
* Copyright 2007, Hugo Santos. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
@@ -13,7 +14,10 @@
|
||||
|
||||
|
||||
struct callout {
|
||||
struct net_timer c_timer;
|
||||
struct list_link link;
|
||||
bigtime_t due;
|
||||
uint32 flags;
|
||||
|
||||
void * c_arg;
|
||||
void (*c_func)(void *);
|
||||
struct mtx * c_mtx;
|
||||
@@ -24,18 +28,17 @@ struct callout {
|
||||
#define CALLOUT_MPSAFE 0x0001
|
||||
|
||||
|
||||
void callout_init(struct callout *c, int mpsafe);
|
||||
void callout_init_mtx(struct callout *c, struct mtx *mutex, int flags);
|
||||
int callout_reset(struct callout *c, int, void (*func)(void *), void *arg);
|
||||
int callout_schedule(struct callout *c, int when);
|
||||
int callout_reset(struct callout *c, int when, void (*func)(void *), void *arg);
|
||||
int callout_pending(struct callout *c);
|
||||
int callout_active(struct callout *c);
|
||||
|
||||
#define callout_drain(c) _callout_stop_safe(c, 1)
|
||||
#define callout_stop(c) _callout_stop_safe(c, 0)
|
||||
int _callout_stop_safe(struct callout *, int);
|
||||
int _callout_stop_safe(struct callout *c, int safe);
|
||||
|
||||
inline void
|
||||
callout_init(struct callout *c, int mpsafe);
|
||||
|
||||
int callout_schedule(struct callout *, int);
|
||||
|
||||
#endif /* _FBSD_COMPAT_SYS_CALLOUT_H_ */
|
||||
|
||||
@@ -42,9 +42,10 @@ void mtx_destroy(struct mtx*);
|
||||
static inline void
|
||||
mtx_lock(struct mtx* mutex)
|
||||
{
|
||||
if (mutex->type == MTX_DEF)
|
||||
mutex_lock(&mutex->u.mutex);
|
||||
else if (mutex->type == MTX_RECURSE)
|
||||
if (mutex->type == MTX_DEF) {
|
||||
mutex_lock(&mutex->u.mutex.lock);
|
||||
mutex->u.mutex.owner = thread_get_current_thread_id();
|
||||
} else if (mutex->type == MTX_RECURSE)
|
||||
recursive_lock_lock(&mutex->u.recursive);
|
||||
}
|
||||
|
||||
@@ -52,9 +53,10 @@ mtx_lock(struct mtx* mutex)
|
||||
static inline void
|
||||
mtx_unlock(struct mtx* mutex)
|
||||
{
|
||||
if (mutex->type == MTX_DEF)
|
||||
mutex_unlock(&mutex->u.mutex);
|
||||
else if (mutex->type == MTX_RECURSE)
|
||||
if (mutex->type == MTX_DEF) {
|
||||
mutex->u.mutex.owner = -1;
|
||||
mutex_unlock(&mutex->u.mutex.lock);
|
||||
} else if (mutex->type == MTX_RECURSE)
|
||||
recursive_lock_unlock(&mutex->u.recursive);
|
||||
}
|
||||
|
||||
@@ -62,7 +64,7 @@ mtx_unlock(struct mtx* mutex)
|
||||
static inline int
|
||||
mtx_initialized(struct mtx* mutex)
|
||||
{
|
||||
/* XXX */
|
||||
/* TODO */
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -71,22 +73,17 @@ static inline int
|
||||
mtx_owned(struct mtx* mutex)
|
||||
{
|
||||
if (mutex->type == MTX_DEF)
|
||||
#if KDEBUG
|
||||
return mutex->u.mutex.holder == thread_get_current_thread_id();
|
||||
#else
|
||||
return 0;
|
||||
// found no way how to determine the holder of the mutex
|
||||
// so we setting it to 0 because a starving thread is easier
|
||||
// to detect than a race condition; Colin Günther
|
||||
#endif
|
||||
else if (mutex->type == MTX_RECURSE)
|
||||
return mutex->u.mutex.owner == thread_get_current_thread_id();
|
||||
if (mutex->type == MTX_RECURSE) {
|
||||
#if KDEBUG
|
||||
return mutex->u.recursive.lock.holder == thread_get_current_thread_id();
|
||||
#else
|
||||
return mutex->u.recursive.holder == thread_get_current_thread_id();
|
||||
#endif
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif /* _FBSD_COMPAT_SYS_MUTEX_H_ */
|
||||
|
||||
@@ -37,6 +37,9 @@ compat_open(const char *name, uint32 flags, void **cookie)
|
||||
if (i == MAX_DEVICES)
|
||||
return B_ERROR;
|
||||
|
||||
if (get_module(NET_STACK_MODULE_NAME, (module_info **)&gStack) != B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
ifp = gDevices[i];
|
||||
if_printf(ifp, "compat_open(0x%lx)\n", flags);
|
||||
|
||||
|
||||
@@ -68,6 +68,9 @@ void uninit_taskqueues(void);
|
||||
status_t init_hard_clock(void);
|
||||
void uninit_hard_clock(void);
|
||||
|
||||
status_t init_callout(void);
|
||||
void uninit_callout(void);
|
||||
|
||||
device_t find_root_device(int);
|
||||
|
||||
/* busdma_machdep.c */
|
||||
|
||||
@@ -166,17 +166,21 @@ _fbsd_init_driver(driver_t *driver)
|
||||
if (status < B_OK)
|
||||
goto err3;
|
||||
|
||||
status = init_callout();
|
||||
if (status < B_OK)
|
||||
goto err4;
|
||||
|
||||
init_bounce_pages();
|
||||
|
||||
if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) {
|
||||
status = init_taskqueues();
|
||||
if (status < B_OK)
|
||||
goto err4;
|
||||
goto err5;
|
||||
}
|
||||
|
||||
status = init_wlan_stack();
|
||||
if (status < B_OK)
|
||||
goto err5;
|
||||
goto err6;
|
||||
|
||||
while (gDeviceCount < MAX_DEVICES) {
|
||||
device_t root, device;
|
||||
@@ -214,11 +218,13 @@ _fbsd_init_driver(driver_t *driver)
|
||||
|
||||
uninit_wlan_stack();
|
||||
|
||||
err5:
|
||||
err6:
|
||||
if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES))
|
||||
uninit_taskqueues();
|
||||
err4:
|
||||
err5:
|
||||
uninit_mbufs();
|
||||
err4:
|
||||
uninit_callout();
|
||||
err3:
|
||||
uninit_mutexes();
|
||||
err2:
|
||||
@@ -248,6 +254,7 @@ _fbsd_uninit_driver(driver_t *driver)
|
||||
uninit_mbufs();
|
||||
if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES))
|
||||
uninit_taskqueues();
|
||||
uninit_callout();
|
||||
uninit_mutexes();
|
||||
|
||||
put_module(B_PCI_MODULE_NAME);
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
* Copyright 2009, Colin Günther, coling@gmx.de.
|
||||
* Copyright 2007, Hugo Santos. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Hugo Santos, hugosantos@gmail.com
|
||||
*/
|
||||
|
||||
|
||||
@@ -25,12 +22,13 @@ mtx_init(struct mtx *mutex, const char *name, const char *type,
|
||||
int options)
|
||||
{
|
||||
if (options == MTX_DEF) {
|
||||
mutex_init_etc(&mutex->u.mutex, name, MUTEX_FLAG_CLONE_NAME);
|
||||
mutex_init_etc(&mutex->u.mutex.lock, name, MUTEX_FLAG_CLONE_NAME);
|
||||
mutex->u.mutex.owner = -1;
|
||||
} else if (options == MTX_RECURSE) {
|
||||
recursive_lock_init_etc(&mutex->u.recursive, name,
|
||||
MUTEX_FLAG_CLONE_NAME);
|
||||
} else
|
||||
panic("Uh-oh, someone is pressing the wrong buttons");
|
||||
panic("fbsd: unsupported mutex type");
|
||||
|
||||
mutex->type = options;
|
||||
}
|
||||
@@ -39,12 +37,10 @@ mtx_init(struct mtx *mutex, const char *name, const char *type,
|
||||
void
|
||||
mtx_destroy(struct mtx *mutex)
|
||||
{
|
||||
if (mutex->type == MTX_DEF) {
|
||||
mutex_destroy(&mutex->u.mutex);
|
||||
} else if (mutex->type == MTX_RECURSE) {
|
||||
if (mutex->type == MTX_DEF)
|
||||
mutex_destroy(&mutex->u.mutex.lock);
|
||||
else if (mutex->type == MTX_RECURSE)
|
||||
recursive_lock_destroy(&mutex->u.recursive);
|
||||
} else
|
||||
panic("Uh-oh, someone is pressing the wrong buttons");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright 2009, Colin Günther, coling@gmx.de
|
||||
* Copyright 2007, Hugo Santos. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/callout.h>
|
||||
#include <sys/mutex.h>
|
||||
|
||||
|
||||
inline void
|
||||
callout_init(struct callout *callout, int mpsafe)
|
||||
{
|
||||
if (mpsafe)
|
||||
callout_init_mtx(callout, NULL, 0);
|
||||
else
|
||||
callout_init_mtx(callout, &Giant, 0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
callout_schedule(struct callout *callout, int to_ticks)
|
||||
{
|
||||
return callout_reset(callout, to_ticks, callout->c_func, callout->c_arg);
|
||||
}
|
||||
Reference in New Issue
Block a user