1313535Sngie/* $NetBSD: h_execthr.c,v 1.7 2016/11/24 00:37:29 dholland Exp $ */ 2272343Sngie 3272343Sngie/* 4272343Sngie * Copyright (c) 2011 The NetBSD Foundation, Inc. 5272343Sngie * All rights reserved. 6272343Sngie * 7272343Sngie * Redistribution and use in source and binary forms, with or without 8272343Sngie * modification, are permitted provided that the following conditions 9272343Sngie * are met: 10272343Sngie * 1. Redistributions of source code must retain the above copyright 11272343Sngie * notice, this list of conditions and the following disclaimer. 12272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 13272343Sngie * notice, this list of conditions and the following disclaimer in the 14272343Sngie * documentation and/or other materials provided with the distribution. 15272343Sngie * 16272343Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 17272343Sngie * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 18272343Sngie * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19272343Sngie * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20272343Sngie * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 21272343Sngie * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22272343Sngie * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 23272343Sngie * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24272343Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25272343Sngie * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26272343Sngie * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27272343Sngie * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28272343Sngie */ 29272343Sngie 30272343Sngie#include <sys/types.h> 31272343Sngie#include <sys/sysctl.h> 32272343Sngie 33272343Sngie#include <err.h> 34272343Sngie#include <errno.h> 35272343Sngie#include <fcntl.h> 36272343Sngie#include <pthread.h> 37272343Sngie#include <stdio.h> 38272343Sngie#include <stdlib.h> 39272343Sngie#include <string.h> 40272343Sngie#include <unistd.h> 41272343Sngie 42272343Sngie#include <rump/rumpclient.h> 43272343Sngie#include <rump/rump_syscalls.h> 44272343Sngie 45313535Sngie//#define VERBOSE 46313535Sngie 47313535Sngie#ifdef VERBOSE 48313535Sngie#define SAY(...) printf(__VA_ARGS__) 49313535Sngie#else 50313535Sngie#define SAY(...) 51313535Sngie#endif 52313535Sngie 53272343Sngiestatic int canreturn = 0; 54272343Sngie 55272343Sngie/* 56272343Sngie * Use a fairly large number of threads so that we have 57272343Sngie * a better chance catching races. XXX: this is rumpuser's 58272343Sngie * MAXWORKER-1. 59272343Sngie */ 60272343Sngie#define NTHR 63 61272343Sngie 62272343Sngie#define P1_0 3 63272343Sngie#define P1_1 4 64272343Sngie#define P2_0 5 65272343Sngie#define P2_1 6 66272343Sngie 67272343Sngiestatic void * 68272343Sngiewrk(void *arg) 69272343Sngie{ 70272343Sngie int fd = (uintptr_t)arg; 71272343Sngie 72272343Sngie rump_sys_read(fd, &fd, sizeof(fd)); 73272343Sngie if (!canreturn) 74272343Sngie errx(1, "should not have returned"); 75272343Sngie if (fd != 37) 76272343Sngie errx(1, "got invalid magic"); 77272343Sngie 78272343Sngie return NULL; 79272343Sngie} 80272343Sngie 81272343Sngiestatic int 82272343Sngiegetproc(pid_t mypid, struct kinfo_proc2 *p) 83272343Sngie{ 84272343Sngie int name[6]; 85272343Sngie size_t len = sizeof(*p); 86272343Sngie 87272343Sngie name[0] = CTL_KERN; 88272343Sngie name[1] = KERN_PROC2; 89272343Sngie name[2] = KERN_PROC_PID; 90272343Sngie name[3] = mypid; 91272343Sngie name[4] = len; 92272343Sngie name[5] = 1; 93272343Sngie 94272343Sngie return rump_sys___sysctl(name, __arraycount(name), p, &len, NULL, 0); 95272343Sngie} 96272343Sngie 97272343Sngieint 98272343Sngiemain(int argc, char *argv[], char *envp[]) 99272343Sngie{ 100272343Sngie struct kinfo_proc2 p; 101272343Sngie char *execarg[3]; 102272343Sngie int p1[2], p2[2]; 103272343Sngie pid_t mypid; 104272343Sngie pthread_t pt; 105272343Sngie ssize_t n; 106272343Sngie int i, execd; 107272343Sngie char nexec[16]; 108272343Sngie 109272343Sngie if (argc > 1) 110272343Sngie execd = atoi(argv[1]); 111272343Sngie else 112272343Sngie execd = 0; 113272343Sngie sprintf(nexec, "%d", execd+1); 114313535Sngie SAY("execd: %d\n", execd); 115272343Sngie 116272343Sngie if (rumpclient_init() == -1) { 117272343Sngie if (execd) 118272343Sngie err(1, "init execd"); 119272343Sngie else 120272343Sngie err(1, "init"); 121272343Sngie } 122272343Sngie mypid = rump_sys_getpid(); 123313535Sngie SAY("rumpclient_init finished.\n"); 124272343Sngie 125272343Sngie if (execd) { 126272343Sngie canreturn = 1; 127313535Sngie errno = pthread_create(&pt, NULL, 128313535Sngie wrk, (void *)(uintptr_t)P2_0); 129313535Sngie if (errno != 0) 130313535Sngie err(1, "exec pthread_create"); 131313535Sngie SAY("startup pthread_create finished.\n"); 132272343Sngie 133272343Sngie i = 37; 134272343Sngie rump_sys_write(P2_1, &i, sizeof(i)); 135272343Sngie pthread_join(pt, NULL); 136313535Sngie SAY("startup pthread_join finished.\n"); 137272343Sngie 138272343Sngie n = rump_sys_read(P1_0, &i, sizeof(i)); 139272343Sngie if (n != -1 || errno != EBADF) 140272343Sngie errx(1, "post-exec cloexec works"); 141313535Sngie SAY("startup rump_sys_read finished.\n"); 142272343Sngie 143272343Sngie getproc(mypid, &p); 144313535Sngie SAY("startup getproc finished.\n"); 145272343Sngie if (p.p_nlwps != 2) 146272343Sngie errx(1, "invalid nlwps: %lld", (long long)p.p_nlwps); 147272343Sngie 148272343Sngie /* we passed? */ 149313535Sngie if (execd > 10) { 150313535Sngie SAY("done.\n"); 151272343Sngie exit(0); 152313535Sngie } 153272343Sngie 154272343Sngie rump_sys_close(P2_0); 155272343Sngie rump_sys_close(P2_1); 156272343Sngie } 157272343Sngie 158313535Sngie SAY("making pipes...\n"); 159313535Sngie 160272343Sngie if (rump_sys_pipe(p1) == -1) 161272343Sngie err(1, "pipe1"); 162272343Sngie if (p1[0] != P1_0 || p1[1] != P1_1) 163272343Sngie errx(1, "p1 assumptions failed %d %d", p1[0], p1[1]); 164272343Sngie if (rump_sys_pipe(p2) == -1) 165272343Sngie err(1, "pipe1"); 166272343Sngie if (p2[0] != P2_0 || p2[1] != P2_1) 167272343Sngie errx(1, "p2 assumptions failed"); 168272343Sngie if (rump_sys_fcntl(p1[0], F_SETFD, FD_CLOEXEC) == -1) 169272343Sngie err(1, "cloexec"); 170272343Sngie if (rump_sys_fcntl(p1[1], F_SETFD, FD_CLOEXEC) == -1) 171272343Sngie err(1, "cloexec"); 172272343Sngie 173313535Sngie SAY("making threads...\n"); 174272343Sngie 175313535Sngie for (i = 0; i < NTHR; i++) { 176313535Sngie errno = pthread_create(&pt, NULL, 177313535Sngie wrk, (void *)(uintptr_t)p1[0]); 178313535Sngie if (errno != 0) 179313535Sngie err(1, "pthread_create 1 %d", i); 180313535Sngie } 181272343Sngie 182313535Sngie for (i = 0; i < NTHR; i++) { 183313535Sngie errno = pthread_create(&pt, NULL, 184313535Sngie wrk, (void *)(uintptr_t)p2[0]); 185313535Sngie if (errno != 0) 186313535Sngie err(1, "pthread_create 2 %d", i); 187313535Sngie } 188313535Sngie 189313535Sngie SAY("waiting for threads to start...\n"); 190313535Sngie 191272343Sngie /* wait for all the threads to be enjoying themselves */ 192272343Sngie for (;;) { 193272343Sngie getproc(mypid, &p); 194313535Sngie SAY("getproc finished.\n"); 195272343Sngie if (p.p_nlwps == 2*NTHR + 2) 196272343Sngie break; 197272343Sngie usleep(10000); 198272343Sngie } 199272343Sngie 200313535Sngie SAY("making some more threads start...\n"); 201313535Sngie 202272343Sngie /* 203272343Sngie * load up one more (big) set. these won't start executing, though, 204272343Sngie * but we're interested in if they create blockage 205272343Sngie */ 206313535Sngie for (i = 0; i < 3*NTHR; i++) { 207313535Sngie errno = pthread_create(&pt, NULL, 208313535Sngie wrk, (void *)(uintptr_t)p1[0]); 209313535Sngie if (errno != 0) 210313535Sngie err(1, "pthread_create 3 %d", i); 211313535Sngie } 212272343Sngie 213313535Sngie SAY("calling exec...\n"); 214313535Sngie 215272343Sngie /* then, we exec! */ 216272343Sngie execarg[0] = argv[0]; 217272343Sngie execarg[1] = nexec; 218272343Sngie execarg[2] = NULL; 219272343Sngie if (rumpclient_exec(argv[0], execarg, envp) == -1) 220272343Sngie err(1, "exec"); 221272343Sngie} 222