From owner-p4-projects@FreeBSD.ORG Tue Nov 4 15:56:43 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id BFFAE1065672; Tue, 4 Nov 2008 15:56:43 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 844D91065689 for ; Tue, 4 Nov 2008 15:56:43 +0000 (UTC) (envelope-from peter-gmail@wemm.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 714088FC1E for ; Tue, 4 Nov 2008 15:56:43 +0000 (UTC) (envelope-from peter-gmail@wemm.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id mA4Fuh2o010327 for ; Tue, 4 Nov 2008 15:56:43 GMT (envelope-from peter-gmail@wemm.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id mA4FuhRH010325 for perforce@freebsd.org; Tue, 4 Nov 2008 15:56:43 GMT (envelope-from peter-gmail@wemm.org) Date: Tue, 4 Nov 2008 15:56:43 GMT Message-Id: <200811041556.mA4FuhRH010325@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to peter-gmail@wemm.org using -f From: Peter Wemm To: Perforce Change Reviews Cc: Subject: PERFORCE change 152457 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 04 Nov 2008 15:56:44 -0000 http://perforce.freebsd.org/chv.cgi?CH=152457 Change 152457 by peter@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 ---*/ /*--------------------------------------------------------------------*/