1*cdebaff8SEnji Cooper /* $NetBSD: h_execthr.c,v 1.7 2016/11/24 00:37:29 dholland Exp $ */ 257718be8SEnji Cooper 357718be8SEnji Cooper /* 457718be8SEnji Cooper * Copyright (c) 2011 The NetBSD Foundation, Inc. 557718be8SEnji Cooper * All rights reserved. 657718be8SEnji Cooper * 757718be8SEnji Cooper * Redistribution and use in source and binary forms, with or without 857718be8SEnji Cooper * modification, are permitted provided that the following conditions 957718be8SEnji Cooper * are met: 1057718be8SEnji Cooper * 1. Redistributions of source code must retain the above copyright 1157718be8SEnji Cooper * notice, this list of conditions and the following disclaimer. 1257718be8SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright 1357718be8SEnji Cooper * notice, this list of conditions and the following disclaimer in the 1457718be8SEnji Cooper * documentation and/or other materials provided with the distribution. 1557718be8SEnji Cooper * 1657718be8SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 1757718be8SEnji Cooper * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 1857718be8SEnji Cooper * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 1957718be8SEnji Cooper * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2057718be8SEnji Cooper * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 2157718be8SEnji Cooper * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2257718be8SEnji Cooper * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 2357718be8SEnji Cooper * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2457718be8SEnji Cooper * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 2557718be8SEnji Cooper * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 2657718be8SEnji Cooper * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 2757718be8SEnji Cooper * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2857718be8SEnji Cooper */ 2957718be8SEnji Cooper 3057718be8SEnji Cooper #include <sys/types.h> 3157718be8SEnji Cooper #include <sys/sysctl.h> 3257718be8SEnji Cooper 3357718be8SEnji Cooper #include <err.h> 3457718be8SEnji Cooper #include <errno.h> 3557718be8SEnji Cooper #include <fcntl.h> 3657718be8SEnji Cooper #include <pthread.h> 3757718be8SEnji Cooper #include <stdio.h> 3857718be8SEnji Cooper #include <stdlib.h> 3957718be8SEnji Cooper #include <string.h> 4057718be8SEnji Cooper #include <unistd.h> 4157718be8SEnji Cooper 4257718be8SEnji Cooper #include <rump/rumpclient.h> 4357718be8SEnji Cooper #include <rump/rump_syscalls.h> 4457718be8SEnji Cooper 45*cdebaff8SEnji Cooper //#define VERBOSE 46*cdebaff8SEnji Cooper 47*cdebaff8SEnji Cooper #ifdef VERBOSE 48*cdebaff8SEnji Cooper #define SAY(...) printf(__VA_ARGS__) 49*cdebaff8SEnji Cooper #else 50*cdebaff8SEnji Cooper #define SAY(...) 51*cdebaff8SEnji Cooper #endif 52*cdebaff8SEnji Cooper 5357718be8SEnji Cooper static int canreturn = 0; 5457718be8SEnji Cooper 5557718be8SEnji Cooper /* 5657718be8SEnji Cooper * Use a fairly large number of threads so that we have 5757718be8SEnji Cooper * a better chance catching races. XXX: this is rumpuser's 5857718be8SEnji Cooper * MAXWORKER-1. 5957718be8SEnji Cooper */ 6057718be8SEnji Cooper #define NTHR 63 6157718be8SEnji Cooper 6257718be8SEnji Cooper #define P1_0 3 6357718be8SEnji Cooper #define P1_1 4 6457718be8SEnji Cooper #define P2_0 5 6557718be8SEnji Cooper #define P2_1 6 6657718be8SEnji Cooper 6757718be8SEnji Cooper static void * 6857718be8SEnji Cooper wrk(void *arg) 6957718be8SEnji Cooper { 7057718be8SEnji Cooper int fd = (uintptr_t)arg; 7157718be8SEnji Cooper 7257718be8SEnji Cooper rump_sys_read(fd, &fd, sizeof(fd)); 7357718be8SEnji Cooper if (!canreturn) 7457718be8SEnji Cooper errx(1, "should not have returned"); 7557718be8SEnji Cooper if (fd != 37) 7657718be8SEnji Cooper errx(1, "got invalid magic"); 7757718be8SEnji Cooper 7857718be8SEnji Cooper return NULL; 7957718be8SEnji Cooper } 8057718be8SEnji Cooper 8157718be8SEnji Cooper static int 8257718be8SEnji Cooper getproc(pid_t mypid, struct kinfo_proc2 *p) 8357718be8SEnji Cooper { 8457718be8SEnji Cooper int name[6]; 8557718be8SEnji Cooper size_t len = sizeof(*p); 8657718be8SEnji Cooper 8757718be8SEnji Cooper name[0] = CTL_KERN; 8857718be8SEnji Cooper name[1] = KERN_PROC2; 8957718be8SEnji Cooper name[2] = KERN_PROC_PID; 9057718be8SEnji Cooper name[3] = mypid; 9157718be8SEnji Cooper name[4] = len; 9257718be8SEnji Cooper name[5] = 1; 9357718be8SEnji Cooper 9457718be8SEnji Cooper return rump_sys___sysctl(name, __arraycount(name), p, &len, NULL, 0); 9557718be8SEnji Cooper } 9657718be8SEnji Cooper 9757718be8SEnji Cooper int 9857718be8SEnji Cooper main(int argc, char *argv[], char *envp[]) 9957718be8SEnji Cooper { 10057718be8SEnji Cooper struct kinfo_proc2 p; 10157718be8SEnji Cooper char *execarg[3]; 10257718be8SEnji Cooper int p1[2], p2[2]; 10357718be8SEnji Cooper pid_t mypid; 10457718be8SEnji Cooper pthread_t pt; 10557718be8SEnji Cooper ssize_t n; 10657718be8SEnji Cooper int i, execd; 10757718be8SEnji Cooper char nexec[16]; 10857718be8SEnji Cooper 10957718be8SEnji Cooper if (argc > 1) 11057718be8SEnji Cooper execd = atoi(argv[1]); 11157718be8SEnji Cooper else 11257718be8SEnji Cooper execd = 0; 11357718be8SEnji Cooper sprintf(nexec, "%d", execd+1); 114*cdebaff8SEnji Cooper SAY("execd: %d\n", execd); 11557718be8SEnji Cooper 11657718be8SEnji Cooper if (rumpclient_init() == -1) { 11757718be8SEnji Cooper if (execd) 11857718be8SEnji Cooper err(1, "init execd"); 11957718be8SEnji Cooper else 12057718be8SEnji Cooper err(1, "init"); 12157718be8SEnji Cooper } 12257718be8SEnji Cooper mypid = rump_sys_getpid(); 123*cdebaff8SEnji Cooper SAY("rumpclient_init finished.\n"); 12457718be8SEnji Cooper 12557718be8SEnji Cooper if (execd) { 12657718be8SEnji Cooper canreturn = 1; 127*cdebaff8SEnji Cooper errno = pthread_create(&pt, NULL, 128*cdebaff8SEnji Cooper wrk, (void *)(uintptr_t)P2_0); 129*cdebaff8SEnji Cooper if (errno != 0) 130*cdebaff8SEnji Cooper err(1, "exec pthread_create"); 131*cdebaff8SEnji Cooper SAY("startup pthread_create finished.\n"); 13257718be8SEnji Cooper 13357718be8SEnji Cooper i = 37; 13457718be8SEnji Cooper rump_sys_write(P2_1, &i, sizeof(i)); 13557718be8SEnji Cooper pthread_join(pt, NULL); 136*cdebaff8SEnji Cooper SAY("startup pthread_join finished.\n"); 13757718be8SEnji Cooper 13857718be8SEnji Cooper n = rump_sys_read(P1_0, &i, sizeof(i)); 13957718be8SEnji Cooper if (n != -1 || errno != EBADF) 14057718be8SEnji Cooper errx(1, "post-exec cloexec works"); 141*cdebaff8SEnji Cooper SAY("startup rump_sys_read finished.\n"); 14257718be8SEnji Cooper 14357718be8SEnji Cooper getproc(mypid, &p); 144*cdebaff8SEnji Cooper SAY("startup getproc finished.\n"); 14557718be8SEnji Cooper if (p.p_nlwps != 2) 14657718be8SEnji Cooper errx(1, "invalid nlwps: %lld", (long long)p.p_nlwps); 14757718be8SEnji Cooper 14857718be8SEnji Cooper /* we passed? */ 149*cdebaff8SEnji Cooper if (execd > 10) { 150*cdebaff8SEnji Cooper SAY("done.\n"); 15157718be8SEnji Cooper exit(0); 152*cdebaff8SEnji Cooper } 15357718be8SEnji Cooper 15457718be8SEnji Cooper rump_sys_close(P2_0); 15557718be8SEnji Cooper rump_sys_close(P2_1); 15657718be8SEnji Cooper } 15757718be8SEnji Cooper 158*cdebaff8SEnji Cooper SAY("making pipes...\n"); 159*cdebaff8SEnji Cooper 16057718be8SEnji Cooper if (rump_sys_pipe(p1) == -1) 16157718be8SEnji Cooper err(1, "pipe1"); 16257718be8SEnji Cooper if (p1[0] != P1_0 || p1[1] != P1_1) 16357718be8SEnji Cooper errx(1, "p1 assumptions failed %d %d", p1[0], p1[1]); 16457718be8SEnji Cooper if (rump_sys_pipe(p2) == -1) 16557718be8SEnji Cooper err(1, "pipe1"); 16657718be8SEnji Cooper if (p2[0] != P2_0 || p2[1] != P2_1) 16757718be8SEnji Cooper errx(1, "p2 assumptions failed"); 16857718be8SEnji Cooper if (rump_sys_fcntl(p1[0], F_SETFD, FD_CLOEXEC) == -1) 16957718be8SEnji Cooper err(1, "cloexec"); 17057718be8SEnji Cooper if (rump_sys_fcntl(p1[1], F_SETFD, FD_CLOEXEC) == -1) 17157718be8SEnji Cooper err(1, "cloexec"); 17257718be8SEnji Cooper 173*cdebaff8SEnji Cooper SAY("making threads...\n"); 17457718be8SEnji Cooper 175*cdebaff8SEnji Cooper for (i = 0; i < NTHR; i++) { 176*cdebaff8SEnji Cooper errno = pthread_create(&pt, NULL, 177*cdebaff8SEnji Cooper wrk, (void *)(uintptr_t)p1[0]); 178*cdebaff8SEnji Cooper if (errno != 0) 179*cdebaff8SEnji Cooper err(1, "pthread_create 1 %d", i); 180*cdebaff8SEnji Cooper } 181*cdebaff8SEnji Cooper 182*cdebaff8SEnji Cooper for (i = 0; i < NTHR; i++) { 183*cdebaff8SEnji Cooper errno = pthread_create(&pt, NULL, 184*cdebaff8SEnji Cooper wrk, (void *)(uintptr_t)p2[0]); 185*cdebaff8SEnji Cooper if (errno != 0) 186*cdebaff8SEnji Cooper err(1, "pthread_create 2 %d", i); 187*cdebaff8SEnji Cooper } 188*cdebaff8SEnji Cooper 189*cdebaff8SEnji Cooper SAY("waiting for threads to start...\n"); 19057718be8SEnji Cooper 19157718be8SEnji Cooper /* wait for all the threads to be enjoying themselves */ 19257718be8SEnji Cooper for (;;) { 19357718be8SEnji Cooper getproc(mypid, &p); 194*cdebaff8SEnji Cooper SAY("getproc finished.\n"); 19557718be8SEnji Cooper if (p.p_nlwps == 2*NTHR + 2) 19657718be8SEnji Cooper break; 19757718be8SEnji Cooper usleep(10000); 19857718be8SEnji Cooper } 19957718be8SEnji Cooper 200*cdebaff8SEnji Cooper SAY("making some more threads start...\n"); 201*cdebaff8SEnji Cooper 20257718be8SEnji Cooper /* 20357718be8SEnji Cooper * load up one more (big) set. these won't start executing, though, 20457718be8SEnji Cooper * but we're interested in if they create blockage 20557718be8SEnji Cooper */ 206*cdebaff8SEnji Cooper for (i = 0; i < 3*NTHR; i++) { 207*cdebaff8SEnji Cooper errno = pthread_create(&pt, NULL, 208*cdebaff8SEnji Cooper wrk, (void *)(uintptr_t)p1[0]); 209*cdebaff8SEnji Cooper if (errno != 0) 210*cdebaff8SEnji Cooper err(1, "pthread_create 3 %d", i); 211*cdebaff8SEnji Cooper } 212*cdebaff8SEnji Cooper 213*cdebaff8SEnji Cooper SAY("calling exec...\n"); 21457718be8SEnji Cooper 21557718be8SEnji Cooper /* then, we exec! */ 21657718be8SEnji Cooper execarg[0] = argv[0]; 21757718be8SEnji Cooper execarg[1] = nexec; 21857718be8SEnji Cooper execarg[2] = NULL; 21957718be8SEnji Cooper if (rumpclient_exec(argv[0], execarg, envp) == -1) 22057718be8SEnji Cooper err(1, "exec"); 22157718be8SEnji Cooper } 222