PERFORCE change 152601 for review
Peter Wemm
peter at FreeBSD.org
Thu Nov 6 15:13:55 PST 2008
http://perforce.freebsd.org/chv.cgi?CH=152601
Change 152601 by peter at peter_overcee on 2008/11/06 23:12:57
Make freebsd-style orderly thread shutdown work. On linux, each thread
calls exit(2), and there is an exit_group(2) syscall exit and take your peers
with you.
On FreeBSD, we have thr_exit(2) for a thread to finish by itself, and exit(2)
takes all your peers with you.
Teach valgrind about our semantics and implement the thr_kill() call.
Affected files ...
.. //depot/projects/valgrind/coregrind/m_libcsignal.c#5 edit
.. //depot/projects/valgrind/coregrind/m_syswrap/priv_syswrap-freebsd.h#15 edit
.. //depot/projects/valgrind/coregrind/m_syswrap/syswrap-freebsd.c#27 edit
.. //depot/projects/valgrind/coregrind/m_syswrap/syswrap-generic.c#8 edit
Differences ...
==== //depot/projects/valgrind/coregrind/m_libcsignal.c#5 (text+ko) ====
@@ -191,7 +191,7 @@
{
SysRes res = VG_(mk_SysRes_Error)(VKI_ENOSYS);
#ifdef VGO_freebsd
- res = VG_(do_syscall2)(__NR_kill, tid, signo);
+ res = VG_(do_syscall2)(__NR_thr_kill, tid, signo);
#else
res = VG_(do_syscall2)(__NR_tkill, tid, signo);
if (res.isError && res.err == VKI_ENOSYS)
==== //depot/projects/valgrind/coregrind/m_syswrap/priv_syswrap-freebsd.h#15 (text+ko) ====
@@ -44,6 +44,7 @@
DECL_TEMPLATE(freebsd, sys_syscall);
+DECL_TEMPLATE(freebsd, sys_exit);
DECL_TEMPLATE(freebsd, sys_getfsstat);
DECL_TEMPLATE(freebsd, sys_mount);
DECL_TEMPLATE(freebsd, sys_unmount);
==== //depot/projects/valgrind/coregrind/m_syswrap/syswrap-freebsd.c#27 (text+ko) ====
@@ -168,27 +168,28 @@
reallocation. We need to make sure we don't touch the stack
between marking it Empty and exiting. Hence the
assembler. */
- /* QQQ might have to use thr_exit here */
#if defined(VGP_x86_freebsd) /* FreeBSD has args on the stack */
asm volatile (
"movl %1, %0\n" /* set tst->status = VgTs_Empty */
- "movl %2, %%eax\n" /* set %eax = __NR_exit */
- "movl %3, %%ebx\n" /* set %ebx = tst->os_state.exitcode */
+ "movl %2, %%eax\n" /* set %eax = __NR_thr_exit */
+ "leaq %3, %%ebx\n" /* set %ebx = tst->os_state.exitcode */
"pushl %%ebx\n" /* arg on stack */
"pushl %%ebx\n" /* fake return address */
- "int $0x80\n" /* exit(tst->os_state.exitcode) */
+ "int $0x80\n" /* thr_exit(&tst->os_state.exitcode) */
"popl %%ebx\n" /* fake return address */
"popl %%ebx\n" /* arg off stack */
: "=m" (tst->status)
- : "n" (VgTs_Empty), "n" (__NR_exit), "m" (tst->os_state.exitcode));
+ : "n" (VgTs_Empty), "n" (__NR_thr_exit), "m" (tst->os_state.exitcode));
#elif defined(VGP_amd64_freebsd)
asm volatile (
"movl %1, %0\n" /* set tst->status = VgTs_Empty */
- "movq %2, %%rax\n" /* set %rax = __NR_exit */
- "movq %3, %%rdi\n" /* set %rdi = tst->os_state.exitcode */
- "syscall\n" /* exit(tst->os_state.exitcode) */
+ "movq %2, %%rax\n" /* set %rax = __NR_thr_exit */
+ "leaq %3, %%rdi\n" /* set %rdi = tst->os_state.exitcode */
+ "pushq %%rdi\n" /* fake return address */
+ "syscall\n" /* thr_exit(&tst->os_state.exitcode) */
+ "popq %%rdi\n" /* fake return address */
: "=m" (tst->status)
- : "n" (VgTs_Empty), "n" (__NR_exit), "m" (tst->os_state.exitcode));
+ : "n" (VgTs_Empty), "n" (__NR_thr_exit), "m" (tst->os_state.exitcode));
#else
# error Unknown platform
#endif
@@ -681,7 +682,7 @@
VG_(threads)[t].os_state.exitcode = ARG1;
if (t != tid)
- VG_(kill_thread)(t); /* unblock it, if blocked */
+ VG_(get_thread_out_of_syscall)(t); /* unblock it, if blocked */
}
/* We have to claim the syscall already succeeded. */
@@ -689,6 +690,35 @@
}
#endif
+/* On FreeBSD, if any thread calls exit(2), then they are all shut down, pretty
+ * much like linux's exit_group().
+ */
+PRE(sys_exit)
+{
+ ThreadId t;
+ ThreadState* tst;
+
+ PRINT("exit( %ld )", ARG1);
+ PRE_REG_READ1(void, "exit", int, exitcode);
+ tst = VG_(get_ThreadState)(tid);
+
+ /* Mark all threads (including this one) to exit. */
+ for (t = 1; t < VG_N_THREADS; t++) {
+ if ( /* not alive */ VG_(threads)[t].status == VgTs_Empty )
+ continue;
+
+ VG_(threads)[t].exitreason = VgSrc_ExitThread;
+ VG_(threads)[t].os_state.exitcode = ARG1;
+
+ if (t != tid)
+ VG_(get_thread_out_of_syscall)(t); /* unblock it, if blocked */
+ }
+
+ /* We have to claim the syscall already succeeded. */
+ SET_STATUS_Success(0);
+}
+
+
PRE(sys_getlogin)
{
PRINT("sys_getlogin ( %#lx, %ld )",ARG1,ARG2);
@@ -2929,7 +2959,7 @@
const SyscallTableEntry ML_(syscall_table)[] = {
// syscall (handled specially) // 0
- GENX_(__NR_exit, sys_exit), // 1
+ BSDX_(__NR_exit, sys_exit), // 1
BSDX_(__NR_fork, sys_fork), // 2
GENXY(__NR_read, sys_read), // 3
==== //depot/projects/valgrind/coregrind/m_syswrap/syswrap-generic.c#8 (text+ko) ====
@@ -2115,6 +2115,7 @@
//zz // VG_(core_panic)("syscall exit_group() not caught by the scheduler?!");
//zz //}
+#if !defined(VGO_freebsd) /* On freebsd, exit(2) is all-threads shutdown */
PRE(sys_exit)
{
ThreadState* tst;
@@ -2128,6 +2129,7 @@
tst->os_state.exitcode = ARG1;
SET_STATUS_Success(0);
}
+#endif
PRE(sys_ni_syscall)
{
More information about the p4-projects
mailing list