From 337fe4b20d0cb3057cfe6e269f49259753200fde Mon Sep 17 00:00:00 2001 From: "Masamichi Takagi m-takagi@ab.jp.nec.com" Date: Mon, 26 Nov 2012 15:14:41 +0900 Subject: [PATCH] timer sleep and wakeup functions by Balazs-san --- kernel/Makefile.build | 2 +- kernel/Makefile.build.mpiu | 49 +++++++++++++++ kernel/futex.c | 1 + kernel/include/timer.h | 34 +++++++++++ kernel/process.c | 6 ++ kernel/syscall.c | 15 +++-- kernel/timer.c | 119 +++++++++++++++++++++++++++++++++++++ 7 files changed, 221 insertions(+), 5 deletions(-) create mode 100755 kernel/Makefile.build.mpiu create mode 100644 kernel/include/timer.h create mode 100644 kernel/timer.c diff --git a/kernel/Makefile.build b/kernel/Makefile.build index def70322..d5f3f4d4 100644 --- a/kernel/Makefile.build +++ b/kernel/Makefile.build @@ -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 waitq.o futex.o +OBJS += process.o copy.o waitq.o futex.o timer.o DEPSRCS=$(wildcard $(SRC)/*.c) CFLAGS += -I$(SRC)/include -mcmodel=kernel -D__KERNEL__ diff --git a/kernel/Makefile.build.mpiu b/kernel/Makefile.build.mpiu new file mode 100755 index 00000000..5bac4b4e --- /dev/null +++ b/kernel/Makefile.build.mpiu @@ -0,0 +1,49 @@ +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 waitq.o futex.o +DEPSRCS=$(wildcard $(SRC)/*.c) + +#CFLAGS += -I$(SRC)/include -mcmodel=kernel -D__KERNEL__ -DDCFA_KMOD -DIOCTL_FUNC_EXTENSION +CFLAGS += -I$(SRC)/include -mcmodel=kernel -D__KERNEL__ -DDCFA_KMOD -DKNC_MAP_MICPA -DUSE_NOCACHE_MMAP +CFLAGS += -DCONFIG_$(CONFIG_V) + +LDFLAGS += -e arch_start +AALOBJ = aal/aal.o + +include $(SRC)/configs/config.$(TARGET) +include $(AALBASE)/Makefile.common + +SUBCMD_OPTS = TARGET=$(TARGET) O=$(CURDIR)/aal CC=$(CC) LD=$(LD) CONFIG_V=$(CONFIG_V) + +ld_kern_cmd_base = $(LD) $(LDFLAGS) -o $@.elf $^ +mkimage_cmd_base = [ -f $(SRC)/scripts/mkimage.$(TARGET) ] && CC=$(CC) LD=$(LD) LDFLAGS="$(LDFLAGS_MKIMAGE)" sh $(SRC)/scripts/mkimage.$(TARGET) '$@.elf' '$@' '$(SRC)' || cp $@.elf $@ + +ld_kern_cmd = $(call echo_cmd,LDKERN,$@)$(ld_kern_cmd_base) +mkimage_cmd = $(call echo_cmd,MKIMAGE,$@)$(mkimage_cmd_base) + +all: depend kernel.img + +kernel.img: $(OBJS) $(AALOBJ) $(EXTRA_OBJS) + $(ld_kern_cmd) + $(mkimage_cmd) + +clean: + $(rm_cmd) $(OBJS) kernel.img kernel.img.elf Makefile.dep + @$(submake) -C $(AALBASE) $(SUBCMD_OPTS) clean + +depend: Makefile.dep + +Makefile.dep: + $(call dep_cmd,$(DEPSRCS)) + +$(AALOBJ): FORCE + @mkdir -p $(dir $(AALOBJ)) + $(call echo_cmd,BUILD AAL,$(TARGET))$(submake) -C $(AALBASE) $(SUBCMD_OPTS) prepare + $(call echo_cmd,BUILD AAL,$(TARGET))$(submake) -C $(AALBASE) $(SUBCMD_OPTS) + +%.o: $(SRC)/%.c + $(cc_cmd) + +FORCE: + +-include Makefile.dep diff --git a/kernel/futex.c b/kernel/futex.c index bb1d1ef4..76113c35 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -62,6 +62,7 @@ #include #include #include +#include #if 0 #include diff --git a/kernel/include/timer.h b/kernel/include/timer.h new file mode 100644 index 00000000..d048b6b7 --- /dev/null +++ b/kernel/include/timer.h @@ -0,0 +1,34 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TIMER_CPU_ID 227 + +struct timer { + uint64_t timeout; + struct waitq processes; + struct list_head list; + struct process *proc; +}; + +uint64_t schedule_timeout(uint64_t timeout); + +void init_timers(void); +void wake_timers_loop(void); + diff --git a/kernel/process.c b/kernel/process.c index f283bb6d..702d4a02 100644 --- a/kernel/process.c +++ b/kernel/process.c @@ -7,6 +7,7 @@ #include #include #include +#include #define DEBUG_PRINT_PROCESS @@ -365,6 +366,11 @@ void sched_init(void) INIT_LIST_HEAD(&cpu_local_var(runq)); cpu_local_var(runq_len) = 0; aal_mc_spinlock_init(&cpu_local_var(runq_lock)); + + if (aal_mc_get_processor_id() == TIMER_CPU_ID) { + init_timers(); + wake_timers_loop(); + } } void schedule(void) diff --git a/kernel/syscall.c b/kernel/syscall.c index 43791d49..d3699507 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -750,7 +750,7 @@ SYSCALL_DECLARE(futex) { // TODO: timespec support! //struct timespec _utime; - uint64_t timeout = 1000; // MAX_SCHEDULE_TIMEOUT; + uint64_t timeout = 0; // No timeout uint32_t val2 = 0; uint32_t *uaddr = (uint32_t *)aal_mc_syscall_arg0(ctx); @@ -780,13 +780,13 @@ SYSCALL_DECLARE(futex) val2 = (uint32_t) (unsigned long) aal_mc_syscall_arg3(ctx); // we don't have timer interrupt and wakeup, so fake it by just pausing - if (op == FUTEX_WAIT_BITSET && utime) { - + if (utime && (op == FUTEX_WAIT_BITSET || op == FUTEX_WAIT)) { // gettimeofday(&tv_now, NULL); struct syscall_request request AAL_DMA_ALIGN; struct timeval tv_now; request.number = 96; +#if 1 unsigned long __phys; if (aal_mc_pt_virt_to_phys(cpu_local_var(current)->vm->page_table, (void *)&tv_now, @@ -810,11 +810,18 @@ SYSCALL_DECLARE(futex) long nsec_timeout = ((long)utime->tv_sec * 1000000000ULL) + utime->tv_nsec * 1; long diff_nsec = nsec_timeout - nsec_now; + + /* if(diff_nsec > 0) { dkprintf("pausing %016ldnsec\n", diff_nsec); arch_delay(diff_nsec/1000); // unit is usec } - return -ETIMEDOUT; + */ + timeout = (diff_nsec / 1000) * 1100; // (usec * 1.1GHz) +#else + arch_delay(200000); // unit is usec + return -ETIMEDOUT; +#endif } return futex(uaddr, op, val, timeout, uaddr2, val2, val3); diff --git a/kernel/timer.c b/kernel/timer.c new file mode 100644 index 00000000..0c527660 --- /dev/null +++ b/kernel/timer.c @@ -0,0 +1,119 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#define DEBUG_PRINT_TIMER + +#ifdef DEBUG_PRINT_TIMER +#define dkprintf kprintf +#else +#define dkprintf(...) +#endif + +#define LOOP_TIMEOUT 1000 /* default 1000 */ + +struct list_head timers; +aal_spinlock_t timers_lock; + + +void init_timers(void) +{ + aal_mc_spinlock_init(&timers_lock); + INIT_LIST_HEAD(&timers); +} + +uint64_t schedule_timeout(uint64_t timeout) +{ + struct waitq_entry my_wait; + struct timer my_timer; + unsigned long irqflags; + + /* Init waitq and wait entry for this timer */ + my_timer.timeout = (timeout < LOOP_TIMEOUT) ? LOOP_TIMEOUT : timeout; + my_timer.proc = cpu_local_var(current); + waitq_init(&my_timer.processes); + waitq_init_entry(&my_wait, cpu_local_var(current)); + + /* Add ourself to the timer queue */ + irqflags = aal_mc_spinlock_lock(&timers_lock); + list_add_tail(&my_timer.list, &timers); + aal_mc_spinlock_unlock(&timers_lock, irqflags); + + dkprintf("schedule_timeout() sleep timeout: %lu\n", my_timer.timeout); + + /* Add ourself to the waitqueue and sleep */ + waitq_prepare_to_wait(&my_timer.processes, &my_wait, PS_INTERRUPTIBLE); + schedule(); + waitq_finish_wait(&my_timer.processes, &my_wait); + + irqflags = aal_mc_spinlock_lock(&timers_lock); + + /* Waken up by someone else then timeout? */ + if (my_timer.timeout) { + list_del(&my_timer.list); + } + aal_mc_spinlock_unlock(&timers_lock, irqflags); + + dkprintf("schedule_timeout() woken up, timeout: %lu\n", + my_timer.timeout); + + return my_timer.timeout; +} + + +void wake_timers_loop(void) +{ + unsigned long loop_s; + unsigned long irqflags; + struct timer *timer; + struct timer *timer_next; + + dkprintf("timers thread, entering loop\n"); + for (;;) { + loop_s = rdtsc(); + + while (rdtsc() < (loop_s + LOOP_TIMEOUT)) { + cpu_pause(); + } + + /* Iterate and decrease timeout for all timers, + * wake up if timeout reaches zero. */ + irqflags = aal_mc_spinlock_lock(&timers_lock); + + list_for_each_entry_safe(timer, timer_next, &timers, list) { + + timer->timeout -= LOOP_TIMEOUT; + if (timer->timeout < LOOP_TIMEOUT) { + timer->timeout = 0; + list_del(&timer->list); + + dkprintf("timers timeout occurred, waking up pid: %d\n", + timer->proc->pid); + + waitq_wakeup(&timer->processes); + } + } + + aal_mc_spinlock_unlock(&timers_lock, irqflags); + } +}