]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libthread/ioproc.c
libthread: make ioproc even when opening /proc/n/ctl fails (factotum)
[plan9front.git] / sys / src / libthread / ioproc.c
1 #include <u.h>
2 #include <libc.h>
3 #include <thread.h>
4 #include "threadimpl.h"
5
6 enum
7 {
8         STACK = 8192,
9 };
10
11 void
12 iointerrupt(Ioproc *io)
13 {
14         if(io->ctl < 0)
15                 return;
16         qlock(io);
17         if(++io->intr == 1)
18                 write(io->ctl, "interrupt", 9);
19         qunlock(io);
20 }
21
22 static void
23 xioproc(void *a)
24 {
25         Channel *c;
26         Ioproc *io;
27         Iocall *r;
28
29         c = a;
30         if(io = mallocz(sizeof(*io), 1)){
31                 char buf[128];
32
33                 /*
34                  * open might fail, ignore it for programs like factotum
35                  * that don't use iointerrupt() anyway.
36                  */
37                 snprint(buf, sizeof(buf), "/proc/%d/ctl", getpid());
38                 io->ctl = open(buf, OWRITE);
39
40                 if((io->creply = chancreate(sizeof(void*), 0)) == nil){
41                         if(io->ctl >= 0)
42                                 close(io->ctl);
43                         free(io);
44                         io = nil;
45                 } else
46                         io->c = c;
47         }
48         while(send(c, &io) < 0)
49                 ;
50         if(io == nil)
51                 return;
52
53         for(;;){
54                 while(recv(io->c, &r) < 0)
55                         ;
56                 if(r == 0)
57                         break;
58                 if(io->intr){
59                         r->ret = -1;
60                         strcpy(r->err, "interrupted");
61                 } else if((r->ret = r->op(&r->arg)) < 0)
62                         rerrstr(r->err, sizeof r->err);
63                 qlock(io);
64                 if(io->intr){
65                         io->intr = 0;
66                         if(io->ctl >= 0)
67                                 write(io->ctl, "nointerrupt", 11);
68                 }
69                 while(send(io->creply, &r) < 0)
70                         ;
71                 qunlock(io);
72         }
73
74         if(io->ctl >= 0)
75                 close(io->ctl);
76         chanfree(io->c);
77         chanfree(io->creply);
78         free(io);
79 }
80
81 Ioproc*
82 ioproc(void)
83 {
84         Channel *c;
85         Ioproc *io;
86
87         if((c = chancreate(sizeof(void*), 0)) == nil)
88                 sysfatal("ioproc chancreate");
89         proccreate(xioproc, c, STACK);
90         while(recv(c, &io) < 0)
91                 ;
92         if(io == nil)
93                 sysfatal("ioproc alloc");
94         return io;
95 }
96
97 void
98 closeioproc(Ioproc *io)
99 {
100         if(io == nil)
101                 return;
102         iointerrupt(io);
103         while(sendp(io->c, nil) < 0)
104                 ;
105 }