kitten LWK waitqueue adoptation
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
AALDIR=$(AALBASE)/$(TARGET)
|
AALDIR=$(AALBASE)/$(TARGET)
|
||||||
OBJS = init.o mem.o debug.o mikc.o listeners.o ap.o syscall.o cls.o host.o
|
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)
|
DEPSRCS=$(wildcard $(SRC)/*.c)
|
||||||
|
|
||||||
CFLAGS += -I$(SRC)/include -mcmodel=kernel -D__KERNEL__
|
CFLAGS += -I$(SRC)/include -mcmodel=kernel -D__KERNEL__
|
||||||
|
|||||||
@@ -14,9 +14,11 @@
|
|||||||
|
|
||||||
#define PS_RUNNING 0x1
|
#define PS_RUNNING 0x1
|
||||||
#define PS_INTERRUPTIBLE 0x2
|
#define PS_INTERRUPTIBLE 0x2
|
||||||
#define PS_UNINTERRUPTIBLE 0x3
|
#define PS_UNINTERRUPTIBLE 0x4
|
||||||
#define PS_ZOMBIE 0x4
|
#define PS_ZOMBIE 0x8
|
||||||
#define PS_EXITED 0x5
|
#define PS_EXITED 0x10
|
||||||
|
|
||||||
|
#define PS_NORMAL (PS_INTERRUPTIBLE | PS_UNINTERRUPTIBLE)
|
||||||
|
|
||||||
struct vm_range {
|
struct vm_range {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
@@ -78,5 +80,6 @@ unsigned long extend_process_region(struct process *proc,
|
|||||||
void schedule(void);
|
void schedule(void);
|
||||||
void runq_add_proc(struct process *proc, int cpu_id);
|
void runq_add_proc(struct process *proc, int cpu_id);
|
||||||
void runq_del_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
|
#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 <cls.h>
|
||||||
#include <aal/debug.h>
|
#include <aal/debug.h>
|
||||||
#include <page.h>
|
#include <page.h>
|
||||||
|
#include <cpulocal.h>
|
||||||
|
|
||||||
#define DEBUG_PRINT_PROCESS
|
#define DEBUG_PRINT_PROCESS
|
||||||
|
|
||||||
@@ -307,6 +308,7 @@ void schedule(void)
|
|||||||
|
|
||||||
aal_mc_load_page_table(next->vm->page_table);
|
aal_mc_load_page_table(next->vm->page_table);
|
||||||
do_arch_prctl(ARCH_SET_FS, next->vm->region.tlsblock_base);
|
do_arch_prctl(ARCH_SET_FS, next->vm->region.tlsblock_base);
|
||||||
|
cpu_local_var(status) = CPU_STATUS_RUNNING;
|
||||||
|
|
||||||
if (prev) {
|
if (prev) {
|
||||||
aal_mc_switch_context(&prev->ctx, &next->ctx);
|
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 */
|
/* Runq lock must be held here */
|
||||||
void __runq_add_proc(struct process *proc, int cpu_id)
|
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