xref: /minix/tests/lib/librumpclient/h_execthr.c (revision 0a6a1f1d)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: h_execthr.c,v 1.3 2014/08/13 00:03:00 pooka Exp $	*/
211be35a1SLionel Sambuc 
311be35a1SLionel Sambuc /*
411be35a1SLionel Sambuc  * Copyright (c) 2011 The NetBSD Foundation, Inc.
511be35a1SLionel Sambuc  * All rights reserved.
611be35a1SLionel Sambuc  *
711be35a1SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
811be35a1SLionel Sambuc  * modification, are permitted provided that the following conditions
911be35a1SLionel Sambuc  * are met:
1011be35a1SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
1111be35a1SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
1211be35a1SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
1311be35a1SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in the
1411be35a1SLionel Sambuc  *    documentation and/or other materials provided with the distribution.
1511be35a1SLionel Sambuc  *
1611be35a1SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
1711be35a1SLionel Sambuc  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
1811be35a1SLionel Sambuc  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1911be35a1SLionel Sambuc  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2011be35a1SLionel Sambuc  * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
2111be35a1SLionel Sambuc  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2211be35a1SLionel Sambuc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
2311be35a1SLionel Sambuc  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2411be35a1SLionel Sambuc  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
2511be35a1SLionel Sambuc  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
2611be35a1SLionel Sambuc  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
2711be35a1SLionel Sambuc  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2811be35a1SLionel Sambuc  */
2911be35a1SLionel Sambuc 
3011be35a1SLionel Sambuc #include <sys/types.h>
3111be35a1SLionel Sambuc #include <sys/sysctl.h>
3211be35a1SLionel Sambuc 
3311be35a1SLionel Sambuc #include <err.h>
3411be35a1SLionel Sambuc #include <errno.h>
3511be35a1SLionel Sambuc #include <fcntl.h>
3611be35a1SLionel Sambuc #include <pthread.h>
3711be35a1SLionel Sambuc #include <stdio.h>
3811be35a1SLionel Sambuc #include <stdlib.h>
3911be35a1SLionel Sambuc #include <string.h>
4011be35a1SLionel Sambuc #include <unistd.h>
4111be35a1SLionel Sambuc 
4211be35a1SLionel Sambuc #include <rump/rumpclient.h>
4311be35a1SLionel Sambuc #include <rump/rump_syscalls.h>
4411be35a1SLionel Sambuc 
4511be35a1SLionel Sambuc static int canreturn = 0;
4611be35a1SLionel Sambuc 
4711be35a1SLionel Sambuc /*
4811be35a1SLionel Sambuc  * Use a fairly large number of threads so that we have
4911be35a1SLionel Sambuc  * a better chance catching races.  XXX: this is rumpuser's
5011be35a1SLionel Sambuc  * MAXWORKER-1.
5111be35a1SLionel Sambuc  */
5211be35a1SLionel Sambuc #define NTHR 63
5311be35a1SLionel Sambuc 
54*0a6a1f1dSLionel Sambuc #define P1_0 3
55*0a6a1f1dSLionel Sambuc #define P1_1 4
56*0a6a1f1dSLionel Sambuc #define P2_0 5
57*0a6a1f1dSLionel Sambuc #define P2_1 6
58*0a6a1f1dSLionel Sambuc 
5911be35a1SLionel Sambuc static void *
wrk(void * arg)6011be35a1SLionel Sambuc wrk(void *arg)
6111be35a1SLionel Sambuc {
6211be35a1SLionel Sambuc 	int fd = (uintptr_t)arg;
6311be35a1SLionel Sambuc 
6411be35a1SLionel Sambuc 	rump_sys_read(fd, &fd, sizeof(fd));
6511be35a1SLionel Sambuc 	if (!canreturn)
6611be35a1SLionel Sambuc 		errx(1, "should not have returned");
6711be35a1SLionel Sambuc 	if (fd != 37)
6811be35a1SLionel Sambuc 		errx(1, "got invalid magic");
6911be35a1SLionel Sambuc 
7011be35a1SLionel Sambuc 	return NULL;
7111be35a1SLionel Sambuc }
7211be35a1SLionel Sambuc 
7311be35a1SLionel Sambuc static int
getproc(pid_t mypid,struct kinfo_proc2 * p)7411be35a1SLionel Sambuc getproc(pid_t mypid, struct kinfo_proc2 *p)
7511be35a1SLionel Sambuc {
7611be35a1SLionel Sambuc 	int name[6];
7711be35a1SLionel Sambuc 	size_t len = sizeof(*p);
7811be35a1SLionel Sambuc 
7911be35a1SLionel Sambuc 	name[0] = CTL_KERN;
8011be35a1SLionel Sambuc 	name[1] = KERN_PROC2;
8111be35a1SLionel Sambuc 	name[2] = KERN_PROC_PID;
8211be35a1SLionel Sambuc 	name[3] = mypid;
8311be35a1SLionel Sambuc 	name[4] = len;
8411be35a1SLionel Sambuc 	name[5] = 1;
8511be35a1SLionel Sambuc 
8611be35a1SLionel Sambuc 	return rump_sys___sysctl(name, __arraycount(name), p, &len, NULL, 0);
8711be35a1SLionel Sambuc }
8811be35a1SLionel Sambuc 
8911be35a1SLionel Sambuc int
main(int argc,char * argv[],char * envp[])9011be35a1SLionel Sambuc main(int argc, char *argv[], char *envp[])
9111be35a1SLionel Sambuc {
9211be35a1SLionel Sambuc 	struct kinfo_proc2 p;
9311be35a1SLionel Sambuc 	char *execarg[3];
9411be35a1SLionel Sambuc 	int p1[2], p2[2];
9511be35a1SLionel Sambuc 	pid_t mypid;
9611be35a1SLionel Sambuc 	pthread_t pt;
9711be35a1SLionel Sambuc 	ssize_t n;
9811be35a1SLionel Sambuc 	int i, execd;
9911be35a1SLionel Sambuc 	char nexec[16];
10011be35a1SLionel Sambuc 
10111be35a1SLionel Sambuc 	if (argc > 1)
10211be35a1SLionel Sambuc 		execd = atoi(argv[1]);
10311be35a1SLionel Sambuc 	else
10411be35a1SLionel Sambuc 		execd = 0;
10511be35a1SLionel Sambuc 	sprintf(nexec, "%d", execd+1);
10611be35a1SLionel Sambuc 
10711be35a1SLionel Sambuc 	if (rumpclient_init() == -1) {
10811be35a1SLionel Sambuc 		if (execd)
10911be35a1SLionel Sambuc 			err(1, "init execd");
11011be35a1SLionel Sambuc 		else
11111be35a1SLionel Sambuc 			err(1, "init");
11211be35a1SLionel Sambuc 	}
11311be35a1SLionel Sambuc 	mypid = rump_sys_getpid();
11411be35a1SLionel Sambuc 
11511be35a1SLionel Sambuc 	if (execd) {
11611be35a1SLionel Sambuc 		canreturn = 1;
11711be35a1SLionel Sambuc 		if (pthread_create(&pt, NULL,
118*0a6a1f1dSLionel Sambuc 		    wrk, (void *)(uintptr_t)P2_0) != 0)
11911be35a1SLionel Sambuc 			errx(1, "exec pthread_create");
12011be35a1SLionel Sambuc 
12111be35a1SLionel Sambuc 		i = 37;
122*0a6a1f1dSLionel Sambuc 		rump_sys_write(P2_1, &i, sizeof(i));
12311be35a1SLionel Sambuc 		pthread_join(pt, NULL);
12411be35a1SLionel Sambuc 
125*0a6a1f1dSLionel Sambuc 		n = rump_sys_read(P1_0, &i, sizeof(i));
12611be35a1SLionel Sambuc 		if (n != -1 || errno != EBADF)
12711be35a1SLionel Sambuc 			errx(1, "post-exec cloexec works");
12811be35a1SLionel Sambuc 
12911be35a1SLionel Sambuc 		getproc(mypid, &p);
13011be35a1SLionel Sambuc 		if (p.p_nlwps != 2)
13111be35a1SLionel Sambuc 			errx(1, "invalid nlwps: %lld", (long long)p.p_nlwps);
13211be35a1SLionel Sambuc 
13311be35a1SLionel Sambuc 		/* we passed? */
13411be35a1SLionel Sambuc 		if (execd > 10)
13511be35a1SLionel Sambuc 			exit(0);
13611be35a1SLionel Sambuc 
137*0a6a1f1dSLionel Sambuc 		rump_sys_close(P2_0);
138*0a6a1f1dSLionel Sambuc 		rump_sys_close(P2_1);
13911be35a1SLionel Sambuc 	}
14011be35a1SLionel Sambuc 
14111be35a1SLionel Sambuc 	if (rump_sys_pipe(p1) == -1)
14211be35a1SLionel Sambuc 		err(1, "pipe1");
143*0a6a1f1dSLionel Sambuc 	if (p1[0] != P1_0 || p1[1] != P1_1)
14411be35a1SLionel Sambuc 		errx(1, "p1 assumptions failed %d %d", p1[0], p1[1]);
14511be35a1SLionel Sambuc 	if (rump_sys_pipe(p2) == -1)
14611be35a1SLionel Sambuc 		err(1, "pipe1");
147*0a6a1f1dSLionel Sambuc 	if (p2[0] != P2_0 || p2[1] != P2_1)
14811be35a1SLionel Sambuc 		errx(1, "p2 assumptions failed");
14911be35a1SLionel Sambuc 	if (rump_sys_fcntl(p1[0], F_SETFD, FD_CLOEXEC) == -1)
15011be35a1SLionel Sambuc 		err(1, "cloexec");
15111be35a1SLionel Sambuc 	if (rump_sys_fcntl(p1[1], F_SETFD, FD_CLOEXEC) == -1)
15211be35a1SLionel Sambuc 		err(1, "cloexec");
15311be35a1SLionel Sambuc 
15411be35a1SLionel Sambuc 	for (i = 0; i < NTHR; i++)
15511be35a1SLionel Sambuc 		if (pthread_create(&pt, NULL,
15611be35a1SLionel Sambuc 		    wrk, (void *)(uintptr_t)p1[0]) != 0)
15711be35a1SLionel Sambuc 			errx(1, "pthread_create 1 %d", i);
15811be35a1SLionel Sambuc 
15911be35a1SLionel Sambuc 	for (i = 0; i < NTHR; i++)
16011be35a1SLionel Sambuc 		if (pthread_create(&pt, NULL,
16111be35a1SLionel Sambuc 		    wrk, (void *)(uintptr_t)p2[0]) != 0)
16211be35a1SLionel Sambuc 			errx(1, "pthread_create 2 %d", i);
16311be35a1SLionel Sambuc 
16411be35a1SLionel Sambuc 	/* wait for all the threads to be enjoying themselves */
16511be35a1SLionel Sambuc 	for (;;) {
16611be35a1SLionel Sambuc 		getproc(mypid, &p);
16711be35a1SLionel Sambuc 		if (p.p_nlwps == 2*NTHR + 2)
16811be35a1SLionel Sambuc 			break;
16911be35a1SLionel Sambuc 		usleep(10000);
17011be35a1SLionel Sambuc 	}
17111be35a1SLionel Sambuc 
17211be35a1SLionel Sambuc 	/*
17311be35a1SLionel Sambuc 	 * load up one more (big) set.  these won't start executing, though,
17411be35a1SLionel Sambuc 	 * but we're interested in if they create blockage
17511be35a1SLionel Sambuc 	 */
17611be35a1SLionel Sambuc 	for (i = 0; i < 3*NTHR; i++)
17711be35a1SLionel Sambuc 		if (pthread_create(&pt, NULL,
17811be35a1SLionel Sambuc 		    wrk, (void *)(uintptr_t)p1[0]) != 0)
17911be35a1SLionel Sambuc 			errx(1, "pthread_create 1 %d", i);
18011be35a1SLionel Sambuc 
18111be35a1SLionel Sambuc 	/* then, we exec! */
18211be35a1SLionel Sambuc 	execarg[0] = argv[0];
18311be35a1SLionel Sambuc 	execarg[1] = nexec;
18411be35a1SLionel Sambuc 	execarg[2] = NULL;
18511be35a1SLionel Sambuc 	if (rumpclient_exec(argv[0], execarg, envp) == -1)
18611be35a1SLionel Sambuc 		err(1, "exec");
18711be35a1SLionel Sambuc }
188