* Added a net_timer::flags field, and used it to implement the new

wait_for_timer() function.
* Moved the internal Fifo class into utility.cpp - we should probably just
  remove it again.
* Fixed uninit_timers() so that it would even work in combination with the
  timer thread if there are timers left to be scheduled.
* Minor cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26980 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2008-08-15 14:46:16 +00:00
parent 2bf20e253b
commit 9e8be8bb9c
4 changed files with 149 additions and 105 deletions
+2
View File
@@ -44,6 +44,7 @@ struct net_timer {
net_timer_func hook;
void *data;
bigtime_t due;
uint32 flags;
};
typedef int32 (*net_deframe_func)(struct net_device *device,
@@ -140,6 +141,7 @@ struct net_stack_module_info {
void (*init_timer)(struct net_timer *timer, net_timer_func hook, void *data);
void (*set_timer)(struct net_timer *timer, bigtime_t delay);
bool (*cancel_timer)(struct net_timer *timer);
void (*wait_for_timer)(struct net_timer *timer);
bool (*is_timer_active)(struct net_timer *timer);
// syscall restart
@@ -913,6 +913,7 @@ net_stack_module_info gNetStackModule = {
init_timer,
set_timer,
cancel_timer,
wait_for_timer,
is_timer_active,
is_syscall,
+73 -9
View File
@@ -7,20 +7,57 @@
*/
#include "stack_private.h"
#include "utility.h"
#include <ByteOrder.h>
#include <KernelExport.h>
#include <condition_variable.h>
#include <net_buffer.h>
#include <syscall_restart.h>
#include <util/AutoLock.h>
#include <ByteOrder.h>
#include <KernelExport.h>
#include "stack_private.h"
#define TIMER_IS_RUNNING 0x80000000
// internal Fifo class which doesn't maintain it's own lock
// TODO: do we need this one for anything?
class Fifo {
public:
Fifo(const char* name, size_t maxBytes);
~Fifo();
status_t InitCheck() const;
status_t Enqueue(net_buffer* buffer);
status_t EnqueueAndNotify(net_buffer* _buffer, net_socket* socket,
uint8 event);
status_t Wait(mutex* lock, bigtime_t timeout);
net_buffer* Dequeue(bool clone);
status_t Clear();
void WakeAll();
bool IsEmpty() const { return current_bytes == 0; }
//private:
// these field names are kept so we can use templatized
// functions together with net_fifo
sem_id notify;
int32 waiting;
size_t max_bytes;
size_t current_bytes;
struct list buffers;
};
static struct list sTimers;
static mutex sTimerLock;
static sem_id sTimerWaitSem;
static ConditionVariable sWaitForTimerCondition;
static thread_id sTimerThread;
static bigtime_t sTimerTimeout;
@@ -51,7 +88,8 @@ base_fifo_init(FifoType *fifo, const char *name, size_t maxBytes)
template<typename FifoType> static inline status_t
base_fifo_enqueue_buffer(FifoType* fifo, net_buffer* buffer)
{
if (fifo->max_bytes > 0 && fifo->current_bytes + buffer->size > fifo->max_bytes)
if (fifo->max_bytes > 0
&& fifo->current_bytes + buffer->size > fifo->max_bytes)
return ENOBUFS;
list_add_item(&fifo->buffers, buffer);
@@ -286,8 +324,7 @@ fifo_enqueue_buffer(net_fifo *fifo, net_buffer *buffer)
}
/*!
Gets the first buffer from the FIFO. If there is no buffer, it
/*! Gets the first buffer from the FIFO. If there is no buffer, it
will wait depending on the \a flags and \a timeout.
The following flags are supported (the rest is ignored):
MSG_DONTWAIT - ignores the timeout and never wait for a buffer; if your
@@ -392,8 +429,7 @@ timer_thread(void * /*data*/)
if (status == B_TIMED_OUT || status == B_OK) {
// scan timers for new timeout and/or execute a timer
if (mutex_lock(&sTimerLock) < B_OK)
return B_OK;
mutex_lock(&sTimerLock);
struct net_timer* timer = NULL;
while (true) {
@@ -405,11 +441,14 @@ timer_thread(void * /*data*/)
// execute timer
list_remove_item(&sTimers, timer);
timer->due = -1;
timer->flags |= TIMER_IS_RUNNING;
mutex_unlock(&sTimerLock);
timer->hook(timer, timer->data);
mutex_lock(&sTimerLock);
timer->flags &= ~TIMER_IS_RUNNING;
sWaitForTimerCondition.NotifyAll();
timer = NULL;
// restart scanning as we unlocked the list
} else {
@@ -446,6 +485,7 @@ init_timer(net_timer *timer, net_timer_func hook, void *data)
timer->hook = hook;
timer->data = data;
timer->due = 0;
timer->flags = 0;
}
@@ -497,6 +537,26 @@ cancel_timer(struct net_timer *timer)
}
void
wait_for_timer(struct net_timer* timer)
{
while (true) {
MutexLocker locker(sTimerLock);
if (timer->due <= 0 && (timer->flags & TIMER_IS_RUNNING) == 0)
return;
// we actually need to wait for this timer
ConditionVariableEntry entry;
sWaitForTimerCondition.Add(&entry);
locker.Unlock();
entry.Wait();
}
}
bool
is_timer_active(net_timer* timer)
{
@@ -545,6 +605,8 @@ init_timers(void)
goto err2;
}
sWaitForTimerCondition.Init(NULL, "wait for net timer");
add_debugger_command("net_timer", dump_timer,
"Lists all active network timer");
@@ -561,8 +623,10 @@ err2:
void
uninit_timers(void)
{
mutex_destroy(&sTimerLock);
delete_sem(sTimerWaitSem);
mutex_lock(&sTimerLock);
mutex_destroy(&sTimerLock);
status_t status;
wait_for_thread(sTimerThread, &status);
+9 -32
View File
@@ -11,6 +11,7 @@
#include <net_stack.h>
class UserBuffer {
public:
UserBuffer(void* buffer, size_t size);
@@ -26,38 +27,13 @@ private:
};
// internal Fifo class which doesn't maintain it's own lock
class Fifo {
public:
Fifo(const char *name, size_t maxBytes);
~Fifo();
status_t InitCheck() const;
status_t Enqueue(net_buffer *buffer);
status_t EnqueueAndNotify(net_buffer *_buffer, net_socket *socket, uint8 event);
status_t Wait(mutex *lock, bigtime_t timeout);
net_buffer *Dequeue(bool clone);
status_t Clear();
void WakeAll();
bool IsEmpty() const { return current_bytes == 0; }
//private:
// these field names are kept so we can use templatized
// functions together with net_fifo
sem_id notify;
int32 waiting;
size_t max_bytes;
size_t current_bytes;
struct list buffers;
};
inline
UserBuffer::UserBuffer(void* buffer, size_t size)
: fBuffer((uint8 *)buffer), fBufferSize(size),
fAvailable(size), fStatus(B_OK)
:
fBuffer((uint8*)buffer),
fBufferSize(size),
fAvailable(size),
fStatus(B_OK)
{
}
@@ -90,13 +66,14 @@ status_t fifo_enqueue_buffer(net_fifo *fifo, struct net_buffer *buffer);
ssize_t fifo_dequeue_buffer(net_fifo* fifo, uint32 flags, bigtime_t timeout,
struct net_buffer** _buffer);
status_t clear_fifo(net_fifo* fifo);
status_t fifo_socket_enqueue_buffer(net_fifo *, net_socket *, uint8 event,
net_buffer *);
status_t fifo_socket_enqueue_buffer(net_fifo* fifo, net_socket* socket,
uint8 event, net_buffer* buffer);
// timer
void init_timer(net_timer* timer, net_timer_func hook, void* data);
void set_timer(net_timer* timer, bigtime_t delay);
bool cancel_timer(struct net_timer* timer);
void wait_for_timer(struct net_timer* timer);
bool is_timer_active(net_timer* timer);
status_t init_timers(void);
void uninit_timers(void);