Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 2314 → Rev 2315

/branches/rcu/kernel/test/synch/rcu1.c
36,24 → 36,28
#include <arch.h>
#include <preemption.h>
bool gquiet;
bool called;
 
static void callback(void* data)
{
if (!gquiet)
printf("callback called\n");
called = true;
}
char * test_rcu1(bool quiet)
{
gquiet = quiet;
called = false;
int* p;
rcu_read_lock();
rcu_read_unlock();
rcu_assign_pointer(p,malloc(sizeof(int),0));
if (!quiet)
printf("p:%x\n",rcu_dereference_pointer(p));
rcu_read_unlock();
rcu_sync_callback(&callback, NULL);
if (!quiet)
printf("Callback scheduled\n");
while(!called);
rcu_synchronize();
if (!quiet)
printf("Synchronized\n");
/branches/rcu/kernel/generic/include/synch/waitq.h
40,18 → 40,11
#include <synch/synch.h>
#include <adt/list.h>
 
 
/** 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;
WAKEUP_FIRST = 0,
WAKEUP_ALL
} wakeup_mode_t;
 
 
/** Wait queue structure. */
typedef struct {
 
79,8 → 72,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, int all);
extern void _waitq_wakeup_unsafe(waitq_t *wq, int all);
extern void waitq_wakeup(waitq_t *wq, wakeup_mode_t mode);
extern void _waitq_wakeup_unsafe(waitq_t *wq, wakeup_mode_t mode);
extern void waitq_interrupt_sleep(struct thread *t);
 
#endif
/branches/rcu/kernel/generic/src/synch/waitq.c
383,13 → 383,10
* Besides its 'normal' wakeup operation, it attempts to unregister possible
* timeout.
*
* @param wq Pointer to wait queue.
* @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
* @param wq Pointer to wait queue.
* @param mode Wakeup mode.
*/
void waitq_wakeup(waitq_t *wq, int all)
void waitq_wakeup(waitq_t *wq, wakeup_mode_t mode)
{
ipl_t ipl;
 
396,10 → 393,10
ipl = interrupts_disable();
spinlock_lock(&wq->lock);
 
_waitq_wakeup_unsafe(wq, all);
_waitq_wakeup_unsafe(wq, mode);
 
spinlock_unlock(&wq->lock);
interrupts_restore(ipl);
spinlock_unlock(&wq->lock);
interrupts_restore(ipl);
}
 
/** Internal SMP- and IRQ-unsafe version of waitq_wakeup()
407,25 → 404,27
* This is the internal SMP- and IRQ-unsafe version of waitq_wakeup(). It
* assumes wq->lock is already locked and interrupts are already disabled.
*
* @param wq Pointer to wait queue.
* @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
* @param wq Pointer to wait queue.
* @param mode If mode is WAKEUP_FIRST, then the longest waiting thread,
* if any, is woken up. If mode is WAKEUP_ALL, then all
* waiting threads, if any, are woken up. If there are no
* waiting threads to be woken up, the missed wakeup is
* recorded in the wait queue.
*/
void _waitq_wakeup_unsafe(waitq_t *wq, int all)
void _waitq_wakeup_unsafe(waitq_t *wq, wakeup_mode_t mode)
{
thread_t *t;
count_t count = 0;
 
loop:
if (list_empty(&wq->head)) {
if (all == WAKEUP_ALL)
wq->missed_wakeups = 0;
else
wq->missed_wakeups++;
wq->missed_wakeups++;
if (count && mode == WAKEUP_ALL)
wq->missed_wakeups--;
return;
}
loop:
 
count++;
t = list_get_instance(wq->head.next, thread_t, wq_link);
/*
453,10 → 452,8
spinlock_unlock(&t->lock);
 
thread_ready(t);
if (list_empty(&wq->head)) {
return;
}
if (all != WAKEUP_FIRST)
 
if (mode == WAKEUP_ALL)
goto loop;
}
 
/branches/rcu/kernel/generic/src/synch/rcu.c
95,9 → 95,10
waitq_t *wq = malloc(sizeof(waitq_t),0);
waitq_initialize(wq);
rcu_sync_callback(&rcu_synchronize_callback_function, wq);
printf("going to sleep\n");
printf("going to sleep, tlock:%x, wqlock:%x\n", THREAD->lock.val, wq->lock.val);
waitq_sleep(wq);
printf("woken up\n");
free(wq);
#endif
}
 
104,8 → 105,13
#ifdef CONFIG_SMP
void rcu_synchronize_callback_function(void* waitq)
{
printf("waking up\n");
waitq_wakeup(((waitq_t*)waitq), WAKEUP_ALL_INC_MISSED);
printf("waking up, wq:%x, wq->head:%x, next:%x, tlock:%x, wqlock:%x\n",
waitq,
((waitq_t*)waitq)->head,
((link_t)((waitq_t*)waitq)->head).next,
THREAD->lock.val,
((waitq_t*)waitq)->lock.val );
waitq_wakeup(((waitq_t*)waitq), WAKEUP_ALL);
}
#endif
 
120,8 → 126,10
rd->func = func;
rd->data = data;
rd->next = NULL;
 
printf("synccallback locking \n");
spinlock_lock(&rcu_global_lock);
 
rd->next = _rcu_global->next_batch;
_rcu_global->next_batch = rd;
 
171,19 → 179,18
} else
_rcu_global->done_batch = _rcu_global->current_batch;
printf("setting callback %x as done\n",&_rcu_global->current_batch->func);
_rcu_global->current_batch = NULL;
_rcu_global->current_batch = _rcu_global->next_batch;
_rcu_global->next_batch = NULL;
#ifdef CONFIG_SMP
 
for (i=0;i<config.cpu_count;i++)
_rcu_global->cpu_mask[i]=false;
#endif
//we've surely passed the quiescent point just by running this method
rcu_passQS();
}
 
_rcu_global->current_batch = _rcu_global->next_batch;
_rcu_global->next_batch = NULL;
 
if (_rcu_global->current_batch == NULL) {
//there are no rcu callbacks registered, there is no need to monitor QS
printf("tasklet idle disabling \n");
// tasklet_disable(rcu_tasklet_desc);
spinlock_unlock(&rcu_global_lock);
} else
spinlock_unlock(&rcu_global_lock);
spinlock_unlock(&rcu_global_lock);
printf("tasklet unlocking \n");
}
 
199,15 → 206,16
rcu_callback_list_t* rd;
rcu_passQS();
if (_rcu_global->done_batch) {
printf(".");
printf("run callbacks locking\n");
spinlock_lock(&rcu_global_lock);
for (rd = _rcu_global->done_batch; rd; rd=rd->next) {
rd = _rcu_global->done_batch;
_rcu_global->done_batch = NULL;
spinlock_unlock(&rcu_global_lock);
printf("run callbacks unlocking\n");
for (; rd; rd=rd->next) {
printf("calling %x \n",&rd->func);
rd->func(&rd->data);
}
_rcu_global->done_batch = NULL;
spinlock_unlock(&rcu_global_lock);
printf(":");
}
}
 
/branches/rcu/kernel/arch/ia32/include/cpuid.h
99,18 → 99,20
 
static inline void cpuid(uint32_t cmd, cpu_info_t *info)
{
register int eax asm("eax")=cmd;
register int ebx asm("ebx");
register int ecx asm("ecx");
register int edx asm("edx");
asm volatile (
"movl %4, %%eax\n"
"cpuid\n"
"movl %%eax, %0\n"
"movl %%ebx, %1\n"
"movl %%ecx, %2\n"
"movl %%edx, %3\n"
: "=m" (info->cpuid_eax), "=m" (info->cpuid_ebx), "=m" (info->cpuid_ecx), "=m" (info->cpuid_edx)
: "m" (cmd)
: "eax", "ebx", "ecx", "edx"
: "=r" (eax), "=r" (ebx), "=r" (ecx), "=r" (edx)
: "r" (eax)
);
info->cpuid_eax=eax;
info->cpuid_ebx=ebx;
info->cpuid_ecx=ecx;
info->cpuid_edx=edx;
}
 
#endif