aboutsummaryrefslogtreecommitdiffstats
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.c68
1 files changed, 16 insertions, 52 deletions
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index 42e3d1ed802c..cb9ab54146cc 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -444,56 +444,22 @@ void map_stub_pages(int fd, unsigned long code,
444 } 444 }
445} 445}
446 446
447void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, 447void new_thread(void *stack, jmp_buf *buf, void (*handler)(void))
448 void (*handler)(int))
449{ 448{
450 unsigned long flags; 449 (*buf)[0].JB_IP = (unsigned long) handler;
451 jmp_buf switch_buf, fork_buf; 450 (*buf)[0].JB_SP = (unsigned long) stack +
452 451 (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) - sizeof(void *);
453 *switch_buf_ptr = &switch_buf;
454 *fork_buf_ptr = &fork_buf;
455
456 /* Somewhat subtle - siglongjmp restores the signal mask before doing
457 * the longjmp. This means that when jumping from one stack to another
458 * when the target stack has interrupts enabled, an interrupt may occur
459 * on the source stack. This is bad when starting up a process because
460 * it's not supposed to get timer ticks until it has been scheduled.
461 * So, we disable interrupts around the sigsetjmp to ensure that
462 * they can't happen until we get back here where they are safe.
463 */
464 flags = get_signals();
465 block_signals();
466 if(UML_SETJMP(&fork_buf) == 0)
467 new_thread_proc(stack, handler);
468
469 remove_sigstack();
470
471 set_signals(flags);
472} 452}
473 453
474#define INIT_JMP_NEW_THREAD 0 454#define INIT_JMP_NEW_THREAD 0
475#define INIT_JMP_REMOVE_SIGSTACK 1 455#define INIT_JMP_CALLBACK 1
476#define INIT_JMP_CALLBACK 2 456#define INIT_JMP_HALT 2
477#define INIT_JMP_HALT 3 457#define INIT_JMP_REBOOT 3
478#define INIT_JMP_REBOOT 4
479
480void thread_wait(void *sw, void *fb)
481{
482 jmp_buf buf, **switch_buf = sw, *fork_buf;
483
484 *switch_buf = &buf;
485 fork_buf = fb;
486 if(UML_SETJMP(&buf) == 0)
487 UML_LONGJMP(fork_buf, INIT_JMP_REMOVE_SIGSTACK);
488}
489 458
490void switch_threads(void *me, void *next) 459void switch_threads(jmp_buf *me, jmp_buf *you)
491{ 460{
492 jmp_buf my_buf, **me_ptr = me, *next_buf = next; 461 if(UML_SETJMP(me) == 0)
493 462 UML_LONGJMP(you, 1);
494 *me_ptr = &my_buf;
495 if(UML_SETJMP(&my_buf) == 0)
496 UML_LONGJMP(next_buf, 1);
497} 463}
498 464
499static jmp_buf initial_jmpbuf; 465static jmp_buf initial_jmpbuf;
@@ -503,23 +469,21 @@ static void (*cb_proc)(void *arg);
503static void *cb_arg; 469static void *cb_arg;
504static jmp_buf *cb_back; 470static jmp_buf *cb_back;
505 471
506int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) 472int start_idle_thread(void *stack, jmp_buf *switch_buf)
507{ 473{
508 jmp_buf **switch_buf = switch_buf_ptr;
509 int n; 474 int n;
510 475
511 set_handler(SIGWINCH, (__sighandler_t) sig_handler, 476 set_handler(SIGWINCH, (__sighandler_t) sig_handler,
512 SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM, 477 SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM,
513 SIGVTALRM, -1); 478 SIGVTALRM, -1);
514 479
515 *fork_buf_ptr = &initial_jmpbuf;
516 n = UML_SETJMP(&initial_jmpbuf); 480 n = UML_SETJMP(&initial_jmpbuf);
517 switch(n){ 481 switch(n){
518 case INIT_JMP_NEW_THREAD: 482 case INIT_JMP_NEW_THREAD:
519 new_thread_proc((void *) stack, new_thread_handler); 483 (*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler;
520 break; 484 (*switch_buf)[0].JB_SP = (unsigned long) stack +
521 case INIT_JMP_REMOVE_SIGSTACK: 485 (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) -
522 remove_sigstack(); 486 sizeof(void *);
523 break; 487 break;
524 case INIT_JMP_CALLBACK: 488 case INIT_JMP_CALLBACK:
525 (*cb_proc)(cb_arg); 489 (*cb_proc)(cb_arg);
@@ -534,7 +498,7 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
534 default: 498 default:
535 panic("Bad sigsetjmp return in start_idle_thread - %d\n", n); 499 panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
536 } 500 }
537 UML_LONGJMP(*switch_buf, 1); 501 UML_LONGJMP(switch_buf, 1);
538} 502}
539 503
540void initial_thread_cb_skas(void (*proc)(void *), void *arg) 504void initial_thread_cb_skas(void (*proc)(void *), void *arg)