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