schedule(): do not preempt while holding spinlocks or while in offloaded syscall
This commit is contained in:
@@ -14,6 +14,9 @@ int __kprintf(const char *format, ...);
|
|||||||
|
|
||||||
typedef int ihk_spinlock_t;
|
typedef int ihk_spinlock_t;
|
||||||
|
|
||||||
|
extern void preempt_enable(void);
|
||||||
|
extern void preempt_disable(void);
|
||||||
|
|
||||||
#define IHK_STATIC_SPINLOCK_FUNCS
|
#define IHK_STATIC_SPINLOCK_FUNCS
|
||||||
|
|
||||||
static void ihk_mc_spinlock_init(ihk_spinlock_t *lock)
|
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",
|
__kprintf("[%d] trying to grab lock: 0x%lX\n",
|
||||||
ihk_mc_get_processor_id(), lock);
|
ihk_mc_get_processor_id(), lock);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
preempt_disable();
|
||||||
|
|
||||||
asm volatile("lock; xaddl %0, %1\n"
|
asm volatile("lock; xaddl %0, %1\n"
|
||||||
"movzwl %w0, %2\n\t"
|
"movzwl %w0, %2\n\t"
|
||||||
"shrl $16, %0\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)
|
static void ihk_mc_spinlock_unlock_noirq(ihk_spinlock_t *lock)
|
||||||
{
|
{
|
||||||
asm volatile ("lock incw %0" : "+m"(*lock) : : "memory", "cc");
|
asm volatile ("lock incw %0" : "+m"(*lock) : : "memory", "cc");
|
||||||
|
|
||||||
|
preempt_enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ihk_mc_spinlock_unlock(ihk_spinlock_t *lock, unsigned long flags)
|
static void ihk_mc_spinlock_unlock(ihk_spinlock_t *lock, unsigned long flags)
|
||||||
|
|||||||
14
kernel/cls.c
14
kernel/cls.c
@@ -23,6 +23,7 @@
|
|||||||
extern int num_processors;
|
extern int num_processors;
|
||||||
|
|
||||||
struct cpu_local_var *clv;
|
struct cpu_local_var *clv;
|
||||||
|
static int cpu_local_var_initialized = 0;
|
||||||
|
|
||||||
void cpu_local_var_init(void)
|
void cpu_local_var_init(void)
|
||||||
{
|
{
|
||||||
@@ -33,9 +34,22 @@ void cpu_local_var_init(void)
|
|||||||
|
|
||||||
clv = allocate_pages(z, IHK_MC_AP_CRITICAL);
|
clv = allocate_pages(z, IHK_MC_AP_CRITICAL);
|
||||||
memset(clv, 0, z * PAGE_SIZE);
|
memset(clv, 0, z * PAGE_SIZE);
|
||||||
|
cpu_local_var_initialized = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct cpu_local_var *get_cpu_local_var(int id)
|
struct cpu_local_var *get_cpu_local_var(int id)
|
||||||
{
|
{
|
||||||
return clv + 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;
|
ihk_spinlock_t migq_lock;
|
||||||
struct list_head migq;
|
struct list_head migq;
|
||||||
int in_interrupt;
|
int in_interrupt;
|
||||||
|
int no_preempt;
|
||||||
} __attribute__((aligned(64)));
|
} __attribute__((aligned(64)));
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -411,6 +411,7 @@ struct process {
|
|||||||
fp_regs_struct *fp_regs;
|
fp_regs_struct *fp_regs;
|
||||||
char *saved_cmdline;
|
char *saved_cmdline;
|
||||||
long saved_cmdline_len;
|
long saved_cmdline_len;
|
||||||
|
int in_syscall_offload;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct process_vm {
|
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",
|
dkprintf("[%d]page_fault_handler(%p,%lx,%p)\n",
|
||||||
ihk_mc_get_processor_id(), fault_addr, reason, regs);
|
ihk_mc_get_processor_id(), fault_addr, reason, regs);
|
||||||
|
|
||||||
|
preempt_disable();
|
||||||
|
|
||||||
cpu_enable_interrupt();
|
cpu_enable_interrupt();
|
||||||
|
|
||||||
error = page_fault_process_vm(proc->vm, fault_addr, reason);
|
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;
|
error = 0;
|
||||||
out:
|
out:
|
||||||
|
preempt_enable();
|
||||||
dkprintf("[%d]page_fault_handler(%p,%lx,%p): (%d)\n",
|
dkprintf("[%d]page_fault_handler(%p,%lx,%p): (%d)\n",
|
||||||
ihk_mc_get_processor_id(), fault_addr, reason,
|
ihk_mc_get_processor_id(), fault_addr, reason,
|
||||||
regs, error);
|
regs, error);
|
||||||
|
|||||||
@@ -2225,6 +2225,16 @@ void schedule(void)
|
|||||||
unsigned long irqstate;
|
unsigned long irqstate;
|
||||||
struct process *last;
|
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:
|
redo:
|
||||||
irqstate = ihk_mc_spinlock_lock(&(get_this_cpu_local_var()->runq_lock));
|
irqstate = ihk_mc_spinlock_lock(&(get_this_cpu_local_var()->runq_lock));
|
||||||
v = get_this_cpu_local_var();
|
v = get_this_cpu_local_var();
|
||||||
|
|||||||
@@ -192,6 +192,7 @@ long do_syscall(struct syscall_request *req, int cpu, int pid)
|
|||||||
unsigned long irqstate;
|
unsigned long irqstate;
|
||||||
struct process *proc = cpu_local_var(current);
|
struct process *proc = cpu_local_var(current);
|
||||||
|
|
||||||
|
++proc->in_syscall_offload;
|
||||||
dkprintf("SC(%d)[%3d] sending syscall\n",
|
dkprintf("SC(%d)[%3d] sending syscall\n",
|
||||||
ihk_mc_get_processor_id(),
|
ihk_mc_get_processor_id(),
|
||||||
req->number);
|
req->number);
|
||||||
@@ -252,6 +253,7 @@ long do_syscall(struct syscall_request *req, int cpu, int pid)
|
|||||||
ihk_mc_spinlock_unlock(&syscall_lock, irqstate);
|
ihk_mc_spinlock_unlock(&syscall_lock, irqstate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
--proc->in_syscall_offload;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user