kitten LWK waitqueue adoptation
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
AALDIR=$(AALBASE)/$(TARGET)
|
||||
OBJS = init.o mem.o debug.o mikc.o listeners.o ap.o syscall.o cls.o host.o
|
||||
OBJS += process.o copy.o
|
||||
OBJS += process.o copy.o waitq.o
|
||||
DEPSRCS=$(wildcard $(SRC)/*.c)
|
||||
|
||||
CFLAGS += -I$(SRC)/include -mcmodel=kernel -D__KERNEL__
|
||||
|
||||
@@ -14,9 +14,11 @@
|
||||
|
||||
#define PS_RUNNING 0x1
|
||||
#define PS_INTERRUPTIBLE 0x2
|
||||
#define PS_UNINTERRUPTIBLE 0x3
|
||||
#define PS_ZOMBIE 0x4
|
||||
#define PS_EXITED 0x5
|
||||
#define PS_UNINTERRUPTIBLE 0x4
|
||||
#define PS_ZOMBIE 0x8
|
||||
#define PS_EXITED 0x10
|
||||
|
||||
#define PS_NORMAL (PS_INTERRUPTIBLE | PS_UNINTERRUPTIBLE)
|
||||
|
||||
struct vm_range {
|
||||
struct list_head list;
|
||||
@@ -78,5 +80,6 @@ unsigned long extend_process_region(struct process *proc,
|
||||
void schedule(void);
|
||||
void runq_add_proc(struct process *proc, int cpu_id);
|
||||
void runq_del_proc(struct process *proc, int cpu_id);
|
||||
int sched_wakeup_process(struct process *proc, int valid_states);
|
||||
|
||||
#endif
|
||||
|
||||
135
kernel/include/waitq.h
Normal file
135
kernel/include/waitq.h
Normal file
@@ -0,0 +1,135 @@
|
||||
#ifndef _LWK_WAITQ_H
|
||||
#define _LWK_WAITQ_H
|
||||
|
||||
/* Kitten waitqueue adaptation */
|
||||
|
||||
#include <aal/lock.h>
|
||||
#include <list.h>
|
||||
#include <process.h>
|
||||
|
||||
struct waitq_entry;
|
||||
|
||||
typedef int (*waitq_func_t)(struct waitq_entry *wait, unsigned mode,
|
||||
int flags, void *key);
|
||||
|
||||
int default_wake_function(struct waitq_entry *wait, unsigned mode, int flags,
|
||||
void *key);
|
||||
|
||||
typedef struct waitq {
|
||||
aal_spinlock_t lock;
|
||||
struct list_head waitq;
|
||||
} waitq_t;
|
||||
|
||||
#define WQ_FLAG_EXCLUSIVE 0x01
|
||||
|
||||
typedef struct waitq_entry {
|
||||
struct list_head link;
|
||||
void *private;
|
||||
unsigned int flags;
|
||||
waitq_func_t func;
|
||||
} waitq_entry_t;
|
||||
|
||||
#define DECLARE_WAITQ(name) \
|
||||
waitq_t name = __WAITQ_INITIALIZER(name);
|
||||
|
||||
#define __WAITQ_INITIALIZER(name) { \
|
||||
.lock = SPIN_LOCK_UNLOCKED, \
|
||||
.waitq = { &(name).waitq, &(name).waitq } \
|
||||
}
|
||||
|
||||
#define DECLARE_WAITQ_ENTRY(name, tsk) \
|
||||
waitq_entry_t name = { \
|
||||
.private = tsk, \
|
||||
.func = default_wake_function, \
|
||||
.link = { &(name).link, &(name).link } \
|
||||
}
|
||||
|
||||
extern void waitq_init(waitq_t *waitq);
|
||||
extern void waitq_init_entry(waitq_entry_t *entry, struct process *proc);
|
||||
extern int waitq_active(waitq_t *waitq);
|
||||
extern void waitq_add_entry(waitq_t *waitq, waitq_entry_t *entry);
|
||||
extern void waitq_add_entry_locked(waitq_t *waitq, waitq_entry_t *entry);
|
||||
extern void waitq_prepare_to_wait(waitq_t *waitq,
|
||||
waitq_entry_t *entry, int state);
|
||||
extern void waitq_finish_wait(waitq_t *waitq, waitq_entry_t *entry);
|
||||
extern void waitq_wakeup(waitq_t *waitq);
|
||||
extern int waitq_wake_nr(waitq_t *waitq, int nr);
|
||||
extern int waitq_wake_nr_locked(waitq_t *waitq, int nr);
|
||||
extern void waitq_remove_entry(waitq_t *waitq, waitq_entry_t *entry);
|
||||
extern void waitq_remove_entry_locked(waitq_t *waitq, waitq_entry_t *entry);
|
||||
|
||||
#define __wait_event(waitq, condition) \
|
||||
do { \
|
||||
DECLARE_WAITQ_ENTRY(__entry, current); \
|
||||
for (;;) { \
|
||||
waitq_prepare_to_wait(&waitq, &__entry, \
|
||||
TASK_UNINTERRUPTIBLE); \
|
||||
if (condition) \
|
||||
break; \
|
||||
schedule(); \
|
||||
} \
|
||||
waitq_finish_wait(&waitq, &__entry); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* wait_event - sleep until a condition becomes true
|
||||
* @waitq: the waitqueue to wait on
|
||||
* @condition: a C expression for the event to wait for
|
||||
*
|
||||
* The process is put to sleep (TASK_UNINTERRUPTIBLE) until the
|
||||
* @condition evaluates to true. The @condition is checked each time
|
||||
* the waitqueue @waitq is woken up.
|
||||
*
|
||||
* wake_up() has to be called after changing any variable that could
|
||||
* change the result of the wait condition.
|
||||
*/
|
||||
#define wait_event(waitq, condition) \
|
||||
do { \
|
||||
if (condition) \
|
||||
break; \
|
||||
__wait_event(waitq, condition); \
|
||||
} while (0)
|
||||
|
||||
#define __wait_event_interruptible(waitq, condition, ret) \
|
||||
do { \
|
||||
DECLARE_WAITQ_ENTRY(__entry, current); \
|
||||
for (;;) { \
|
||||
waitq_prepare_to_wait(&waitq, &__entry, \
|
||||
TASK_INTERRUPTIBLE); \
|
||||
if (condition) \
|
||||
break; \
|
||||
if (1 /* TODO: !signal_pending(current) */) { \
|
||||
schedule(); \
|
||||
continue; \
|
||||
} \
|
||||
ret = -ERESTARTSYS; \
|
||||
break; \
|
||||
} \
|
||||
waitq_finish_wait(&waitq, &__entry); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* wait_event_interruptible - sleep until a condition becomes true
|
||||
* @waitq: the waitqueue to wait on
|
||||
* @condition: a C expression for the event to wait for
|
||||
*
|
||||
* The process is put to sleep (TASK_INTERRUPTIBLE) until the
|
||||
* @condition evaluates to true or a signal is received. The
|
||||
* @condition is checked each time the waitqueue @waitq is woken up.
|
||||
*
|
||||
* wake_up() has to be called after changing any variable that could
|
||||
* change the result of the wait condition.
|
||||
*
|
||||
* The function will return -ERESTARTSYS if it was interrupted by a
|
||||
* signal and 0 if @condition evaluated to true.
|
||||
*/
|
||||
#define wait_event_interruptible(waitq, condition) \
|
||||
({ \
|
||||
int __ret = 0; \
|
||||
if (!(condition)) \
|
||||
__wait_event_interruptible(waitq, condition, __ret); \
|
||||
__ret; \
|
||||
})
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <cls.h>
|
||||
#include <aal/debug.h>
|
||||
#include <page.h>
|
||||
#include <cpulocal.h>
|
||||
|
||||
#define DEBUG_PRINT_PROCESS
|
||||
|
||||
@@ -307,6 +308,7 @@ void schedule(void)
|
||||
|
||||
aal_mc_load_page_table(next->vm->page_table);
|
||||
do_arch_prctl(ARCH_SET_FS, next->vm->region.tlsblock_base);
|
||||
cpu_local_var(status) = CPU_STATUS_RUNNING;
|
||||
|
||||
if (prev) {
|
||||
aal_mc_switch_context(&prev->ctx, &next->ctx);
|
||||
@@ -316,6 +318,35 @@ void schedule(void)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int sched_wakeup_process(struct process *proc, int valid_states)
|
||||
{
|
||||
int status;
|
||||
unsigned long irqstate;
|
||||
struct cpu_local_var *v = get_cpu_local_var(proc->cpu_id);
|
||||
|
||||
irqstate = aal_mc_spinlock_lock(&(v->runq_lock));
|
||||
|
||||
if (proc->status & valid_states) {
|
||||
proc->status = PS_RUNNING;
|
||||
status = 0;
|
||||
}
|
||||
else {
|
||||
status = -EINVAL;
|
||||
}
|
||||
|
||||
aal_mc_spinlock_unlock(&(v->runq_lock), irqstate);
|
||||
|
||||
if (!status && (proc->cpu_id != aal_mc_get_processor_id())) {
|
||||
aal_mc_interrupt_cpu(get_x86_cpu_local_variable(proc->cpu_id)->apic_id,
|
||||
0xd1);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Runq lock must be held here */
|
||||
void __runq_add_proc(struct process *proc, int cpu_id)
|
||||
{
|
||||
|
||||
147
kernel/waitq.c
Normal file
147
kernel/waitq.c
Normal file
@@ -0,0 +1,147 @@
|
||||
|
||||
/* Kitten waitqueue adaptation */
|
||||
|
||||
#include <waitq.h>
|
||||
#include <process.h>
|
||||
#include <cls.h>
|
||||
|
||||
int
|
||||
default_wake_function(waitq_entry_t *entry, unsigned mode,
|
||||
int flags, void *key)
|
||||
{
|
||||
return sched_wakeup_process(entry->private, PS_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
waitq_init(waitq_t *waitq)
|
||||
{
|
||||
aal_mc_spinlock_init(&waitq->lock);
|
||||
INIT_LIST_HEAD(&waitq->waitq);
|
||||
}
|
||||
|
||||
void
|
||||
waitq_init_entry(waitq_entry_t *entry, struct process *proc)
|
||||
{
|
||||
entry->private = proc;
|
||||
entry->func = default_wake_function;
|
||||
INIT_LIST_HEAD(&entry->link);
|
||||
}
|
||||
|
||||
int
|
||||
waitq_active(waitq_t *waitq)
|
||||
{
|
||||
int active;
|
||||
unsigned long irqstate;
|
||||
|
||||
irqstate = aal_mc_spinlock_lock(&waitq->lock);
|
||||
active = !list_empty(&waitq->waitq);
|
||||
aal_mc_spinlock_unlock(&waitq->lock, irqstate);
|
||||
|
||||
return active;
|
||||
}
|
||||
|
||||
void
|
||||
waitq_add_entry(waitq_t *waitq, waitq_entry_t *entry)
|
||||
{
|
||||
unsigned long irqstate;
|
||||
|
||||
irqstate = aal_mc_spinlock_lock(&waitq->lock);
|
||||
waitq_add_entry_locked(waitq, entry);
|
||||
aal_mc_spinlock_unlock(&waitq->lock, irqstate);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
waitq_add_entry_locked(waitq_t *waitq, waitq_entry_t *entry)
|
||||
{
|
||||
//BUG_ON(!list_empty(&entry->link));
|
||||
list_add_tail(&entry->link, &waitq->waitq);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
waitq_remove_entry(waitq_t *waitq, waitq_entry_t *entry)
|
||||
{
|
||||
unsigned long irqstate;
|
||||
|
||||
irqstate = aal_mc_spinlock_lock(&waitq->lock);
|
||||
waitq_remove_entry_locked(waitq, entry);
|
||||
aal_mc_spinlock_unlock(&waitq->lock, irqstate);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
waitq_remove_entry_locked(waitq_t *waitq, waitq_entry_t *entry)
|
||||
{
|
||||
//BUG_ON(list_empty(&entry->link));
|
||||
list_del_init(&entry->link);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
waitq_prepare_to_wait(waitq_t *waitq, waitq_entry_t *entry, int state)
|
||||
{
|
||||
unsigned long irqstate;
|
||||
|
||||
irqstate = aal_mc_spinlock_lock(&waitq->lock);
|
||||
if (list_empty(&entry->link))
|
||||
list_add(&entry->link, &waitq->waitq);
|
||||
cpu_local_var(current)->status = state;
|
||||
aal_mc_spinlock_unlock(&waitq->lock, irqstate);
|
||||
}
|
||||
|
||||
void
|
||||
waitq_finish_wait(waitq_t *waitq, waitq_entry_t *entry)
|
||||
{
|
||||
cpu_local_var(current)->status = PS_RUNNING;
|
||||
waitq_remove_entry(waitq, entry);
|
||||
}
|
||||
|
||||
void
|
||||
waitq_wakeup(waitq_t *waitq)
|
||||
{
|
||||
unsigned long irqstate;
|
||||
struct list_head *tmp;
|
||||
waitq_entry_t *entry;
|
||||
|
||||
irqstate = aal_mc_spinlock_lock(&waitq->lock);
|
||||
list_for_each(tmp, &waitq->waitq) {
|
||||
entry = list_entry(tmp, waitq_entry_t, link);
|
||||
entry->func(entry, 0, 0, NULL);
|
||||
}
|
||||
aal_mc_spinlock_unlock(&waitq->lock, irqstate);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
waitq_wake_nr(waitq_t * waitq, int nr)
|
||||
{
|
||||
unsigned long irqstate;
|
||||
|
||||
irqstate = aal_mc_spinlock_lock(&waitq->lock);
|
||||
int count = waitq_wake_nr_locked(waitq, nr);
|
||||
aal_mc_spinlock_unlock(&waitq->lock, irqstate);
|
||||
|
||||
if (count > 0)
|
||||
schedule();
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
waitq_wake_nr_locked( waitq_t * waitq, int nr )
|
||||
{
|
||||
int count = 0;
|
||||
waitq_entry_t *entry;
|
||||
|
||||
list_for_each_entry(entry, &waitq->waitq, link) {
|
||||
if (++count > nr)
|
||||
break;
|
||||
|
||||
entry->func(entry, 0, 0, NULL);
|
||||
}
|
||||
|
||||
return count - 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user