Hi, ports Valgrind does not run Pthread target program. I made patch to run Pthread target program.
I applied this patch and run attached main.c as: $ cc main.c -lpthread $ while :; do valgrind ./a.out 32 8; done for 24 hours. I got no problem. ok? Index: patches/patch-coregrind_m_libcsignal_c =================================================================== RCS file: patches/patch-coregrind_m_libcsignal_c diff -N patches/patch-coregrind_m_libcsignal_c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-coregrind_m_libcsignal_c 9 Dec 2019 05:30:18 -0000 @@ -0,0 +1,21 @@ +--- coregrind/m_libcsignal.c.orig ++++ coregrind/m_libcsignal.c +@@ -397,6 +397,7 @@ + Int VG_(tkill)( Int lwpid, Int signo ) + { + # if defined(__NR_tkill) ++ PRINT("sys___tfork ( %ld, %ld )",ARG1,ARG2); + SysRes res = VG_(mk_SysRes_Error)(VKI_ENOSYS); + res = VG_(do_syscall2)(__NR_tkill, lwpid, signo); + if (sr_isError(res) && sr_Err(res) == VKI_ENOSYS) +@@ -415,7 +416,9 @@ + return sr_isError(res) ? -1 : 0; + + # elif defined(VGO_openbsd) +- I_die_here; ++ SysRes res; ++ res = VG_(do_syscall3)(__NR_thrkill, lwpid, signo, NULL); ++ return sr_isError(res) ? -1 : 0; + + # else + # error "Unsupported plat" Index: patches/patch-coregrind_m_syswrap_priv_syswrap_openbsd_h =================================================================== RCS file: /cvs/ports/devel/valgrind/patches/patch-coregrind_m_syswrap_priv_syswrap_openbsd_h,v retrieving revision 1.1 diff -u -p -r1.1 patch-coregrind_m_syswrap_priv_syswrap_openbsd_h --- patches/patch-coregrind_m_syswrap_priv_syswrap_openbsd_h 23 Oct 2019 02:35:05 -0000 1.1 +++ patches/patch-coregrind_m_syswrap_priv_syswrap_openbsd_h 9 Dec 2019 05:30:18 -0000 @@ -1,5 +1,14 @@ --- coregrind/m_syswrap/priv_syswrap-openbsd.h.orig +++ coregrind/m_syswrap/priv_syswrap-openbsd.h +@@ -50,7 +50,7 @@ + DECL_TEMPLATE(openbsd, sys_open); + DECL_TEMPLATE(openbsd, sys_close); + DECL_TEMPLATE(openbsd, sys_getentropy); +-DECL_TEMPLATE(openbsd, sys___tfork); ++DECL_TEMPLATE(openbsd, sys___tfork_thread); + DECL_TEMPLATE(openbsd, sys_link); + DECL_TEMPLATE(openbsd, sys_unlink); + DECL_TEMPLATE(openbsd, sys_wait4); @@ -144,6 +144,7 @@ DECL_TEMPLATE(openbsd, sys_pledge); DECL_TEMPLATE(openbsd, sys_ppoll); Index: patches/patch-coregrind_m_syswrap_syswrap_amd64_openbsd_c =================================================================== RCS file: patches/patch-coregrind_m_syswrap_syswrap_amd64_openbsd_c diff -N patches/patch-coregrind_m_syswrap_syswrap_amd64_openbsd_c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-coregrind_m_syswrap_syswrap_amd64_openbsd_c 9 Dec 2019 05:30:18 -0000 @@ -0,0 +1,215 @@ +--- coregrind/m_syswrap/syswrap-amd64-openbsd.c.orig ++++ coregrind/m_syswrap/syswrap-amd64-openbsd.c +@@ -120,6 +120,212 @@ + #define PRE(name) DEFN_PRE_TEMPLATE(openbsd, name) + #define POST(name) DEFN_POST_TEMPLATE(openbsd, name) + ++extern UWord do_syscall_tfork_amd64_openbsd ( ++ Addr params, ++ UWord psize, ++ Addr startfunc, ++ Addr startarg); ++asm( ++".text\n" ++".globl do_syscall_tfork_amd64_openbsd\n" ++"do_syscall_tfork_amd64_openbsd:\n" ++ /* Copy %rdx to %r8 and %rcx to %r9. See: ++ - lib/libc/arch/amd64/sys/tfork_thread.S */ ++" movq %rdx, %r8\n" ++" movq %rcx, %r9\n" ++" movq $8, %rax\n" /* syscall_no */ ++" syscall\n" ++" jb 5f\n" /* error */ ++ /* ++ * Check to see if we are in the parent or child ++ */ ++" cmpl $0, %eax\n" ++" jz 4f\n" /* child */ ++" jmp 5f\n" /* parent */ ++ /* the retpoline we'll use to call the child's main */ ++".align 16, 0xcc\n" /* _ALIGN_TRAPS */ ++"1:\n" /* JMP_RETPOLINE(r8) --> */ ++" call 3f\n" ++"2: pause\n" ++" lfence\n" ++" jmp 2b\n" ++".align 16, 0xcc\n" /* _ALIGN_TRAPS */ ++"3: mov %r8,(%rsp)\n" ++" ret\n" ++ /* JMP_RETPOLINE(r8) <-- */ ++ /* ++ * If we are in the child (new thread), then ++ * set-up the call to the internal subroutine. If it ++ * returns, then call __threxit. ++ */ ++".align 16, 0xcc\n" /* _ALIGN_TRAPS */ ++"4:\n" ++" movq %r9, %rdi\n" ++" call 1b\n" ++ /* ++ * Thread exit system call ++ */ ++" movl $302, %eax\n" /* 302 == SYS___threxit */ ++" xorl %edi, %edi\n" ++" syscall\n" ++ /*NOTREACHED*/ ++"5:\n" /* parent or error */ ++" ret\n" ++".previous\n" ++); ++ ++static void setup_child ( ThreadArchState*, ThreadArchState* ); ++ ++void setup_child ( /*OUT*/ ThreadArchState *child, ++ /*IN*/ ThreadArchState *parent ) ++{ ++ /* We inherit our parent's guest state. */ ++ child->vex = parent->vex; ++ child->vex_shadow1 = parent->vex_shadow1; ++ child->vex_shadow2 = parent->vex_shadow2; ++} ++ ++/* ++ When a client clones, we need to keep track of the new thread. This means: ++ 1. allocate a ThreadId+ThreadState+stack for the the thread ++ ++ 2. initialize the thread's new VCPU state ++ ++ 3. create the thread using the same args as the client requested, ++ but using the scheduler entrypoint for EIP, and a separate stack ++ for ESP. ++ ++ This function was implemented with reference to the syswrap-amd64-linux.c: ++ do_clone() function. ++ */ ++static SysRes do_tfork_thread ( ThreadId ptid, ++ Addr params, ++ ULong psize, ++ Addr startfunc, ++ Addr startarg) ++{ ++ ThreadId ctid = VG_(alloc_ThreadState)(); ++ ThreadState* ptst = VG_(get_ThreadState)(ptid); ++ ThreadState* ctst = VG_(get_ThreadState)(ctid); ++ UWord* stack; ++ SysRes res; ++ Long rax; ++ vki_sigset_t blockall, savedmask; ++ struct __vki_tfork * tfork; ++ ++ VG_(sigfillset)(&blockall); ++ ++ vg_assert(params != 0); ++ vg_assert(psize > 0); ++ vg_assert(startfunc != 0); ++ vg_assert(VG_(is_running_thread)(ptid)); ++ vg_assert(VG_(is_valid_tid)(ctid)); ++ ++ stack = (UWord*)ML_(allocstack)(ctid); ++ if (stack == NULL) { ++ res = VG_(mk_SysRes_Error)( VKI_ENOMEM ); ++ goto out; ++ } ++ ++ /* Copy register state ++ ++ Both parent and child return to the same place, and the code ++ following the __tfork_thread syscall works out which is which, so we ++ don't need to worry about it. ++ ++ The parent gets the child's new tid returned from clone, but the ++ child gets 0. ++ ++ If the clone call specifies a NULL tfork->tf_stack for the new thread, ++ then it actually gets a copy of the parent's rsp. ++ */ ++ setup_child( &ctst->arch, &ptst->arch ); ++ ++ /* Make sys___tfork appear to have returned Success(0) in the ++ child. */ ++ ctst->arch.vex.guest_RAX = 0; ++ ++ tfork = (struct __vki_tfork *)params; ++ vg_assert(tfork->tf_stack != 0); ++ ctst->arch.vex.guest_RSP = (ULong) tfork->tf_stack; ++ tfork->tf_stack = stack; ++ ++ ctst->os_state.parent = ptid; ++ ++ /* inherit signal mask */ ++ ctst->sig_mask = ptst->sig_mask; ++ ctst->tmp_sig_mask = ptst->sig_mask; ++ ++ /* Start the child with its threadgroup being the same as the ++ parent's. This is so that any exit_group calls that happen ++ after the child is created but before it sets its ++ os_state.threadgroup field for real (in thread_wrapper in ++ syswrap-linux.c), really kill the new thread. a.k.a this avoids ++ a race condition in which the thread is unkillable (via ++ exit_group) because its threadgroup is not set. The race window ++ is probably only a few hundred or a few thousand cycles long. ++ See #226116. */ ++ ctst->os_state.threadgroup = ptst->os_state.threadgroup; ++ ++ ML_(guess_and_register_stack) ((Addr)tfork->tf_stack, ctst); ++ ++ /* 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_assert(VG_(owns_BigLock_LL)(ptid)); ++ VG_TRACK ( pre_thread_ll_create, ptid, ctid ); ++ ++ /* start the thread with everything blocked */ ++#if 1 /* for debug by asou */ ++ VG_(sigdelset)(&blockall, VKI_SIGTRAP); ++#endif ++ VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask); ++ ++ /* Create the new thread */ ++ rax = do_syscall_tfork_amd64_openbsd( ++ params, psize, ML_(start_thread_NORETURN), &VG_(threads)[ctid]); ++ res = VG_(mk_SysRes_amd64_openbsd)( rax, ptst->arch.vex.guest_RDX, ++ (rax == -1) ? True : False ); ++ ++ VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL); ++ ++ out: ++ if (sr_isError(res)) { ++ /* clone failed */ ++ VG_(cleanup_thread)(&ctst->arch); ++ ctst->status = VgTs_Empty; ++ /* oops. Better tell the tool the thread exited in a hurry :-) */ ++ VG_TRACK( pre_thread_ll_exit, ctid ); ++ } ++ ++ return res; ++} ++ ++PRE(sys___tfork_thread) ++{ ++ struct __vki_tfork * tfork; ++ PRINT("sys___tfork_thread ( %#lx, %ld, %#lx, %#lx )",ARG1,ARG2,ARG3,ARG4); ++ PRE_REG_READ4(long, "__tfork_thread", struct __tfork *, params, size_t, psize, ++ void (*)(void *), startfunc, void *, startarg); ++ PRE_MEM_READ( "__tfork_thread(params, psize)", ARG1, ARG2 ); ++ tfork = (struct __vki_tfork *)ARG1; ++ if (tfork->tf_tid != NULL) ++ PRE_MEM_READ("__tfork_thread(params.tf_tid)", (Addr)tfork->tf_tid, ++ sizeof (pid_t)); ++ SET_STATUS_from_SysRes( ++ do_tfork_thread(tid, (Addr)ARG1, (ULong)ARG2, (Addr)ARG3, (Addr)ARG4)); ++ ++ if (SUCCESS) { ++ POST_MEM_WRITE((Addr)tfork->tf_tcb, sizeof (void *)); ++ POST_MEM_WRITE((Addr)tfork->tf_tid, sizeof (pid_t)); ++ ++ /* Thread creation was successful; let the child have the chance ++ to run */ ++ *flags |= SfYieldAfter; ++ } ++} ++ + #if 0 + PRE(sys_thr_new) + { Index: patches/patch-coregrind_m_syswrap_syswrap_generic_c =================================================================== RCS file: patches/patch-coregrind_m_syswrap_syswrap_generic_c diff -N patches/patch-coregrind_m_syswrap_syswrap_generic_c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-coregrind_m_syswrap_syswrap_generic_c 9 Dec 2019 05:30:18 -0000 @@ -0,0 +1,16 @@ +--- coregrind/m_syswrap/syswrap-generic.c.orig ++++ coregrind/m_syswrap/syswrap-generic.c +@@ -2240,7 +2240,13 @@ + /* Otherwise we're OK (so far). Install aspacem's choice of + address, and let the mmap go through. */ + sres = VG_(am_do_mmap_NO_NOTIFY)(advised, arg2, arg3, ++#if defined(VGO_openbsd) ++ /* Could not specified VKI_MAP_STACK and VKI_MAP_FIXED at the same ++ time */ ++ arg4, ++#else + arg4 | VKI_MAP_FIXED, ++#endif + arg5, arg6); + + /* A refinement: it may be that the kernel refused aspacem's choice Index: patches/patch-coregrind_m_syswrap_syswrap_openbsd_c =================================================================== RCS file: /cvs/ports/devel/valgrind/patches/patch-coregrind_m_syswrap_syswrap_openbsd_c,v retrieving revision 1.1 diff -u -p -r1.1 patch-coregrind_m_syswrap_syswrap_openbsd_c --- patches/patch-coregrind_m_syswrap_syswrap_openbsd_c 23 Oct 2019 02:35:05 -0000 1.1 +++ patches/patch-coregrind_m_syswrap_syswrap_openbsd_c 9 Dec 2019 05:30:18 -0000 @@ -1,6 +1,43 @@ --- coregrind/m_syswrap/syswrap-openbsd.c.orig +++ coregrind/m_syswrap/syswrap-openbsd.c -@@ -575,6 +579,17 @@ +@@ -210,21 +210,21 @@ + /* : "n" (VgTs_Empty), "n" (__NR_thr_exit), "m" (tst->os_state.exitcode) */ + /* : "eax", "ebx" */ + /* ); */ +-/* #elif defined(VGP_amd64_openbsd) */ +- /* asm volatile ( */ +- /* "movl %1, %0\n" /\* set tst->status = VgTs_Empty *\/ */ +- /* "movq %2, %%rax\n" /\* set %rax = __NR_thr_exit *\/ */ +- /* "movq %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_thr_exit), "m" (tst->os_state.exitcode) */ +- /* : "rax", "rdi" */ +- /* ); */ +-/* #else */ +-/* # error Unknown platform */ +-/* #endif */ ++#if defined(VGP_amd64_openbsd) ++ asm volatile ( ++ "movl %1, %0\n" /* set tst->status = VgTs_Empty */ ++ "movq %2, %%rax\n" /* set %rax = __NR_thr_exit */ ++ "movq %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___threxit), "m" (tst->os_state.exitcode) ++ : "rax", "rdi" ++ ); ++#else ++# error Unknown platform ++#endif + + VG_(core_panic)("Thread exit failed?\n"); + } +@@ -575,6 +575,17 @@ // XXXTBD } @@ -18,7 +55,154 @@ PRE(sys_getsockname) { PRINT("sys_getsockname ( %ld, %#lx, %#lx )",ARG1,ARG2,ARG3); -@@ -4079,7 +4093,7 @@ +@@ -791,15 +791,6 @@ + SET_STATUS_Success(0); + } + +-PRE(sys___tfork) +-{ +-// XXXTBD +-} +-POST(sys___tfork) +-{ +-// XXXTBD +-} +- + PRE(sys_getlogin) + { + PRINT("sys_getlogin ( %#lx, %ld )",ARG1,ARG2); +@@ -2787,17 +2778,40 @@ + + PRE(sys___thrsleep) + { +-// XXXTBD ++ *flags |= SfMayBlock; ++ PRINT("__thrsleep( %#lx, %ld, %#lx, %#lx, %#lx )", ARG1,ARG2,ARG3,ARG4,ARG5); ++ PRE_REG_READ5(int, "__thrsleep", ++ void *, id, ++ int, clock_id, ++ struct timespec *, abstime, ++ void *, lock, ++ int *, abort); ++ if (ARG3 != 0) ++ PRE_MEM_READ(" __thrsleep(abstime)", ARG3, sizeof(struct timespec)); ++ if (ARG5 != 0) ++ PRE_MEM_READ(" __thrsleep(abort)", ARG5, sizeof (int)); + } + + PRE(sys___thrwakeup) + { +-// XXXTBD ++ PRINT("__thrwakeup( %#lx, %ld, %#lx, %#lx, %#lx )", ARG1,ARG2,ARG3,ARG4,ARG5); ++ PRE_REG_READ2(int, "__thrwakeup", ++ void *, id, ++ int, count); + } + + PRE(sys___threxit) + { +-// XXXTBD ++ ThreadState* tst; ++ /* simple; just make this thread exit */ ++ PRINT("__threxit( %#lx )", ARG1); ++ PRE_REG_READ1(void, "__threxit", void *, value_ptr); ++ tst = VG_(get_ThreadState)(tid); ++ /* Set the thread's status to be exiting, then claim that the ++ syscall succeeded. */ ++ tst->exitreason = VgSrc_ExitThread; ++ /* tst->os_state.exitcode = ARG1; */ ++ SET_STATUS_Success(0); + } + + PRE(sys___thrsigdivert) +@@ -2830,6 +2843,68 @@ + // XXXTBD + } + ++PRE(sys_futex) ++{ ++ /* ++ arg param used by ops ++ ++ ARG1 - uint32_t *uaddr all ++ ARG2 - int op ++ ARG3 - int val WAIT,WAKE,REQUEUE ++ ARG4 - struct timespec *utime WAIT, REQUEUE ++ ARG5 - uint32_t *uaddr2 REQUEUE ++ */ ++ PRINT("sys_futex ( %#lx, %ld, %ld, %#lx, %#lx )", ARG1,ARG2,ARG3,ARG4,ARG5); ++ switch(ARG2 & ~VKI_FUTEX_PRIVATE_FLAG) { ++ case VKI_FUTEX_WAIT: ++ PRE_REG_READ4(long, "futex", ++ vki_uint32_t *, uaddr, int, op, int, val, ++ struct timespec *, utime); ++ break; ++ case VKI_FUTEX_WAKE: ++ PRE_REG_READ3(long, "futex", ++ vki_uint32_t *, uaddr, int, op, int, val); ++ break; ++ case VKI_FUTEX_REQUEUE: ++ PRE_REG_READ5(long, "futex", ++ vki_uint32_t *, uaddr, int, op, int, val, ++ struct timespec *, utime, vki_uint32_t *, uaddr2); ++ break; ++ default: ++ PRE_REG_READ2(long, "futex", vki_uint32_t *, uaddr, int, op); ++ break; ++ } ++ ++ *flags |= SfMayBlock; ++ ++ switch(ARG2 & ~VKI_FUTEX_PRIVATE_FLAG) { ++ case VKI_FUTEX_WAIT: ++ PRE_MEM_READ( "futex(uaddr)", ARG1, sizeof(Int) ); ++ if (ARG4 != 0) ++ PRE_MEM_READ( "futex(timeout)", ARG4, sizeof(struct vki_timespec) ); ++ break; ++ ++ case VKI_FUTEX_WAKE: ++ /* no additional pointers */ ++ break; ++ ++ case VKI_FUTEX_REQUEUE: ++ PRE_MEM_READ( "futex(uaddr)", ARG1, sizeof(Int) ); ++ PRE_MEM_READ( "futex(val2)", ARG4, sizeof(Int) ); ++ PRE_MEM_READ( "futex(uaddr2)", ARG5, sizeof(Int) ); ++ break; ++ ++ default: ++ SET_STATUS_Failure( VKI_ENOSYS ); // some futex function we don't understand ++ break; ++ } ++} ++POST(sys_futex) ++{ ++ vg_assert(SUCCESS); ++ POST_MEM_WRITE( ARG1, sizeof(int) ); ++} ++ + PRE(sys_utimensat) + { + // XXXTBD +@@ -3961,7 +4036,7 @@ + + GENXY(__NR_close, sys_close), // 6 + BSDXY(__NR_getentropy, sys_getentropy), // 7 +- BSDXY(__NR___tfork, sys___tfork), // 8 ++ BSDX_(__NR___tfork_thread, sys___tfork_thread), // 8 + GENX_(__NR_link, sys_link), // 9 + GENX_(__NR_unlink, sys_unlink), // 10 + +@@ -4053,7 +4128,7 @@ + + GENX_(__NR_getpgrp, sys_getpgrp), // 81 + GENX_(__NR_setpgid, sys_setpgid), // 82 +- BSDX_(__NR_osendsyslog, sys_sendsyslog), // 83 ++ BSDXY(__NR_futex, sys_futex), // 83 + BSDX_(__NR_utimensat, sys_utimensat), // 84 + BSDX_(__NR_futimens, sys_futimens), // 85 + +@@ -4079,7 +4094,7 @@ BSDX_(__NR_sigsuspend, sys_sigsuspend), // 111 BSDX_(__NR_sendsyslog, sys_sendsyslog), // 112 // obsol orecvmsg // 113 @@ -27,4 +211,3 @@ // obsol vtrace // 115 BSDX_(__NR_getsockopt, sys_getsockopt), // 118 -Only in pobj/valgrind-3.10.1/valgrind-3.10.1/coregrind/m_syswrap: syswrap-openbsd.c.orig Index: patches/patch-coregrind_m_syswrap_syswrap_x86_openbsd_c =================================================================== RCS file: patches/patch-coregrind_m_syswrap_syswrap_x86_openbsd_c diff -N patches/patch-coregrind_m_syswrap_syswrap_x86_openbsd_c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-coregrind_m_syswrap_syswrap_x86_openbsd_c 9 Dec 2019 05:30:18 -0000 @@ -0,0 +1,18 @@ +--- coregrind/m_syswrap/syswrap-x86-openbsd.c.orig ++++ coregrind/m_syswrap/syswrap-x86-openbsd.c +@@ -525,6 +525,15 @@ + #define PRE(name) DEFN_PRE_TEMPLATE(openbsd, name) + #define POST(name) DEFN_POST_TEMPLATE(openbsd, name) + ++PRE(sys___tfork_thread) ++{ ++// XXXTBD ++} ++POST(sys___tfork_thread) ++{ ++// XXXTBD ++} ++ + #if 0 + struct thr_param { + void (*start_func)(void *); /* thread entry function. */ Index: patches/patch-include_vki_vki-openbsd_h =================================================================== RCS file: /cvs/ports/devel/valgrind/patches/patch-include_vki_vki-openbsd_h,v retrieving revision 1.1 diff -u -p -r1.1 patch-include_vki_vki-openbsd_h --- patches/patch-include_vki_vki-openbsd_h 2 Oct 2019 17:19:29 -0000 1.1 +++ patches/patch-include_vki_vki-openbsd_h 9 Dec 2019 05:30:18 -0000 @@ -1,5 +1,21 @@ --- include/vki/vki-openbsd.h.orig +++ include/vki/vki-openbsd.h +@@ -76,6 +76,15 @@ + + + //---------------------------------------------------------------------- ++// From linux-2.6.31-rc4/include/linux/futex.h ++//---------------------------------------------------------------------- ++ ++#define VKI_FUTEX_WAIT (1) ++#define VKI_FUTEX_WAKE (2) ++#define VKI_FUTEX_REQUEUE (3) ++#define VKI_FUTEX_PRIVATE_FLAG (128) ++ ++//---------------------------------------------------------------------- + // From sys/select.h + //---------------------------------------------------------------------- + @@ -1544,9 +1544,9 @@ #define VKI_MAP_PRIVATE 0x02 /* Changes are private */ #define VKI_MAP_FIXED 0x10 /* Interpret addr exactly */ @@ -11,3 +27,16 @@ //---------------------------------------------------------------------- // From sys/stat.h +@@ -1650,6 +1659,12 @@ + #define VKI_X_OK 0x01 /* test for execute or search permission */ + #define VKI_W_OK 0x02 /* test for write permission */ + #define VKI_R_OK 0x04 /* test for read permission */ ++ ++struct __vki_tfork { ++ void *tf_tcb; ++ pid_t *tf_tid; ++ void *tf_stack; ++}; + + //---------------------------------------------------------------------- + // From sys/msg.h Index: patches/patch-include_vki_vki_scnums_openbsd_h =================================================================== RCS file: /cvs/ports/devel/valgrind/patches/patch-include_vki_vki_scnums_openbsd_h,v retrieving revision 1.1 diff -u -p -r1.1 patch-include_vki_vki_scnums_openbsd_h --- patches/patch-include_vki_vki_scnums_openbsd_h 23 Oct 2019 02:35:05 -0000 1.1 +++ patches/patch-include_vki_vki_scnums_openbsd_h 9 Dec 2019 05:30:18 -0000 @@ -1,5 +1,23 @@ --- include/vki/vki-scnums-openbsd.h.orig +++ include/vki/vki-scnums-openbsd.h +@@ -41,7 +41,7 @@ + #define __NR_open 5 + #define __NR_close 6 + #define __NR_getentropy 7 +-#define __NR___tfork 8 ++#define __NR___tfork_thread 8 + #define __NR_link 9 + #define __NR_unlink 10 + #define __NR_wait4 11 +@@ -116,7 +116,7 @@ + #define __NR_setgroups 80 + #define __NR_getpgrp 81 + #define __NR_setpgid 82 +-#define __NR_osendsyslog 83 ++#define __NR_futex 83 + #define __NR_utimensat 84 + #define __NR_futimens 85 + #define __NR_kbind 86 @@ -146,6 +146,7 @@ #define __NR_pselect 110 #define __NR_sigsuspend 111 -- ASOU Masato
#include <err.h> #include <limits.h> #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <sys/mman.h> #include <sys/time.h> #include <unistd.h> #define MAX_NTHREADS 64 static void * sub(void *arg) { static int retval[MAX_NTHREADS]; struct timeval tv; int id = *(int *)arg; int i; for (i = 0; i < 5; i++) { printf("Thread: %d: %d\n", id, i); usleep(100 * 1000); } gettimeofday(&tv, NULL); retval[id] = tv.tv_usec % ((id + 1) * 1000); printf("Thread: %d: retval = %d\n", id, retval[id]); return &retval[id]; } pthread_t thread[MAX_NTHREADS]; int thrid[MAX_NTHREADS]; int result[MAX_NTHREADS]; void *value[MAX_NTHREADS]; static void th_create(int id) { thrid[id] = id; result[id] = -1; value[id] = NULL; result[id] = pthread_create(&thread[id], NULL, sub, &thrid[id]); if (result[id] != 0) { fprintf(stderr, "pthread_create: %d: error = %d\n", thrid[id], result[0]); } } static void th_join(int id) { int *val; if (result[id] == 0) { pthread_join(thread[id], &value[id]); val = value[id]; if (val != NULL) printf("Thread: %d: value = %d\n", thrid[id], *val); } } int main(int argc, char *argv[]) { int nthreads = 4; int count = 1; int icnt, ith, idx; if (argc >= 2) { int nthrs; nthrs = strtol(argv[1], NULL, 0); if (nthrs > 0 && nthrs <= MAX_NTHREADS) nthreads = nthrs; } if (argc >= 3) { int cnt; cnt = strtol(argv[2], NULL, 0); if (cnt > 0) count = cnt; } idx = 0; for (icnt = 0; icnt < count; icnt++) { for (ith = 0; ith < nthreads; ith++) th_create(idx + ith); for (ith = 0; ith < nthreads; ith++) th_join(idx + ith); idx += ith; if (idx >= MAX_NTHREADS) idx = 0; } return (0); }