aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/os-Linux
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
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')
-rw-r--r--arch/um/os-Linux/main.c12
-rw-r--r--arch/um/os-Linux/process.c30
-rw-r--r--arch/um/os-Linux/signal.c203
-rw-r--r--arch/um/os-Linux/skas/process.c29
-rw-r--r--arch/um/os-Linux/trap.c3
-rw-r--r--arch/um/os-Linux/uaccess.c4
-rw-r--r--arch/um/os-Linux/util.c1
7 files changed, 164 insertions, 118 deletions
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index 98becd18f211..2878e89a674f 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -81,20 +81,8 @@ extern void scan_elf_aux( char **envp);
81int main(int argc, char **argv, char **envp) 81int main(int argc, char **argv, char **envp)
82{ 82{
83 char **new_argv; 83 char **new_argv;
84 sigset_t mask;
85 int ret, i, err; 84 int ret, i, err;
86 85
87 /* Enable all signals except SIGIO - in some environments, we can
88 * enter with some signals blocked
89 */
90
91 sigemptyset(&mask);
92 sigaddset(&mask, SIGIO);
93 if(sigprocmask(SIG_SETMASK, &mask, NULL) < 0){
94 perror("sigprocmask");
95 exit(1);
96 }
97
98#ifdef UML_CONFIG_CMDLINE_ON_HOST 86#ifdef UML_CONFIG_CMDLINE_ON_HOST
99 /* Allocate memory for thread command lines */ 87 /* Allocate memory for thread command lines */
100 if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){ 88 if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index 39815c6b5e45..7f5e2dac2a35 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -18,6 +18,7 @@
18#include "process.h" 18#include "process.h"
19#include "irq_user.h" 19#include "irq_user.h"
20#include "kern_util.h" 20#include "kern_util.h"
21#include "longjmp.h"
21 22
22#define ARBITRARY_ADDR -1 23#define ARBITRARY_ADDR -1
23#define FAILURE_PID -1 24#define FAILURE_PID -1
@@ -205,24 +206,13 @@ void init_new_thread_signals(int altstack)
205 206
206int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr) 207int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr)
207{ 208{
208 sigjmp_buf buf; 209 sigjmp_buf buf;
209 int n; 210 int n, enable;
210 211
211 *jmp_ptr = &buf; 212 *jmp_ptr = &buf;
212 n = sigsetjmp(buf, 1); 213 n = UML_SIGSETJMP(&buf, enable);
213 if(n != 0) 214 if(n != 0)
214 return(n); 215 return(n);
215 (*fn)(arg); 216 (*fn)(arg);
216 return(0); 217 return(0);
217} 218}
218
219/*
220 * Overrides for Emacs so that we follow Linus's tabbing style.
221 * Emacs will notice this stuff at the end of the file and automatically
222 * adjust the settings for this buffer only. This must remain at the end
223 * of the file.
224 * ---------------------------------------------------------------------------
225 * Local variables:
226 * c-file-style: "linux"
227 * End:
228 */
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index 56ca95931b41..f11b3124a0c8 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -20,23 +20,58 @@
20#include "mode.h" 20#include "mode.h"
21#include "os.h" 21#include "os.h"
22 22
23/* These are the asynchronous signals. SIGVTALRM and SIGARLM are handled
24 * together under SIGVTALRM_BIT. SIGPROF is excluded because we want to
25 * be able to profile all of UML, not just the non-critical sections. If
26 * profiling is not thread-safe, then that is not my problem. We can disable
27 * profiling when SMP is enabled in that case.
28 */
29#define SIGIO_BIT 0
30#define SIGIO_MASK (1 << SIGIO_BIT)
31
32#define SIGVTALRM_BIT 1
33#define SIGVTALRM_MASK (1 << SIGVTALRM_BIT)
34
35#define SIGALRM_BIT 2
36#define SIGALRM_MASK (1 << SIGALRM_BIT)
37
38static int signals_enabled = 1;
39static int pending = 0;
40
23void sig_handler(ARCH_SIGHDLR_PARAM) 41void sig_handler(ARCH_SIGHDLR_PARAM)
24{ 42{
25 struct sigcontext *sc; 43 struct sigcontext *sc;
44 int enabled;
45
46 /* Must be the first thing that this handler does - x86_64 stores
47 * the sigcontext in %rdx, and we need to save it before it has a
48 * chance to get trashed.
49 */
26 50
27 ARCH_GET_SIGCONTEXT(sc, sig); 51 ARCH_GET_SIGCONTEXT(sc, sig);
52
53 enabled = signals_enabled;
54 if(!enabled && (sig == SIGIO)){
55 pending |= SIGIO_MASK;
56 return;
57 }
58
59 block_signals();
60
28 CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas, 61 CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas,
29 sig, sc); 62 sig, sc);
63
64 set_signals(enabled);
30} 65}
31 66
32extern int timer_irq_inited; 67extern int timer_irq_inited;
33 68
34void alarm_handler(ARCH_SIGHDLR_PARAM) 69static void real_alarm_handler(int sig, struct sigcontext *sc)
35{ 70{
36 struct sigcontext *sc; 71 if(!timer_irq_inited){
37 72 signals_enabled = 1;
38 ARCH_GET_SIGCONTEXT(sc, sig); 73 return;
39 if(!timer_irq_inited) return; 74 }
40 75
41 if(sig == SIGALRM) 76 if(sig == SIGALRM)
42 switch_timers(0); 77 switch_timers(0);
@@ -46,6 +81,29 @@ void alarm_handler(ARCH_SIGHDLR_PARAM)
46 81
47 if(sig == SIGALRM) 82 if(sig == SIGALRM)
48 switch_timers(1); 83 switch_timers(1);
84
85}
86
87void alarm_handler(ARCH_SIGHDLR_PARAM)
88{
89 struct sigcontext *sc;
90 int enabled;
91
92 ARCH_GET_SIGCONTEXT(sc, sig);
93
94 enabled = signals_enabled;
95 if(!signals_enabled){
96 if(sig == SIGVTALRM)
97 pending |= SIGVTALRM_MASK;
98 else pending |= SIGALRM_MASK;
99
100 return;
101 }
102
103 block_signals();
104
105 real_alarm_handler(sig, sc);
106 set_signals(enabled);
49} 107}
50 108
51extern void do_boot_timer_handler(struct sigcontext * sc); 109extern void do_boot_timer_handler(struct sigcontext * sc);
@@ -53,10 +111,22 @@ extern void do_boot_timer_handler(struct sigcontext * sc);
53void boot_timer_handler(ARCH_SIGHDLR_PARAM) 111void boot_timer_handler(ARCH_SIGHDLR_PARAM)
54{ 112{
55 struct sigcontext *sc; 113 struct sigcontext *sc;
114 int enabled;
56 115
57 ARCH_GET_SIGCONTEXT(sc, sig); 116 ARCH_GET_SIGCONTEXT(sc, sig);
58 117
118 enabled = signals_enabled;
119 if(!enabled){
120 if(sig == SIGVTALRM)
121 pending |= SIGVTALRM_MASK;
122 else pending |= SIGALRM_MASK;
123 return;
124 }
125
126 block_signals();
127
59 do_boot_timer_handler(sc); 128 do_boot_timer_handler(sc);
129 set_signals(enabled);
60} 130}
61 131
62void set_sigstack(void *sig_stack, int size) 132void set_sigstack(void *sig_stack, int size)
@@ -83,6 +153,7 @@ void set_handler(int sig, void (*handler)(int), int flags, ...)
83{ 153{
84 struct sigaction action; 154 struct sigaction action;
85 va_list ap; 155 va_list ap;
156 sigset_t sig_mask;
86 int mask; 157 int mask;
87 158
88 va_start(ap, flags); 159 va_start(ap, flags);
@@ -95,7 +166,12 @@ void set_handler(int sig, void (*handler)(int), int flags, ...)
95 action.sa_flags = flags; 166 action.sa_flags = flags;
96 action.sa_restorer = NULL; 167 action.sa_restorer = NULL;
97 if(sigaction(sig, &action, NULL) < 0) 168 if(sigaction(sig, &action, NULL) < 0)
98 panic("sigaction failed"); 169 panic("sigaction failed - errno = %d\n", errno);
170
171 sigemptyset(&sig_mask);
172 sigaddset(&sig_mask, sig);
173 if(sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0)
174 panic("sigprocmask failed - errno = %d\n", errno);
99} 175}
100 176
101int change_sig(int signal, int on) 177int change_sig(int signal, int on)
@@ -108,91 +184,74 @@ int change_sig(int signal, int on)
108 return(!sigismember(&old, signal)); 184 return(!sigismember(&old, signal));
109} 185}
110 186
111/* Both here and in set/get_signal we don't touch SIGPROF, because we must not
112 * disable profiling; it's safe because the profiling code does not interact
113 * with the kernel code at all.*/
114
115static void change_signals(int type)
116{
117 sigset_t mask;
118
119 sigemptyset(&mask);
120 sigaddset(&mask, SIGVTALRM);
121 sigaddset(&mask, SIGALRM);
122 sigaddset(&mask, SIGIO);
123 if(sigprocmask(type, &mask, NULL) < 0)
124 panic("Failed to change signal mask - errno = %d", errno);
125}
126
127void block_signals(void) 187void block_signals(void)
128{ 188{
129 change_signals(SIG_BLOCK); 189 signals_enabled = 0;
130} 190}
131 191
132void unblock_signals(void) 192void unblock_signals(void)
133{ 193{
134 change_signals(SIG_UNBLOCK); 194 int save_pending;
135}
136 195
137/* These are the asynchronous signals. SIGVTALRM and SIGARLM are handled 196 if(signals_enabled == 1)
138 * together under SIGVTALRM_BIT. SIGPROF is excluded because we want to 197 return;
139 * be able to profile all of UML, not just the non-critical sections. If
140 * profiling is not thread-safe, then that is not my problem. We can disable
141 * profiling when SMP is enabled in that case.
142 */
143#define SIGIO_BIT 0
144#define SIGVTALRM_BIT 1
145
146static int enable_mask(sigset_t *mask)
147{
148 int sigs;
149 198
150 sigs = sigismember(mask, SIGIO) ? 0 : 1 << SIGIO_BIT; 199 /* We loop because the IRQ handler returns with interrupts off. So,
151 sigs |= sigismember(mask, SIGVTALRM) ? 0 : 1 << SIGVTALRM_BIT; 200 * interrupts may have arrived and we need to re-enable them and
152 sigs |= sigismember(mask, SIGALRM) ? 0 : 1 << SIGVTALRM_BIT; 201 * recheck pending.
153 return(sigs); 202 */
203 while(1){
204 /* Save and reset save_pending after enabling signals. This
205 * way, pending won't be changed while we're reading it.
206 */
207 signals_enabled = 1;
208
209 save_pending = pending;
210 if(save_pending == 0)
211 return;
212
213 pending = 0;
214
215 /* We have pending interrupts, so disable signals, as the
216 * handlers expect them off when they are called. They will
217 * be enabled again above.
218 */
219
220 signals_enabled = 0;
221
222 /* Deal with SIGIO first because the alarm handler might
223 * schedule, leaving the pending SIGIO stranded until we come
224 * back here.
225 */
226 if(save_pending & SIGIO_MASK)
227 CHOOSE_MODE_PROC(sig_handler_common_tt,
228 sig_handler_common_skas, SIGIO, NULL);
229
230 if(save_pending & SIGALRM_MASK)
231 real_alarm_handler(SIGALRM, NULL);
232
233 if(save_pending & SIGVTALRM_MASK)
234 real_alarm_handler(SIGVTALRM, NULL);
235 }
154} 236}
155 237
156int get_signals(void) 238int get_signals(void)
157{ 239{
158 sigset_t mask; 240 return signals_enabled;
159
160 if(sigprocmask(SIG_SETMASK, NULL, &mask) < 0)
161 panic("Failed to get signal mask");
162 return(enable_mask(&mask));
163} 241}
164 242
165int set_signals(int enable) 243int set_signals(int enable)
166{ 244{
167 sigset_t mask;
168 int ret; 245 int ret;
246 if(signals_enabled == enable)
247 return enable;
169 248
170 sigemptyset(&mask); 249 ret = signals_enabled;
171 if(enable & (1 << SIGIO_BIT)) 250 if(enable)
172 sigaddset(&mask, SIGIO); 251 unblock_signals();
173 if(enable & (1 << SIGVTALRM_BIT)){ 252 else block_signals();
174 sigaddset(&mask, SIGVTALRM);
175 sigaddset(&mask, SIGALRM);
176 }
177
178 /* This is safe - sigprocmask is guaranteed to copy locally the
179 * value of new_set, do his work and then, at the end, write to
180 * old_set.
181 */
182 if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0)
183 panic("Failed to enable signals");
184 ret = enable_mask(&mask);
185 sigemptyset(&mask);
186 if((enable & (1 << SIGIO_BIT)) == 0)
187 sigaddset(&mask, SIGIO);
188 if((enable & (1 << SIGVTALRM_BIT)) == 0){
189 sigaddset(&mask, SIGVTALRM);
190 sigaddset(&mask, SIGALRM);
191 }
192 if(sigprocmask(SIG_BLOCK, &mask, NULL) < 0)
193 panic("Failed to block signals");
194 253
195 return(ret); 254 return ret;
196} 255}
197 256
198void os_usr1_signal(int on) 257void os_usr1_signal(int on)
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)
diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c
index 321e1c8e227d..a9f6b26f9828 100644
--- a/arch/um/os-Linux/trap.c
+++ b/arch/um/os-Linux/trap.c
@@ -10,6 +10,7 @@
10#include "user_util.h" 10#include "user_util.h"
11#include "os.h" 11#include "os.h"
12#include "mode.h" 12#include "mode.h"
13#include "longjmp.h"
13 14
14void usr2_handler(int sig, union uml_pt_regs *regs) 15void usr2_handler(int sig, union uml_pt_regs *regs)
15{ 16{
@@ -36,5 +37,5 @@ void do_longjmp(void *b, int val)
36{ 37{
37 sigjmp_buf *buf = b; 38 sigjmp_buf *buf = b;
38 39
39 siglongjmp(*buf, val); 40 UML_SIGLONGJMP(buf, val);
40} 41}
diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c
index 38d710158c3d..166fb66995df 100644
--- a/arch/um/os-Linux/uaccess.c
+++ b/arch/um/os-Linux/uaccess.c
@@ -6,6 +6,7 @@
6 6
7#include <setjmp.h> 7#include <setjmp.h>
8#include <string.h> 8#include <string.h>
9#include "longjmp.h"
9 10
10unsigned long __do_user_copy(void *to, const void *from, int n, 11unsigned long __do_user_copy(void *to, const void *from, int n,
11 void **fault_addr, void **fault_catcher, 12 void **fault_addr, void **fault_catcher,
@@ -13,10 +14,11 @@ unsigned long __do_user_copy(void *to, const void *from, int n,
13 int n), int *faulted_out) 14 int n), int *faulted_out)
14{ 15{
15 unsigned long *faddrp = (unsigned long *) fault_addr, ret; 16 unsigned long *faddrp = (unsigned long *) fault_addr, ret;
17 int enable;
16 18
17 sigjmp_buf jbuf; 19 sigjmp_buf jbuf;
18 *fault_catcher = &jbuf; 20 *fault_catcher = &jbuf;
19 if(sigsetjmp(jbuf, 1) == 0){ 21 if(UML_SIGSETJMP(&jbuf, enable) == 0){
20 (*op)(to, from, n); 22 (*op)(to, from, n);
21 ret = 0; 23 ret = 0;
22 *faulted_out = 0; 24 *faulted_out = 0;
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
index d224434d5610..e32065e2fdc8 100644
--- a/arch/um/os-Linux/util.c
+++ b/arch/um/os-Linux/util.c
@@ -30,6 +30,7 @@
30#include "ptrace_user.h" 30#include "ptrace_user.h"
31#include "uml-config.h" 31#include "uml-config.h"
32#include "os.h" 32#include "os.h"
33#include "longjmp.h"
33 34
34void stack_protections(unsigned long address) 35void stack_protections(unsigned long address)
35{ 36{