Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 6 Nov 2008 23:13:54 GMT
From:      Peter Wemm <peter@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 152601 for review
Message-ID:  <200811062313.mA6NDsiV038307@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=152601

Change 152601 by peter@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)
 {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200811062313.mA6NDsiV038307>