diff options
Diffstat (limited to 'arch/um/os-Linux/skas/process.c')
-rw-r--r-- | arch/um/os-Linux/skas/process.c | 68 |
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 | ||
447 | void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, | 447 | void 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 | |||
480 | void 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 | ||
490 | void switch_threads(void *me, void *next) | 459 | void 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 | ||
499 | static jmp_buf initial_jmpbuf; | 465 | static jmp_buf initial_jmpbuf; |
@@ -503,23 +469,21 @@ static void (*cb_proc)(void *arg); | |||
503 | static void *cb_arg; | 469 | static void *cb_arg; |
504 | static jmp_buf *cb_back; | 470 | static jmp_buf *cb_back; |
505 | 471 | ||
506 | int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) | 472 | int 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 | ||
540 | void initial_thread_cb_skas(void (*proc)(void *), void *arg) | 504 | void initial_thread_cb_skas(void (*proc)(void *), void *arg) |