1#include <stdlib.h> 2#include <stdio.h> 3#include <unistd.h> 4#include <stdint.h> 5#include <errno.h> 6#include <err.h> 7#include <pthread.h> 8#include <spawn.h> 9 10extern char **environ; 11 12char * const *newargv; 13 14void usage(void); 15 16void *work(void *); 17 18int main(int argc, char *argv[]) { 19 20 int i, count, threadcount; 21 int ret; 22 pthread_t *threads; 23 24 if (argc < 4) { 25 usage(); 26 } 27 28 threadcount = atoi(argv[1]); 29 count = atoi(argv[2]); 30 31 newargv = &argv[3]; 32 33 threads = (pthread_t *)calloc(threadcount, sizeof(pthread_t)); 34 for (i=0; i < threadcount; i++) { 35 ret = pthread_create(&threads[i], NULL, work, (void *)(intptr_t)count); 36 if (ret) { 37 err(1, "pthread_create"); 38 } 39 } 40 41 for (i=0; i < threadcount; i++) { 42 ret = pthread_join(threads[i], NULL); 43 if (ret) { 44 err(1, "pthread_join"); 45 } 46 } 47 48 return 0; 49} 50 51void usage(void) { 52 fprintf(stderr, "Usage: %s <threadcount> <count> <program> [<arg1> [<arg2> ...]]\n", 53 getprogname()); 54 exit(1); 55} 56 57void *work(void *arg) 58{ 59 int count = (int)(intptr_t)arg; 60 int i; 61 int ret; 62 pid_t pid; 63 64 for (i=0; i < count; i++) { 65 ret = posix_spawn(&pid, newargv[0], NULL, NULL, newargv, environ); 66 if (ret != 0) { 67 errc(1, ret, "posix_spawn(%s)", newargv[0]); 68 } 69 70 while (-1 == waitpid(pid, &ret, 0)) { 71 if (errno != EINTR) { 72 err(1, "waitpid(%d)", pid); 73 } 74 } 75 76 if (WIFSIGNALED(ret)) { 77 errx(1, "process exited with signal %d", WTERMSIG(ret)); 78 } else if (WIFSTOPPED(ret)) { 79 errx(1, "process stopped with signal %d", WSTOPSIG(ret)); 80 } else if (WIFEXITED(ret)) { 81 if (WEXITSTATUS(ret) != 42) { 82 errx(1, "process exited with unexpected exit code %d", WEXITSTATUS(ret)); 83 } 84 } else { 85 errx(1, "unknown exit condition %x", ret); 86 } 87 } 88 89 return NULL; 90} 91