Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 2307 → Rev 2308

/branches/rcu/kernel/generic/include/synch/waitq.h
40,9 → 40,18
#include <synch/synch.h>
#include <adt/list.h>
 
#define WAKEUP_FIRST 0
#define WAKEUP_ALL 1
 
/** Specifies behavior of the waitq_wakeup */
typedef enum {
WAKEUP_FIRST = 0, /**< Wakes up only the first sleeping thread, if there
aren't any sleeping threads increments missed wakeups */
WAKEUP_ALL = 1, /**< Wakes up all sleeping threads AND zeroes out
missed_wakeups */
WAKEUP_ALL_INC_MISSED, /**< Wakes up all sleeping threads OR increments
missed_wakeups if there aren't any */
} wakeup_all_flag_t;
 
 
/** Wait queue structure. */
typedef struct {
 
70,8 → 79,8
extern ipl_t waitq_sleep_prepare(waitq_t *wq);
extern int waitq_sleep_timeout_unsafe(waitq_t *wq, uint32_t usec, int flags);
extern void waitq_sleep_finish(waitq_t *wq, int rc, ipl_t ipl);
extern void waitq_wakeup(waitq_t *wq, bool all);
extern void _waitq_wakeup_unsafe(waitq_t *wq, bool all);
extern void waitq_wakeup(waitq_t *wq, int all);
extern void _waitq_wakeup_unsafe(waitq_t *wq, int all);
extern void waitq_interrupt_sleep(struct thread *t);
 
#endif
/branches/rcu/kernel/generic/src/synch/waitq.c
86,6 → 86,7
thread_t *t = (thread_t *) data;
waitq_t *wq;
bool do_wakeup = false;
DEADLOCK_PROBE_INIT(p_wqlock);
 
spinlock_lock(&threads_lock);
if (!thread_exists(t))
96,6 → 97,7
if ((wq = t->sleep_queue)) { /* assignment */
if (!spinlock_trylock(&wq->lock)) {
spinlock_unlock(&t->lock);
DEADLOCK_PROBE(p_wqlock, DEADLOCK_THRESHOLD);
goto grab_locks; /* avoid deadlock */
}
 
128,6 → 130,7
waitq_t *wq;
bool do_wakeup = false;
ipl_t ipl;
DEADLOCK_PROBE_INIT(p_wqlock);
 
ipl = interrupts_disable();
spinlock_lock(&threads_lock);
147,6 → 150,7
if (!spinlock_trylock(&wq->lock)) {
spinlock_unlock(&t->lock);
DEADLOCK_PROBE(p_wqlock, DEADLOCK_THRESHOLD);
goto grab_locks; /* avoid deadlock */
}
 
380,10 → 384,12
* timeout.
*
* @param wq Pointer to wait queue.
* @param all If this is non-zero, all sleeping threads will be woken up and
* missed count will be zeroed.
* @param all If this is WAKEUP_ALL, all sleeping threads will be woken up and
* missed count will be zeroed. WAKEUP_FIRST wakes up just one thread or
* increments the missed count. WAKEUP_ALL_INC_MISSED wakes up all sleeping threads
* or increments missed_wakeups if there aren't any
*/
void waitq_wakeup(waitq_t *wq, bool all)
void waitq_wakeup(waitq_t *wq, int all)
{
ipl_t ipl;
 
402,20 → 408,23
* assumes wq->lock is already locked and interrupts are already disabled.
*
* @param wq Pointer to wait queue.
* @param all If this is non-zero, all sleeping threads will be woken up and
* missed count will be zeroed.
* @param all If this is WAKEUP_ALL, all sleeping threads will be woken up and
* missed count will be zeroed. WAKEUP_FIRST wakes up just one thread or
* increments the missed count. WAKEUP_ALL_INC_MISSED wakes up all sleeping threads
* or increments missed_wakeups if there aren't any
*/
void _waitq_wakeup_unsafe(waitq_t *wq, bool all)
void _waitq_wakeup_unsafe(waitq_t *wq, int all)
{
thread_t *t;
 
loop:
if (list_empty(&wq->head)) {
wq->missed_wakeups++;
if (all)
if (all == WAKEUP_ALL)
wq->missed_wakeups = 0;
else
wq->missed_wakeups++;
return;
}
loop:
 
t = list_get_instance(wq->head.next, thread_t, wq_link);
444,8 → 453,10
spinlock_unlock(&t->lock);
 
thread_ready(t);
 
if (all)
if (list_empty(&wq->head)) {
return;
}
if (all != WAKEUP_FIRST)
goto loop;
}