Commit 624f7979058b84cbf81c76d45f302ce757b213ca
1 parent
afd7cd92
Make signal queues per thread.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4635 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
204 additions
and
173 deletions
linux-user/main.c
| ... | ... | @@ -230,7 +230,7 @@ void cpu_loop(CPUX86State *env) |
| 230 | 230 | info.si_errno = 0; |
| 231 | 231 | info.si_code = TARGET_SI_KERNEL; |
| 232 | 232 | info._sifields._sigfault._addr = 0; |
| 233 | - queue_signal(info.si_signo, &info); | |
| 233 | + queue_signal(env, info.si_signo, &info); | |
| 234 | 234 | break; |
| 235 | 235 | case EXCP0D_GPF: |
| 236 | 236 | /* XXX: potential problem if ABI32 */ |
| ... | ... | @@ -244,7 +244,7 @@ void cpu_loop(CPUX86State *env) |
| 244 | 244 | info.si_errno = 0; |
| 245 | 245 | info.si_code = TARGET_SI_KERNEL; |
| 246 | 246 | info._sifields._sigfault._addr = 0; |
| 247 | - queue_signal(info.si_signo, &info); | |
| 247 | + queue_signal(env, info.si_signo, &info); | |
| 248 | 248 | } |
| 249 | 249 | break; |
| 250 | 250 | case EXCP0E_PAGE: |
| ... | ... | @@ -255,7 +255,7 @@ void cpu_loop(CPUX86State *env) |
| 255 | 255 | else |
| 256 | 256 | info.si_code = TARGET_SEGV_ACCERR; |
| 257 | 257 | info._sifields._sigfault._addr = env->cr[2]; |
| 258 | - queue_signal(info.si_signo, &info); | |
| 258 | + queue_signal(env, info.si_signo, &info); | |
| 259 | 259 | break; |
| 260 | 260 | case EXCP00_DIVZ: |
| 261 | 261 | #ifndef TARGET_X86_64 |
| ... | ... | @@ -269,7 +269,7 @@ void cpu_loop(CPUX86State *env) |
| 269 | 269 | info.si_errno = 0; |
| 270 | 270 | info.si_code = TARGET_FPE_INTDIV; |
| 271 | 271 | info._sifields._sigfault._addr = env->eip; |
| 272 | - queue_signal(info.si_signo, &info); | |
| 272 | + queue_signal(env, info.si_signo, &info); | |
| 273 | 273 | } |
| 274 | 274 | break; |
| 275 | 275 | case EXCP01_SSTP: |
| ... | ... | @@ -289,7 +289,7 @@ void cpu_loop(CPUX86State *env) |
| 289 | 289 | info.si_code = TARGET_SI_KERNEL; |
| 290 | 290 | info._sifields._sigfault._addr = 0; |
| 291 | 291 | } |
| 292 | - queue_signal(info.si_signo, &info); | |
| 292 | + queue_signal(env, info.si_signo, &info); | |
| 293 | 293 | } |
| 294 | 294 | break; |
| 295 | 295 | case EXCP04_INTO: |
| ... | ... | @@ -304,7 +304,7 @@ void cpu_loop(CPUX86State *env) |
| 304 | 304 | info.si_errno = 0; |
| 305 | 305 | info.si_code = TARGET_SI_KERNEL; |
| 306 | 306 | info._sifields._sigfault._addr = 0; |
| 307 | - queue_signal(info.si_signo, &info); | |
| 307 | + queue_signal(env, info.si_signo, &info); | |
| 308 | 308 | } |
| 309 | 309 | break; |
| 310 | 310 | case EXCP06_ILLOP: |
| ... | ... | @@ -312,7 +312,7 @@ void cpu_loop(CPUX86State *env) |
| 312 | 312 | info.si_errno = 0; |
| 313 | 313 | info.si_code = TARGET_ILL_ILLOPN; |
| 314 | 314 | info._sifields._sigfault._addr = env->eip; |
| 315 | - queue_signal(info.si_signo, &info); | |
| 315 | + queue_signal(env, info.si_signo, &info); | |
| 316 | 316 | break; |
| 317 | 317 | case EXCP_INTERRUPT: |
| 318 | 318 | /* just indicate that signals should be handled asap */ |
| ... | ... | @@ -327,7 +327,7 @@ void cpu_loop(CPUX86State *env) |
| 327 | 327 | info.si_signo = sig; |
| 328 | 328 | info.si_errno = 0; |
| 329 | 329 | info.si_code = TARGET_TRAP_BRKPT; |
| 330 | - queue_signal(info.si_signo, &info); | |
| 330 | + queue_signal(env, info.si_signo, &info); | |
| 331 | 331 | } |
| 332 | 332 | } |
| 333 | 333 | break; |
| ... | ... | @@ -441,7 +441,7 @@ void cpu_loop(CPUARMState *env) |
| 441 | 441 | info.si_errno = 0; |
| 442 | 442 | info.si_code = TARGET_ILL_ILLOPN; |
| 443 | 443 | info._sifields._sigfault._addr = env->regs[15]; |
| 444 | - queue_signal(info.si_signo, &info); | |
| 444 | + queue_signal(env, info.si_signo, &info); | |
| 445 | 445 | } else if (rc < 0) { /* FP exception */ |
| 446 | 446 | int arm_fpe=0; |
| 447 | 447 | |
| ... | ... | @@ -472,7 +472,7 @@ void cpu_loop(CPUARMState *env) |
| 472 | 472 | if (arm_fpe & BIT_IOC) info.si_code = TARGET_FPE_FLTINV; |
| 473 | 473 | |
| 474 | 474 | info._sifields._sigfault._addr = env->regs[15]; |
| 475 | - queue_signal(info.si_signo, &info); | |
| 475 | + queue_signal(env, info.si_signo, &info); | |
| 476 | 476 | } else { |
| 477 | 477 | env->regs[15] += 4; |
| 478 | 478 | } |
| ... | ... | @@ -584,7 +584,7 @@ void cpu_loop(CPUARMState *env) |
| 584 | 584 | /* XXX: check env->error_code */ |
| 585 | 585 | info.si_code = TARGET_SEGV_MAPERR; |
| 586 | 586 | info._sifields._sigfault._addr = addr; |
| 587 | - queue_signal(info.si_signo, &info); | |
| 587 | + queue_signal(env, info.si_signo, &info); | |
| 588 | 588 | } |
| 589 | 589 | break; |
| 590 | 590 | case EXCP_DEBUG: |
| ... | ... | @@ -597,7 +597,7 @@ void cpu_loop(CPUARMState *env) |
| 597 | 597 | info.si_signo = sig; |
| 598 | 598 | info.si_errno = 0; |
| 599 | 599 | info.si_code = TARGET_TRAP_BRKPT; |
| 600 | - queue_signal(info.si_signo, &info); | |
| 600 | + queue_signal(env, info.si_signo, &info); | |
| 601 | 601 | } |
| 602 | 602 | } |
| 603 | 603 | break; |
| ... | ... | @@ -780,7 +780,7 @@ void cpu_loop (CPUSPARCState *env) |
| 780 | 780 | /* XXX: check env->error_code */ |
| 781 | 781 | info.si_code = TARGET_SEGV_MAPERR; |
| 782 | 782 | info._sifields._sigfault._addr = env->mmuregs[4]; |
| 783 | - queue_signal(info.si_signo, &info); | |
| 783 | + queue_signal(env, info.si_signo, &info); | |
| 784 | 784 | } |
| 785 | 785 | break; |
| 786 | 786 | #else |
| ... | ... | @@ -801,7 +801,7 @@ void cpu_loop (CPUSPARCState *env) |
| 801 | 801 | info._sifields._sigfault._addr = env->dmmuregs[4]; |
| 802 | 802 | else |
| 803 | 803 | info._sifields._sigfault._addr = env->tsptr->tpc; |
| 804 | - queue_signal(info.si_signo, &info); | |
| 804 | + queue_signal(env, info.si_signo, &info); | |
| 805 | 805 | } |
| 806 | 806 | break; |
| 807 | 807 | #ifndef TARGET_ABI32 |
| ... | ... | @@ -828,7 +828,7 @@ void cpu_loop (CPUSPARCState *env) |
| 828 | 828 | info.si_signo = sig; |
| 829 | 829 | info.si_errno = 0; |
| 830 | 830 | info.si_code = TARGET_TRAP_BRKPT; |
| 831 | - queue_signal(info.si_signo, &info); | |
| 831 | + queue_signal(env, info.si_signo, &info); | |
| 832 | 832 | } |
| 833 | 833 | } |
| 834 | 834 | break; |
| ... | ... | @@ -949,7 +949,7 @@ void cpu_loop(CPUPPCState *env) |
| 949 | 949 | break; |
| 950 | 950 | } |
| 951 | 951 | info._sifields._sigfault._addr = env->nip; |
| 952 | - queue_signal(info.si_signo, &info); | |
| 952 | + queue_signal(env, info.si_signo, &info); | |
| 953 | 953 | break; |
| 954 | 954 | case POWERPC_EXCP_ISI: /* Instruction storage exception */ |
| 955 | 955 | EXCP_DUMP(env, "Invalid instruction fetch: 0x\n" ADDRX "\n", |
| ... | ... | @@ -977,7 +977,7 @@ void cpu_loop(CPUPPCState *env) |
| 977 | 977 | break; |
| 978 | 978 | } |
| 979 | 979 | info._sifields._sigfault._addr = env->nip - 4; |
| 980 | - queue_signal(info.si_signo, &info); | |
| 980 | + queue_signal(env, info.si_signo, &info); | |
| 981 | 981 | break; |
| 982 | 982 | case POWERPC_EXCP_EXTERNAL: /* External input */ |
| 983 | 983 | cpu_abort(env, "External interrupt while in user mode. " |
| ... | ... | @@ -990,7 +990,7 @@ void cpu_loop(CPUPPCState *env) |
| 990 | 990 | info.si_errno = 0; |
| 991 | 991 | info.si_code = TARGET_BUS_ADRALN; |
| 992 | 992 | info._sifields._sigfault._addr = env->nip - 4; |
| 993 | - queue_signal(info.si_signo, &info); | |
| 993 | + queue_signal(env, info.si_signo, &info); | |
| 994 | 994 | break; |
| 995 | 995 | case POWERPC_EXCP_PROGRAM: /* Program exception */ |
| 996 | 996 | /* XXX: check this */ |
| ... | ... | @@ -1083,7 +1083,7 @@ void cpu_loop(CPUPPCState *env) |
| 1083 | 1083 | break; |
| 1084 | 1084 | } |
| 1085 | 1085 | info._sifields._sigfault._addr = env->nip - 4; |
| 1086 | - queue_signal(info.si_signo, &info); | |
| 1086 | + queue_signal(env, info.si_signo, &info); | |
| 1087 | 1087 | break; |
| 1088 | 1088 | case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ |
| 1089 | 1089 | EXCP_DUMP(env, "No floating point allowed\n"); |
| ... | ... | @@ -1091,7 +1091,7 @@ void cpu_loop(CPUPPCState *env) |
| 1091 | 1091 | info.si_errno = 0; |
| 1092 | 1092 | info.si_code = TARGET_ILL_COPROC; |
| 1093 | 1093 | info._sifields._sigfault._addr = env->nip - 4; |
| 1094 | - queue_signal(info.si_signo, &info); | |
| 1094 | + queue_signal(env, info.si_signo, &info); | |
| 1095 | 1095 | break; |
| 1096 | 1096 | case POWERPC_EXCP_SYSCALL: /* System call exception */ |
| 1097 | 1097 | cpu_abort(env, "Syscall exception while in user mode. " |
| ... | ... | @@ -1103,7 +1103,7 @@ void cpu_loop(CPUPPCState *env) |
| 1103 | 1103 | info.si_errno = 0; |
| 1104 | 1104 | info.si_code = TARGET_ILL_COPROC; |
| 1105 | 1105 | info._sifields._sigfault._addr = env->nip - 4; |
| 1106 | - queue_signal(info.si_signo, &info); | |
| 1106 | + queue_signal(env, info.si_signo, &info); | |
| 1107 | 1107 | break; |
| 1108 | 1108 | case POWERPC_EXCP_DECR: /* Decrementer exception */ |
| 1109 | 1109 | cpu_abort(env, "Decrementer interrupt while in user mode. " |
| ... | ... | @@ -1135,7 +1135,7 @@ void cpu_loop(CPUPPCState *env) |
| 1135 | 1135 | info.si_signo = sig; |
| 1136 | 1136 | info.si_errno = 0; |
| 1137 | 1137 | info.si_code = TARGET_TRAP_BRKPT; |
| 1138 | - queue_signal(info.si_signo, &info); | |
| 1138 | + queue_signal(env, info.si_signo, &info); | |
| 1139 | 1139 | } |
| 1140 | 1140 | } |
| 1141 | 1141 | break; |
| ... | ... | @@ -1145,7 +1145,7 @@ void cpu_loop(CPUPPCState *env) |
| 1145 | 1145 | info.si_errno = 0; |
| 1146 | 1146 | info.si_code = TARGET_ILL_COPROC; |
| 1147 | 1147 | info._sifields._sigfault._addr = env->nip - 4; |
| 1148 | - queue_signal(info.si_signo, &info); | |
| 1148 | + queue_signal(env, info.si_signo, &info); | |
| 1149 | 1149 | break; |
| 1150 | 1150 | case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */ |
| 1151 | 1151 | cpu_abort(env, "Embedded floating-point data IRQ not handled\n"); |
| ... | ... | @@ -1209,7 +1209,7 @@ void cpu_loop(CPUPPCState *env) |
| 1209 | 1209 | info.si_errno = 0; |
| 1210 | 1210 | info.si_code = TARGET_ILL_COPROC; |
| 1211 | 1211 | info._sifields._sigfault._addr = env->nip - 4; |
| 1212 | - queue_signal(info.si_signo, &info); | |
| 1212 | + queue_signal(env, info.si_signo, &info); | |
| 1213 | 1213 | break; |
| 1214 | 1214 | case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */ |
| 1215 | 1215 | cpu_abort(env, "Programable interval timer interrupt " |
| ... | ... | @@ -1685,7 +1685,7 @@ void cpu_loop(CPUMIPSState *env) |
| 1685 | 1685 | info.si_signo = TARGET_SIGILL; |
| 1686 | 1686 | info.si_errno = 0; |
| 1687 | 1687 | info.si_code = 0; |
| 1688 | - queue_signal(info.si_signo, &info); | |
| 1688 | + queue_signal(env, info.si_signo, &info); | |
| 1689 | 1689 | break; |
| 1690 | 1690 | case EXCP_INTERRUPT: |
| 1691 | 1691 | /* just indicate that signals should be handled asap */ |
| ... | ... | @@ -1700,7 +1700,7 @@ void cpu_loop(CPUMIPSState *env) |
| 1700 | 1700 | info.si_signo = sig; |
| 1701 | 1701 | info.si_errno = 0; |
| 1702 | 1702 | info.si_code = TARGET_TRAP_BRKPT; |
| 1703 | - queue_signal(info.si_signo, &info); | |
| 1703 | + queue_signal(env, info.si_signo, &info); | |
| 1704 | 1704 | } |
| 1705 | 1705 | } |
| 1706 | 1706 | break; |
| ... | ... | @@ -1751,7 +1751,7 @@ void cpu_loop (CPUState *env) |
| 1751 | 1751 | info.si_signo = sig; |
| 1752 | 1752 | info.si_errno = 0; |
| 1753 | 1753 | info.si_code = TARGET_TRAP_BRKPT; |
| 1754 | - queue_signal(info.si_signo, &info); | |
| 1754 | + queue_signal(env, info.si_signo, &info); | |
| 1755 | 1755 | } |
| 1756 | 1756 | } |
| 1757 | 1757 | break; |
| ... | ... | @@ -1761,7 +1761,7 @@ void cpu_loop (CPUState *env) |
| 1761 | 1761 | info.si_errno = 0; |
| 1762 | 1762 | info.si_code = TARGET_SEGV_MAPERR; |
| 1763 | 1763 | info._sifields._sigfault._addr = env->tea; |
| 1764 | - queue_signal(info.si_signo, &info); | |
| 1764 | + queue_signal(env, info.si_signo, &info); | |
| 1765 | 1765 | break; |
| 1766 | 1766 | |
| 1767 | 1767 | default: |
| ... | ... | @@ -1790,7 +1790,7 @@ void cpu_loop (CPUState *env) |
| 1790 | 1790 | /* XXX: check env->error_code */ |
| 1791 | 1791 | info.si_code = TARGET_SEGV_MAPERR; |
| 1792 | 1792 | info._sifields._sigfault._addr = env->pregs[PR_EDA]; |
| 1793 | - queue_signal(info.si_signo, &info); | |
| 1793 | + queue_signal(env, info.si_signo, &info); | |
| 1794 | 1794 | } |
| 1795 | 1795 | break; |
| 1796 | 1796 | case EXCP_INTERRUPT: |
| ... | ... | @@ -1818,7 +1818,7 @@ void cpu_loop (CPUState *env) |
| 1818 | 1818 | info.si_signo = sig; |
| 1819 | 1819 | info.si_errno = 0; |
| 1820 | 1820 | info.si_code = TARGET_TRAP_BRKPT; |
| 1821 | - queue_signal(info.si_signo, &info); | |
| 1821 | + queue_signal(env, info.si_signo, &info); | |
| 1822 | 1822 | } |
| 1823 | 1823 | } |
| 1824 | 1824 | break; |
| ... | ... | @@ -1869,7 +1869,7 @@ void cpu_loop(CPUM68KState *env) |
| 1869 | 1869 | info.si_errno = 0; |
| 1870 | 1870 | info.si_code = TARGET_ILL_ILLOPN; |
| 1871 | 1871 | info._sifields._sigfault._addr = env->pc; |
| 1872 | - queue_signal(info.si_signo, &info); | |
| 1872 | + queue_signal(env, info.si_signo, &info); | |
| 1873 | 1873 | break; |
| 1874 | 1874 | case EXCP_TRAP0: |
| 1875 | 1875 | { |
| ... | ... | @@ -1896,7 +1896,7 @@ void cpu_loop(CPUM68KState *env) |
| 1896 | 1896 | /* XXX: check env->error_code */ |
| 1897 | 1897 | info.si_code = TARGET_SEGV_MAPERR; |
| 1898 | 1898 | info._sifields._sigfault._addr = env->mmu.ar; |
| 1899 | - queue_signal(info.si_signo, &info); | |
| 1899 | + queue_signal(env, info.si_signo, &info); | |
| 1900 | 1900 | } |
| 1901 | 1901 | break; |
| 1902 | 1902 | case EXCP_DEBUG: |
| ... | ... | @@ -1909,7 +1909,7 @@ void cpu_loop(CPUM68KState *env) |
| 1909 | 1909 | info.si_signo = sig; |
| 1910 | 1910 | info.si_errno = 0; |
| 1911 | 1911 | info.si_code = TARGET_TRAP_BRKPT; |
| 1912 | - queue_signal(info.si_signo, &info); | |
| 1912 | + queue_signal(env, info.si_signo, &info); | |
| 1913 | 1913 | } |
| 1914 | 1914 | } |
| 1915 | 1915 | break; |
| ... | ... | @@ -2000,7 +2000,7 @@ void cpu_loop (CPUState *env) |
| 2000 | 2000 | info.si_signo = sig; |
| 2001 | 2001 | info.si_errno = 0; |
| 2002 | 2002 | info.si_code = TARGET_TRAP_BRKPT; |
| 2003 | - queue_signal(info.si_signo, &info); | |
| 2003 | + queue_signal(env, info.si_signo, &info); | |
| 2004 | 2004 | } |
| 2005 | 2005 | } |
| 2006 | 2006 | break; |
| ... | ... | @@ -2047,9 +2047,19 @@ void usage(void) |
| 2047 | 2047 | /* XXX: currently only used for async signals (see signal.c) */ |
| 2048 | 2048 | CPUState *global_env; |
| 2049 | 2049 | |
| 2050 | -/* used to free thread contexts */ | |
| 2051 | -TaskState *first_task_state; | |
| 2052 | - | |
| 2050 | +void init_task_state(TaskState *ts) | |
| 2051 | +{ | |
| 2052 | + int i; | |
| 2053 | + | |
| 2054 | + memset(ts, 0, sizeof(TaskState)); | |
| 2055 | + ts->used = 1; | |
| 2056 | + ts->first_free = ts->sigqueue_table; | |
| 2057 | + for (i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++) { | |
| 2058 | + ts->sigqueue_table[i].next = &ts->sigqueue_table[i + 1]; | |
| 2059 | + } | |
| 2060 | + ts->sigqueue_table[i].next = NULL; | |
| 2061 | +} | |
| 2062 | + | |
| 2053 | 2063 | int main(int argc, char **argv) |
| 2054 | 2064 | { |
| 2055 | 2065 | const char *filename; |
| ... | ... | @@ -2246,9 +2256,9 @@ int main(int argc, char **argv) |
| 2246 | 2256 | |
| 2247 | 2257 | /* build Task State */ |
| 2248 | 2258 | memset(ts, 0, sizeof(TaskState)); |
| 2249 | - env->opaque = ts; | |
| 2250 | - ts->used = 1; | |
| 2259 | + init_task_state(ts); | |
| 2251 | 2260 | ts->info = info; |
| 2261 | + env->opaque = ts; | |
| 2252 | 2262 | env->user_mode_only = 1; |
| 2253 | 2263 | |
| 2254 | 2264 | #if defined(TARGET_I386) | ... | ... |
linux-user/qemu.h
| ... | ... | @@ -82,6 +82,20 @@ struct vm86_saved_state { |
| 82 | 82 | #include "nwfpe/fpa11.h" |
| 83 | 83 | #endif |
| 84 | 84 | |
| 85 | +#define MAX_SIGQUEUE_SIZE 1024 | |
| 86 | + | |
| 87 | +struct sigqueue { | |
| 88 | + struct sigqueue *next; | |
| 89 | + target_siginfo_t info; | |
| 90 | +}; | |
| 91 | + | |
| 92 | +struct emulated_sigtable { | |
| 93 | + int pending; /* true if signal is pending */ | |
| 94 | + struct sigqueue *first; | |
| 95 | + struct sigqueue info; /* in order to always have memory for the | |
| 96 | + first signal, we put it here */ | |
| 97 | +}; | |
| 98 | + | |
| 85 | 99 | /* NOTE: we force a big alignment so that the stack stored after is |
| 86 | 100 | aligned too */ |
| 87 | 101 | typedef struct TaskState { |
| ... | ... | @@ -109,10 +123,16 @@ typedef struct TaskState { |
| 109 | 123 | #endif |
| 110 | 124 | int used; /* non zero if used */ |
| 111 | 125 | struct image_info *info; |
| 126 | + | |
| 127 | + struct emulated_sigtable sigtab[TARGET_NSIG]; | |
| 128 | + struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */ | |
| 129 | + struct sigqueue *first_free; /* first free siginfo queue entry */ | |
| 130 | + int signal_pending; /* non zero if a signal may be pending */ | |
| 131 | + | |
| 112 | 132 | uint8_t stack[0]; |
| 113 | 133 | } __attribute__((aligned(16))) TaskState; |
| 114 | 134 | |
| 115 | -extern TaskState *first_task_state; | |
| 135 | +void init_task_state(TaskState *ts); | |
| 116 | 136 | extern const char *qemu_uname_release; |
| 117 | 137 | |
| 118 | 138 | /* ??? See if we can avoid exposing so much of the loader internals. */ |
| ... | ... | @@ -182,9 +202,9 @@ void print_syscall_ret(int num, abi_long arg1); |
| 182 | 202 | extern int do_strace; |
| 183 | 203 | |
| 184 | 204 | /* signal.c */ |
| 185 | -void process_pending_signals(void *cpu_env); | |
| 205 | +void process_pending_signals(CPUState *cpu_env); | |
| 186 | 206 | void signal_init(void); |
| 187 | -int queue_signal(int sig, target_siginfo_t *info); | |
| 207 | +int queue_signal(CPUState *env, int sig, target_siginfo_t *info); | |
| 188 | 208 | void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info); |
| 189 | 209 | void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo); |
| 190 | 210 | int target_to_host_signal(int sig); | ... | ... |
linux-user/signal.c
| ... | ... | @@ -31,31 +31,13 @@ |
| 31 | 31 | |
| 32 | 32 | //#define DEBUG_SIGNAL |
| 33 | 33 | |
| 34 | -#define MAX_SIGQUEUE_SIZE 1024 | |
| 35 | - | |
| 36 | -struct sigqueue { | |
| 37 | - struct sigqueue *next; | |
| 38 | - target_siginfo_t info; | |
| 39 | -}; | |
| 40 | - | |
| 41 | -struct emulated_sigaction { | |
| 42 | - struct target_sigaction sa; | |
| 43 | - int pending; /* true if signal is pending */ | |
| 44 | - struct sigqueue *first; | |
| 45 | - struct sigqueue info; /* in order to always have memory for the | |
| 46 | - first signal, we put it here */ | |
| 47 | -}; | |
| 48 | - | |
| 49 | 34 | struct target_sigaltstack target_sigaltstack_used = { |
| 50 | 35 | .ss_sp = 0, |
| 51 | 36 | .ss_size = 0, |
| 52 | 37 | .ss_flags = TARGET_SS_DISABLE, |
| 53 | 38 | }; |
| 54 | 39 | |
| 55 | -static struct emulated_sigaction sigact_table[TARGET_NSIG]; | |
| 56 | -static struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */ | |
| 57 | -static struct sigqueue *first_free; /* first free siginfo queue entry */ | |
| 58 | -static int signal_pending; /* non zero if a signal may be pending */ | |
| 40 | +static struct target_sigaction sigact_table[TARGET_NSIG]; | |
| 59 | 41 | |
| 60 | 42 | static void host_signal_handler(int host_signum, siginfo_t *info, |
| 61 | 43 | void *puc); |
| ... | ... | @@ -96,6 +78,12 @@ static uint8_t host_to_target_signal_table[65] = { |
| 96 | 78 | [SIGPWR] = TARGET_SIGPWR, |
| 97 | 79 | [SIGSYS] = TARGET_SIGSYS, |
| 98 | 80 | /* next signals stay the same */ |
| 81 | + /* Nasty hack: Reverse SIGRTMIN and SIGRTMAX to avoid overlap with | |
| 82 | + host libpthread signals. This assumes noone actually uses SIGRTMAX :-/ | |
| 83 | + To fix this properly we need to do manual signal delivery multiplexed | |
| 84 | + over a single host signal. */ | |
| 85 | + [__SIGRTMIN] = __SIGRTMAX, | |
| 86 | + [__SIGRTMAX] = __SIGRTMIN, | |
| 99 | 87 | }; |
| 100 | 88 | static uint8_t target_to_host_signal_table[65]; |
| 101 | 89 | |
| ... | ... | @@ -278,7 +266,9 @@ void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo) |
| 278 | 266 | void signal_init(void) |
| 279 | 267 | { |
| 280 | 268 | struct sigaction act; |
| 269 | + struct sigaction oact; | |
| 281 | 270 | int i, j; |
| 271 | + int host_sig; | |
| 282 | 272 | |
| 283 | 273 | /* generate signal conversion tables */ |
| 284 | 274 | for(i = 1; i <= 64; i++) { |
| ... | ... | @@ -292,36 +282,45 @@ void signal_init(void) |
| 292 | 282 | |
| 293 | 283 | /* set all host signal handlers. ALL signals are blocked during |
| 294 | 284 | the handlers to serialize them. */ |
| 285 | + memset(sigact_table, 0, sizeof(sigact_table)); | |
| 286 | + | |
| 295 | 287 | sigfillset(&act.sa_mask); |
| 296 | 288 | act.sa_flags = SA_SIGINFO; |
| 297 | 289 | act.sa_sigaction = host_signal_handler; |
| 298 | - for(i = 1; i < NSIG; i++) { | |
| 299 | - sigaction(i, &act, NULL); | |
| 290 | + for(i = 1; i <= TARGET_NSIG; i++) { | |
| 291 | + host_sig = target_to_host_signal(i); | |
| 292 | + sigaction(host_sig, NULL, &oact); | |
| 293 | + if (oact.sa_sigaction == (void *)SIG_IGN) { | |
| 294 | + sigact_table[i - 1]._sa_handler = TARGET_SIG_IGN; | |
| 295 | + } else if (oact.sa_sigaction == (void *)SIG_DFL) { | |
| 296 | + sigact_table[i - 1]._sa_handler = TARGET_SIG_DFL; | |
| 297 | + } | |
| 298 | + /* If there's already a handler installed then something has | |
| 299 | + gone horribly wrong, so don't even try to handle that case. */ | |
| 300 | + /* Install some handlers for our own use. */ | |
| 301 | + if (host_sig == SIGSEGV || host_sig == SIGBUS) { | |
| 302 | + sigaction(host_sig, &act, NULL); | |
| 303 | + } | |
| 300 | 304 | } |
| 301 | - | |
| 302 | - memset(sigact_table, 0, sizeof(sigact_table)); | |
| 303 | - | |
| 304 | - first_free = &sigqueue_table[0]; | |
| 305 | - for(i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++) | |
| 306 | - sigqueue_table[i].next = &sigqueue_table[i + 1]; | |
| 307 | - sigqueue_table[MAX_SIGQUEUE_SIZE - 1].next = NULL; | |
| 308 | 305 | } |
| 309 | 306 | |
| 310 | 307 | /* signal queue handling */ |
| 311 | 308 | |
| 312 | -static inline struct sigqueue *alloc_sigqueue(void) | |
| 309 | +static inline struct sigqueue *alloc_sigqueue(CPUState *env) | |
| 313 | 310 | { |
| 314 | - struct sigqueue *q = first_free; | |
| 311 | + TaskState *ts = env->opaque; | |
| 312 | + struct sigqueue *q = ts->first_free; | |
| 315 | 313 | if (!q) |
| 316 | 314 | return NULL; |
| 317 | - first_free = q->next; | |
| 315 | + ts->first_free = q->next; | |
| 318 | 316 | return q; |
| 319 | 317 | } |
| 320 | 318 | |
| 321 | -static inline void free_sigqueue(struct sigqueue *q) | |
| 319 | +static inline void free_sigqueue(CPUState *env, struct sigqueue *q) | |
| 322 | 320 | { |
| 323 | - q->next = first_free; | |
| 324 | - first_free = q; | |
| 321 | + TaskState *ts = env->opaque; | |
| 322 | + q->next = ts->first_free; | |
| 323 | + ts->first_free = q; | |
| 325 | 324 | } |
| 326 | 325 | |
| 327 | 326 | /* abort execution with signal */ |
| ... | ... | @@ -347,9 +346,10 @@ void __attribute((noreturn)) force_sig(int sig) |
| 347 | 346 | |
| 348 | 347 | /* queue a signal so that it will be send to the virtual CPU as soon |
| 349 | 348 | as possible */ |
| 350 | -int queue_signal(int sig, target_siginfo_t *info) | |
| 349 | +int queue_signal(CPUState *env, int sig, target_siginfo_t *info) | |
| 351 | 350 | { |
| 352 | - struct emulated_sigaction *k; | |
| 351 | + TaskState *ts = env->opaque; | |
| 352 | + struct emulated_sigtable *k; | |
| 353 | 353 | struct sigqueue *q, **pq; |
| 354 | 354 | abi_ulong handler; |
| 355 | 355 | |
| ... | ... | @@ -357,8 +357,8 @@ int queue_signal(int sig, target_siginfo_t *info) |
| 357 | 357 | fprintf(stderr, "queue_signal: sig=%d\n", |
| 358 | 358 | sig); |
| 359 | 359 | #endif |
| 360 | - k = &sigact_table[sig - 1]; | |
| 361 | - handler = k->sa._sa_handler; | |
| 360 | + k = &ts->sigtab[sig - 1]; | |
| 361 | + handler = sigact_table[sig - 1]._sa_handler; | |
| 362 | 362 | if (handler == TARGET_SIG_DFL) { |
| 363 | 363 | /* default handler : ignore some signal. The other are fatal */ |
| 364 | 364 | if (sig != TARGET_SIGCHLD && |
| ... | ... | @@ -386,7 +386,7 @@ int queue_signal(int sig, target_siginfo_t *info) |
| 386 | 386 | /* first signal */ |
| 387 | 387 | q = &k->info; |
| 388 | 388 | } else { |
| 389 | - q = alloc_sigqueue(); | |
| 389 | + q = alloc_sigqueue(env); | |
| 390 | 390 | if (!q) |
| 391 | 391 | return -EAGAIN; |
| 392 | 392 | while (*pq != NULL) |
| ... | ... | @@ -398,7 +398,7 @@ int queue_signal(int sig, target_siginfo_t *info) |
| 398 | 398 | q->next = NULL; |
| 399 | 399 | k->pending = 1; |
| 400 | 400 | /* signal that a new signal is pending */ |
| 401 | - signal_pending = 1; | |
| 401 | + ts->signal_pending = 1; | |
| 402 | 402 | return 1; /* indicates that the signal was queued */ |
| 403 | 403 | } |
| 404 | 404 | } |
| ... | ... | @@ -424,7 +424,7 @@ static void host_signal_handler(int host_signum, siginfo_t *info, |
| 424 | 424 | fprintf(stderr, "qemu: got signal %d\n", sig); |
| 425 | 425 | #endif |
| 426 | 426 | host_to_target_siginfo_noswap(&tinfo, info); |
| 427 | - if (queue_signal(sig, &tinfo) == 1) { | |
| 427 | + if (queue_signal(global_env, sig, &tinfo) == 1) { | |
| 428 | 428 | /* interrupt the virtual CPU as soon as possible */ |
| 429 | 429 | cpu_interrupt(global_env, CPU_INTERRUPT_EXIT); |
| 430 | 430 | } |
| ... | ... | @@ -496,7 +496,7 @@ out: |
| 496 | 496 | int do_sigaction(int sig, const struct target_sigaction *act, |
| 497 | 497 | struct target_sigaction *oact) |
| 498 | 498 | { |
| 499 | - struct emulated_sigaction *k; | |
| 499 | + struct target_sigaction *k; | |
| 500 | 500 | struct sigaction act1; |
| 501 | 501 | int host_sig; |
| 502 | 502 | int ret = 0; |
| ... | ... | @@ -509,34 +509,35 @@ int do_sigaction(int sig, const struct target_sigaction *act, |
| 509 | 509 | sig, (int)act, (int)oact); |
| 510 | 510 | #endif |
| 511 | 511 | if (oact) { |
| 512 | - oact->_sa_handler = tswapl(k->sa._sa_handler); | |
| 513 | - oact->sa_flags = tswapl(k->sa.sa_flags); | |
| 512 | + oact->_sa_handler = tswapl(k->_sa_handler); | |
| 513 | + oact->sa_flags = tswapl(k->sa_flags); | |
| 514 | 514 | #if !defined(TARGET_MIPS) |
| 515 | - oact->sa_restorer = tswapl(k->sa.sa_restorer); | |
| 515 | + oact->sa_restorer = tswapl(k->sa_restorer); | |
| 516 | 516 | #endif |
| 517 | - oact->sa_mask = k->sa.sa_mask; | |
| 517 | + oact->sa_mask = k->sa_mask; | |
| 518 | 518 | } |
| 519 | 519 | if (act) { |
| 520 | - k->sa._sa_handler = tswapl(act->_sa_handler); | |
| 521 | - k->sa.sa_flags = tswapl(act->sa_flags); | |
| 520 | + /* FIXME: This is not threadsafe. */ | |
| 521 | + k->_sa_handler = tswapl(act->_sa_handler); | |
| 522 | + k->sa_flags = tswapl(act->sa_flags); | |
| 522 | 523 | #if !defined(TARGET_MIPS) |
| 523 | - k->sa.sa_restorer = tswapl(act->sa_restorer); | |
| 524 | + k->sa_restorer = tswapl(act->sa_restorer); | |
| 524 | 525 | #endif |
| 525 | - k->sa.sa_mask = act->sa_mask; | |
| 526 | + k->sa_mask = act->sa_mask; | |
| 526 | 527 | |
| 527 | 528 | /* we update the host linux signal state */ |
| 528 | 529 | host_sig = target_to_host_signal(sig); |
| 529 | 530 | if (host_sig != SIGSEGV && host_sig != SIGBUS) { |
| 530 | 531 | sigfillset(&act1.sa_mask); |
| 531 | 532 | act1.sa_flags = SA_SIGINFO; |
| 532 | - if (k->sa.sa_flags & TARGET_SA_RESTART) | |
| 533 | + if (k->sa_flags & TARGET_SA_RESTART) | |
| 533 | 534 | act1.sa_flags |= SA_RESTART; |
| 534 | 535 | /* NOTE: it is important to update the host kernel signal |
| 535 | 536 | ignore state to avoid getting unexpected interrupted |
| 536 | 537 | syscalls */ |
| 537 | - if (k->sa._sa_handler == TARGET_SIG_IGN) { | |
| 538 | + if (k->_sa_handler == TARGET_SIG_IGN) { | |
| 538 | 539 | act1.sa_sigaction = (void *)SIG_IGN; |
| 539 | - } else if (k->sa._sa_handler == TARGET_SIG_DFL) { | |
| 540 | + } else if (k->_sa_handler == TARGET_SIG_DFL) { | |
| 540 | 541 | act1.sa_sigaction = (void *)SIG_DFL; |
| 541 | 542 | } else { |
| 542 | 543 | act1.sa_sigaction = host_signal_handler; |
| ... | ... | @@ -712,14 +713,14 @@ setup_sigcontext(struct target_sigcontext *sc, struct target_fpstate *fpstate, |
| 712 | 713 | */ |
| 713 | 714 | |
| 714 | 715 | static inline abi_ulong |
| 715 | -get_sigframe(struct emulated_sigaction *ka, CPUX86State *env, size_t frame_size) | |
| 716 | +get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t frame_size) | |
| 716 | 717 | { |
| 717 | 718 | unsigned long esp; |
| 718 | 719 | |
| 719 | 720 | /* Default to using normal stack */ |
| 720 | 721 | esp = env->regs[R_ESP]; |
| 721 | 722 | /* This is the X/Open sanctioned signal stack switching. */ |
| 722 | - if (ka->sa.sa_flags & TARGET_SA_ONSTACK) { | |
| 723 | + if (ka->sa_flags & TARGET_SA_ONSTACK) { | |
| 723 | 724 | if (sas_ss_flags(esp) == 0) |
| 724 | 725 | esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; |
| 725 | 726 | } |
| ... | ... | @@ -727,15 +728,15 @@ get_sigframe(struct emulated_sigaction *ka, CPUX86State *env, size_t frame_size) |
| 727 | 728 | /* This is the legacy signal stack switching. */ |
| 728 | 729 | else |
| 729 | 730 | if ((env->segs[R_SS].selector & 0xffff) != __USER_DS && |
| 730 | - !(ka->sa.sa_flags & TARGET_SA_RESTORER) && | |
| 731 | - ka->sa.sa_restorer) { | |
| 732 | - esp = (unsigned long) ka->sa.sa_restorer; | |
| 731 | + !(ka->sa_flags & TARGET_SA_RESTORER) && | |
| 732 | + ka->sa_restorer) { | |
| 733 | + esp = (unsigned long) ka->sa_restorer; | |
| 733 | 734 | } |
| 734 | 735 | return (esp - frame_size) & -8ul; |
| 735 | 736 | } |
| 736 | 737 | |
| 737 | 738 | /* compare linux/arch/i386/kernel/signal.c:setup_frame() */ |
| 738 | -static void setup_frame(int sig, struct emulated_sigaction *ka, | |
| 739 | +static void setup_frame(int sig, struct target_sigaction *ka, | |
| 739 | 740 | target_sigset_t *set, CPUX86State *env) |
| 740 | 741 | { |
| 741 | 742 | abi_ulong frame_addr; |
| ... | ... | @@ -764,8 +765,8 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, |
| 764 | 765 | |
| 765 | 766 | /* Set up to return from userspace. If provided, use a stub |
| 766 | 767 | already in userspace. */ |
| 767 | - if (ka->sa.sa_flags & TARGET_SA_RESTORER) { | |
| 768 | - err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); | |
| 768 | + if (ka->sa_flags & TARGET_SA_RESTORER) { | |
| 769 | + err |= __put_user(ka->sa_restorer, &frame->pretcode); | |
| 769 | 770 | } else { |
| 770 | 771 | uint16_t val16; |
| 771 | 772 | abi_ulong retcode_addr; |
| ... | ... | @@ -784,7 +785,7 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, |
| 784 | 785 | |
| 785 | 786 | /* Set up registers for signal handler */ |
| 786 | 787 | env->regs[R_ESP] = frame_addr; |
| 787 | - env->eip = ka->sa._sa_handler; | |
| 788 | + env->eip = ka->_sa_handler; | |
| 788 | 789 | |
| 789 | 790 | cpu_x86_load_seg(env, R_DS, __USER_DS); |
| 790 | 791 | cpu_x86_load_seg(env, R_ES, __USER_DS); |
| ... | ... | @@ -799,12 +800,12 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, |
| 799 | 800 | give_sigsegv: |
| 800 | 801 | unlock_user_struct(frame, frame_addr, 1); |
| 801 | 802 | if (sig == TARGET_SIGSEGV) |
| 802 | - ka->sa._sa_handler = TARGET_SIG_DFL; | |
| 803 | + ka->_sa_handler = TARGET_SIG_DFL; | |
| 803 | 804 | force_sig(TARGET_SIGSEGV /* , current */); |
| 804 | 805 | } |
| 805 | 806 | |
| 806 | 807 | /* compare linux/arch/i386/kernel/signal.c:setup_rt_frame() */ |
| 807 | -static void setup_rt_frame(int sig, struct emulated_sigaction *ka, | |
| 808 | +static void setup_rt_frame(int sig, struct target_sigaction *ka, | |
| 808 | 809 | target_siginfo_t *info, |
| 809 | 810 | target_sigset_t *set, CPUX86State *env) |
| 810 | 811 | { |
| ... | ... | @@ -846,8 +847,8 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka, |
| 846 | 847 | |
| 847 | 848 | /* Set up to return from userspace. If provided, use a stub |
| 848 | 849 | already in userspace. */ |
| 849 | - if (ka->sa.sa_flags & TARGET_SA_RESTORER) { | |
| 850 | - err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); | |
| 850 | + if (ka->sa_flags & TARGET_SA_RESTORER) { | |
| 851 | + err |= __put_user(ka->sa_restorer, &frame->pretcode); | |
| 851 | 852 | } else { |
| 852 | 853 | uint16_t val16; |
| 853 | 854 | addr = frame_addr + offsetof(struct rt_sigframe, retcode); |
| ... | ... | @@ -864,7 +865,7 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka, |
| 864 | 865 | |
| 865 | 866 | /* Set up registers for signal handler */ |
| 866 | 867 | env->regs[R_ESP] = frame_addr; |
| 867 | - env->eip = ka->sa._sa_handler; | |
| 868 | + env->eip = ka->_sa_handler; | |
| 868 | 869 | |
| 869 | 870 | cpu_x86_load_seg(env, R_DS, __USER_DS); |
| 870 | 871 | cpu_x86_load_seg(env, R_ES, __USER_DS); |
| ... | ... | @@ -879,7 +880,7 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka, |
| 879 | 880 | give_sigsegv: |
| 880 | 881 | unlock_user_struct(frame, frame_addr, 1); |
| 881 | 882 | if (sig == TARGET_SIGSEGV) |
| 882 | - ka->sa._sa_handler = TARGET_SIG_DFL; | |
| 883 | + ka->_sa_handler = TARGET_SIG_DFL; | |
| 883 | 884 | force_sig(TARGET_SIGSEGV /* , current */); |
| 884 | 885 | } |
| 885 | 886 | |
| ... | ... | @@ -1122,14 +1123,14 @@ setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/ |
| 1122 | 1123 | } |
| 1123 | 1124 | |
| 1124 | 1125 | static inline abi_ulong |
| 1125 | -get_sigframe(struct emulated_sigaction *ka, CPUState *regs, int framesize) | |
| 1126 | +get_sigframe(struct target_sigaction *ka, CPUState *regs, int framesize) | |
| 1126 | 1127 | { |
| 1127 | 1128 | unsigned long sp = regs->regs[13]; |
| 1128 | 1129 | |
| 1129 | 1130 | /* |
| 1130 | 1131 | * This is the X/Open sanctioned signal stack switching. |
| 1131 | 1132 | */ |
| 1132 | - if ((ka->sa.sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) | |
| 1133 | + if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) | |
| 1133 | 1134 | sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; |
| 1134 | 1135 | /* |
| 1135 | 1136 | * ATPCS B01 mandates 8-byte alignment |
| ... | ... | @@ -1138,19 +1139,19 @@ get_sigframe(struct emulated_sigaction *ka, CPUState *regs, int framesize) |
| 1138 | 1139 | } |
| 1139 | 1140 | |
| 1140 | 1141 | static int |
| 1141 | -setup_return(CPUState *env, struct emulated_sigaction *ka, | |
| 1142 | +setup_return(CPUState *env, struct target_sigaction *ka, | |
| 1142 | 1143 | abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr) |
| 1143 | 1144 | { |
| 1144 | - abi_ulong handler = ka->sa._sa_handler; | |
| 1145 | + abi_ulong handler = ka->_sa_handler; | |
| 1145 | 1146 | abi_ulong retcode; |
| 1146 | 1147 | int thumb = handler & 1; |
| 1147 | 1148 | |
| 1148 | - if (ka->sa.sa_flags & TARGET_SA_RESTORER) { | |
| 1149 | - retcode = ka->sa.sa_restorer; | |
| 1149 | + if (ka->sa_flags & TARGET_SA_RESTORER) { | |
| 1150 | + retcode = ka->sa_restorer; | |
| 1150 | 1151 | } else { |
| 1151 | 1152 | unsigned int idx = thumb; |
| 1152 | 1153 | |
| 1153 | - if (ka->sa.sa_flags & TARGET_SA_SIGINFO) | |
| 1154 | + if (ka->sa_flags & TARGET_SA_SIGINFO) | |
| 1154 | 1155 | idx += 2; |
| 1155 | 1156 | |
| 1156 | 1157 | if (__put_user(retcodes[idx], rc)) |
| ... | ... | @@ -1200,7 +1201,7 @@ static void setup_sigframe_v2(struct target_ucontext_v2 *uc, |
| 1200 | 1201 | } |
| 1201 | 1202 | |
| 1202 | 1203 | /* compare linux/arch/arm/kernel/signal.c:setup_frame() */ |
| 1203 | -static void setup_frame_v1(int usig, struct emulated_sigaction *ka, | |
| 1204 | +static void setup_frame_v1(int usig, struct target_sigaction *ka, | |
| 1204 | 1205 | target_sigset_t *set, CPUState *regs) |
| 1205 | 1206 | { |
| 1206 | 1207 | struct sigframe_v1 *frame; |
| ... | ... | @@ -1224,7 +1225,7 @@ end: |
| 1224 | 1225 | unlock_user_struct(frame, frame_addr, 1); |
| 1225 | 1226 | } |
| 1226 | 1227 | |
| 1227 | -static void setup_frame_v2(int usig, struct emulated_sigaction *ka, | |
| 1228 | +static void setup_frame_v2(int usig, struct target_sigaction *ka, | |
| 1228 | 1229 | target_sigset_t *set, CPUState *regs) |
| 1229 | 1230 | { |
| 1230 | 1231 | struct sigframe_v2 *frame; |
| ... | ... | @@ -1241,7 +1242,7 @@ static void setup_frame_v2(int usig, struct emulated_sigaction *ka, |
| 1241 | 1242 | unlock_user_struct(frame, frame_addr, 1); |
| 1242 | 1243 | } |
| 1243 | 1244 | |
| 1244 | -static void setup_frame(int usig, struct emulated_sigaction *ka, | |
| 1245 | +static void setup_frame(int usig, struct target_sigaction *ka, | |
| 1245 | 1246 | target_sigset_t *set, CPUState *regs) |
| 1246 | 1247 | { |
| 1247 | 1248 | if (get_osversion() >= 0x020612) { |
| ... | ... | @@ -1252,7 +1253,7 @@ static void setup_frame(int usig, struct emulated_sigaction *ka, |
| 1252 | 1253 | } |
| 1253 | 1254 | |
| 1254 | 1255 | /* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */ |
| 1255 | -static void setup_rt_frame_v1(int usig, struct emulated_sigaction *ka, | |
| 1256 | +static void setup_rt_frame_v1(int usig, struct target_sigaction *ka, | |
| 1256 | 1257 | target_siginfo_t *info, |
| 1257 | 1258 | target_sigset_t *set, CPUState *env) |
| 1258 | 1259 | { |
| ... | ... | @@ -1296,7 +1297,7 @@ end: |
| 1296 | 1297 | unlock_user_struct(frame, frame_addr, 1); |
| 1297 | 1298 | } |
| 1298 | 1299 | |
| 1299 | -static void setup_rt_frame_v2(int usig, struct emulated_sigaction *ka, | |
| 1300 | +static void setup_rt_frame_v2(int usig, struct target_sigaction *ka, | |
| 1300 | 1301 | target_siginfo_t *info, |
| 1301 | 1302 | target_sigset_t *set, CPUState *env) |
| 1302 | 1303 | { |
| ... | ... | @@ -1322,7 +1323,7 @@ static void setup_rt_frame_v2(int usig, struct emulated_sigaction *ka, |
| 1322 | 1323 | unlock_user_struct(frame, frame_addr, 1); |
| 1323 | 1324 | } |
| 1324 | 1325 | |
| 1325 | -static void setup_rt_frame(int usig, struct emulated_sigaction *ka, | |
| 1326 | +static void setup_rt_frame(int usig, struct target_sigaction *ka, | |
| 1326 | 1327 | target_siginfo_t *info, |
| 1327 | 1328 | target_sigset_t *set, CPUState *env) |
| 1328 | 1329 | { |
| ... | ... | @@ -1650,7 +1651,7 @@ struct target_rt_signal_frame { |
| 1650 | 1651 | #define UREG_FP UREG_I6 |
| 1651 | 1652 | #define UREG_SP UREG_O6 |
| 1652 | 1653 | |
| 1653 | -static inline abi_ulong get_sigframe(struct emulated_sigaction *sa, | |
| 1654 | +static inline abi_ulong get_sigframe(struct target_sigaction *sa, | |
| 1654 | 1655 | CPUState *env, unsigned long framesize) |
| 1655 | 1656 | { |
| 1656 | 1657 | abi_ulong sp; |
| ... | ... | @@ -1658,7 +1659,7 @@ static inline abi_ulong get_sigframe(struct emulated_sigaction *sa, |
| 1658 | 1659 | sp = env->regwptr[UREG_FP]; |
| 1659 | 1660 | |
| 1660 | 1661 | /* This is the X/Open sanctioned signal stack switching. */ |
| 1661 | - if (sa->sa.sa_flags & TARGET_SA_ONSTACK) { | |
| 1662 | + if (sa->sa_flags & TARGET_SA_ONSTACK) { | |
| 1662 | 1663 | if (!on_sig_stack(sp) |
| 1663 | 1664 | && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7)) |
| 1664 | 1665 | sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; |
| ... | ... | @@ -1705,7 +1706,7 @@ setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/ |
| 1705 | 1706 | #endif |
| 1706 | 1707 | #define NF_ALIGNEDSZ (((sizeof(struct target_signal_frame) + 7) & (~7))) |
| 1707 | 1708 | |
| 1708 | -static void setup_frame(int sig, struct emulated_sigaction *ka, | |
| 1709 | +static void setup_frame(int sig, struct target_sigaction *ka, | |
| 1709 | 1710 | target_sigset_t *set, CPUState *env) |
| 1710 | 1711 | { |
| 1711 | 1712 | abi_ulong sf_addr; |
| ... | ... | @@ -1758,11 +1759,11 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, |
| 1758 | 1759 | offsetof(struct target_signal_frame, info); |
| 1759 | 1760 | |
| 1760 | 1761 | /* 4. signal handler */ |
| 1761 | - env->pc = ka->sa._sa_handler; | |
| 1762 | + env->pc = ka->_sa_handler; | |
| 1762 | 1763 | env->npc = (env->pc + 4); |
| 1763 | 1764 | /* 5. return to kernel instructions */ |
| 1764 | - if (ka->sa.sa_restorer) | |
| 1765 | - env->regwptr[UREG_I7] = ka->sa.sa_restorer; | |
| 1765 | + if (ka->sa_restorer) | |
| 1766 | + env->regwptr[UREG_I7] = ka->sa_restorer; | |
| 1766 | 1767 | else { |
| 1767 | 1768 | uint32_t val32; |
| 1768 | 1769 | |
| ... | ... | @@ -1834,7 +1835,7 @@ restore_fpu_state(CPUState *env, qemu_siginfo_fpu_t *fpu) |
| 1834 | 1835 | } |
| 1835 | 1836 | |
| 1836 | 1837 | |
| 1837 | -static void setup_rt_frame(int sig, struct emulated_sigaction *ka, | |
| 1838 | +static void setup_rt_frame(int sig, struct target_sigaction *ka, | |
| 1838 | 1839 | target_siginfo_t *info, |
| 1839 | 1840 | target_sigset_t *set, CPUState *env) |
| 1840 | 1841 | { |
| ... | ... | @@ -2182,13 +2183,13 @@ void sparc64_get_context(CPUSPARCState *env) |
| 2182 | 2183 | |
| 2183 | 2184 | # warning signal handling not implemented |
| 2184 | 2185 | |
| 2185 | -static void setup_frame(int sig, struct emulated_sigaction *ka, | |
| 2186 | +static void setup_frame(int sig, struct target_sigaction *ka, | |
| 2186 | 2187 | target_sigset_t *set, CPUState *env) |
| 2187 | 2188 | { |
| 2188 | 2189 | fprintf(stderr, "setup_frame: not implemented\n"); |
| 2189 | 2190 | } |
| 2190 | 2191 | |
| 2191 | -static void setup_rt_frame(int sig, struct emulated_sigaction *ka, | |
| 2192 | +static void setup_rt_frame(int sig, struct target_sigaction *ka, | |
| 2192 | 2193 | target_siginfo_t *info, |
| 2193 | 2194 | target_sigset_t *set, CPUState *env) |
| 2194 | 2195 | { |
| ... | ... | @@ -2211,13 +2212,13 @@ long do_rt_sigreturn(CPUState *env) |
| 2211 | 2212 | |
| 2212 | 2213 | # warning signal handling not implemented |
| 2213 | 2214 | |
| 2214 | -static void setup_frame(int sig, struct emulated_sigaction *ka, | |
| 2215 | +static void setup_frame(int sig, struct target_sigaction *ka, | |
| 2215 | 2216 | target_sigset_t *set, CPUState *env) |
| 2216 | 2217 | { |
| 2217 | 2218 | fprintf(stderr, "setup_frame: not implemented\n"); |
| 2218 | 2219 | } |
| 2219 | 2220 | |
| 2220 | -static void setup_rt_frame(int sig, struct emulated_sigaction *ka, | |
| 2221 | +static void setup_rt_frame(int sig, struct target_sigaction *ka, | |
| 2221 | 2222 | target_siginfo_t *info, |
| 2222 | 2223 | target_sigset_t *set, CPUState *env) |
| 2223 | 2224 | { |
| ... | ... | @@ -2431,7 +2432,7 @@ restore_sigcontext(CPUState *regs, struct target_sigcontext *sc) |
| 2431 | 2432 | * Determine which stack to use.. |
| 2432 | 2433 | */ |
| 2433 | 2434 | static inline abi_ulong |
| 2434 | -get_sigframe(struct emulated_sigaction *ka, CPUState *regs, size_t frame_size) | |
| 2435 | +get_sigframe(struct target_sigaction *ka, CPUState *regs, size_t frame_size) | |
| 2435 | 2436 | { |
| 2436 | 2437 | unsigned long sp; |
| 2437 | 2438 | |
| ... | ... | @@ -2446,7 +2447,7 @@ get_sigframe(struct emulated_sigaction *ka, CPUState *regs, size_t frame_size) |
| 2446 | 2447 | sp -= 32; |
| 2447 | 2448 | |
| 2448 | 2449 | /* This is the X/Open sanctioned signal stack switching. */ |
| 2449 | - if ((ka->sa.sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) { | |
| 2450 | + if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) { | |
| 2450 | 2451 | sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; |
| 2451 | 2452 | } |
| 2452 | 2453 | |
| ... | ... | @@ -2454,7 +2455,7 @@ get_sigframe(struct emulated_sigaction *ka, CPUState *regs, size_t frame_size) |
| 2454 | 2455 | } |
| 2455 | 2456 | |
| 2456 | 2457 | /* compare linux/arch/mips/kernel/signal.c:setup_frame() */ |
| 2457 | -static void setup_frame(int sig, struct emulated_sigaction * ka, | |
| 2458 | +static void setup_frame(int sig, struct target_sigaction * ka, | |
| 2458 | 2459 | target_sigset_t *set, CPUState *regs) |
| 2459 | 2460 | { |
| 2460 | 2461 | struct sigframe *frame; |
| ... | ... | @@ -2493,7 +2494,7 @@ static void setup_frame(int sig, struct emulated_sigaction * ka, |
| 2493 | 2494 | /* The original kernel code sets CP0_EPC to the handler |
| 2494 | 2495 | * since it returns to userland using eret |
| 2495 | 2496 | * we cannot do this here, and we must set PC directly */ |
| 2496 | - regs->PC[regs->current_tc] = regs->gpr[regs->current_tc][25] = ka->sa._sa_handler; | |
| 2497 | + regs->PC[regs->current_tc] = regs->gpr[regs->current_tc][25] = ka->_sa_handler; | |
| 2497 | 2498 | unlock_user_struct(frame, frame_addr, 1); |
| 2498 | 2499 | return; |
| 2499 | 2500 | |
| ... | ... | @@ -2552,7 +2553,7 @@ badframe: |
| 2552 | 2553 | return 0; |
| 2553 | 2554 | } |
| 2554 | 2555 | |
| 2555 | -static void setup_rt_frame(int sig, struct emulated_sigaction *ka, | |
| 2556 | +static void setup_rt_frame(int sig, struct target_sigaction *ka, | |
| 2556 | 2557 | target_siginfo_t *info, |
| 2557 | 2558 | target_sigset_t *set, CPUState *env) |
| 2558 | 2559 | { |
| ... | ... | @@ -2620,10 +2621,10 @@ struct target_rt_sigframe |
| 2620 | 2621 | #define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */ |
| 2621 | 2622 | #define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) SH3/4 */ |
| 2622 | 2623 | |
| 2623 | -static abi_ulong get_sigframe(struct emulated_sigaction *ka, | |
| 2624 | +static abi_ulong get_sigframe(struct target_sigaction *ka, | |
| 2624 | 2625 | unsigned long sp, size_t frame_size) |
| 2625 | 2626 | { |
| 2626 | - if ((ka->sa.sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) { | |
| 2627 | + if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) { | |
| 2627 | 2628 | sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; |
| 2628 | 2629 | } |
| 2629 | 2630 | |
| ... | ... | @@ -2682,7 +2683,7 @@ static int restore_sigcontext(struct CPUState *regs, |
| 2682 | 2683 | return err; |
| 2683 | 2684 | } |
| 2684 | 2685 | |
| 2685 | -static void setup_frame(int sig, struct emulated_sigaction *ka, | |
| 2686 | +static void setup_frame(int sig, struct target_sigaction *ka, | |
| 2686 | 2687 | target_sigset_t *set, CPUState *regs) |
| 2687 | 2688 | { |
| 2688 | 2689 | struct target_sigframe *frame; |
| ... | ... | @@ -2705,8 +2706,8 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, |
| 2705 | 2706 | |
| 2706 | 2707 | /* Set up to return from userspace. If provided, use a stub |
| 2707 | 2708 | already in userspace. */ |
| 2708 | - if (ka->sa.sa_flags & TARGET_SA_RESTORER) { | |
| 2709 | - regs->pr = (unsigned long) ka->sa.sa_restorer; | |
| 2709 | + if (ka->sa_flags & TARGET_SA_RESTORER) { | |
| 2710 | + regs->pr = (unsigned long) ka->sa_restorer; | |
| 2710 | 2711 | } else { |
| 2711 | 2712 | /* Generate return code (system call to sigreturn) */ |
| 2712 | 2713 | err |= __put_user(MOVW(2), &frame->retcode[0]); |
| ... | ... | @@ -2723,7 +2724,7 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, |
| 2723 | 2724 | regs->gregs[4] = signal; /* Arg for signal handler */ |
| 2724 | 2725 | regs->gregs[5] = 0; |
| 2725 | 2726 | regs->gregs[6] = (unsigned long) &frame->sc; |
| 2726 | - regs->pc = (unsigned long) ka->sa._sa_handler; | |
| 2727 | + regs->pc = (unsigned long) ka->_sa_handler; | |
| 2727 | 2728 | |
| 2728 | 2729 | unlock_user_struct(frame, frame_addr, 1); |
| 2729 | 2730 | return; |
| ... | ... | @@ -2733,7 +2734,7 @@ give_sigsegv: |
| 2733 | 2734 | force_sig(SIGSEGV); |
| 2734 | 2735 | } |
| 2735 | 2736 | |
| 2736 | -static void setup_rt_frame(int sig, struct emulated_sigaction *ka, | |
| 2737 | +static void setup_rt_frame(int sig, struct target_sigaction *ka, | |
| 2737 | 2738 | target_siginfo_t *info, |
| 2738 | 2739 | target_sigset_t *set, CPUState *regs) |
| 2739 | 2740 | { |
| ... | ... | @@ -2768,8 +2769,8 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka, |
| 2768 | 2769 | |
| 2769 | 2770 | /* Set up to return from userspace. If provided, use a stub |
| 2770 | 2771 | already in userspace. */ |
| 2771 | - if (ka->sa.sa_flags & TARGET_SA_RESTORER) { | |
| 2772 | - regs->pr = (unsigned long) ka->sa.sa_restorer; | |
| 2772 | + if (ka->sa_flags & TARGET_SA_RESTORER) { | |
| 2773 | + regs->pr = (unsigned long) ka->sa_restorer; | |
| 2773 | 2774 | } else { |
| 2774 | 2775 | /* Generate return code (system call to sigreturn) */ |
| 2775 | 2776 | err |= __put_user(MOVW(2), &frame->retcode[0]); |
| ... | ... | @@ -2786,7 +2787,7 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka, |
| 2786 | 2787 | regs->gregs[4] = signal; /* Arg for signal handler */ |
| 2787 | 2788 | regs->gregs[5] = (unsigned long) &frame->info; |
| 2788 | 2789 | regs->gregs[6] = (unsigned long) &frame->uc; |
| 2789 | - regs->pc = (unsigned long) ka->sa._sa_handler; | |
| 2790 | + regs->pc = (unsigned long) ka->_sa_handler; | |
| 2790 | 2791 | |
| 2791 | 2792 | unlock_user_struct(frame, frame_addr, 1); |
| 2792 | 2793 | return; |
| ... | ... | @@ -2944,7 +2945,7 @@ static abi_ulong get_sigframe(CPUState *env, int framesize) |
| 2944 | 2945 | return sp - framesize; |
| 2945 | 2946 | } |
| 2946 | 2947 | |
| 2947 | -static void setup_frame(int sig, struct emulated_sigaction *ka, | |
| 2948 | +static void setup_frame(int sig, struct target_sigaction *ka, | |
| 2948 | 2949 | target_sigset_t *set, CPUState *env) |
| 2949 | 2950 | { |
| 2950 | 2951 | struct target_signal_frame *frame; |
| ... | ... | @@ -2983,7 +2984,7 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, |
| 2983 | 2984 | /* Move the stack and setup the arguments for the handler. */ |
| 2984 | 2985 | env->regs[R_SP] = (uint32_t) frame; |
| 2985 | 2986 | env->regs[10] = sig; |
| 2986 | - env->pc = (unsigned long) ka->sa._sa_handler; | |
| 2987 | + env->pc = (unsigned long) ka->_sa_handler; | |
| 2987 | 2988 | /* Link SRP so the guest returns through the trampoline. */ |
| 2988 | 2989 | env->pregs[PR_SRP] = (uint32_t) &frame->retcode[0]; |
| 2989 | 2990 | |
| ... | ... | @@ -2994,7 +2995,7 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, |
| 2994 | 2995 | force_sig(TARGET_SIGSEGV); |
| 2995 | 2996 | } |
| 2996 | 2997 | |
| 2997 | -static void setup_rt_frame(int sig, struct emulated_sigaction *ka, | |
| 2998 | +static void setup_rt_frame(int sig, struct target_sigaction *ka, | |
| 2998 | 2999 | target_siginfo_t *info, |
| 2999 | 3000 | target_sigset_t *set, CPUState *env) |
| 3000 | 3001 | { |
| ... | ... | @@ -3043,13 +3044,13 @@ long do_rt_sigreturn(CPUState *env) |
| 3043 | 3044 | |
| 3044 | 3045 | #else |
| 3045 | 3046 | |
| 3046 | -static void setup_frame(int sig, struct emulated_sigaction *ka, | |
| 3047 | +static void setup_frame(int sig, struct target_sigaction *ka, | |
| 3047 | 3048 | target_sigset_t *set, CPUState *env) |
| 3048 | 3049 | { |
| 3049 | 3050 | fprintf(stderr, "setup_frame: not implemented\n"); |
| 3050 | 3051 | } |
| 3051 | 3052 | |
| 3052 | -static void setup_rt_frame(int sig, struct emulated_sigaction *ka, | |
| 3053 | +static void setup_rt_frame(int sig, struct target_sigaction *ka, | |
| 3053 | 3054 | target_siginfo_t *info, |
| 3054 | 3055 | target_sigset_t *set, CPUState *env) |
| 3055 | 3056 | { |
| ... | ... | @@ -3070,26 +3071,29 @@ long do_rt_sigreturn(CPUState *env) |
| 3070 | 3071 | |
| 3071 | 3072 | #endif |
| 3072 | 3073 | |
| 3073 | -void process_pending_signals(void *cpu_env) | |
| 3074 | +void process_pending_signals(CPUState *cpu_env) | |
| 3074 | 3075 | { |
| 3075 | 3076 | int sig; |
| 3076 | 3077 | abi_ulong handler; |
| 3077 | 3078 | sigset_t set, old_set; |
| 3078 | 3079 | target_sigset_t target_old_set; |
| 3079 | - struct emulated_sigaction *k; | |
| 3080 | + struct emulated_sigtable *k; | |
| 3081 | + struct target_sigaction *sa; | |
| 3080 | 3082 | struct sigqueue *q; |
| 3083 | + TaskState *ts = cpu_env->opaque; | |
| 3081 | 3084 | |
| 3082 | - if (!signal_pending) | |
| 3085 | + if (!ts->signal_pending) | |
| 3083 | 3086 | return; |
| 3084 | 3087 | |
| 3085 | - k = sigact_table; | |
| 3088 | + /* FIXME: This is not threadsafe. */ | |
| 3089 | + k = ts->sigtab; | |
| 3086 | 3090 | for(sig = 1; sig <= TARGET_NSIG; sig++) { |
| 3087 | 3091 | if (k->pending) |
| 3088 | 3092 | goto handle_signal; |
| 3089 | 3093 | k++; |
| 3090 | 3094 | } |
| 3091 | 3095 | /* if no signal is pending, just return */ |
| 3092 | - signal_pending = 0; | |
| 3096 | + ts->signal_pending = 0; | |
| 3093 | 3097 | return; |
| 3094 | 3098 | |
| 3095 | 3099 | handle_signal: |
| ... | ... | @@ -3108,7 +3112,8 @@ void process_pending_signals(void *cpu_env) |
| 3108 | 3112 | abort(); |
| 3109 | 3113 | } |
| 3110 | 3114 | |
| 3111 | - handler = k->sa._sa_handler; | |
| 3115 | + sa = &sigact_table[sig - 1]; | |
| 3116 | + handler = sa->_sa_handler; | |
| 3112 | 3117 | if (handler == TARGET_SIG_DFL) { |
| 3113 | 3118 | /* default handler : ignore some signal. The other are fatal */ |
| 3114 | 3119 | if (sig != TARGET_SIGCHLD && |
| ... | ... | @@ -3122,10 +3127,10 @@ void process_pending_signals(void *cpu_env) |
| 3122 | 3127 | force_sig(sig); |
| 3123 | 3128 | } else { |
| 3124 | 3129 | /* compute the blocked signals during the handler execution */ |
| 3125 | - target_to_host_sigset(&set, &k->sa.sa_mask); | |
| 3130 | + target_to_host_sigset(&set, &sa->sa_mask); | |
| 3126 | 3131 | /* SA_NODEFER indicates that the current signal should not be |
| 3127 | 3132 | blocked during the handler */ |
| 3128 | - if (!(k->sa.sa_flags & TARGET_SA_NODEFER)) | |
| 3133 | + if (!(sa->sa_flags & TARGET_SA_NODEFER)) | |
| 3129 | 3134 | sigaddset(&set, target_to_host_signal(sig)); |
| 3130 | 3135 | |
| 3131 | 3136 | /* block signals in the handler using Linux */ |
| ... | ... | @@ -3143,13 +3148,13 @@ void process_pending_signals(void *cpu_env) |
| 3143 | 3148 | } |
| 3144 | 3149 | #endif |
| 3145 | 3150 | /* prepare the stack frame of the virtual CPU */ |
| 3146 | - if (k->sa.sa_flags & TARGET_SA_SIGINFO) | |
| 3147 | - setup_rt_frame(sig, k, &q->info, &target_old_set, cpu_env); | |
| 3151 | + if (sa->sa_flags & TARGET_SA_SIGINFO) | |
| 3152 | + setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env); | |
| 3148 | 3153 | else |
| 3149 | - setup_frame(sig, k, &target_old_set, cpu_env); | |
| 3150 | - if (k->sa.sa_flags & TARGET_SA_RESETHAND) | |
| 3151 | - k->sa._sa_handler = TARGET_SIG_DFL; | |
| 3154 | + setup_frame(sig, sa, &target_old_set, cpu_env); | |
| 3155 | + if (sa->sa_flags & TARGET_SA_RESETHAND) | |
| 3156 | + sa->_sa_handler = TARGET_SIG_DFL; | |
| 3152 | 3157 | } |
| 3153 | 3158 | if (q != &k->info) |
| 3154 | - free_sigqueue(q); | |
| 3159 | + free_sigqueue(cpu_env, q); | |
| 3155 | 3160 | } | ... | ... |
linux-user/syscall.c
| ... | ... | @@ -2736,12 +2736,8 @@ int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp) |
| 2736 | 2736 | } |
| 2737 | 2737 | #endif |
| 2738 | 2738 | ts = malloc(sizeof(TaskState) + NEW_STACK_SIZE); |
| 2739 | - memset(ts, 0, sizeof(TaskState)); | |
| 2739 | + init_task_state(ts); | |
| 2740 | 2740 | new_stack = ts->stack; |
| 2741 | - ts->used = 1; | |
| 2742 | - /* add in task state list */ | |
| 2743 | - ts->next = first_task_state; | |
| 2744 | - first_task_state = ts; | |
| 2745 | 2741 | /* we create a new CPU instance. */ |
| 2746 | 2742 | new_env = cpu_copy(env); |
| 2747 | 2743 | /* Init regs that differ from the parent. */ | ... | ... |