Blame


1 1544f909 2004-12-25 devnull #include "u.h"
2 1544f909 2004-12-25 devnull #include <errno.h>
3 1544f909 2004-12-25 devnull #include "libc.h"
4 1544f909 2004-12-25 devnull #include "thread.h"
5 1544f909 2004-12-25 devnull #include "threadimpl.h"
6 1544f909 2004-12-25 devnull
7 1544f909 2004-12-25 devnull static Lock thewaitlock;
8 1544f909 2004-12-25 devnull static Channel *thewaitchan;
9 1544f909 2004-12-25 devnull static Channel *dowaitchan;
10 1544f909 2004-12-25 devnull
11 1544f909 2004-12-25 devnull /* BUG - start waitproc on first exec, not when threadwaitchan is called */
12 1544f909 2004-12-25 devnull static void
13 1544f909 2004-12-25 devnull waitproc(void *v)
14 1544f909 2004-12-25 devnull {
15 1544f909 2004-12-25 devnull Channel *c;
16 1544f909 2004-12-25 devnull Waitmsg *w;
17 1544f909 2004-12-25 devnull
18 1544f909 2004-12-25 devnull _threadsetsysproc();
19 1544f909 2004-12-25 devnull for(;;){
20 1544f909 2004-12-25 devnull while((w = wait()) == nil){
21 1544f909 2004-12-25 devnull if(errno == ECHILD)
22 1544f909 2004-12-25 devnull recvul(dowaitchan);
23 1544f909 2004-12-25 devnull }
24 1544f909 2004-12-25 devnull if((c = thewaitchan) != nil)
25 1544f909 2004-12-25 devnull sendp(c, w);
26 1544f909 2004-12-25 devnull else
27 1544f909 2004-12-25 devnull free(w);
28 1544f909 2004-12-25 devnull }
29 1544f909 2004-12-25 devnull }
30 1544f909 2004-12-25 devnull
31 1544f909 2004-12-25 devnull Channel*
32 1544f909 2004-12-25 devnull threadwaitchan(void)
33 1544f909 2004-12-25 devnull {
34 1544f909 2004-12-25 devnull if(thewaitchan)
35 1544f909 2004-12-25 devnull return thewaitchan;
36 1544f909 2004-12-25 devnull lock(&thewaitlock);
37 1544f909 2004-12-25 devnull if(thewaitchan){
38 1544f909 2004-12-25 devnull unlock(&thewaitlock);
39 1544f909 2004-12-25 devnull return thewaitchan;
40 1544f909 2004-12-25 devnull }
41 1544f909 2004-12-25 devnull thewaitchan = chancreate(sizeof(Waitmsg*), 4);
42 1544f909 2004-12-25 devnull chansetname(thewaitchan, "threadwaitchan");
43 1544f909 2004-12-25 devnull dowaitchan = chancreate(sizeof(ulong), 1);
44 1544f909 2004-12-25 devnull chansetname(dowaitchan, "dowaitchan");
45 1544f909 2004-12-25 devnull proccreate(waitproc, nil, STACK);
46 1544f909 2004-12-25 devnull unlock(&thewaitlock);
47 1544f909 2004-12-25 devnull return thewaitchan;
48 1544f909 2004-12-25 devnull }
49 1544f909 2004-12-25 devnull
50 1544f909 2004-12-25 devnull int
51 1544f909 2004-12-25 devnull threadspawn(int fd[3], char *cmd, char *argv[])
52 1544f909 2004-12-25 devnull {
53 1544f909 2004-12-25 devnull int i, n, p[2], pid;
54 1544f909 2004-12-25 devnull char exitstr[100];
55 1544f909 2004-12-25 devnull
56 1544f909 2004-12-25 devnull if(pipe(p) < 0)
57 1544f909 2004-12-25 devnull return -1;
58 1544f909 2004-12-25 devnull if(fcntl(p[0], F_SETFD, 1) < 0 || fcntl(p[1], F_SETFD, 1) < 0){
59 1544f909 2004-12-25 devnull close(p[0]);
60 1544f909 2004-12-25 devnull close(p[1]);
61 1544f909 2004-12-25 devnull return -1;
62 1544f909 2004-12-25 devnull }
63 1544f909 2004-12-25 devnull switch(pid = fork()){
64 1544f909 2004-12-25 devnull case -1:
65 1544f909 2004-12-25 devnull close(p[0]);
66 1544f909 2004-12-25 devnull close(p[1]);
67 1544f909 2004-12-25 devnull return -1;
68 1544f909 2004-12-25 devnull case 0:
69 1544f909 2004-12-25 devnull dup2(fd[0], 0);
70 1544f909 2004-12-25 devnull dup2(fd[1], 1);
71 1544f909 2004-12-25 devnull dup2(fd[2], 2);
72 1544f909 2004-12-25 devnull for(i=3; i<100; i++)
73 1544f909 2004-12-25 devnull if(i != p[1])
74 1544f909 2004-12-25 devnull close(i);
75 1544f909 2004-12-25 devnull execvp(cmd, argv);
76 1544f909 2004-12-25 devnull fprint(p[1], "%d", errno);
77 1544f909 2004-12-25 devnull close(p[1]);
78 1544f909 2004-12-25 devnull _exit(0);
79 1544f909 2004-12-25 devnull }
80 1544f909 2004-12-25 devnull
81 1544f909 2004-12-25 devnull close(p[1]);
82 1544f909 2004-12-25 devnull n = read(p[0], exitstr, sizeof exitstr-1);
83 1544f909 2004-12-25 devnull close(p[0]);
84 1544f909 2004-12-25 devnull if(n > 0){ /* exec failed */
85 1544f909 2004-12-25 devnull exitstr[n] = 0;
86 1544f909 2004-12-25 devnull errno = atoi(exitstr);
87 1544f909 2004-12-25 devnull return -1;
88 1544f909 2004-12-25 devnull }
89 1544f909 2004-12-25 devnull
90 1544f909 2004-12-25 devnull close(fd[0]);
91 1544f909 2004-12-25 devnull if(fd[1] != fd[0])
92 1544f909 2004-12-25 devnull close(fd[1]);
93 1544f909 2004-12-25 devnull if(fd[2] != fd[1] && fd[2] != fd[0])
94 1544f909 2004-12-25 devnull close(fd[2]);
95 1544f909 2004-12-25 devnull channbsendul(dowaitchan, 1);
96 1544f909 2004-12-25 devnull return pid;
97 1544f909 2004-12-25 devnull }
98 1544f909 2004-12-25 devnull
99 1544f909 2004-12-25 devnull int
100 1544f909 2004-12-25 devnull _threadexec(Channel *cpid, int fd[3], char *cmd, char *argv[])
101 1544f909 2004-12-25 devnull {
102 1544f909 2004-12-25 devnull int pid;
103 1544f909 2004-12-25 devnull
104 1544f909 2004-12-25 devnull pid = threadspawn(fd, cmd, argv);
105 1544f909 2004-12-25 devnull if(cpid){
106 1544f909 2004-12-25 devnull if(pid < 0)
107 1544f909 2004-12-25 devnull chansendul(cpid, ~0);
108 1544f909 2004-12-25 devnull else
109 1544f909 2004-12-25 devnull chansendul(cpid, pid);
110 1544f909 2004-12-25 devnull }
111 1544f909 2004-12-25 devnull return pid;
112 1544f909 2004-12-25 devnull }
113 1544f909 2004-12-25 devnull
114 1544f909 2004-12-25 devnull void
115 1544f909 2004-12-25 devnull threadexec(Channel *cpid, int fd[3], char *cmd, char *argv[])
116 1544f909 2004-12-25 devnull {
117 1544f909 2004-12-25 devnull if(_threadexec(cpid, fd, cmd, argv) >= 0)
118 1544f909 2004-12-25 devnull threadexits("threadexec");
119 1544f909 2004-12-25 devnull }
120 1544f909 2004-12-25 devnull
121 1544f909 2004-12-25 devnull void
122 1544f909 2004-12-25 devnull threadexecl(Channel *cpid, int fd[3], char *cmd, ...)
123 1544f909 2004-12-25 devnull {
124 1544f909 2004-12-25 devnull char **argv, *s;
125 1544f909 2004-12-25 devnull int n, pid;
126 1544f909 2004-12-25 devnull va_list arg;
127 1544f909 2004-12-25 devnull
128 1544f909 2004-12-25 devnull va_start(arg, cmd);
129 1544f909 2004-12-25 devnull for(n=0; va_arg(arg, char*) != nil; n++)
130 1544f909 2004-12-25 devnull ;
131 1544f909 2004-12-25 devnull n++;
132 1544f909 2004-12-25 devnull va_end(arg);
133 1544f909 2004-12-25 devnull
134 1544f909 2004-12-25 devnull argv = malloc(n*sizeof(argv[0]));
135 1544f909 2004-12-25 devnull if(argv == nil){
136 1544f909 2004-12-25 devnull if(cpid)
137 1544f909 2004-12-25 devnull chansendul(cpid, ~0);
138 1544f909 2004-12-25 devnull return;
139 1544f909 2004-12-25 devnull }
140 1544f909 2004-12-25 devnull
141 1544f909 2004-12-25 devnull va_start(arg, cmd);
142 1544f909 2004-12-25 devnull for(n=0; (s=va_arg(arg, char*)) != nil; n++)
143 1544f909 2004-12-25 devnull argv[n] = s;
144 1544f909 2004-12-25 devnull argv[n] = 0;
145 1544f909 2004-12-25 devnull va_end(arg);
146 1544f909 2004-12-25 devnull
147 1544f909 2004-12-25 devnull pid = _threadexec(cpid, fd, cmd, argv);
148 1544f909 2004-12-25 devnull free(argv);
149 1544f909 2004-12-25 devnull
150 1544f909 2004-12-25 devnull if(pid >= 0)
151 1544f909 2004-12-25 devnull threadexits("threadexecl");
152 1544f909 2004-12-25 devnull }
153 1544f909 2004-12-25 devnull