1 | .. SPDX-License-Identifier: CC-BY-SA-4.0 |
---|
2 | |
---|
3 | .. Copyright (C) 2014, 2017. |
---|
4 | .. COMMENT: embedded brains GmbH. |
---|
5 | |
---|
6 | Self-Contained Objects |
---|
7 | ********************** |
---|
8 | |
---|
9 | Introduction |
---|
10 | ============ |
---|
11 | |
---|
12 | One of the original design goals of RTEMS was the support for heterogeneous |
---|
13 | computing based on message passing. This was realized by synchronization |
---|
14 | objects with an architecture-independent identifier provided by the system |
---|
15 | during object creation (a 32-bit unsigned integer used as a bitfield) and a |
---|
16 | user-defined four character name. This approach in the so called Classic API |
---|
17 | has some weaknesses: |
---|
18 | |
---|
19 | * Dynamic memory (the workspace) is used to allocate object pools. This |
---|
20 | requires a complex configuration with heavy use of the C pre-processor. |
---|
21 | The unlimited objects support optionally expands and shrinks the object pool. |
---|
22 | Dynamic memory is strongly discouraged by some coding standards, e.g. MISRA |
---|
23 | C:2012 :cite:`MISRA:2012:C`. |
---|
24 | |
---|
25 | * Objects are created via function calls which return an object identifier. |
---|
26 | The object operations use this identifier and map it internally to an object |
---|
27 | representation. |
---|
28 | |
---|
29 | * The object identifier is only known at run-time. This hinders compiler |
---|
30 | optimizations and static analysis. |
---|
31 | |
---|
32 | * The objects reside in a table, e.g. they are subject to false sharing of |
---|
33 | cache lines :cite:`Drepper:2007:Memory`. |
---|
34 | |
---|
35 | * The object operations use a rich set of options and attributes. For each |
---|
36 | object operation these parameters must be evaluated and validated at run-time |
---|
37 | to figure out what to do exactly for this operation. |
---|
38 | |
---|
39 | For applications that use fine grained locking the mapping of the identifier to |
---|
40 | the object representation and the parameter evaluation are a significant |
---|
41 | overhead that may degrade the performance dramatically. An example is the `new |
---|
42 | network stack (libbsd) <https://git.rtems.org/rtems-libbsd>`_ which uses |
---|
43 | hundreds of locks in a basic setup. Another example is the OpenMP support |
---|
44 | (libgomp). |
---|
45 | |
---|
46 | To overcome these issues new self-contained synchronization objects are |
---|
47 | available since RTEMS 4.11. Self-contained synchronization objects encapsulate |
---|
48 | all their state in exactly one data structure. The user must provide the |
---|
49 | storage space for this structure and nothing more. The user is responsible for |
---|
50 | the object life-cycle. Initialization and destruction of self-contained |
---|
51 | synchronization objects cannot fail provided all function parameters are valid. |
---|
52 | In particular, a not enough memory error cannot happen. It is possible to |
---|
53 | statically initialize self-contained synchronization objects. This allows an |
---|
54 | efficient use of static analysis tools. |
---|
55 | |
---|
56 | Several header files define self-contained synchronization objects. The Newlib |
---|
57 | :file:`<sys/lock.h>` header file provides |
---|
58 | |
---|
59 | * mutexes, |
---|
60 | |
---|
61 | * recursive mutexes, |
---|
62 | |
---|
63 | * condition variables, |
---|
64 | |
---|
65 | * counting semaphores, |
---|
66 | |
---|
67 | * binary semaphores, and |
---|
68 | |
---|
69 | * Futex synchronization :cite:`Franke:2002:Futex`. |
---|
70 | |
---|
71 | They are used internally in Newlib (e.g. for FILE objects), for the C++11 |
---|
72 | threads and the OpenMP support (libgomp). The Newlib provided self-contained |
---|
73 | synchronization objects focus on performance. There are no error checks to |
---|
74 | catch software errors, e.g. invalid parameters. The application configuration |
---|
75 | is significantly simplified, since it is no longer necessary to account for |
---|
76 | lock objects used by Newlib and GCC. The Newlib defined self-contained |
---|
77 | synchronization objects can be a statically initialized and reside in the |
---|
78 | ``.bss`` section. Destruction is a no-operation. |
---|
79 | |
---|
80 | The header file :file:`<pthread.h>` provides |
---|
81 | |
---|
82 | * POSIX barriers (:c:type:`pthread_barrier_t`), |
---|
83 | |
---|
84 | * POSIX condition variables (:c:type:`pthread_cond_t`), |
---|
85 | |
---|
86 | * POSIX mutexes (:c:type:`pthread_mutex_t`), |
---|
87 | |
---|
88 | * POSIX reader/writer locks (:c:type:`pthread_rwlock_t`), and |
---|
89 | |
---|
90 | * POSIX spinlocks (:c:type:`pthread_spinlock_t`) |
---|
91 | |
---|
92 | as self-contained synchronization objects. The POSIX synchronization objects are |
---|
93 | used for example by the Ada run-time support. The header file |
---|
94 | :file:`<semaphore.h>` provides self-contained |
---|
95 | |
---|
96 | * POSIX unnamed semaphores (:c:type:`sem_t` initialized via :c:func:`sem_init`). |
---|
97 | |
---|
98 | RTEMS Thread API |
---|
99 | ================ |
---|
100 | |
---|
101 | To give RTEMS users access to self-contained synchronization objects an API is |
---|
102 | necessary. One option would be to simply use the POSIX threads API (pthreads), |
---|
103 | C11 threads or C++11 threads. However, these standard APIs lack for example |
---|
104 | binary semaphores which are important for task/interrupt synchronization. The |
---|
105 | timed operations use in general time values specified by seconds and |
---|
106 | nanoseconds. Setting up the time values in seconds (time_t has 64 bits) and |
---|
107 | nanoseconds is burdened with a high overhead compared to time values in clock |
---|
108 | ticks for relative timeouts. The POSIX API mutexes can be configured for |
---|
109 | various protocols and options, this adds a run-time overhead. There are a |
---|
110 | variety of error conditions. This is a problem in combination with some coding |
---|
111 | standards, e.g. MISRA C:2012. APIs used by Linux (e.g. `<linux/mutex.h> |
---|
112 | <http://lxr.free-electrons.com/source/include/linux/mutex.h>`_) or the FreeBSD |
---|
113 | kernel (e.g. `MUTEX(9) |
---|
114 | <https://www.freebsd.org/cgi/man.cgi?query=mutex&sektion=9>`_) are better |
---|
115 | suited as a template for high-performance synchronization objects. The goal of |
---|
116 | the `RTEMS Thread API` is to offer the highest performance with the lowest |
---|
117 | space-overhead on RTEMS. It should be suitable for device drivers. |
---|
118 | |
---|
119 | Mutual Exclusion |
---|
120 | ================ |
---|
121 | |
---|
122 | The :c:type:`rtems_mutex` and :c:type:`rtems_recursive_mutex` objects provide |
---|
123 | mutual-exclusion synchronization using the :ref:`PriorityInheritance` in |
---|
124 | uniprocessor configurations or the :ref:`OMIP` in SMP configurations. |
---|
125 | Recursive locking should be used with care :cite:`Williams:2012:CA`. The |
---|
126 | storage space for these object must be provided by the user. There are no |
---|
127 | defined comparison or assignment operators for these type. Only the object |
---|
128 | itself may be used for performing synchronization. The result of referring to |
---|
129 | copies of the object in calls to |
---|
130 | |
---|
131 | * :c:func:`rtems_mutex_lock`, |
---|
132 | |
---|
133 | * :c:func:`rtems_recursive_mutex_lock`, |
---|
134 | |
---|
135 | * :c:func:`rtems_mutex_unlock`, |
---|
136 | |
---|
137 | * :c:func:`rtems_recursive_mutex_unlock`, |
---|
138 | |
---|
139 | * :c:func:`rtems_mutex_set_name`, |
---|
140 | |
---|
141 | * :c:func:`rtems_recursive_mutex_set_name`, |
---|
142 | |
---|
143 | * :c:func:`rtems_mutex_get_name`, |
---|
144 | |
---|
145 | * :c:func:`rtems_recursive_mutex_get_name`, |
---|
146 | |
---|
147 | * :c:func:`rtems_mutex_destroy`, and |
---|
148 | |
---|
149 | * :c:func:`rtems_recursive_mutex_destroy` |
---|
150 | |
---|
151 | is undefined. Objects of the type :c:type:`rtems_mutex` must be initialized |
---|
152 | via |
---|
153 | |
---|
154 | * :c:func:`RTEMS_MUTEX_INITIALIZER`, or |
---|
155 | |
---|
156 | * :c:func:`rtems_mutex_init`. |
---|
157 | |
---|
158 | They must be destroyed via |
---|
159 | |
---|
160 | * :c:func:`rtems_mutex_destroy`. |
---|
161 | |
---|
162 | is undefined. Objects of the type :c:type:`rtems_recursive_mutex` must be |
---|
163 | initialized via |
---|
164 | |
---|
165 | * :c:func:`RTEMS_RECURSIVE_MUTEX_INITIALIZER`, or |
---|
166 | |
---|
167 | * :c:func:`rtems_recursive_mutex_init`. |
---|
168 | |
---|
169 | They must be destroyed via |
---|
170 | |
---|
171 | * :c:func:`rtems_recursive_mutex_destroy`. |
---|
172 | |
---|
173 | .. raw:: latex |
---|
174 | |
---|
175 | \clearpage |
---|
176 | |
---|
177 | Static mutex initialization |
---|
178 | --------------------------- |
---|
179 | |
---|
180 | CALLING SEQUENCE: |
---|
181 | .. code-block:: c |
---|
182 | |
---|
183 | rtems_mutex mutex = RTEMS_MUTEX_INITIALIZER( |
---|
184 | name |
---|
185 | ); |
---|
186 | |
---|
187 | rtems_recursive_mutex mutex = RTEMS_RECURSIVE_MUTEX_INITIALIZER( |
---|
188 | name |
---|
189 | ); |
---|
190 | |
---|
191 | DESCRIPTION: |
---|
192 | An initializer for static initialization. It is equivalent to a call to |
---|
193 | :c:func:`rtems_mutex_init` or :c:func:`rtems_recursive_mutex_init` |
---|
194 | respectively. |
---|
195 | |
---|
196 | NOTES: |
---|
197 | Global mutexes with a ``name`` of ``NULL`` may reside in the ``.bss`` |
---|
198 | section. |
---|
199 | |
---|
200 | .. raw:: latex |
---|
201 | |
---|
202 | \clearpage |
---|
203 | |
---|
204 | Run-time mutex initialization |
---|
205 | ----------------------------- |
---|
206 | |
---|
207 | CALLING SEQUENCE: |
---|
208 | .. code-block:: c |
---|
209 | |
---|
210 | void rtems_mutex_init( |
---|
211 | rtems_mutex *mutex, |
---|
212 | const char *name |
---|
213 | ); |
---|
214 | |
---|
215 | void rtems_recursive_mutex_init( |
---|
216 | rtems_recursive_mutex *mutex, |
---|
217 | const char *name |
---|
218 | ); |
---|
219 | |
---|
220 | DESCRIPTION: |
---|
221 | Initializes the ``mutex`` with the specified ``name``. |
---|
222 | |
---|
223 | NOTES: |
---|
224 | The ``name`` must be persistent throughout the life-time of the mutex. A |
---|
225 | ``name`` of ``NULL`` is valid. The mutex is unlocked after initialization. |
---|
226 | |
---|
227 | .. raw:: latex |
---|
228 | |
---|
229 | \clearpage |
---|
230 | |
---|
231 | Lock the mutex |
---|
232 | -------------- |
---|
233 | |
---|
234 | CALLING SEQUENCE: |
---|
235 | .. code-block:: c |
---|
236 | |
---|
237 | void rtems_mutex_lock( |
---|
238 | rtems_mutex *mutex |
---|
239 | ); |
---|
240 | |
---|
241 | void rtems_recursive_mutex_lock( |
---|
242 | rtems_recursive_mutex *mutex |
---|
243 | ); |
---|
244 | |
---|
245 | DESCRIPTION: |
---|
246 | Locks the ``mutex``. |
---|
247 | |
---|
248 | NOTES: |
---|
249 | This function must be called from thread context with interrupts enabled. |
---|
250 | In case the mutex is currently locked by another thread, then the thread is |
---|
251 | blocked until it becomes the mutex owner. Threads wait in priority order. |
---|
252 | |
---|
253 | A recursive lock happens in case the mutex owner tries to lock the mutex |
---|
254 | again. The result of recursively locking a mutex depends on the mutex |
---|
255 | variant. For a normal (non-recursive) mutex (:c:type:`rtems_mutex`) the |
---|
256 | result is unpredictable. It could block the owner indefinetly or lead to a |
---|
257 | fatal deadlock error. A recursive mutex (:c:type:`rtems_recursive_mutex`) |
---|
258 | can be locked recursively by the mutex owner. |
---|
259 | |
---|
260 | Each mutex lock operation must have a corresponding unlock operation. |
---|
261 | |
---|
262 | .. raw:: latex |
---|
263 | |
---|
264 | \clearpage |
---|
265 | |
---|
266 | Unlock the mutex |
---|
267 | ---------------- |
---|
268 | |
---|
269 | CALLING SEQUENCE: |
---|
270 | .. code-block:: c |
---|
271 | |
---|
272 | void rtems_mutex_unlock( |
---|
273 | rtems_mutex *mutex |
---|
274 | ); |
---|
275 | |
---|
276 | void rtems_recursive_mutex_unlock( |
---|
277 | rtems_recursive_mutex *mutex |
---|
278 | ); |
---|
279 | |
---|
280 | DESCRIPTION: |
---|
281 | Unlocks the ``mutex``. |
---|
282 | |
---|
283 | NOTES: |
---|
284 | This function must be called from thread context with interrupts enabled. |
---|
285 | In case the currently executing thread is not the owner of the ``mutex``, |
---|
286 | then the result is unpredictable. |
---|
287 | |
---|
288 | Exactly the outer-most unlock will make a recursive mutex available to |
---|
289 | other threads. |
---|
290 | |
---|
291 | .. raw:: latex |
---|
292 | |
---|
293 | \clearpage |
---|
294 | |
---|
295 | .. raw:: latex |
---|
296 | |
---|
297 | \clearpage |
---|
298 | |
---|
299 | Set mutex name |
---|
300 | -------------- |
---|
301 | |
---|
302 | CALLING SEQUENCE: |
---|
303 | .. code-block:: c |
---|
304 | |
---|
305 | void rtems_mutex_set_name( |
---|
306 | rtems_mutex *mutex, |
---|
307 | const char *name |
---|
308 | ); |
---|
309 | |
---|
310 | void rtems_recursive_mutex_set_name( |
---|
311 | rtems_recursive_mutex *mutex, |
---|
312 | const char *name |
---|
313 | ); |
---|
314 | |
---|
315 | DESCRIPTION: |
---|
316 | Sets the ``mutex`` name to ``name``. |
---|
317 | |
---|
318 | NOTES: |
---|
319 | The ``name`` must be persistent throughout the life-time of the mutex. A |
---|
320 | ``name`` of ``NULL`` is valid. |
---|
321 | |
---|
322 | .. raw:: latex |
---|
323 | |
---|
324 | \clearpage |
---|
325 | |
---|
326 | Get mutex name |
---|
327 | -------------- |
---|
328 | |
---|
329 | CALLING SEQUENCE: |
---|
330 | .. code-block:: c |
---|
331 | |
---|
332 | const char *rtems_mutex_get_name( |
---|
333 | const rtems_mutex *mutex |
---|
334 | ); |
---|
335 | |
---|
336 | const char *rtems_recursive_mutex_get_name( |
---|
337 | const rtems_recursive_mutex *mutex |
---|
338 | ); |
---|
339 | |
---|
340 | DESCRIPTION: |
---|
341 | Returns the ``mutex`` name. |
---|
342 | |
---|
343 | NOTES: |
---|
344 | The name may be ``NULL``. |
---|
345 | |
---|
346 | Mutex destruction |
---|
347 | ----------------- |
---|
348 | |
---|
349 | CALLING SEQUENCE: |
---|
350 | .. code-block:: c |
---|
351 | |
---|
352 | void rtems_mutex_destroy( |
---|
353 | rtems_mutex *mutex |
---|
354 | ); |
---|
355 | |
---|
356 | void rtems_recursive_mutex_destroy( |
---|
357 | rtems_recursive_mutex *mutex |
---|
358 | ); |
---|
359 | |
---|
360 | DESCRIPTION: |
---|
361 | Destroys the ``mutex``. |
---|
362 | |
---|
363 | NOTES: |
---|
364 | In case the mutex is locked or still in use, then the result is |
---|
365 | unpredictable. |
---|
366 | |
---|
367 | Condition Variables |
---|
368 | =================== |
---|
369 | |
---|
370 | The :c:type:`rtems_condition_variable` object provides a condition variable |
---|
371 | synchronization object. The storage space for this object must be provided by |
---|
372 | the user. There are no defined comparison or assignment operators for this |
---|
373 | type. Only the object itself may be used for performing synchronization. The |
---|
374 | result of referring to copies of the object in calls to |
---|
375 | |
---|
376 | * :c:func:`rtems_condition_variable_wait`, |
---|
377 | |
---|
378 | * :c:func:`rtems_condition_variable_signal`, |
---|
379 | |
---|
380 | * :c:func:`rtems_condition_variable_broadcast`, |
---|
381 | |
---|
382 | * :c:func:`rtems_condition_variable_set_name`, |
---|
383 | |
---|
384 | * :c:func:`rtems_condition_variable_get_name`, and |
---|
385 | |
---|
386 | * :c:func:`rtems_condition_variable_destroy` |
---|
387 | |
---|
388 | is undefined. Objects of this type must be initialized via |
---|
389 | |
---|
390 | * :c:func:`RTEMS_CONDITION_VARIABLE_INITIALIZER`, or |
---|
391 | |
---|
392 | * :c:func:`rtems_condition_variable_init`. |
---|
393 | |
---|
394 | They must be destroyed via |
---|
395 | |
---|
396 | * :c:func:`rtems_condition_variable_destroy`. |
---|
397 | |
---|
398 | .. raw:: latex |
---|
399 | |
---|
400 | \clearpage |
---|
401 | |
---|
402 | Static condition variable initialization |
---|
403 | ---------------------------------------- |
---|
404 | |
---|
405 | CALLING SEQUENCE: |
---|
406 | .. code-block:: c |
---|
407 | |
---|
408 | rtems_condition_variable condition_variable = RTEMS_CONDITION_VARIABLE_INITIALIZER( |
---|
409 | name |
---|
410 | ); |
---|
411 | |
---|
412 | DESCRIPTION: |
---|
413 | An initializer for static initialization. It is equivalent to a call to |
---|
414 | :c:func:`rtems_condition_variable_init`. |
---|
415 | |
---|
416 | NOTES: |
---|
417 | Global condition variables with a ``name`` of ``NULL`` may reside in the |
---|
418 | ``.bss`` section. |
---|
419 | |
---|
420 | .. raw:: latex |
---|
421 | |
---|
422 | \clearpage |
---|
423 | |
---|
424 | Run-time condition variable initialization |
---|
425 | ------------------------------------------ |
---|
426 | |
---|
427 | CALLING SEQUENCE: |
---|
428 | .. code-block:: c |
---|
429 | |
---|
430 | void rtems_condition_variable_init( |
---|
431 | rtems_condition_variable *condition_variable, |
---|
432 | const char *name |
---|
433 | ); |
---|
434 | |
---|
435 | DESCRIPTION: |
---|
436 | Initializes the ``condition_variable`` with the specified ``name``. |
---|
437 | |
---|
438 | NOTES: |
---|
439 | The ``name`` must be persistent throughout the life-time of the condition |
---|
440 | variable. A ``name`` of ``NULL`` is valid. |
---|
441 | |
---|
442 | .. raw:: latex |
---|
443 | |
---|
444 | \clearpage |
---|
445 | |
---|
446 | Wait for condition signal |
---|
447 | ------------------------- |
---|
448 | |
---|
449 | CALLING SEQUENCE: |
---|
450 | .. code-block:: c |
---|
451 | |
---|
452 | void rtems_condition_variable_wait( |
---|
453 | rtems_condition_variable *condition_variable, |
---|
454 | rtems_mutex *mutex |
---|
455 | ); |
---|
456 | |
---|
457 | DESCRIPTION: |
---|
458 | Atomically waits for a condition signal and unlocks the mutex. Once the |
---|
459 | condition is signalled to the thread it wakes up and locks the mutex again. |
---|
460 | |
---|
461 | NOTES: |
---|
462 | This function must be called from thread context with interrupts enabled. |
---|
463 | Threads wait in priority order. |
---|
464 | |
---|
465 | .. raw:: latex |
---|
466 | |
---|
467 | \clearpage |
---|
468 | |
---|
469 | Signals a condition change |
---|
470 | -------------------------- |
---|
471 | |
---|
472 | CALLING SEQUENCE: |
---|
473 | .. code-block:: c |
---|
474 | |
---|
475 | void rtems_condition_variable_signal( |
---|
476 | rtems_condition_variable *condition_variable |
---|
477 | ); |
---|
478 | |
---|
479 | DESCRIPTION: |
---|
480 | Signals a condition change to the highest priority waiting thread. If no |
---|
481 | threads wait currently on this condition variable, then nothing happens. |
---|
482 | |
---|
483 | .. raw:: latex |
---|
484 | |
---|
485 | \clearpage |
---|
486 | |
---|
487 | Broadcasts a condition change |
---|
488 | ----------------------------- |
---|
489 | |
---|
490 | CALLING SEQUENCE: |
---|
491 | .. code-block:: c |
---|
492 | |
---|
493 | void rtems_condition_variable_broadcast( |
---|
494 | rtems_condition_variable *condition_variable |
---|
495 | ); |
---|
496 | |
---|
497 | DESCRIPTION: |
---|
498 | Signals a condition change to all waiting thread. If no threads wait |
---|
499 | currently on this condition variable, then nothing happens. |
---|
500 | |
---|
501 | .. raw:: latex |
---|
502 | |
---|
503 | \clearpage |
---|
504 | |
---|
505 | .. raw:: latex |
---|
506 | |
---|
507 | \clearpage |
---|
508 | |
---|
509 | Set condition variable name |
---|
510 | --------------------------- |
---|
511 | |
---|
512 | CALLING SEQUENCE: |
---|
513 | .. code-block:: c |
---|
514 | |
---|
515 | void rtems_condition_variable_set_name( |
---|
516 | rtems_condition_variable *condition_variable, |
---|
517 | const char *name |
---|
518 | ); |
---|
519 | |
---|
520 | DESCRIPTION: |
---|
521 | Sets the ``condition_variable`` name to ``name``. |
---|
522 | |
---|
523 | NOTES: |
---|
524 | The ``name`` must be persistent throughout the life-time of the condition |
---|
525 | variable. A ``name`` of ``NULL`` is valid. |
---|
526 | |
---|
527 | .. raw:: latex |
---|
528 | |
---|
529 | \clearpage |
---|
530 | |
---|
531 | Get condition variable name |
---|
532 | --------------------------- |
---|
533 | |
---|
534 | CALLING SEQUENCE: |
---|
535 | .. code-block:: c |
---|
536 | |
---|
537 | const char *rtems_condition_variable_get_name( |
---|
538 | const rtems_condition_variable *condition_variable |
---|
539 | ); |
---|
540 | |
---|
541 | DESCRIPTION: |
---|
542 | Returns the ``condition_variable`` name. |
---|
543 | |
---|
544 | NOTES: |
---|
545 | The name may be ``NULL``. |
---|
546 | |
---|
547 | Condition variable destruction |
---|
548 | ------------------------------ |
---|
549 | |
---|
550 | CALLING SEQUENCE: |
---|
551 | .. code-block:: c |
---|
552 | |
---|
553 | void rtems_condition_variable_destroy( |
---|
554 | rtems_condition_variable *condition_variable |
---|
555 | ); |
---|
556 | |
---|
557 | DESCRIPTION: |
---|
558 | Destroys the ``condition_variable``. |
---|
559 | |
---|
560 | NOTES: |
---|
561 | In case the condition variable still in use, then the result is |
---|
562 | unpredictable. |
---|
563 | |
---|
564 | Counting Semaphores |
---|
565 | =================== |
---|
566 | |
---|
567 | The :c:type:`rtems_counting_semaphore` object provides a counting semaphore |
---|
568 | synchronization object. The storage space for this object must be provided by |
---|
569 | the user. There are no defined comparison or assignment operators for this |
---|
570 | type. Only the object itself may be used for performing synchronization. The |
---|
571 | result of referring to copies of the object in calls to |
---|
572 | |
---|
573 | * :c:func:`rtems_counting_semaphore_wait`, |
---|
574 | |
---|
575 | * :c:func:`rtems_counting_semaphore_post`, |
---|
576 | |
---|
577 | * :c:func:`rtems_counting_semaphore_set_name`, |
---|
578 | |
---|
579 | * :c:func:`rtems_counting_semaphore_get_name`, and |
---|
580 | |
---|
581 | * :c:func:`rtems_counting_semaphore_destroy` |
---|
582 | |
---|
583 | is undefined. Objects of this type must be initialized via |
---|
584 | |
---|
585 | * :c:func:`RTEMS_COUNTING_SEMAPHORE_INITIALIZER`, or |
---|
586 | |
---|
587 | * :c:func:`rtems_counting_semaphore_init`. |
---|
588 | |
---|
589 | They must be destroyed via |
---|
590 | |
---|
591 | * :c:func:`rtems_counting_semaphore_destroy`. |
---|
592 | |
---|
593 | .. raw:: latex |
---|
594 | |
---|
595 | \clearpage |
---|
596 | |
---|
597 | Static counting semaphore initialization |
---|
598 | ---------------------------------------- |
---|
599 | |
---|
600 | CALLING SEQUENCE: |
---|
601 | .. code-block:: c |
---|
602 | |
---|
603 | rtems_counting_semaphore counting_semaphore = RTEMS_COUNTING_SEMAPHORE_INITIALIZER( |
---|
604 | name, |
---|
605 | value |
---|
606 | ); |
---|
607 | |
---|
608 | DESCRIPTION: |
---|
609 | An initializer for static initialization. It is equivalent to a call to |
---|
610 | :c:func:`rtems_counting_semaphore_init`. |
---|
611 | |
---|
612 | NOTES: |
---|
613 | Global counting semaphores with a ``name`` of ``NULL`` may reside in the |
---|
614 | ``.bss`` section. |
---|
615 | |
---|
616 | .. raw:: latex |
---|
617 | |
---|
618 | \clearpage |
---|
619 | |
---|
620 | Run-time counting semaphore initialization |
---|
621 | ------------------------------------------ |
---|
622 | |
---|
623 | CALLING SEQUENCE: |
---|
624 | .. code-block:: c |
---|
625 | |
---|
626 | void rtems_counting_semaphore_init( |
---|
627 | rtems_counting_semaphore *counting_semaphore, |
---|
628 | const char *name, |
---|
629 | unsigned int value |
---|
630 | ); |
---|
631 | |
---|
632 | DESCRIPTION: |
---|
633 | Initializes the ``counting_semaphore`` with the specified ``name`` and |
---|
634 | ``value``. The initial value is set to ``value``. |
---|
635 | |
---|
636 | NOTES: |
---|
637 | The ``name`` must be persistent throughout the life-time of the counting |
---|
638 | semaphore. A ``name`` of ``NULL`` is valid. |
---|
639 | |
---|
640 | .. raw:: latex |
---|
641 | |
---|
642 | \clearpage |
---|
643 | |
---|
644 | Wait for a counting semaphore |
---|
645 | ----------------------------- |
---|
646 | |
---|
647 | CALLING SEQUENCE: |
---|
648 | .. code-block:: c |
---|
649 | |
---|
650 | void rtems_counting_semaphore_wait( |
---|
651 | rtems_counting_semaphore *counting_semaphore |
---|
652 | ); |
---|
653 | |
---|
654 | DESCRIPTION: |
---|
655 | Waits for the ``counting_semaphore``. In case the current semaphore value |
---|
656 | is positive, then the value is decremented and the function returns |
---|
657 | immediately, otherwise the thread is blocked waiting for a semaphore post. |
---|
658 | |
---|
659 | NOTES: |
---|
660 | This function must be called from thread context with interrupts enabled. |
---|
661 | Threads wait in priority order. |
---|
662 | |
---|
663 | .. raw:: latex |
---|
664 | |
---|
665 | \clearpage |
---|
666 | |
---|
667 | Post a counting semaphore |
---|
668 | ------------------------- |
---|
669 | |
---|
670 | CALLING SEQUENCE: |
---|
671 | .. code-block:: c |
---|
672 | |
---|
673 | void rtems_counting_semaphore_post( |
---|
674 | rtems_counting_semaphore *counting_semaphore |
---|
675 | ); |
---|
676 | |
---|
677 | DESCRIPTION: |
---|
678 | Posts the ``counting_semaphore``. In case at least one thread is waiting |
---|
679 | on the counting semaphore, then the highest priority thread is woken up, |
---|
680 | otherwise the current value is incremented. |
---|
681 | |
---|
682 | NOTES: |
---|
683 | This function may be called from interrupt context. In case it is called |
---|
684 | from thread context, then interrupts must be enabled. |
---|
685 | |
---|
686 | .. raw:: latex |
---|
687 | |
---|
688 | \clearpage |
---|
689 | |
---|
690 | .. raw:: latex |
---|
691 | |
---|
692 | \clearpage |
---|
693 | |
---|
694 | Set counting semaphore name |
---|
695 | --------------------------- |
---|
696 | |
---|
697 | CALLING SEQUENCE: |
---|
698 | .. code-block:: c |
---|
699 | |
---|
700 | void rtems_counting_semaphore_set_name( |
---|
701 | rtems_counting_semaphore *counting_semaphore, |
---|
702 | const char *name |
---|
703 | ); |
---|
704 | |
---|
705 | DESCRIPTION: |
---|
706 | Sets the ``counting_semaphore`` name to ``name``. |
---|
707 | |
---|
708 | NOTES: |
---|
709 | The ``name`` must be persistent throughout the life-time of the counting |
---|
710 | semaphore. A ``name`` of ``NULL`` is valid. |
---|
711 | |
---|
712 | .. raw:: latex |
---|
713 | |
---|
714 | \clearpage |
---|
715 | |
---|
716 | Get counting semaphore name |
---|
717 | --------------------------- |
---|
718 | |
---|
719 | CALLING SEQUENCE: |
---|
720 | .. code-block:: c |
---|
721 | |
---|
722 | const char *rtems_counting_semaphore_get_name( |
---|
723 | const rtems_counting_semaphore *counting_semaphore |
---|
724 | ); |
---|
725 | |
---|
726 | DESCRIPTION: |
---|
727 | Returns the ``counting_semaphore`` name. |
---|
728 | |
---|
729 | NOTES: |
---|
730 | The name may be ``NULL``. |
---|
731 | |
---|
732 | Counting semaphore destruction |
---|
733 | ------------------------------ |
---|
734 | |
---|
735 | CALLING SEQUENCE: |
---|
736 | .. code-block:: c |
---|
737 | |
---|
738 | void rtems_counting_semaphore_destroy( |
---|
739 | rtems_counting_semaphore *counting_semaphore |
---|
740 | ); |
---|
741 | |
---|
742 | DESCRIPTION: |
---|
743 | Destroys the ``counting_semaphore``. |
---|
744 | |
---|
745 | NOTES: |
---|
746 | In case the counting semaphore still in use, then the result is |
---|
747 | unpredictable. |
---|
748 | |
---|
749 | Binary Semaphores |
---|
750 | ================= |
---|
751 | |
---|
752 | The :c:type:`rtems_binary_semaphore` object provides a binary semaphore |
---|
753 | synchronization object. The storage space for this object must be provided by |
---|
754 | the user. There are no defined comparison or assignment operators for this |
---|
755 | type. Only the object itself may be used for performing synchronization. The |
---|
756 | result of referring to copies of the object in calls to |
---|
757 | |
---|
758 | * :c:func:`rtems_binary_semaphore_wait`, |
---|
759 | |
---|
760 | * :c:func:`rtems_binary_semaphore_wait_timed_ticks`, |
---|
761 | |
---|
762 | * :c:func:`rtems_binary_semaphore_try_wait`, |
---|
763 | |
---|
764 | * :c:func:`rtems_binary_semaphore_post`, |
---|
765 | |
---|
766 | * :c:func:`rtems_binary_semaphore_set_name`, |
---|
767 | |
---|
768 | * :c:func:`rtems_binary_semaphore_get_name`, and |
---|
769 | |
---|
770 | * :c:func:`rtems_binary_semaphore_destroy` |
---|
771 | |
---|
772 | is undefined. Objects of this type must be initialized via |
---|
773 | |
---|
774 | * :c:func:`RTEMS_BINARY_SEMAPHORE_INITIALIZER`, or |
---|
775 | |
---|
776 | * :c:func:`rtems_binary_semaphore_init`. |
---|
777 | |
---|
778 | They must be destroyed via |
---|
779 | |
---|
780 | * :c:func:`rtems_binary_semaphore_destroy`. |
---|
781 | |
---|
782 | .. raw:: latex |
---|
783 | |
---|
784 | \clearpage |
---|
785 | |
---|
786 | Static binary semaphore initialization |
---|
787 | -------------------------------------- |
---|
788 | |
---|
789 | CALLING SEQUENCE: |
---|
790 | .. code-block:: c |
---|
791 | |
---|
792 | rtems_binary_semaphore binary_semaphore = RTEMS_BINARY_SEMAPHORE_INITIALIZER( |
---|
793 | name |
---|
794 | ); |
---|
795 | |
---|
796 | DESCRIPTION: |
---|
797 | An initializer for static initialization. It is equivalent to a call to |
---|
798 | :c:func:`rtems_binary_semaphore_init`. |
---|
799 | |
---|
800 | NOTES: |
---|
801 | Global binary semaphores with a ``name`` of ``NULL`` may reside in the |
---|
802 | ``.bss`` section. |
---|
803 | |
---|
804 | .. raw:: latex |
---|
805 | |
---|
806 | \clearpage |
---|
807 | |
---|
808 | Run-time binary semaphore initialization |
---|
809 | ---------------------------------------- |
---|
810 | |
---|
811 | CALLING SEQUENCE: |
---|
812 | .. code-block:: c |
---|
813 | |
---|
814 | void rtems_binary_semaphore_init( |
---|
815 | rtems_binary_semaphore *binary_semaphore, |
---|
816 | const char *name |
---|
817 | ); |
---|
818 | |
---|
819 | DESCRIPTION: |
---|
820 | Initializes the ``binary_semaphore`` with the specified ``name``. The |
---|
821 | initial value is set to zero. |
---|
822 | |
---|
823 | NOTES: |
---|
824 | The ``name`` must be persistent throughout the life-time of the binary |
---|
825 | semaphore. A ``name`` of ``NULL`` is valid. |
---|
826 | |
---|
827 | .. raw:: latex |
---|
828 | |
---|
829 | \clearpage |
---|
830 | |
---|
831 | Wait for a binary semaphore |
---|
832 | --------------------------- |
---|
833 | |
---|
834 | CALLING SEQUENCE: |
---|
835 | .. code-block:: c |
---|
836 | |
---|
837 | void rtems_binary_semaphore_wait( |
---|
838 | rtems_binary_semaphore *binary_semaphore |
---|
839 | ); |
---|
840 | |
---|
841 | DESCRIPTION: |
---|
842 | Waits for the ``binary_semaphore``. In case the current semaphore value is |
---|
843 | one, then the value is set to zero and the function returns immediately, |
---|
844 | otherwise the thread is blocked waiting for a semaphore post. |
---|
845 | |
---|
846 | NOTES: |
---|
847 | This function must be called from thread context with interrupts enabled. |
---|
848 | Threads wait in priority order. |
---|
849 | |
---|
850 | .. raw:: latex |
---|
851 | |
---|
852 | \clearpage |
---|
853 | |
---|
854 | Wait for a binary semaphore with timeout in ticks |
---|
855 | ------------------------------------------------- |
---|
856 | |
---|
857 | CALLING SEQUENCE: |
---|
858 | .. code-block:: c |
---|
859 | |
---|
860 | int rtems_binary_semaphore_wait_timed_ticks( |
---|
861 | rtems_binary_semaphore *binary_semaphore, |
---|
862 | uint32_t ticks |
---|
863 | ); |
---|
864 | |
---|
865 | DIRECTIVE STATUS CODES: |
---|
866 | .. list-table:: |
---|
867 | :class: rtems-table |
---|
868 | |
---|
869 | * - ``0`` |
---|
870 | - The semaphore wait was successful. |
---|
871 | * - ``ETIMEDOUT`` |
---|
872 | - The semaphore wait timed out. |
---|
873 | |
---|
874 | DESCRIPTION: |
---|
875 | Waits for the ``binary_semaphore`` with a timeout in ``ticks``. In case |
---|
876 | the current semaphore value is one, then the value is set to zero and the |
---|
877 | function returns immediately with a return value of ``0``, otherwise the |
---|
878 | thread is blocked waiting for a semaphore post. The time waiting for a |
---|
879 | semaphore post is limited by ``ticks``. A ``ticks`` value of zero |
---|
880 | specifies an infinite timeout. |
---|
881 | |
---|
882 | NOTES: |
---|
883 | This function must be called from thread context with interrupts enabled. |
---|
884 | Threads wait in priority order. |
---|
885 | |
---|
886 | .. raw:: latex |
---|
887 | |
---|
888 | \clearpage |
---|
889 | |
---|
890 | Tries to wait for a binary semaphore |
---|
891 | ------------------------------------ |
---|
892 | |
---|
893 | CALLING SEQUENCE: |
---|
894 | .. code-block:: c |
---|
895 | |
---|
896 | int rtems_binary_semaphore_try_wait( |
---|
897 | rtems_binary_semaphore *binary_semaphore |
---|
898 | ); |
---|
899 | |
---|
900 | DIRECTIVE STATUS CODES: |
---|
901 | .. list-table:: |
---|
902 | :class: rtems-table |
---|
903 | |
---|
904 | * - ``0`` |
---|
905 | - The semaphore wait was successful. |
---|
906 | * - ``EAGAIN`` |
---|
907 | - The semaphore wait failed. |
---|
908 | |
---|
909 | DESCRIPTION: |
---|
910 | Tries to wait for the ``binary_semaphore``. In case the current semaphore |
---|
911 | value is one, then the value is set to zero and the function returns |
---|
912 | immediately with a return value of ``0``, otherwise it returns immediately |
---|
913 | with a return value of ``EAGAIN``. |
---|
914 | |
---|
915 | NOTES: |
---|
916 | This function may be called from interrupt context. In case it is called |
---|
917 | from thread context, then interrupts must be enabled. |
---|
918 | |
---|
919 | .. raw:: latex |
---|
920 | |
---|
921 | \clearpage |
---|
922 | |
---|
923 | Post a binary semaphore |
---|
924 | ----------------------- |
---|
925 | |
---|
926 | CALLING SEQUENCE: |
---|
927 | .. code-block:: c |
---|
928 | |
---|
929 | void rtems_binary_semaphore_post( |
---|
930 | rtems_binary_semaphore *binary_semaphore |
---|
931 | ); |
---|
932 | |
---|
933 | DESCRIPTION: |
---|
934 | Posts the ``binary_semaphore``. In case at least one thread is waiting |
---|
935 | on the binary semaphore, then the highest priority thread is woken up, |
---|
936 | otherwise the current value is set to one. |
---|
937 | |
---|
938 | NOTES: |
---|
939 | This function may be called from interrupt context. In case it is called |
---|
940 | from thread context, then interrupts must be enabled. |
---|
941 | |
---|
942 | .. raw:: latex |
---|
943 | |
---|
944 | \clearpage |
---|
945 | |
---|
946 | .. raw:: latex |
---|
947 | |
---|
948 | \clearpage |
---|
949 | |
---|
950 | Set binary semaphore name |
---|
951 | ------------------------- |
---|
952 | |
---|
953 | CALLING SEQUENCE: |
---|
954 | .. code-block:: c |
---|
955 | |
---|
956 | void rtems_binary_semaphore_set_name( |
---|
957 | rtems_binary_semaphore *binary_semaphore, |
---|
958 | const char *name |
---|
959 | ); |
---|
960 | |
---|
961 | DESCRIPTION: |
---|
962 | Sets the ``binary_semaphore`` name to ``name``. |
---|
963 | |
---|
964 | NOTES: |
---|
965 | The ``name`` must be persistent throughout the life-time of the binary |
---|
966 | semaphore. A ``name`` of ``NULL`` is valid. |
---|
967 | |
---|
968 | .. raw:: latex |
---|
969 | |
---|
970 | \clearpage |
---|
971 | |
---|
972 | Get binary semaphore name |
---|
973 | ------------------------- |
---|
974 | |
---|
975 | CALLING SEQUENCE: |
---|
976 | .. code-block:: c |
---|
977 | |
---|
978 | const char *rtems_binary_semaphore_get_name( |
---|
979 | const rtems_binary_semaphore *binary_semaphore |
---|
980 | ); |
---|
981 | |
---|
982 | DESCRIPTION: |
---|
983 | Returns the ``binary_semaphore`` name. |
---|
984 | |
---|
985 | NOTES: |
---|
986 | The name may be ``NULL``. |
---|
987 | |
---|
988 | Binary semaphore destruction |
---|
989 | ---------------------------- |
---|
990 | |
---|
991 | CALLING SEQUENCE: |
---|
992 | .. code-block:: c |
---|
993 | |
---|
994 | void rtems_binary_semaphore_destroy( |
---|
995 | rtems_binary_semaphore *binary_semaphore |
---|
996 | ); |
---|
997 | |
---|
998 | DESCRIPTION: |
---|
999 | Destroys the ``binary_semaphore``. |
---|
1000 | |
---|
1001 | NOTES: |
---|
1002 | In case the binary semaphore still in use, then the result is |
---|
1003 | unpredictable. |
---|
1004 | |
---|
1005 | Threads |
---|
1006 | ======= |
---|
1007 | |
---|
1008 | .. warning:: |
---|
1009 | |
---|
1010 | The self-contained threads support is work in progress. In contrast to the |
---|
1011 | synchronization objects the self-contained thread support is not just an API |
---|
1012 | glue layer to already existing implementations. |
---|
1013 | |
---|
1014 | The :c:type:`rtems_thread` object provides a thread of execution. |
---|
1015 | |
---|
1016 | CALLING SEQUENCE: |
---|
1017 | .. code-block:: c |
---|
1018 | |
---|
1019 | RTEMS_THREAD_INITIALIZER( |
---|
1020 | name, |
---|
1021 | thread_size, |
---|
1022 | priority, |
---|
1023 | flags, |
---|
1024 | entry, |
---|
1025 | arg |
---|
1026 | ); |
---|
1027 | |
---|
1028 | void rtems_thread_start( |
---|
1029 | rtems_thread *thread, |
---|
1030 | const char *name, |
---|
1031 | size_t thread_size, |
---|
1032 | uint32_t priority, |
---|
1033 | uint32_t flags, |
---|
1034 | void ( *entry )( void * ), |
---|
1035 | void *arg |
---|
1036 | ); |
---|
1037 | |
---|
1038 | void rtems_thread_restart( |
---|
1039 | rtems_thread *thread, |
---|
1040 | void *arg |
---|
1041 | ) RTEMS_NO_RETURN; |
---|
1042 | |
---|
1043 | void rtems_thread_event_send( |
---|
1044 | rtems_thread *thread, |
---|
1045 | uint32_t events |
---|
1046 | ); |
---|
1047 | |
---|
1048 | uint32_t rtems_thread_event_poll( |
---|
1049 | rtems_thread *thread, |
---|
1050 | uint32_t events_of_interest |
---|
1051 | ); |
---|
1052 | |
---|
1053 | uint32_t rtems_thread_event_wait_all( |
---|
1054 | rtems_thread *thread, |
---|
1055 | uint32_t events_of_interest |
---|
1056 | ); |
---|
1057 | |
---|
1058 | uint32_t rtems_thread_event_wait_any( |
---|
1059 | rtems_thread *thread, |
---|
1060 | uint32_t events_of_interest |
---|
1061 | ); |
---|
1062 | |
---|
1063 | void rtems_thread_destroy( |
---|
1064 | rtems_thread *thread |
---|
1065 | ); |
---|
1066 | |
---|
1067 | void rtems_thread_destroy_self( |
---|
1068 | void |
---|
1069 | ) RTEMS_NO_RETURN; |
---|