schedule(): do not preempt while holding spinlocks or while in offloaded syscall
This commit is contained in:
14
kernel/cls.c
14
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);
|
||||
}
|
||||
|
||||
@ -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)));
|
||||
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user