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:
Axel Dörfler
2010-07-19 10:41:16 +00:00
parent 69d34a505b
commit e7c3a8ffd7
12 changed files with 297 additions and 157 deletions
+1 -2
View File
@@ -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
;
-80
View File
@@ -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);
}
+237
View File
@@ -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;
}
+2 -7
View File
@@ -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_ */
+3
View File
@@ -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);
+3
View File
@@ -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 */
+11 -4
View File
@@ -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);
+6 -10
View File
@@ -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");
}
-26
View File
@@ -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);
}