summaryrefslogtreecommitdiffstats
path: root/arch/um/os-Linux/skas/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/os-Linux/skas/process.c')
-rw-r--r--arch/um/os-Linux/skas/process.c92
1 files changed, 35 insertions, 57 deletions
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index 7baf90f..cb9ab54 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -8,7 +8,6 @@
#include <unistd.h>
#include <errno.h>
#include <signal.h>
-#include <setjmp.h>
#include <sched.h>
#include "ptrace_user.h"
#include <sys/wait.h>
@@ -156,11 +155,15 @@ extern int __syscall_stub_start;
static int userspace_tramp(void *stack)
{
void *addr;
+ int err;
ptrace(PTRACE_TRACEME, 0, 0, 0);
init_new_thread_signals();
- enable_timer();
+ err = set_interval(1);
+ if(err)
+ panic("userspace_tramp - setting timer failed, errno = %d\n",
+ err);
if(!proc_mm){
/* This has a pte, but it can't be mapped in with the usual
@@ -190,14 +193,25 @@ static int userspace_tramp(void *stack)
}
}
if(!ptrace_faultinfo && (stack != NULL)){
+ struct sigaction sa;
+
unsigned long v = UML_CONFIG_STUB_CODE +
(unsigned long) stub_segv_handler -
(unsigned long) &__syscall_stub_start;
set_sigstack((void *) UML_CONFIG_STUB_DATA, page_size());
- set_handler(SIGSEGV, (void *) v, SA_ONSTACK,
- SIGIO, SIGWINCH, SIGALRM, SIGVTALRM,
- SIGUSR1, -1);
+ sigemptyset(&sa.sa_mask);
+ sigaddset(&sa.sa_mask, SIGIO);
+ sigaddset(&sa.sa_mask, SIGWINCH);
+ sigaddset(&sa.sa_mask, SIGALRM);
+ sigaddset(&sa.sa_mask, SIGVTALRM);
+ sigaddset(&sa.sa_mask, SIGUSR1);
+ sa.sa_flags = SA_ONSTACK;
+ sa.sa_handler = (void *) v;
+ sa.sa_restorer = NULL;
+ if(sigaction(SIGSEGV, &sa, NULL) < 0)
+ panic("userspace_tramp - setting SIGSEGV handler "
+ "failed - errno = %d\n", errno);
}
os_stop_process(os_getpid());
@@ -430,56 +444,22 @@ void map_stub_pages(int fd, unsigned long code,
}
}
-void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
- void (*handler)(int))
+void new_thread(void *stack, jmp_buf *buf, void (*handler)(void))
{
- unsigned long flags;
- jmp_buf switch_buf, fork_buf;
-
- *switch_buf_ptr = &switch_buf;
- *fork_buf_ptr = &fork_buf;
-
- /* Somewhat subtle - siglongjmp restores the signal mask before doing
- * the longjmp. This means that when jumping from one stack to another
- * when the target stack has interrupts enabled, an interrupt may occur
- * on the source stack. This is bad when starting up a process because
- * it's not supposed to get timer ticks until it has been scheduled.
- * So, we disable interrupts around the sigsetjmp to ensure that
- * they can't happen until we get back here where they are safe.
- */
- flags = get_signals();
- block_signals();
- if(UML_SETJMP(&fork_buf) == 0)
- new_thread_proc(stack, handler);
-
- remove_sigstack();
-
- set_signals(flags);
+ (*buf)[0].JB_IP = (unsigned long) handler;
+ (*buf)[0].JB_SP = (unsigned long) stack +
+ (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) - sizeof(void *);
}
#define INIT_JMP_NEW_THREAD 0
-#define INIT_JMP_REMOVE_SIGSTACK 1
-#define INIT_JMP_CALLBACK 2
-#define INIT_JMP_HALT 3
-#define INIT_JMP_REBOOT 4
+#define INIT_JMP_CALLBACK 1
+#define INIT_JMP_HALT 2
+#define INIT_JMP_REBOOT 3
-void thread_wait(void *sw, void *fb)
+void switch_threads(jmp_buf *me, jmp_buf *you)
{
- jmp_buf buf, **switch_buf = sw, *fork_buf;
-
- *switch_buf = &buf;
- fork_buf = fb;
- if(UML_SETJMP(&buf) == 0)
- siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK);
-}
-
-void switch_threads(void *me, void *next)
-{
- jmp_buf my_buf, **me_ptr = me, *next_buf = next;
-
- *me_ptr = &my_buf;
- if(UML_SETJMP(&my_buf) == 0)
- UML_LONGJMP(next_buf, 1);
+ if(UML_SETJMP(me) == 0)
+ UML_LONGJMP(you, 1);
}
static jmp_buf initial_jmpbuf;
@@ -489,23 +469,21 @@ static void (*cb_proc)(void *arg);
static void *cb_arg;
static jmp_buf *cb_back;
-int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
+int start_idle_thread(void *stack, jmp_buf *switch_buf)
{
- jmp_buf **switch_buf = switch_buf_ptr;
int n;
set_handler(SIGWINCH, (__sighandler_t) sig_handler,
SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM,
SIGVTALRM, -1);
- *fork_buf_ptr = &initial_jmpbuf;
n = UML_SETJMP(&initial_jmpbuf);
switch(n){
case INIT_JMP_NEW_THREAD:
- new_thread_proc((void *) stack, new_thread_handler);
- break;
- case INIT_JMP_REMOVE_SIGSTACK:
- remove_sigstack();
+ (*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler;
+ (*switch_buf)[0].JB_SP = (unsigned long) stack +
+ (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) -
+ sizeof(void *);
break;
case INIT_JMP_CALLBACK:
(*cb_proc)(cb_arg);
@@ -520,7 +498,7 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
default:
panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
}
- UML_LONGJMP(*switch_buf, 1);
+ UML_LONGJMP(switch_buf, 1);
}
void initial_thread_cb_skas(void (*proc)(void *), void *arg)
OpenPOWER on IntegriCloud