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. */ | ... | ... |