1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
|
.TH IOPROC 3
.SH NAME
closeioproc,
iocall,
ioclose,
iointerrupt,
iodial,
ioopen,
ioproc,
ioread,
ioreadn,
iowrite \- slave I/O processes for threaded programs
.SH SYNOPSIS
.PP
.de XX
.ift .sp 0.5
.ifn .sp
..
.EX
.ta \w'Ioproc* 'u
#include <u.h>
#include <libc.h>
#include <thread.h>
.sp
typedef struct Ioproc Ioproc;
.sp
Ioproc* ioproc(void);
.XX
int ioopen(Ioproc *io, char *file, int omode);
int ioclose(Ioproc *io, int fd);
long ioread(Ioproc *io, int fd, void *a, long n);
long ioreadn(Ioproc *io, int fd, void *a, long n);
long iowrite(Ioproc *io, int fd, void *a, long n);
int iodial(Ioproc *io, char *addr, char *local, char *dir, char *cdfp);
.XX
void iointerrupt(Ioproc *io);
void closeioproc(Ioproc *io);
.XX
long iocall(Ioproc *io, long (*op)(va_list *arg), ...);
.EE
.SH DESCRIPTION
.PP
These routines provide access to I/O in slave procs.
Since the I/O itself is done in a slave proc, other threads
in the calling proc can run while the calling thread
waits for the I/O to complete.
.PP
.I Ioproc
forks a new slave proc and returns a pointer to the
.B Ioproc
associated with it.
.I Ioproc
uses
.I mallocz
and
.IR proccreate ;
if either fails, it calls
.I sysfatal
rather than return an error.
.PP
.IR Ioopen ,
.IR ioclose ,
.IR ioread ,
.IR ioreadn ,
.IR iowrite ,
and
.IR iodial
are execute the
similarly named library or system calls
(see
.IR open (2),
.IR read (2),
and
.IR dial (2))
in the slave process associated with
.IR io .
It is an error to execute more than one call
at a time in an I/O proc.
.PP
.I Iointerrupt
interrupts the call currently executing in the I/O proc.
If no call is executing,
.IR iointerrupt
is a no-op.
.PP
.I Closeioproc
terminates the I/O proc and frees the associated
.B Ioproc .
.PP
.I Iocall
is a primitive that may be used to implement
more slave I/O routines.
.I Iocall
arranges for
.I op
to be called in
.IR io 's
proc, with
.I arg
set to the variable parameter list,
returning the value that
.I op
returns.
.SH EXAMPLE
Relay messages between two file descriptors,
counting the total number of bytes seen:
.IP
.EX
.ta +\w'xxxx'u +\w'xxxx'u +\w'xxxx'u
int tot;
void
relaythread(void *v)
{
int *fd, n;
char buf[1024];
Ioproc *io;
fd = v;
io = ioproc();
while((n = ioread(io, fd[0], buf, sizeof buf)) > 0){
if(iowrite(io, fd[1], buf, n) != n)
sysfatal("iowrite: %r");
tot += n;
}
closeioproc(io);
}
void
relay(int fd0, int fd1)
{
int fd[4];
fd[0] = fd[3] = fd0;
fd[1] = fd[2] = fd1;
threadcreate(relaythread, fd, 8192);
threadcreate(relaythread, fd+2, 8192);
}
.EE
.LP
If the two
.I relaythread
instances were running in different procs, the
common access to
.I tot
would be unsafe.
.EE
.PP
Implement
.IR ioread :
.IP
.EX
static long
_ioread(va_list *arg)
{
int fd;
void *a;
long n;
fd = va_arg(*arg, int);
a = va_arg(*arg, void*);
n = va_arg(*arg, long);
return read(fd, a, n);
}
long
ioread(Ioproc *io, int fd, void *a, long n)
{
return iocall(io, _ioread, fd, a, n);
}
.EE
.SH SOURCE
.B /sys/src/libthread/io*.c
.SH SEE ALSO
.IR dial (2),
.IR open (2),
.IR read (2),
.IR thread (2)
|