Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Signal to be delivered on the correct thread. #9

Merged
merged 24 commits into from
Sep 15, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
e81db9d
Change the signal delivery (formally in do_signal) from delivering all
KenGordon Aug 27, 2020
113e697
tabs vs spaces
KenGordon Aug 28, 2020
f64013f
Merge branch 'upstream-refactor' into ken/sgxlkl709
KenGordon Aug 28, 2020
0eaf1f8
Per (some of) david's suggestions, remove volatile, improve comments,…
KenGordon Aug 28, 2020
6878f09
Merge branch 'ken/sgxlkl709' of ssh://github.com/lsds/lkl into ken/sg…
KenGordon Aug 28, 2020
89b22af
Formatting and left over conflict tag.
KenGordon Aug 28, 2020
36a56e0
Update arch/lkl/kernel/signal.c
KenGordon Aug 28, 2020
19a9133
Keep a tail pointer to make consuming signal nodes fast.
KenGordon Aug 28, 2020
b8db5b8
Basically a backup commit. Add much debugging code.
KenGordon Sep 2, 2020
9ce0c62
Support traps getting only the trap signal and not throw away any others
KenGordon Sep 7, 2020
4546860
Do not take teh cpu lock an extra time in move_signals_to_task as
KenGordon Sep 9, 2020
c919fcd
Remove bogus debug code.
KenGordon Sep 9, 2020
be2938b
Remove bogus print
KenGordon Sep 9, 2020
69505a4
Hold the signal list lock while deleting elements as suggested by Sean
KenGordon Sep 9, 2020
952818a
Fix commenting style, move allocation and init of signal list node in…
KenGordon Sep 9, 2020
651b1f3
Undo accidental checkin of patched config.
KenGordon Sep 10, 2020
6c15e96
Revert accidental commit of patched build files
KenGordon Sep 10, 2020
3159974
SGX-LKL Issue 709, signals improvements. Changes as per PR comments
KenGordon Sep 10, 2020
aa9bb4e
Take out bug check in lkl_cpu_put which would slow the fast path.
KenGordon Sep 10, 2020
515cb84
Update comment.
KenGordon Sep 10, 2020
033b7c0
Update arch/lkl/include/asm/thread_info.h
KenGordon Sep 14, 2020
3ca325a
Update arch/lkl/kernel/signal.c
KenGordon Sep 14, 2020
8757429
defconfig reverted again due to patching scheme.
KenGordon Sep 14, 2020
d4d06c1
Update commenst in cpu.c. Fix bug in linked list handling in signal.c.
KenGordon Sep 15, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion arch/lkl/include/asm/signal.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
#pragma once
KenGordon marked this conversation as resolved.
Show resolved Hide resolved
#include <asm-generic/signal.h>

struct ucontext;

struct thread_info;
struct ksignal_list_node;
struct ksignal;

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

extern void append_ksignal_node(struct thread_info *task, struct ksignal_list_node* node);
KenGordon marked this conversation as resolved.
Show resolved Hide resolved
extern void move_signals_to_task(void);
extern int get_next_ksignal(struct thread_info *task, struct ksignal* sig);

#include <asm-generic/signal.h>
//void initialize_uctx(struct ucontext *uctx, const struct pt_regs *regs);
KenGordon marked this conversation as resolved.
Show resolved Hide resolved
void send_current_signals(struct ucontext *uctx);
13 changes: 13 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,15 @@
#include <asm/processor.h>
#include <asm/host_ops.h>

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

struct ksignal_list_node
KenGordon marked this conversation as resolved.
Show resolved Hide resolved
{
struct ksignal sig;
volatile struct ksignal_list_node *next; /* consider using the kernel lists, but they are doubly linked and clumsy in this simple case */
KenGordon marked this conversation as resolved.
Show resolved Hide resolved
};

typedef struct {
unsigned long seg;
} mm_segment_t;
Expand All @@ -29,6 +38,10 @@ 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;

/* a linked list of pending signals, pushed onto here as they are detected in move_signals_to_task */
KenGordon marked this conversation as resolved.
Show resolved Hide resolved
spinlock_t signal_list_lock; /* the init is in the thread_info creation fn */
volatile struct ksignal_list_node* signal_list;
KenGordon marked this conversation as resolved.
Show resolved Hide resolved
};

#define INIT_THREAD_INFO(tsk) \
Expand Down
102 changes: 93 additions & 9 deletions arch/lkl/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,17 @@ static void handle_signal(struct ksignal *ksig, struct ucontext *uctx)
ksig->ka.sa.sa_handler(ksig->sig, (void*)&ksig->info, (void*)uctx);
}

/*
While you might think this should call move_signals_to_task, send_current_signals
KenGordon marked this conversation as resolved.
Show resolved Hide resolved
it is different here in that only a specific signal is being requested.
This is the sync signal case and that signal will have just been forced into the
regular task queue of signals so the pre-existing code will work. See lkl_do_trap

Up for debate though is whether it would be better to either directly invoke
the handler in lkl_do_trap or here to have versions of move_signals_to_task, send_current_signals
that operate by scanning the list for signr, the given signal.
KenGordon marked this conversation as resolved.
Show resolved Hide resolved
*/

void lkl_process_trap(int signr, struct ucontext *uctx)
{
struct ksignal ksig;
Expand All @@ -50,25 +61,98 @@ void lkl_process_trap(int signr, struct ucontext *uctx)
/* Handle required signal */
if(signr == ksig.sig)
{
LKL_TRACE("trap task %p %d\n", current, signr);
handle_signal(&ksig, uctx);
break;
}
}
}

void do_signal(struct pt_regs *regs)
/*
Walk to the end of the list and make it point at the new node
*/
KenGordon marked this conversation as resolved.
Show resolved Hide resolved


void append_ksignal_node(struct thread_info *task, struct ksignal_list_node* node)
{
struct ksignal ksig;
struct ucontext uc;
volatile struct ksignal_list_node **node_ptr;
spin_lock(&task->signal_list_lock);
node_ptr = &task->signal_list;

LKL_TRACE("enter\n");
while (*node_ptr) {
volatile struct ksignal_list_node *next_node = *node_ptr;
node_ptr = &(next_node->next);
}
KenGordon marked this conversation as resolved.
Show resolved Hide resolved

*node_ptr = node;
spin_unlock(&task->signal_list_lock);
}

memset(&uc, 0, sizeof(uc));
initialize_uctx(&uc, regs);
// probably needs to be called with the cpu lock
KenGordon marked this conversation as resolved.
Show resolved Hide resolved
void move_signals_to_task(void)
{
struct ksignal ksig; // place to hold retrieved signal
KenGordon marked this conversation as resolved.
Show resolved Hide resolved
// get the lkl local version of the current task, so we can store the signals
// in a list hanging off it.
struct thread_info *current_task;
current_task = task_thread_info(current);
while (get_signal(&ksig)) {
LKL_TRACE("ksig.sig=", ksig.sig);
struct ksignal_list_node* node = kmalloc(sizeof(struct ksignal_list_node), GFP_KERNEL); // may sleep, is that ok?
KenGordon marked this conversation as resolved.
Show resolved Hide resolved
if (node == NULL) {
lkl_bug("kmalloc returned NULL");
KenGordon marked this conversation as resolved.
Show resolved Hide resolved
}
LKL_TRACE("Appending task %p signal %d\n", current, ksig.sig);
memcpy(&node->sig, &ksig, sizeof(ksig));
node->next = NULL;
KenGordon marked this conversation as resolved.
Show resolved Hide resolved
append_ksignal_node(current_task, node);
}
}

int get_next_ksignal(struct thread_info *task, struct ksignal* sig)
{
struct ksignal_list_node *next;
struct ksignal_list_node *node;

spin_lock(&task->signal_list_lock);
node = task->signal_list;

if (!node) {
spin_unlock(&task->signal_list_lock);
return 0; // no pending signals
}

next = node->next;
task->signal_list = next; // drop the head

spin_unlock(&task->signal_list_lock);

memcpy(sig, &node->sig, sizeof(*sig)); // copy the signal back to the caller
LKL_TRACE("Fetching task %p signal %d\n", current, sig->sig);
kfree(node);
return 1;
}

// Must be called without the cpu lock
KenGordon marked this conversation as resolved.
Show resolved Hide resolved
void send_current_signals(struct ucontext *uctx)
{
struct thread_info *current_task = task_thread_info(current);
KenGordon marked this conversation as resolved.
Show resolved Hide resolved
struct ksignal ksig;

struct ucontext uc;

if (uctx == NULL) {
uctx = &uc;
memset(uctx, 0, sizeof(uc));
initialize_uctx(uctx, NULL);
}

/* Whee! Actually deliver the signal. */
handle_signal(&ksig, &uc);
LKL_TRACE("enter\n");

while (get_next_ksignal(current_task, &ksig)) {
KenGordon marked this conversation as resolved.
Show resolved Hide resolved
/* Actually deliver the signal. */
handle_signal(&ksig, uctx);
KenGordon marked this conversation as resolved.
Show resolved Hide resolved
KenGordon marked this conversation as resolved.
Show resolved Hide resolved
}
}



KenGordon marked this conversation as resolved.
Show resolved Hide resolved
20 changes: 16 additions & 4 deletions arch/lkl/kernel/syscalls.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,8 @@ long lkl_syscall(long no, long *params)

ret = run_syscall(no, params);
task_work_run();
do_signal(NULL);
move_signals_to_task();
send_current_signals(NULL);

if (no == __NR_reboot) {
thread_sched_jb();
Expand Down Expand Up @@ -287,7 +288,8 @@ long lkl_syscall(long no, long *params)
switch_to_host_task(task);
}

do_signal(NULL);
/* capture the signals pending while we still have the cpu lock */
move_signals_to_task();

if (no == __NR_reboot) {
thread_sched_jb();
Expand All @@ -296,10 +298,12 @@ long lkl_syscall(long no, long *params)

out:
lkl_cpu_put();

LKL_TRACE("done (no=%li task=%s current=%s ret=%i)\n", no,
task ? task->comm : "NULL", current->comm, ret);

/* once cpu is released, run any pending signal handlers */
/* experiment indicates that all the signal sending happens here, not in the idle loop. */
send_current_signals(NULL);
KenGordon marked this conversation as resolved.
Show resolved Hide resolved
return ret;
}

Expand All @@ -325,6 +329,9 @@ static int idle_host_task_loop(void *unused)
idle_host_task = current;

for (;;) {
// any pending signals, capture them in lists per task
// so we can send them to the appropriate task later
move_signals_to_task();
lkl_cpu_put();
lkl_ops->sem_down(ti->sched_sem);

Expand All @@ -342,6 +349,11 @@ static int idle_host_task_loop(void *unused)
return 0;
}

// I am not convinced any signas are ever available here
// if the send at the end of lkl_syscall is removed nothing
// arrives in my test case
send_current_signals(NULL);

KenGordon marked this conversation as resolved.
Show resolved Hide resolved
schedule_tail(ti->prev_sched);
}
}
Expand Down
15 changes: 14 additions & 1 deletion arch/lkl/kernel/threads.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ static int init_ti(struct thread_info *ti)
ti->tid = 0;
ti->cloned_child = NULL;

spin_lock_init(&ti->signal_list_lock);
ti->signal_list = NULL;

return 0;
}

Expand All @@ -42,7 +45,6 @@ unsigned long *alloc_thread_stack_node(struct task_struct *task, int node)
}
ti->task = task;


return (unsigned long *)ti;
}

Expand Down Expand Up @@ -130,6 +132,17 @@ void free_thread_stack(struct task_struct *tsk)
test_tsk_thread_flag(tsk, TIF_SIGPENDING), ti, current->comm);

kill_thread(ti);

/* free any linked list of pending signals */
/* note that we do not need to take the lock as the thread is dead and ought to be unreachable*/
KenGordon marked this conversation as resolved.
Show resolved Hide resolved

struct ksignal_list_node* signal_list = ti->signal_list;
while (signal_list != NULL) {
struct ksignal_list_node *next = signal_list->next;
kfree(signal_list);
signal_list = next;
}

LKL_TRACE("Deallocating %p\n", ti);
kfree(ti);
}
Expand Down
5 changes: 4 additions & 1 deletion arch/lkl/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ void lkl_do_trap(int trapnr, int signr, char *str, struct ucontext *uctx,

LKL_TRACE("injecting signal into lkl\n");
force_sig_info((struct kernel_siginfo *)info);
lkl_process_trap(signr, uctx);

lkl_cpu_put();

/* invoke the signal handler for this trap once we have given up the CPU */
/* otherwise we may take the CPU lock again and fail. */
lkl_process_trap(signr, uctx);
KenGordon marked this conversation as resolved.
Show resolved Hide resolved
}