OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [doc/] [html/] [ref/] [kernel-condition-variables.html] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 28 unneback
<!-- Copyright (C) 2003 Red Hat, Inc.                                -->
2
<!-- This material may be distributed only subject to the terms      -->
3
<!-- and conditions set forth in the Open Publication License, v1.0  -->
4
<!-- or later (the latest version is presently available at          -->
5
<!-- http://www.opencontent.org/openpub/).                           -->
6
<!-- Distribution of the work or derivative of the work in any       -->
7
<!-- standard (paper) book form is prohibited unless prior           -->
8
<!-- permission is obtained from the copyright holder.               -->
9
<HTML
10
><HEAD
11
><TITLE
12
>Condition Variables</TITLE
13
><meta name="MSSmartTagsPreventParsing" content="TRUE">
14
<META
15
NAME="GENERATOR"
16
CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+
17
"><LINK
18
REL="HOME"
19
TITLE="eCos Reference Manual"
20
HREF="ecos-ref.html"><LINK
21
REL="UP"
22
TITLE="The eCos Kernel"
23
HREF="kernel.html"><LINK
24
REL="PREVIOUS"
25
TITLE="Mutexes"
26
HREF="kernel-mutexes.html"><LINK
27
REL="NEXT"
28
TITLE="Semaphores"
29
HREF="kernel-semaphores.html"></HEAD
30
><BODY
31
CLASS="REFENTRY"
32
BGCOLOR="#FFFFFF"
33
TEXT="#000000"
34
LINK="#0000FF"
35
VLINK="#840084"
36
ALINK="#0000FF"
37
><DIV
38
CLASS="NAVHEADER"
39
><TABLE
40
SUMMARY="Header navigation table"
41
WIDTH="100%"
42
BORDER="0"
43
CELLPADDING="0"
44
CELLSPACING="0"
45
><TR
46
><TH
47
COLSPAN="3"
48
ALIGN="center"
49
>eCos Reference Manual</TH
50
></TR
51
><TR
52
><TD
53
WIDTH="10%"
54
ALIGN="left"
55
VALIGN="bottom"
56
><A
57
HREF="kernel-mutexes.html"
58
ACCESSKEY="P"
59
>Prev</A
60
></TD
61
><TD
62
WIDTH="80%"
63
ALIGN="center"
64
VALIGN="bottom"
65
></TD
66
><TD
67
WIDTH="10%"
68
ALIGN="right"
69
VALIGN="bottom"
70
><A
71
HREF="kernel-semaphores.html"
72
ACCESSKEY="N"
73
>Next</A
74
></TD
75
></TR
76
></TABLE
77
><HR
78
ALIGN="LEFT"
79
WIDTH="100%"></DIV
80
><H1
81
><A
82
NAME="KERNEL-CONDITION-VARIABLES">Condition Variables</H1
83
><DIV
84
CLASS="REFNAMEDIV"
85
><A
86
NAME="AEN1232"
87
></A
88
><H2
89
>Name</H2
90
>cyg_cond_init, cyg_cond_destroy, cyg_cond_wait, cyg_cond_timed_wait, cyg_cond_signal, cyg_cond_broadcast&nbsp;--&nbsp;Synchronization primitive</DIV
91
><DIV
92
CLASS="REFSYNOPSISDIV"
93
><A
94
NAME="AEN1240"><H2
95
>Synopsis</H2
96
><DIV
97
CLASS="FUNCSYNOPSIS"
98
><A
99
NAME="AEN1241"><P
100
></P
101
><TABLE
102
BORDER="5"
103
BGCOLOR="#E0E0F0"
104
WIDTH="70%"
105
><TR
106
><TD
107
><PRE
108
CLASS="FUNCSYNOPSISINFO"
109
>#include &lt;cyg/kernel/kapi.h&gt;
110
        </PRE
111
></TD
112
></TR
113
></TABLE
114
><P
115
><CODE
116
><CODE
117
CLASS="FUNCDEF"
118
>void cyg_cond_init</CODE
119
>(cyg_cond_t* cond, cyg_mutex_t* mutex);</CODE
120
></P
121
><P
122
><CODE
123
><CODE
124
CLASS="FUNCDEF"
125
>void cyg_cond_destroy</CODE
126
>(cyg_cond_t* cond);</CODE
127
></P
128
><P
129
><CODE
130
><CODE
131
CLASS="FUNCDEF"
132
>cyg_bool_t cyg_cond_wait</CODE
133
>(cyg_cond_t* cond);</CODE
134
></P
135
><P
136
><CODE
137
><CODE
138
CLASS="FUNCDEF"
139
>cyg_bool_t cyg_cond_timed_wait</CODE
140
>(cyg_cond_t* cond, cyg_tick_count_t abstime);</CODE
141
></P
142
><P
143
><CODE
144
><CODE
145
CLASS="FUNCDEF"
146
>void cyg_cond_signal</CODE
147
>(cyg_cond_t* cond);</CODE
148
></P
149
><P
150
><CODE
151
><CODE
152
CLASS="FUNCDEF"
153
>void cyg_cond_broadcast</CODE
154
>(cyg_cond_t* cond);</CODE
155
></P
156
><P
157
></P
158
></DIV
159
></DIV
160
><DIV
161
CLASS="REFSECT1"
162
><A
163
NAME="KERNEL-CONDITION-VARIABLES-DESCRIPTION"
164
></A
165
><H2
166
>Description</H2
167
><P
168
>Condition variables are used in conjunction with mutexes to implement
169
long-term waits for some condition to become true. For example
170
consider a set of functions that control access to a pool of
171
resources:
172
      </P
173
><TABLE
174
BORDER="5"
175
BGCOLOR="#E0E0F0"
176
WIDTH="70%"
177
><TR
178
><TD
179
><PRE
180
CLASS="PROGRAMLISTING"
181
>&#13;cyg_mutex_t res_lock;
182
res_t res_pool[RES_MAX];
183
int res_count = RES_MAX;
184
 
185
void res_init(void)
186
{
187
    cyg_mutex_init(&amp;res_lock);
188
    &lt;fill pool with resources&gt;
189
}
190
 
191
res_t res_allocate(void)
192
{
193
    res_t res;
194
 
195
    cyg_mutex_lock(&amp;res_lock);               // lock the mutex
196
 
197
    if( res_count == 0 )                     // check for free resource
198
        res = RES_NONE;                      // return RES_NONE if none
199
    else
200
    {
201
        res_count--;                         // allocate a resources
202
        res = res_pool[res_count];
203
    }
204
 
205
    cyg_mutex_unlock(&amp;res_lock);             // unlock the mutex
206
 
207
    return res;
208
}
209
 
210
void res_free(res_t res)
211
{
212
    cyg_mutex_lock(&amp;res_lock);               // lock the mutex
213
 
214
    res_pool[res_count] = res;               // free the resource
215
    res_count++;
216
 
217
    cyg_mutex_unlock(&amp;res_lock);             // unlock the mutex
218
}
219
      </PRE
220
></TD
221
></TR
222
></TABLE
223
><P
224
>These routines use the variable <TT
225
CLASS="VARNAME"
226
>res_count</TT
227
> to keep
228
track of the resources available. If there are none then
229
<TT
230
CLASS="FUNCTION"
231
>res_allocate</TT
232
> returns <TT
233
CLASS="LITERAL"
234
>RES_NONE</TT
235
>,
236
which the caller must check for and take appropriate error handling
237
actions.
238
      </P
239
><P
240
>Now suppose that we do not want to return
241
<TT
242
CLASS="LITERAL"
243
>RES_NONE</TT
244
> when there are no resources, but want to
245
wait for one to become available. This is where a condition variable
246
can be used:
247
      </P
248
><TABLE
249
BORDER="5"
250
BGCOLOR="#E0E0F0"
251
WIDTH="70%"
252
><TR
253
><TD
254
><PRE
255
CLASS="PROGRAMLISTING"
256
>&#13;cyg_mutex_t res_lock;
257
cyg_cond_t res_wait;
258
res_t res_pool[RES_MAX];
259
int res_count = RES_MAX;
260
 
261
void res_init(void)
262
{
263
    cyg_mutex_init(&amp;res_lock);
264
    cyg_cond_init(&amp;res_wait, &amp;res_lock);
265
    &lt;fill pool with resources&gt;
266
}
267
 
268
res_t res_allocate(void)
269
{
270
    res_t res;
271
 
272
    cyg_mutex_lock(&amp;res_lock);               // lock the mutex
273
 
274
    while( res_count == 0 )                  // wait for a resources
275
        cyg_cond_wait(&amp;res_wait);
276
 
277
    res_count--;                             // allocate a resource
278
    res = res_pool[res_count];
279
 
280
    cyg_mutex_unlock(&amp;res_lock);             // unlock the mutex
281
 
282
    return res;
283
}
284
 
285
void res_free(res_t res)
286
{
287
    cyg_mutex_lock(&amp;res_lock);               // lock the mutex
288
 
289
    res_pool[res_count] = res;               // free the resource
290
    res_count++;
291
 
292
    cyg_cond_signal(&amp;res_wait);              // wake up any waiting allocators
293
 
294
    cyg_mutex_unlock(&amp;res_lock);             // unlock the mutex
295
}
296
      </PRE
297
></TD
298
></TR
299
></TABLE
300
><P
301
>In this version of the code, when <TT
302
CLASS="FUNCTION"
303
>res_allocate</TT
304
>
305
detects that there are no resources it calls
306
<TT
307
CLASS="FUNCTION"
308
>cyg_cond_wait</TT
309
>. This does two things: it unlocks
310
the mutex, and puts the calling thread to sleep on the condition
311
variable. When <TT
312
CLASS="FUNCTION"
313
>res_free</TT
314
> is eventually called, it
315
puts a resource back into the pool and calls
316
<TT
317
CLASS="FUNCTION"
318
>cyg_cond_signal</TT
319
> to wake up any thread waiting on
320
the condition variable. When the waiting thread eventually gets to run again,
321
it will re-lock the mutex before returning from
322
<TT
323
CLASS="FUNCTION"
324
>cyg_cond_wait</TT
325
>.
326
      </P
327
><P
328
>There are two important things to note about the way in which this
329
code works. The first is that the mutex unlock and wait in
330
<TT
331
CLASS="FUNCTION"
332
>cyg_cond_wait</TT
333
> are atomic: no other thread can run
334
between the unlock and the wait. If this were not the case then a call
335
to <TT
336
CLASS="FUNCTION"
337
>res_free</TT
338
> by that thread would release the
339
resource but the call to <TT
340
CLASS="FUNCTION"
341
>cyg_cond_signal</TT
342
> would be
343
lost, and the first thread would end up waiting when there were
344
resources available.
345
      </P
346
><P
347
>The second feature is that the call to
348
<TT
349
CLASS="FUNCTION"
350
>cyg_cond_wait</TT
351
> is in a <TT
352
CLASS="LITERAL"
353
>while</TT
354
>
355
loop and not a simple <TT
356
CLASS="LITERAL"
357
>if</TT
358
> statement. This is because
359
of the need to re-lock the mutex in <TT
360
CLASS="FUNCTION"
361
>cyg_cond_wait</TT
362
>
363
when the signalled thread reawakens. If there are other threads
364
already queued to claim the lock then this thread must wait. Depending
365
on the scheduler and the queue order, many other threads may have
366
entered the critical section before this one gets to run. So the
367
condition that it was waiting for may have been rendered false. Using
368
a loop around all condition variable wait operations is the only way
369
to guarantee that the condition being waited for is still true after
370
waiting.
371
      </P
372
><P
373
>Before a condition variable can be used it must be initialized with a
374
call to <TT
375
CLASS="FUNCTION"
376
>cyg_cond_init</TT
377
>. This requires two
378
arguments, memory for the data structure and a pointer to an existing
379
mutex. This mutex will not be initialized by
380
<TT
381
CLASS="FUNCTION"
382
>cyg_cond_init</TT
383
>, instead a separate call to
384
<TT
385
CLASS="FUNCTION"
386
>cyg_mutex_init</TT
387
> is required. If a condition
388
variable is no longer required and there are no threads waiting on it
389
then <TT
390
CLASS="FUNCTION"
391
>cyg_cond_destroy</TT
392
> can be used.
393
      </P
394
><P
395
>When a thread needs to wait for a condition to be satisfied it can
396
call <TT
397
CLASS="FUNCTION"
398
>cyg_cond_wait</TT
399
>. The thread must have already
400
locked the mutex that was specified in the
401
<TT
402
CLASS="FUNCTION"
403
>cyg_cond_init</TT
404
> call. This mutex will be unlocked
405
and the current thread will be suspended in an atomic operation. When
406
some other thread performs a signal or broadcast operation the current
407
thread will be woken up and automatically reclaim ownership of the mutex
408
again, allowing it to examine global state and determine whether or
409
not the condition is now satisfied. The kernel supplies a variant of
410
this function, <TT
411
CLASS="FUNCTION"
412
>cyg_cond_timed_wait</TT
413
>, which can be
414
used to wait on the condition variable or until some number of clock
415
ticks have occurred. The mutex will always be reclaimed before
416
<TT
417
CLASS="FUNCTION"
418
>cyg_cond_timed_wait</TT
419
> returns, regardless of
420
whether it was a result of a signal operation or a timeout.
421
      </P
422
><P
423
>There is no <TT
424
CLASS="FUNCTION"
425
>cyg_cond_trywait</TT
426
> function because
427
this would not serve any purpose. If a thread has locked the mutex and
428
determined that the condition is satisfied, it can just release the
429
mutex and return. There is no need to perform any operation on the
430
condition variable.
431
      </P
432
><P
433
>When a thread changes shared state that may affect some other thread
434
blocked on a condition variable, it should call either
435
<TT
436
CLASS="FUNCTION"
437
>cyg_cond_signal</TT
438
> or
439
<TT
440
CLASS="FUNCTION"
441
>cyg_cond_broadcast</TT
442
>. These calls do not require
443
ownership of the mutex, but usually the mutex will have been claimed
444
before updating the shared state. A signal operation only wakes up the
445
first thread that is waiting on the condition variable, while a
446
broadcast wakes up all the threads. If there are no threads waiting on
447
the condition variable at the time, then the signal or broadcast will
448
have no effect: past signals are not counted up or remembered in any
449
way. Typically a signal should be used when all threads will check the
450
same condition and at most one thread can continue running. A
451
broadcast should be used if threads check slightly different
452
conditions, or if the change to the global state might allow multiple
453
threads to proceed.
454
      </P
455
></DIV
456
><DIV
457
CLASS="REFSECT1"
458
><A
459
NAME="KERNEL-CONDITION-VARIABLES-CONTEXT"
460
></A
461
><H2
462
>Valid contexts</H2
463
><P
464
><TT
465
CLASS="FUNCTION"
466
>cyg_cond_init</TT
467
> is typically called during system
468
initialization but may also be called in thread context. The same
469
applies to <TT
470
CLASS="FUNCTION"
471
>cyg_cond_delete</TT
472
>.
473
<TT
474
CLASS="FUNCTION"
475
>cyg_cond_wait</TT
476
> and
477
<TT
478
CLASS="FUNCTION"
479
>cyg_cond_timedwait</TT
480
> may only be called from thread
481
context since they may block. <TT
482
CLASS="FUNCTION"
483
>cyg_cond_signal</TT
484
> and
485
<TT
486
CLASS="FUNCTION"
487
>cyg_cond_broadcast</TT
488
> may be called from thread or
489
DSR context.
490
      </P
491
></DIV
492
><DIV
493
CLASS="NAVFOOTER"
494
><HR
495
ALIGN="LEFT"
496
WIDTH="100%"><TABLE
497
SUMMARY="Footer navigation table"
498
WIDTH="100%"
499
BORDER="0"
500
CELLPADDING="0"
501
CELLSPACING="0"
502
><TR
503
><TD
504
WIDTH="33%"
505
ALIGN="left"
506
VALIGN="top"
507
><A
508
HREF="kernel-mutexes.html"
509
ACCESSKEY="P"
510
>Prev</A
511
></TD
512
><TD
513
WIDTH="34%"
514
ALIGN="center"
515
VALIGN="top"
516
><A
517
HREF="ecos-ref.html"
518
ACCESSKEY="H"
519
>Home</A
520
></TD
521
><TD
522
WIDTH="33%"
523
ALIGN="right"
524
VALIGN="top"
525
><A
526
HREF="kernel-semaphores.html"
527
ACCESSKEY="N"
528
>Next</A
529
></TD
530
></TR
531
><TR
532
><TD
533
WIDTH="33%"
534
ALIGN="left"
535
VALIGN="top"
536
>Mutexes</TD
537
><TD
538
WIDTH="34%"
539
ALIGN="center"
540
VALIGN="top"
541
><A
542
HREF="kernel.html"
543
ACCESSKEY="U"
544
>Up</A
545
></TD
546
><TD
547
WIDTH="33%"
548
ALIGN="right"
549
VALIGN="top"
550
>Semaphores</TD
551
></TR
552
></TABLE
553
></DIV
554
></BODY
555
></HTML
556
>

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.