Skip to content

Commit

Permalink
Merge pull request #9 from lsds/ken/sgxlkl709
Browse files Browse the repository at this point in the history
Signal to be delivered on the correct thread.
  • Loading branch information
KenGordon authored Sep 15, 2020
2 parents eced6cd + d4d06c1 commit e041aa7
Show file tree
Hide file tree
Showing 9 changed files with 399 additions and 23 deletions.
15 changes: 15 additions & 0 deletions arch/lkl/include/asm/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,21 @@

int lkl_cpu_get(void);
void lkl_cpu_put(void);

#ifdef DEBUG
/* Bug if you do not have the cpu lock. */
void lkl_assert_cpu_owner(void);
/* Bug if you do have the cpu lock. */
void lkl_assert_cpu_not_owner(void);
/* Prints values of the various locking structure to aid debugging. */
void lkl_print_cpu_lock_state(const char *func_name);
#else
static inline void lkl_assert_cpu_owner(void) {}
static inline void lkl_assert_cpu_not_owner(void) {}
static inline void lkl_print_cpu_lock_state(const char *func_name) {}
#endif


int lkl_cpu_try_run_irq(int irq);
int lkl_cpu_init(void);
void lkl_cpu_shutdown(void);
Expand Down
26 changes: 24 additions & 2 deletions arch/lkl/include/asm/signal.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@
#ifndef _ASM_LKL_SIGNAL_H
#define _ASM_LKL_SIGNAL_H
#include <asm-generic/signal.h>

struct ucontext;
void do_signal(struct pt_regs *regs);

struct thread_info;
struct ksignal_list_node;
struct ksignal;

void lkl_process_trap(int signr, struct ucontext *uctx);

/*
* Capture pending signals and move them to a task-specific list.
* Must be called only with the cpu lock held.
*/

#include <asm-generic/signal.h>
void move_signals_to_task(void);

/*
* Send any signals targeting this task.
* Must be called only with the cpu lock held, it will be unlocked for the call to user code.
*/

void send_current_signals(struct ucontext *uctx);

#endif
20 changes: 20 additions & 0 deletions arch/lkl/include/asm/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,20 @@
#include <asm/processor.h>
#include <asm/host_ops.h>

#include <linux/signal_types.h>
#include <linux/spinlock_types.h>

/*
* Used to track a thread's pending signals.
* See signal_list_head/tail below.
*/

struct ksignal_list_node
{
struct ksignal sig;
struct ksignal_list_node *next; /* consider using the kernel lists, but they are doubly linked and clumsy in this simple case */
};

typedef struct {
unsigned long seg;
} mm_segment_t;
Expand All @@ -29,6 +43,12 @@ struct thread_info {
/* The task for any child that was created during syscall execution. Only
* valid on return from a clone-family syscall. */
struct task_struct *cloned_child;

/* lock for the list below, the init is in the thread_info creation fn */
spinlock_t signal_list_lock;
/* a linked list of pending signals, pushed onto here as they are detected in move_signals_to_task */
struct ksignal_list_node* signal_list_head;
struct ksignal_list_node* signal_list_tail;
};

#define INIT_THREAD_INFO(tsk) \
Expand Down
63 changes: 59 additions & 4 deletions arch/lkl/kernel/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,10 @@ static void __cpu_try_get_unlock(int lock_ret, int n)
void lkl_cpu_change_owner(lkl_thread_t owner)
{
lkl_ops->mutex_lock(cpu.lock);
if (cpu.count > 1)
if (cpu.count > 1) {
lkl_print_cpu_lock_state(__func__);
lkl_bug("bad count while changing owner\n");
}
cpu.owner = owner;
lkl_ops->mutex_unlock(cpu.lock);
}
Expand Down Expand Up @@ -117,8 +119,10 @@ void lkl_cpu_put(void)
lkl_ops->mutex_lock(cpu.lock);

if (!cpu.count || !cpu.owner ||
!lkl_ops->thread_equal(cpu.owner, lkl_ops->thread_self()))
!lkl_ops->thread_equal(cpu.owner, lkl_ops->thread_self())) {
lkl_print_cpu_lock_state(__func__);
lkl_bug("%s: unbalanced put\n", __func__);
}

while (cpu.irqs_pending && !irqs_disabled()) {
cpu.irqs_pending = false;
Expand All @@ -128,9 +132,11 @@ void lkl_cpu_put(void)
}

if (test_ti_thread_flag(current_thread_info(), TIF_HOST_THREAD) &&
!single_task_running() && cpu.count == 1) {
if (in_interrupt())
!single_task_running() && cpu.count == 1) {
if (in_interrupt()) {
lkl_print_cpu_lock_state(__func__);
lkl_bug("%s: in interrupt\n", __func__);
}
lkl_ops->mutex_unlock(cpu.lock);
thread_sched_jb();
return;
Expand All @@ -150,6 +156,55 @@ void lkl_cpu_put(void)
lkl_ops->mutex_unlock(cpu.lock);
}

#ifdef DEBUG

/*
* Debug tool. Essentially allows for assert(cpuLockTaken);
*
* Returns 1 meaning this thread owns the lock, 0 otherwise.
*/

static int lkl_check_cpu_owner()
{
int result;
lkl_ops->mutex_lock(cpu.lock);
lkl_thread_t self = lkl_ops->thread_self();
lkl_thread_t owner = cpu.owner;
if (!cpu.count || !owner ||
!lkl_ops->thread_equal(owner, self)) {
result = 0;
} else {
result = 1;
}
lkl_ops->mutex_unlock(cpu.lock);
return result.
}

/* Expected the cpu to be locked by this task. */
void lkl_assert_cpu_owner(void)
{
BUG_ON(lkl_check_cpu_owner() != 1);
}

/* Expected the cpu to be unlocked or locked by another task. */
void lkl_assert_cpu_not_owner(void)
{
BUG_ON(lkl_check_cpu_owner() != 0);
}

/* Debugging, print state of flags etc for a particular caller. */
void lkl_print_cpu_lock_state(const char *func_name)
{
lkl_thread_t self = lkl_ops->thread_self();
lkl_thread_t owner = cpu.owner;
unsigned int count = cpu.count;
unsigned int sleepers = cpu.sleepers;
unsigned int shutdown_gate = cpu.shutdown_gate;

LKL_TRACE("%s: self %lx owner %lx count %u sleepers %u shutdown gate %u\n", func_name, self, owner, count, sleepers, shutdown_gate);
}
#endif

int lkl_cpu_try_run_irq(int irq)
{
int ret;
Expand Down
11 changes: 11 additions & 0 deletions arch/lkl/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,11 @@ int lkl_is_running(void)

void machine_halt(void)
{
/*
* All lkl_cpu_shutdown does is set cpu.shutdown_gate to MAX_THREADS
* as a flag. It does return and so machine_halt will return too.
*/

lkl_cpu_shutdown();
}

Expand All @@ -156,6 +161,12 @@ long lkl_sys_halt(void)
LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART, };

err = lkl_syscall(__NR_reboot, params);

/*
This code does get run even though machine_halt (above)
is called.
*/

if (err < 0) {
LKL_TRACE("sys_reboot failed (err=%i)\n", err);
return err;
Expand Down
Loading

0 comments on commit e041aa7

Please sign in to comment.