diff --git a/arch/x86/kernel/include/arch-lock.h b/arch/x86/kernel/include/arch-lock.h index 60b69675..110dedcd 100644 --- a/arch/x86/kernel/include/arch-lock.h +++ b/arch/x86/kernel/include/arch-lock.h @@ -14,6 +14,9 @@ int __kprintf(const char *format, ...); typedef int ihk_spinlock_t; +extern void preempt_enable(void); +extern void preempt_disable(void); + #define IHK_STATIC_SPINLOCK_FUNCS static void ihk_mc_spinlock_init(ihk_spinlock_t *lock) @@ -45,6 +48,9 @@ static void ihk_mc_spinlock_lock_noirq(ihk_spinlock_t *lock) __kprintf("[%d] trying to grab lock: 0x%lX\n", ihk_mc_get_processor_id(), lock); #endif + + preempt_disable(); + asm volatile("lock; xaddl %0, %1\n" "movzwl %w0, %2\n\t" "shrl $16, %0\n\t" @@ -79,6 +85,8 @@ static unsigned long ihk_mc_spinlock_lock(ihk_spinlock_t *lock) static void ihk_mc_spinlock_unlock_noirq(ihk_spinlock_t *lock) { asm volatile ("lock incw %0" : "+m"(*lock) : : "memory", "cc"); + + preempt_enable(); } static void ihk_mc_spinlock_unlock(ihk_spinlock_t *lock, unsigned long flags) diff --git a/kernel/cls.c b/kernel/cls.c index 23b7dc76..3d87535b 100644 --- a/kernel/cls.c +++ b/kernel/cls.c @@ -23,6 +23,7 @@ extern int num_processors; struct cpu_local_var *clv; +static int cpu_local_var_initialized = 0; void cpu_local_var_init(void) { @@ -33,9 +34,22 @@ void cpu_local_var_init(void) clv = allocate_pages(z, IHK_MC_AP_CRITICAL); memset(clv, 0, z * PAGE_SIZE); + cpu_local_var_initialized = 1; } struct cpu_local_var *get_cpu_local_var(int id) { return clv + id; } + +void preempt_enable(void) +{ + if (cpu_local_var_initialized) + --cpu_local_var(no_preempt); +} + +void preempt_disable(void) +{ + if (cpu_local_var_initialized) + ++cpu_local_var(no_preempt); +} diff --git a/kernel/include/cls.h b/kernel/include/cls.h index 04dfd308..687a216c 100644 --- a/kernel/include/cls.h +++ b/kernel/include/cls.h @@ -68,6 +68,7 @@ struct cpu_local_var { ihk_spinlock_t migq_lock; struct list_head migq; int in_interrupt; + int no_preempt; } __attribute__((aligned(64))); diff --git a/kernel/include/process.h b/kernel/include/process.h index ec72835d..bd77977d 100644 --- a/kernel/include/process.h +++ b/kernel/include/process.h @@ -411,6 +411,7 @@ struct process { fp_regs_struct *fp_regs; char *saved_cmdline; long saved_cmdline_len; + int in_syscall_offload; }; struct process_vm { diff --git a/kernel/mem.c b/kernel/mem.c index b0aa458a..3e7195fc 100644 --- a/kernel/mem.c +++ b/kernel/mem.c @@ -370,6 +370,8 @@ static void page_fault_handler(void *fault_addr, uint64_t reason, void *regs) dkprintf("[%d]page_fault_handler(%p,%lx,%p)\n", ihk_mc_get_processor_id(), fault_addr, reason, regs); + preempt_disable(); + cpu_enable_interrupt(); error = page_fault_process_vm(proc->vm, fault_addr, reason); @@ -422,6 +424,7 @@ static void page_fault_handler(void *fault_addr, uint64_t reason, void *regs) error = 0; out: + preempt_enable(); dkprintf("[%d]page_fault_handler(%p,%lx,%p): (%d)\n", ihk_mc_get_processor_id(), fault_addr, reason, regs, error); diff --git a/kernel/process.c b/kernel/process.c index d55ca300..ee56cbb6 100644 --- a/kernel/process.c +++ b/kernel/process.c @@ -2225,6 +2225,16 @@ void schedule(void) unsigned long irqstate; struct process *last; + if (cpu_local_var(no_preempt)) { + dkprintf("no schedule() while no preemption! \n"); + return; + } + + if (cpu_local_var(current)->in_syscall_offload) { + dkprintf("no schedule() while syscall offload!\n"); + return; + } + redo: irqstate = ihk_mc_spinlock_lock(&(get_this_cpu_local_var()->runq_lock)); v = get_this_cpu_local_var(); diff --git a/kernel/syscall.c b/kernel/syscall.c index e1ea7350..fda9f0b2 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -192,6 +192,7 @@ long do_syscall(struct syscall_request *req, int cpu, int pid) unsigned long irqstate; struct process *proc = cpu_local_var(current); + ++proc->in_syscall_offload; dkprintf("SC(%d)[%3d] sending syscall\n", ihk_mc_get_processor_id(), req->number); @@ -252,6 +253,7 @@ long do_syscall(struct syscall_request *req, int cpu, int pid) ihk_mc_spinlock_unlock(&syscall_lock, irqstate); } + --proc->in_syscall_offload; return rc; }