PERFORCE change 152457 for review

Peter Wemm peter at FreeBSD.org
Tue Nov 4 07:56:44 PST 2008


http://perforce.freebsd.org/chv.cgi?CH=152457

Change 152457 by peter at peter_overcee on 2008/11/04 15:56:27

	Initial shot at what thr_new() should look like.  It creates threads and doesn't
	crash.  Things dont run yet either though.  I'm guessing I've got to revisit the
	tid stuff elsewhere as everything blocks on umtx_op and no progress happens.

Affected files ...

.. //depot/projects/valgrind/coregrind/m_syswrap/priv_syswrap-freebsd.h#13 edit
.. //depot/projects/valgrind/coregrind/m_syswrap/syswrap-amd64-freebsd.c#6 edit
.. //depot/projects/valgrind/coregrind/m_syswrap/syswrap-freebsd.c#24 edit
.. //depot/projects/valgrind/include/vki/vki-freebsd.h#11 edit

Differences ...

==== //depot/projects/valgrind/coregrind/m_syswrap/priv_syswrap-freebsd.h#13 (text+ko) ====

@@ -256,6 +256,7 @@
 DECL_TEMPLATE(freebsd, sys_unlinkat);
 DECL_TEMPLATE(freebsd, sys_posix_openpt);
 DECL_TEMPLATE(freebsd, sys_uuidgen);
+DECL_TEMPLATE(freebsd, sys_thr_new);
 #endif   // __PRIV_SYSWRAP_FREEBSD_H
 
 /*--------------------------------------------------------------------*/

==== //depot/projects/valgrind/coregrind/m_syswrap/syswrap-amd64-freebsd.c#6 (text+ko) ====

@@ -111,10 +111,6 @@
    More thread stuff
    ------------------------------------------------------------------ */
 
-void VG_(cleanup_thread) ( ThreadArchState* arch )
-{
-}  
-
 
 /* ---------------------------------------------------------------------
    PRE/POST wrappers for x86/Linux-specific syscalls
@@ -123,6 +119,124 @@
 #define PRE(name)       DEFN_PRE_TEMPLATE(freebsd, name)
 #define POST(name)      DEFN_POST_TEMPLATE(freebsd, name)
 
+#if 0
+struct thr_param {
+    void        (*start_func)(void *);  /* thread entry function. */
+    void        *arg;                   /* argument for entry function. */
+    char        *stack_base;            /* stack base address. */
+    size_t      stack_size;             /* stack size. */
+    char        *tls_base;              /* tls base address. */
+    size_t      tls_size;               /* tls size. */
+    long        *child_tid;             /* address to store new TID. */
+    long        *parent_tid;            /* parent accesses the new TID here. */
+    int         flags;                  /* thread flags. */
+    struct rtprio       *rtp;           /* Real-time scheduling priority */
+    void        *spare[3];              /* TODO: cpu affinity mask etc. */
+};
+int thr_new(struct thr_param *param, int param_size);
+#endif
+
+PRE(sys_thr_new)
+{
+   static const Bool debug = False;
+
+   ThreadId     ctid = VG_(alloc_ThreadState)();
+   ThreadState* ptst = VG_(get_ThreadState)(tid);
+   ThreadState* ctst = VG_(get_ThreadState)(ctid);
+   SysRes       res;
+   vki_sigset_t blockall, savedmask;
+   struct vki_thr_param tp;
+
+   PRINT("thr_new ( %#lx, %ld )",ARG1,ARG2);
+   PRE_REG_READ2(int, "thr_new",
+                 struct thr_param *, param,
+                 int, param_size);
+   
+   PRE_MEM_READ( "thr_new(param)", ARG1, offsetof(struct vki_thr_param, spare));
+   if (!ML_(safe_to_deref)( (void*)ARG1, offsetof(struct vki_thr_param, spare))) {
+      SET_STATUS_Failure( VKI_EFAULT );
+      return;
+   }
+   VG_(memset)(&tp, 0, sizeof(tp));
+   VG_(memcpy)(&tp, (void *)ARG1, offsetof(struct vki_thr_param, spare));
+   PRE_MEM_WRITE("clone(parent_tidptr)", (Addr)tp.parent_tid, sizeof(long));
+   PRE_MEM_WRITE("clone(child_tidptr)", (Addr)tp.child_tid, sizeof(long));
+
+   VG_(sigfillset)(&blockall);
+
+   vg_assert(VG_(is_running_thread)(tid));
+   vg_assert(VG_(is_valid_tid)(ctid));
+
+   /* Copy register state
+
+      On linux, both parent and child return to the same place, and the code
+      following the clone syscall works out which is which, so we
+      don't need to worry about it.
+      On FreeBSD, thr_new arranges a direct call.  We don't actually need any
+      of this gunk.
+
+      The parent gets the child's new tid returned from clone, but the
+      child gets 0.
+
+      If the clone call specifies a NULL rsp for the new thread, then
+      it actually gets a copy of the parent's rsp.
+   */
+   /* We inherit our parent's guest state. */
+   ctst->arch.vex = ptst->arch.vex;
+   ctst->arch.vex_shadow1 = ptst->arch.vex_shadow1;
+   ctst->arch.vex_shadow2 = ptst->arch.vex_shadow2;
+
+   /* Make sys_clone appear to have returned Success(0) in the
+      child. */
+   ctst->arch.vex.guest_RAX = 0;
+   ctst->arch.vex.guest_RDX = 0;
+   LibVEX_GuestAMD64_put_rflag_c(0, &ctst->arch.vex);
+
+   ctst->os_state.parent = tid;
+
+   /* inherit signal mask */
+   ctst->sig_mask = ptst->sig_mask;
+   ctst->tmp_sig_mask = ptst->sig_mask;
+
+   /* Linux has to guess, we don't */
+   VG_(register_stack)((Addr)tp.stack_base, (Addr)tp.stack_base + tp.stack_size);
+
+   /* Assume the clone will succeed, and tell any tool that wants to
+      know that this thread has come into existence.  If the clone
+      fails, we'll send out a ll_exit notification for it at the out:
+      label below, to clean up. */
+   VG_TRACK ( pre_thread_ll_create, tid, ctid );
+
+   if (debug)
+      VG_(printf)("clone child has SETTLS: tls at %#lx\n", (Addr)tp.tls_base);
+   ctst->arch.vex.guest_FS_ZERO = (UWord)tp.tls_base;
+   tp.tls_base = 0;	/* Don't have the kernel do it too */
+
+   /* start the thread with everything blocked */
+   VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
+
+
+   /* Create the new thread */
+   res = VG_(do_syscall2)(__NR_thr_new, ARG1, ARG2);
+
+   VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
+
+   if (res.isError) {
+      /* clone failed */
+      ctst->status = VgTs_Empty;
+      /* oops.  Better tell the tool the thread exited in a hurry :-) */
+      VG_TRACK( pre_thread_ll_exit, ctid );
+   } else {
+
+      POST_MEM_WRITE((Addr)tp.parent_tid, sizeof(long));
+      POST_MEM_WRITE((Addr)tp.child_tid, sizeof(long));
+
+      /* Thread creation was successful; let the child have the chance
+         to run */
+      /* *flags |= SfYieldAfter; */
+   }
+}
+
 PRE(sys_sigreturn)
 {
    ThreadState* tst;

==== //depot/projects/valgrind/coregrind/m_syswrap/syswrap-freebsd.c#24 (text+ko) ====

@@ -1774,6 +1774,7 @@
 
 PRE(sys__umtx_op)
 {
+   *flags |= SfMayBlock;
    /* 5 args are always passed through.  The last two can vary, but
       they're always pointers.  They may not be used though. */
    switch(ARG2) {
@@ -3479,7 +3480,7 @@
    // setaudit_addr							   452
    // auditctl								   453
    BSDXY(__NR__umtx_op,			sys__umtx_op),			// 454
-   // thr_new								   455
+   BSDX_(__NR_thr_new,			sys_thr_new),			// 455
 
    // sigqueue								   456
    // kmq_open								   457

==== //depot/projects/valgrind/include/vki/vki-freebsd.h#11 (text+ko) ====

@@ -1818,6 +1818,24 @@
 #define VKI_KERN_PROC        14
 #define VKI_KERN_PROC_VMMAP  13
 
+//----------------------------------------------------------------------
+// From sys/thr.h
+//----------------------------------------------------------------------
+
+struct vki_thr_param {
+	void	(*start_func)(void *);
+	void	*arg;
+	char	*stack_base;
+	vki_size_t	stack_size;
+	char	*tls_base;
+	vki_size_t	tls_size;
+	long	*child_tid;
+	long	*parent_tid;
+	int	flags;
+	struct vki_rtprio *rtp;
+	void	*spare[3];
+};
+
 /*--------------------------------------------------------------------*/
 /*--- end                                                          ---*/
 /*--------------------------------------------------------------------*/


More information about the p4-projects mailing list