aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/os-Linux/skas
diff options
context:
space:
mode:
authorJeff Dike <jdike@addtoit.com>2006-01-18 20:42:49 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-18 22:20:20 -0500
commit1d7173baf286c8b720f97f119ec92be43076ebde (patch)
tree4d562c25063c73a690fe1777fa86c3f48dfbbf13 /arch/um/os-Linux/skas
parent09ee011eb322c2072ec184a88763c250a5485d8b (diff)
[PATCH] uml: implement soft interrupts
This patch implements soft interrupts. Interrupt enabling and disabling no longer map to sigprocmask. Rather, a flag is set indicating whether interrupts may be handled. If a signal comes in and interrupts are marked as OK, then it is handled normally. If interrupts are marked as off, then the signal handler simply returns after noting that a signal needs handling. When interrupts are enabled later on, this pending signals flag is checked, and the IRQ handlers are called at that point. The point of this is to reduce the cost of local_irq_save et al, since they are very much more common than the signals that they are enabling and disabling. Soft interrupts produce a speed-up of ~25% on a kernel build. Subtleties - UML uses sigsetjmp/siglongjmp to switch contexts. sigsetjmp has been wrapped in a save_flags-like macro which remembers the interrupt state at setjmp time, and restores it when it is longjmp-ed back to. The enable_signals function has to loop because the IRQ handler disables interrupts before returning. enable_signals has to return with signals enabled, and signals may come in between the disabling and the return to enable_signals. So, it loops for as long as there are pending signals, ensuring that signals are enabled when it finally returns, and that there are no pending signals that need to be dealt with. Signed-off-by: Jeff Dike <jdike@addtoit.com> Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/um/os-Linux/skas')
-rw-r--r--arch/um/os-Linux/skas/process.c29
1 files changed, 17 insertions, 12 deletions
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index b959b2618b7f..120a21c5883f 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -34,6 +34,7 @@
34#include "mem.h" 34#include "mem.h"
35#include "uml-config.h" 35#include "uml-config.h"
36#include "process.h" 36#include "process.h"
37#include "longjmp.h"
37 38
38int is_skas_winch(int pid, int fd, void *data) 39int is_skas_winch(int pid, int fd, void *data)
39{ 40{
@@ -433,6 +434,7 @@ void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
433{ 434{
434 unsigned long flags; 435 unsigned long flags;
435 sigjmp_buf switch_buf, fork_buf; 436 sigjmp_buf switch_buf, fork_buf;
437 int enable;
436 438
437 *switch_buf_ptr = &switch_buf; 439 *switch_buf_ptr = &switch_buf;
438 *fork_buf_ptr = &fork_buf; 440 *fork_buf_ptr = &fork_buf;
@@ -447,7 +449,7 @@ void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
447 */ 449 */
448 flags = get_signals(); 450 flags = get_signals();
449 block_signals(); 451 block_signals();
450 if(sigsetjmp(fork_buf, 1) == 0) 452 if(UML_SIGSETJMP(&fork_buf, enable) == 0)
451 new_thread_proc(stack, handler); 453 new_thread_proc(stack, handler);
452 454
453 remove_sigstack(); 455 remove_sigstack();
@@ -458,20 +460,22 @@ void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
458void thread_wait(void *sw, void *fb) 460void thread_wait(void *sw, void *fb)
459{ 461{
460 sigjmp_buf buf, **switch_buf = sw, *fork_buf; 462 sigjmp_buf buf, **switch_buf = sw, *fork_buf;
463 int enable;
461 464
462 *switch_buf = &buf; 465 *switch_buf = &buf;
463 fork_buf = fb; 466 fork_buf = fb;
464 if(sigsetjmp(buf, 1) == 0) 467 if(UML_SIGSETJMP(&buf, enable) == 0)
465 siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK); 468 siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK);
466} 469}
467 470
468void switch_threads(void *me, void *next) 471void switch_threads(void *me, void *next)
469{ 472{
470 sigjmp_buf my_buf, **me_ptr = me, *next_buf = next; 473 sigjmp_buf my_buf, **me_ptr = me, *next_buf = next;
474 int enable;
471 475
472 *me_ptr = &my_buf; 476 *me_ptr = &my_buf;
473 if(sigsetjmp(my_buf, 1) == 0) 477 if(UML_SIGSETJMP(&my_buf, enable) == 0)
474 siglongjmp(*next_buf, 1); 478 UML_SIGLONGJMP(next_buf, 1);
475} 479}
476 480
477static sigjmp_buf initial_jmpbuf; 481static sigjmp_buf initial_jmpbuf;
@@ -484,14 +488,14 @@ static sigjmp_buf *cb_back;
484int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) 488int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
485{ 489{
486 sigjmp_buf **switch_buf = switch_buf_ptr; 490 sigjmp_buf **switch_buf = switch_buf_ptr;
487 int n; 491 int n, enable;
488 492
489 set_handler(SIGWINCH, (__sighandler_t) sig_handler, 493 set_handler(SIGWINCH, (__sighandler_t) sig_handler,
490 SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM, 494 SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM,
491 SIGVTALRM, -1); 495 SIGVTALRM, -1);
492 496
493 *fork_buf_ptr = &initial_jmpbuf; 497 *fork_buf_ptr = &initial_jmpbuf;
494 n = sigsetjmp(initial_jmpbuf, 1); 498 n = UML_SIGSETJMP(&initial_jmpbuf, enable);
495 switch(n){ 499 switch(n){
496 case INIT_JMP_NEW_THREAD: 500 case INIT_JMP_NEW_THREAD:
497 new_thread_proc((void *) stack, new_thread_handler); 501 new_thread_proc((void *) stack, new_thread_handler);
@@ -501,7 +505,7 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
501 break; 505 break;
502 case INIT_JMP_CALLBACK: 506 case INIT_JMP_CALLBACK:
503 (*cb_proc)(cb_arg); 507 (*cb_proc)(cb_arg);
504 siglongjmp(*cb_back, 1); 508 UML_SIGLONGJMP(cb_back, 1);
505 break; 509 break;
506 case INIT_JMP_HALT: 510 case INIT_JMP_HALT:
507 kmalloc_ok = 0; 511 kmalloc_ok = 0;
@@ -512,20 +516,21 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
512 default: 516 default:
513 panic("Bad sigsetjmp return in start_idle_thread - %d\n", n); 517 panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
514 } 518 }
515 siglongjmp(**switch_buf, 1); 519 UML_SIGLONGJMP(*switch_buf, 1);
516} 520}
517 521
518void initial_thread_cb_skas(void (*proc)(void *), void *arg) 522void initial_thread_cb_skas(void (*proc)(void *), void *arg)
519{ 523{
520 sigjmp_buf here; 524 sigjmp_buf here;
525 int enable;
521 526
522 cb_proc = proc; 527 cb_proc = proc;
523 cb_arg = arg; 528 cb_arg = arg;
524 cb_back = &here; 529 cb_back = &here;
525 530
526 block_signals(); 531 block_signals();
527 if(sigsetjmp(here, 1) == 0) 532 if(UML_SIGSETJMP(&here, enable) == 0)
528 siglongjmp(initial_jmpbuf, INIT_JMP_CALLBACK); 533 UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK);
529 unblock_signals(); 534 unblock_signals();
530 535
531 cb_proc = NULL; 536 cb_proc = NULL;
@@ -536,13 +541,13 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg)
536void halt_skas(void) 541void halt_skas(void)
537{ 542{
538 block_signals(); 543 block_signals();
539 siglongjmp(initial_jmpbuf, INIT_JMP_HALT); 544 UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_HALT);
540} 545}
541 546
542void reboot_skas(void) 547void reboot_skas(void)
543{ 548{
544 block_signals(); 549 block_signals();
545 siglongjmp(initial_jmpbuf, INIT_JMP_REBOOT); 550 UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT);
546} 551}
547 552
548void switch_mm_skas(struct mm_id *mm_idp) 553void switch_mm_skas(struct mm_id *mm_idp)