aboutsummaryrefslogtreecommitdiff
path: root/man/man3/thread.html
blob: b14d97e629578edf3916d2be15ee26c72e32e5de (plain)
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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
<head>
<title>thread(3) - Plan 9 from User Space</title>
<meta content="text/html; charset=utf-8" http-equiv=Content-Type>
</head>
<body bgcolor=#ffffff>
<table border=0 cellpadding=0 cellspacing=0 width=100%>
<tr height=10><td>
<tr><td width=20><td>
<tr><td width=20><td><b>THREAD(3)</b><td align=right><b>THREAD(3)</b>
<tr><td width=20><td colspan=2>
    <br>
<p><font size=+1><b>NAME     </b></font><br>

<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>

    alt, chancreate, chanfree, chaninit, chanprint, chansetname, mainstacksize,
    proccreate, procdata, recv, recvp, recvul, send, sendp, sendul,
    nbrecv, nbrecvp, nbrecvul, nbsend, nbsendp, nbsendul, threadcreate,
    threaddata, threadexec, threadexecl, threadexits, threadexitsall,
    threadgetgrp, threadgetname, threadint,
    threadintgrp, threadkill, threadkillgrp, threadmain, threadnotify,
    threadid, threadpid, threadsetgrp, threadsetname, threadsetstate,
    threadspawn, threadwaitchan, yield &ndash; thread and proc management<br>
    
</table>
<p><font size=+1><b>SYNOPSIS     </b></font><br>

<table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>


<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>

    <tt><font size=+1>#include &lt;u.h&gt;<br>
    #include &lt;libc.h&gt;<br>
    #include &lt;thread.h&gt;<br>
    #define &nbsp;&nbsp;&nbsp;CHANEND  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0<br>
    #define &nbsp;&nbsp;&nbsp;CHANSND  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1<br>
    #define &nbsp;&nbsp;&nbsp;CHANRCV  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2<br>
    #define &nbsp;&nbsp;&nbsp;CHANNOP  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3<br>
    #define &nbsp;&nbsp;&nbsp;CHANNOBLK &nbsp;&nbsp;&nbsp;4<br>
    typedef struct Alt Alt;<br>
    struct Alt {<br>
    
    <table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>

        Channel *c;<br>
        void &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*v;<br>
        int &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;op;<br>
        Channel **tag;<br>
        int &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entryno;<br>
        char &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*name;<br>
        
    </table>
    };<br>
    
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    void &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;threadmain(int argc, char *argv[])<br>
    int &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mainstacksize<br>
    int &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;proccreate(void (*fn)(void*), void *arg, uint stacksize)<br>
    int &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;threadcreate(void (*fn)(void*), void *arg, uint stacksize)<br>
    void &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;threadexits(char *status)<br>
    void &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;threadexitsall(char *status)<br>
    void &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;yield(void)<br>
    int &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;threadid(void)<br>
    int &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;threadgrp(void)<br>
    int &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;threadsetgrp(int group)<br>
    int &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;threadpid(int id)<br>
    int &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;threadint(int id)<br>
    int &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;threadintgrp(int group)<br>
    int &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;threadkill(int id)<br>
    int &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;threadkillgrp(int group)<br>
    void &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;threadsetname(char *name)<br>
    char* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;threadgetname(void)<br>
    void** &nbsp;&nbsp;&nbsp;&nbsp;threaddata(void)<br>
    void** &nbsp;&nbsp;&nbsp;&nbsp;procdata(void)<br>
    int &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;chaninit(Channel *c, int elsize, int nel)<br>
    Channel* chancreate(int elsize, int nel)<br>
    void &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;chanfree(Channel *c)<br>
    int &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alt(Alt *alts)<br>
    int &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;recv(Channel *c, void *v)<br>
    void* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;recvp(Channel *c)<br>
    ulong &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;recvul(Channel *c)<br>
    int &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nbrecv(Channel *c, void *v)<br>
    void* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nbrecvp(Channel *c)<br>
    ulong &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nbrecvul(Channel *c)<br>
    int &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;send(Channel *c, void *v)<br>
    int &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sendp(Channel *c, void *v)<br>
    int &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sendul(Channel *c, ulong v)<br>
    int &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nbsend(Channel *c, void *v)<br>
    int &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nbsendp(Channel *c, void *v)<br>
    int &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nbsendul(Channel *c, ulong v)<br>
    int &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;chanprint(Channel *c, char *fmt, ...)<br>
    int &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;threadspawn(int fd[3], char *file, char *args[])<br>
    int &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;threadexecl(Channel *cpid, int fd[3], char *file, ...)<br>
    int &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;threadexec(Channel *cpid, int fd[3], char *file, char *args[])<br>
    Channel* threadwaitchan(void)<br>
    int &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;threadnotify(int (*f)(void*, char*), int in)<br>
    </font></tt>
</table>
<p><font size=+1><b>DESCRIPTION     </b></font><br>

<table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>


<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>

    The thread library provides parallel programming support similar
    to that of the languages Alef and Newsqueak. Threads and procs
    occupy a shared address space, communicating and synchronizing
    through <i>channels</i> and shared variables. 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    A <i>proc</i> is a Plan 9 process that contains one or more cooperatively
    scheduled <i>threads</i>. Programs using threads must replace <i>main</i> by
    <i>threadmain</i>. The thread library provides a <i>main</i> function that sets
    up a proc with a single thread executing <i>threadmain</i> on a stack
    of size <i>mainstacksize</i> (default eight kilobytes). To set
    <i>mainstacksize</i>, declare a global variable initialized to the desired
    value (<i>e.g.</i>, <tt><font size=+1>int mainstacksize = 1024</font></tt>). 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    <i>Threadcreate</i> creates a new thread in the calling proc, returning
    a unique integer identifying the thread; the thread executes <i>fn(arg)</i>
    on a stack of size <i>stacksize</i>. Thread stacks are allocated in shared
    memory, making it valid to pass pointers to stack variables between
    threads and procs. <i>Proccreate</i> creates a new proc,
    and inside that proc creates a single thread as <i>threadcreate</i> would,
    returning the id of the created thread. Be aware that the calling
    thread may continue execution before the newly created proc and
    thread are scheduled. Because of this, <i>arg</i> should not point to
    data on the stack of a function that could return before the
    new process is scheduled. 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    <i>Threadexits</i> terminates the calling thread. If the thread is the
    last in its proc, <i>threadexits</i> also terminates the proc, using
    <i>status</i> as the exit status. <i>Threadexitsall</i> terminates all procs
    in the program, using <i>status</i> as the exit status. 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    When the last thread in <i>threadmain</i>&#8217;s proc exits, the program will
    appear to its parent to have exited. The remaining procs will
    still run together, but as a background program. 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    The threads in a proc are coroutines, scheduled nonpreemptively
    in a round-robin fashion. A thread must explicitly relinquish
    control of the processor before another thread in the same proc
    is run. Calls that do this are <i>yield</i>, <i>proccreate</i>, <i>threadexec</i>,
    <i>threadexecl</i>, <i>threadexits</i>, <i>threadspawn</i>, <i>alt</i>, <i>send</i>, and <i>recv</i> (and
    the
    calls related to <i>send</i> and <i>recv</i>--see their descriptions further on).
    Procs are scheduled by the operating system. Therefore, threads
    in different procs can preempt one another in arbitrary ways and
    should synchronize their actions using <tt><font size=+1>qlocks</font></tt> (see <a href="../man3/lock.html"><i>lock</i>(3)</a>) or
    channel communication. System calls such as <a href="../man3/read.html"><i>read</i>(3)</a>
    block the entire proc; all threads in a proc block until the system
    call finishes. 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    As mentioned above, each thread has a unique integer thread id.
    Thread ids are not reused; they are unique across the life of
    the program. <i>Threadid</i> returns the id for the current thread. Each
    thread also has a thread group id. The initial thread has a group
    id of zero. Each new thread inherits the group id of the
    thread that created it. <i>Threadgrp</i> returns the group id for the
    current thread; <i>threadsetgrp</i> sets it. <i>Threadpid</i> returns the pid
    of the Plan 9 process containing the thread identified by <i>id</i>,
    or &ndash;1 if no such thread is found. 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    <i>Threadint</i> interrupts a thread that is blocked in a channel operation
    or system call. <i>Threadintgrp</i> interrupts all threads with the given
    group id. <i>Threadkill</i> marks a thread to die when it next relinquishes
    the processor (via one of the calls listed above). If the thread
    is blocked in a channel operation or system call, it is
    also interrupted. <i>Threadkillgrp</i> kills all threads with the given
    group id. Note that <i>threadkill</i> and <i>threadkillgrp</i> will not terminate
    a thread that never relinquishes the processor. 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    Primarily for debugging, threads can have string names associated
    with them. <i>Threadgetname</i> returns the current thread&#8217;s name; <i>threadsetname</i>
    sets it. The pointer returned by <i>threadgetname</i> is only valid until
    the next call to <i>threadsetname</i>. 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    Also for debugging, threads have a string state associated with
    them. <i>Threadsetstate</i> sets the state string. There is no <i>threadgetstate</i>;
    since the thread scheduler resets the state to <tt><font size=+1>Running</font></tt> every time
    it runs the thread, it is only useful for debuggers to inspect
    the state. 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    <i>Threaddata</i> returns a pointer to a per-thread pointer that may
    be modified by threaded programs for per-thread storage. Similarly,
    <i>procdata</i> returns a pointer to a per-proc pointer. 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    <i>Threadexecl</i> and <i>threadexec</i> are threaded analogues of <i>exec</i> and
    <i>execl</i> (see <a href="../man3/exec.html"><i>exec</i>(3)</a>); on success, they replace the calling thread
    and invoke the external program, never returning. (Unlike on Plan
    9, the calling thread need not be the only thread in its proc--the
    other threads will continue executing.) On error, they return
    &ndash;1. If <i>cpid</i> is not null, the pid of the invoked program will be
    sent along <i>cpid</i> (using <i>sendul</i>) once the program has been started,
    or &ndash;1 will be sent if an error occurs. <i>Threadexec</i> and <i>threadexecl</i>
    will not access their arguments after sending a result along <i>cpid</i>.
    Thus, programs that malloc the <i>argv</i> passed to <i>threadexec
    </i>can safely free it once they have received the <i>cpid</i> response.
    
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    <i>Threadexecl</i> and <i>threadexec</i> will duplicate (see <a href="../man3/dup.html"><i>dup</i>(3)</a>) the three
    file descriptors in <i>fd</i> onto standard input, output, and error
    for the external program and then close them in the calling thread.
    Beware of code that sets<br>
    
    <table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>

        <tt><font size=+1>fd[0] = 0;<br>
        fd[1] = 1;<br>
        fd[2] = 2;<br>
        
        <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
        </font></tt>
        
    </table>
    to use the current standard files. The correct code is<br>
    
    <table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>

        <tt><font size=+1>fd[0] = dup(0, &#8722;1);<br>
        fd[1] = dup(1, &#8722;1);<br>
        fd[2] = dup(2, &#8722;1);<br>
        
        <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
        </font></tt>
        
    </table>
    <i>Threadspawn</i> is like <i>threadexec</i> but does not replace the current
    thread. It returns the pid of the invoked program on success,
    or &ndash;1 on error. 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    <i>Threadwaitchan</i> returns a channel of pointers to <tt><font size=+1>Waitmsg</font></tt> structures
    (see <a href="../man3/wait.html"><i>wait</i>(3)</a>). When an exec&#8217;ed process exits, a pointer to a <tt><font size=+1>Waitmsg</font></tt>
    is sent to this channel. These <tt><font size=+1>Waitmsg</font></tt> structures have been allocated
    with <a href="../man3/malloc.html"><i>malloc</i>(3)</a> and should be freed after use. 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    A <tt><font size=+1>Channel</font></tt> is a buffered or unbuffered queue for fixed-size messages.
    Procs and threads <i>send</i> messages into the channel and <i>recv</i> messages
    from the channel. If the channel is unbuffered, a <i>send</i> operation
    blocks until the corresponding <i>recv</i> operation occurs and <i>vice
    versa</i>. <i>Chaninit</i> initializes a <tt><font size=+1>Channel</font></tt> for
    messages of size <i>elsize</i> and with a buffer holding <i>nel</i> messages.
    If <i>nel</i> is zero, the channel is unbuffered. <i>Chancreate</i> allocates
    a new channel and initializes it. <i>Chanfree</i> frees a channel that
    is no longer used. <i>Chanfree</i> can be called by either sender or
    receiver after the last item has been sent or received. Freeing
    the
    channel will be delayed if there is a thread blocked on it until
    that thread unblocks (but <i>chanfree</i> returns immediately). 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    The <tt><font size=+1>name</font></tt> element in the <tt><font size=+1>Channel</font></tt> structure is a description intended
    for use in debugging. <i>Chansetname</i> sets the name. 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    <i>Send</i> sends the element pointed at by <i>v</i> to the channel <i>c</i>. If <i>v</i>
    is null, zeros are sent. <i>Recv</i> receives an element from <i>c</i> and stores
    it in <i>v</i>. If <i>v</i> is null, the received value is discarded. <i>Send</i> and
    <i>recv</i> return 1 on success, &ndash;1 if interrupted. <i>Nbsend</i> and <i>nbrecv</i>
    behave similarly, but return 0 rather than blocking. 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    <i>Sendp</i>, <i>nbsendp</i>, <i>sendul</i>, and <i>nbsendul</i> send a pointer or an unsigned
    long; the channel must have been initialized with the appropriate
    <i>elsize</i>. <i>Recvp</i>, <i>nbrecvp</i>, <i>recvul</i>, and <i>nbrecvul</i> receive a pointer
    or an unsigned long; they return zero when a zero is received,
    when interrupted, or (for <i>nbrecvp</i> and <i>nbrecvul</i>) when the
    operation would have blocked. To distinguish between these three
    cases, use <i>recv</i> or <i>nbrecv</i>. 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    <i>Alt</i> can be used to recv from or send to one of a number of channels,
    as directed by an array of <tt><font size=+1>Alt</font></tt> structures, each of which describes
    a potential send or receive operation. In an <tt><font size=+1>Alt</font></tt> structure, <tt><font size=+1>c</font></tt>
    is the channel; <tt><font size=+1>v</font></tt> the value pointer (which may be null); and <tt><font size=+1>op</font></tt>
    the operation: <tt><font size=+1>CHANSND</font></tt> for a send operation,
    <tt><font size=+1>CHANRECV</font></tt> for a recv operation; <tt><font size=+1>CHANNOP</font></tt> for no operation (useful
    when <i>alt</i> is called with a varying set of operations). The array
    of <tt><font size=+1>Alt</font></tt> structures is terminated by an entry with <i>op</i> <tt><font size=+1>CHANEND</font></tt> or
    <tt><font size=+1>CHANNOBLK</font></tt>. If at least one <tt><font size=+1>Alt</font></tt> structure can proceed, one of them
    is chosen at random to be executed. <i>Alt</i> returns the
    index of the chosen structure. If no operations can proceed and
    the list is terminated with <tt><font size=+1>CHANNOBLK</font></tt>, <i>alt</i> returns the index of
    the terminating <tt><font size=+1>CHANNOBLK</font></tt> structure. Otherwise, <i>alt</i> blocks until
    one of the operations can proceed, eventually returning the index
    of the structure executes. <i>Alt</i> returns &ndash;1 when
    interrupted. The <tt><font size=+1>tag</font></tt> and <tt><font size=+1>entryno</font></tt> fields in the <tt><font size=+1>Alt</font></tt> structure are
    used internally by <i>alt</i> and need not be initialized. They are not
    used between <i>alt</i> calls. 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    <i>Chanprint</i> formats its arguments in the manner of <a href="../man3/print.html"><i>print</i>(3)</a> and
    sends the result to the channel <i>c.</i> The string delivered by <i>chanprint</i>
    is allocated with <a href="../man3/malloc.html"><i>malloc</i>(3)</a> and should be freed upon receipt.
    
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    Thread library functions do not return on failure; if errors occur,
    the entire program is aborted. 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    Threaded programs should use <i>threadnotify</i> in place of <i>atnotify</i>
    (see <a href="../man3/notify.html"><i>notify</i>(3)</a>). 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    It is safe to use <a href="../man3/sysfatal.html"><i>sysfatal</i>(3)</a> in threaded programs. <i>Sysfatal</i> will
    print the error string and call <i>threadexitsall</i>. 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    It is not safe to call <i>rfork</i> in a threaded program, except to
    call <tt><font size=+1>rfork(RFNOTEG)</font></tt> from the main proc before any other procs
    have been created. To create new processes, use <i>proccreate</i>.<br>
    
</table>
<p><font size=+1><b>FILES     </b></font><br>

<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>

    <tt><font size=+1>/usr/local/plan9/acid/thread</font></tt> contains useful <a href="../man1/acid.html"><i>acid</i>(1)</a> functions
    for debugging threaded programs. 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    <tt><font size=+1>/usr/local/plan9/src/libthread/test</font></tt> contains some example programs.<br>
    
</table>
<p><font size=+1><b>SOURCE     </b></font><br>

<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>

    <tt><font size=+1>/usr/local/plan9/src/libthread<br>
    </font></tt>
</table>
<p><font size=+1><b>SEE ALSO    </b></font><br>

<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>

    <a href="../man3/intro.html"><i>intro</i>(3)</a>, <a href="../man3/ioproc.html"><i>ioproc</i>(3)</a><br>
    
</table>
<p><font size=+1><b>BUGS     </b></font><br>

<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>

    To avoid name conflicts, <i>alt</i>, <i>nbrecv</i>, <i>nbrecvp</i>, <i>nbrecvul</i>, <i>nbsend</i>,
    <i>nbsendp</i>, <i>nbsendul</i>, <i>recv</i>, <i>recvp</i>, <i>recvul</i>, <i>send</i>, <i>sendp</i>, and <i>sendul</i>
    are defined as macros that expand to <i>chanalt</i>, <i>channbrecv</i>, and
    so on. <i>Yield</i> is defined as a macro that expands to <i>threadyield</i>.
    See <a href="../man3/intro.html"><i>intro</i>(3)</a>. 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    The implementation of <i>threadnotify</i> may not be correct.<br>
    
</table>

<td width=20>
<tr height=20><td>
</table>
<!-- TRAILER -->
<table border=0 cellpadding=0 cellspacing=0 width=100%>
<tr height=15><td width=10><td><td width=10>
<tr><td><td>
<center>
<a href="../../"><img src="../../dist/spaceglenda100.png" alt="Space Glenda" border=1></a>
</center>
</table>
<!-- TRAILER -->
</body></html>