diff options
| author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-03-11 12:47:28 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-03-11 12:47:28 -0400 |
| commit | baadac8b10c5ac15ce3d26b68fa266c8889b163f (patch) | |
| tree | 8ab1c758f8b2fe21351102d9845c0f8ec81a52cf /arch/x86/kernel/signal_64.c | |
| parent | 051a82fc0c450f6ca649acf684586477aa6d5c6a (diff) | |
| parent | 985a34bd75cc8c96e43f00dcdda7c3fdb51a3026 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86:
x86: remove quicklists
x86: ia32 syscall restart fix
x86: ioremap, remove WARN_ON()
Diffstat (limited to 'arch/x86/kernel/signal_64.c')
| -rw-r--r-- | arch/x86/kernel/signal_64.c | 38 |
1 files changed, 33 insertions, 5 deletions
diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c index 56b72fb67f9b..1c83e5124c65 100644 --- a/arch/x86/kernel/signal_64.c +++ b/arch/x86/kernel/signal_64.c | |||
| @@ -311,6 +311,35 @@ give_sigsegv: | |||
| 311 | } | 311 | } |
| 312 | 312 | ||
| 313 | /* | 313 | /* |
| 314 | * Return -1L or the syscall number that @regs is executing. | ||
| 315 | */ | ||
| 316 | static long current_syscall(struct pt_regs *regs) | ||
| 317 | { | ||
| 318 | /* | ||
| 319 | * We always sign-extend a -1 value being set here, | ||
| 320 | * so this is always either -1L or a syscall number. | ||
| 321 | */ | ||
| 322 | return regs->orig_ax; | ||
| 323 | } | ||
| 324 | |||
| 325 | /* | ||
| 326 | * Return a value that is -EFOO if the system call in @regs->orig_ax | ||
| 327 | * returned an error. This only works for @regs from @current. | ||
| 328 | */ | ||
| 329 | static long current_syscall_ret(struct pt_regs *regs) | ||
| 330 | { | ||
| 331 | #ifdef CONFIG_IA32_EMULATION | ||
| 332 | if (test_thread_flag(TIF_IA32)) | ||
| 333 | /* | ||
| 334 | * Sign-extend the value so (int)-EFOO becomes (long)-EFOO | ||
| 335 | * and will match correctly in comparisons. | ||
| 336 | */ | ||
| 337 | return (int) regs->ax; | ||
| 338 | #endif | ||
| 339 | return regs->ax; | ||
| 340 | } | ||
| 341 | |||
| 342 | /* | ||
| 314 | * OK, we're invoking a handler | 343 | * OK, we're invoking a handler |
| 315 | */ | 344 | */ |
| 316 | 345 | ||
| @@ -327,9 +356,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
| 327 | #endif | 356 | #endif |
| 328 | 357 | ||
| 329 | /* Are we from a system call? */ | 358 | /* Are we from a system call? */ |
| 330 | if ((long)regs->orig_ax >= 0) { | 359 | if (current_syscall(regs) >= 0) { |
| 331 | /* If so, check system call restarting.. */ | 360 | /* If so, check system call restarting.. */ |
| 332 | switch (regs->ax) { | 361 | switch (current_syscall_ret(regs)) { |
| 333 | case -ERESTART_RESTARTBLOCK: | 362 | case -ERESTART_RESTARTBLOCK: |
| 334 | case -ERESTARTNOHAND: | 363 | case -ERESTARTNOHAND: |
| 335 | regs->ax = -EINTR; | 364 | regs->ax = -EINTR; |
| @@ -426,10 +455,9 @@ static void do_signal(struct pt_regs *regs) | |||
| 426 | } | 455 | } |
| 427 | 456 | ||
| 428 | /* Did we come from a system call? */ | 457 | /* Did we come from a system call? */ |
| 429 | if ((long)regs->orig_ax >= 0) { | 458 | if (current_syscall(regs) >= 0) { |
| 430 | /* Restart the system call - no handlers present */ | 459 | /* Restart the system call - no handlers present */ |
| 431 | long res = regs->ax; | 460 | switch (current_syscall_ret(regs)) { |
| 432 | switch (res) { | ||
| 433 | case -ERESTARTNOHAND: | 461 | case -ERESTARTNOHAND: |
| 434 | case -ERESTARTSYS: | 462 | case -ERESTARTSYS: |
| 435 | case -ERESTARTNOINTR: | 463 | case -ERESTARTNOINTR: |
