tree-object-size: Clean up unknown propagation
[official-gcc.git] / libgcc / config / gthr-vxworks.h
blob98866a00907738c65e93b5ebb4039ea4c29c632c
1 /* Threads compatibility routines for libgcc2 and libobjc for VxWorks. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1997-2023 Free Software Foundation, Inc.
4 Contributed by Mike Stump <mrs@wrs.com>.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
18 Under Section 7 of GPL version 3, you are granted additional
19 permissions described in the GCC Runtime Library Exception, version
20 3.1, as published by the Free Software Foundation.
22 You should have received a copy of the GNU General Public License and
23 a copy of the GCC Runtime Library Exception along with this program;
24 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
25 <http://www.gnu.org/licenses/>. */
27 #ifndef GCC_GTHR_VXWORKS_H
28 #define GCC_GTHR_VXWORKS_H
30 #ifdef _LIBOBJC
32 /* libobjc requires the optional pthreads component. */
33 #include "gthr-posix.h"
35 #else
37 #include <vxWorks.h>
38 #include <_vxworks-versions.h>
40 /* Some VxWorks headers profusely use typedefs of a pointer to a function with
41 undefined number of arguments. Arrange to ignore declaration errors in C++,
42 which is achievable by ignoring Wstrict-prototypes diagnostics even when the
43 option is registered as only valid for c/objc. */
44 #pragma GCC diagnostic push
45 #pragma GCC diagnostic ignored "-Wpragmas"
46 #pragma GCC diagnostic ignored "-Wstrict-prototypes"
47 #include <semLib.h>
48 #pragma GCC diagnostic pop
50 #include <errnoLib.h>
53 /* --------------------- Test & Set/Swap internal API --------------------- */
55 /* We use a bare atomic primitive with busy loops to handle mutual exclusion.
56 Inefficient, but reliable. The actual primitive used depends on the mode
57 (RTP vs Kernel) and the version of VxWorks. We define a macro and a type
58 here, for reuse without conditionals cluttering in the code afterwards. */
60 /* RTP, pre 6.9. */
62 #if defined(__RTP__) && _VXWORKS_PRE(6,9)
64 #define __TAS(x) vxCas ((x), 0, 1)
65 typedef volatile unsigned char __vx_tas_t;
67 #endif
69 /* RTP, 6.9 and beyond. */
71 #if defined(__RTP__) && !_VXWORKS_PRE(6,9)
73 #define __TAS(x) vxAtomicCas ((x), 0, 1)
74 typedef atomic_t __vx_tas_t;
76 /* Our implementation will need the system headers to use the vxAtomic
77 primitives. Other includers won't and could actually be incompatible
78 with this inclusion, for instance libstdc++ sources compiled in C++
79 98 mode while AtomicLib for C++ requires C++ 11 at least. */
81 #if defined(IN_LIBGCC2)
82 #include <vxAtomicLib.h>
83 #endif
85 #endif
87 /* Kernel */
89 #if !defined(__RTP__)
91 #define __TAS(x) vxTas (x)
92 typedef volatile unsigned char __vx_tas_t;
94 #endif
96 #ifdef __cplusplus
97 extern "C" {
98 #endif
100 /* ------------------------ Base __GTHREADS support ----------------------- */
102 #define __GTHREADS 1
103 #define __gthread_active_p() 1
105 /* Mutexes are easy, except that they need to be initialized at runtime. */
107 /* All VxWorks mutexes are recursive. */
108 typedef SEM_ID __gthread_mutex_t;
109 typedef SEM_ID __gthread_recursive_mutex_t;
110 #define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init
111 #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init
113 #define __CHECK_RESULT(result) (((result) == OK) ? OK : errnoGet())
115 /* If a call to the VxWorks API fails, we must propagate the errno value. */
116 #define __RETURN_ERRNO_IF_NOT_OK(exp) if ((exp) != OK) return errnoGet()
118 /* Non re-entrant mutex implementation. Libstdc++ expects the default
119 gthread mutex to be non reentrant. */
121 static inline void
122 __gthread_mutex_init (__gthread_mutex_t * __mutex)
124 if (!__mutex)
125 return;
126 *__mutex = semBCreate (SEM_Q_PRIORITY, SEM_FULL);
129 static inline int
130 __gthread_mutex_destroy (__gthread_mutex_t * __mutex)
132 if (!__mutex)
133 return ERROR;
134 return __CHECK_RESULT (semDelete (*__mutex));
137 static inline int
138 __gthread_mutex_lock (__gthread_mutex_t * __mutex)
140 if (!__mutex)
141 return ERROR;
142 return __CHECK_RESULT (semTake(*__mutex, WAIT_FOREVER));
145 static inline int
146 __gthread_mutex_trylock (__gthread_mutex_t * __mutex)
148 if (!__mutex)
149 return ERROR;
150 return __CHECK_RESULT (semTake (*__mutex, NO_WAIT));
153 static inline int
154 __gthread_mutex_unlock (__gthread_mutex_t * __mutex)
156 if (!__mutex)
157 return ERROR;
158 return __CHECK_RESULT (semGive (*__mutex));
161 /* Recursive mutex implementation. The only change is that we use semMCreate()
162 instead of semBCreate(). */
164 static inline void
165 __gthread_recursive_mutex_init (__gthread_recursive_mutex_t * __mutex)
167 if (!__mutex)
168 return;
169 *__mutex =
170 semMCreate (SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE);
173 static inline int
174 __gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t * __mutex)
176 return __gthread_mutex_destroy (__mutex);
179 static inline int
180 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t * __mutex)
182 return __gthread_mutex_lock (__mutex);
185 static inline int
186 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t * __mutex)
188 return __gthread_mutex_trylock (__mutex);
191 static inline int
192 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t * __mutex)
194 return __gthread_mutex_unlock (__mutex);
197 typedef struct
199 /* PPC's test-and-set kernel mode implementation requires a pointer aligned
200 object, of which it only sets the first byte. We use padding in addition
201 to an alignment request here to maxmise the factors leading to the
202 desired actual alignment choice by the compiler. */
203 #if defined(__PPC__)
204 __attribute ((aligned (__alignof__ (void *))))
205 #endif
207 __vx_tas_t busy;
208 volatile unsigned char done;
210 #if !defined(__RTP__) && defined(__PPC__)
211 unsigned char pad1;
212 unsigned char pad2;
213 #endif
214 #if !defined(__RTP__) && defined(__PPC64__)
215 unsigned char pad3;
216 unsigned char pad4;
217 unsigned char pad5;
218 unsigned char pad6;
219 #endif
220 } __gthread_once_t;
222 #define __GTHREAD_ONCE_INIT {}
224 extern int __gthread_once (__gthread_once_t *__once, void (*__func)(void));
226 /* All the TSD routines are sufficiently complex that they
227 need to be implemented out of line. */
229 typedef unsigned int __gthread_key_t;
231 extern int __gthread_key_create (__gthread_key_t *__keyp,
232 void (*__dtor)(void *));
233 extern int __gthread_key_delete (__gthread_key_t __key);
235 extern void *__gthread_getspecific (__gthread_key_t __key);
236 extern int __gthread_setspecific (__gthread_key_t __key, void *__ptr);
238 /* ------------------ Base condition variables support ------------------- */
240 /* VxWorks prio to 6 misses a few services key to a correct
241 implementation of condition variables with reasonable complexity.
242 semExchange in particular. */
244 #if _VXWORKS_MAJOR_GE(6)
246 #define __GTHREAD_HAS_COND 1
248 typedef SEM_ID __gthread_cond_t;
250 #define __GTHREAD_COND_INIT_FUNCTION __gthread_cond_init
252 /* Condition variable declarations. */
254 extern void __gthread_cond_init (__gthread_cond_t *cond);
256 extern int __gthread_cond_destroy (__gthread_cond_t *cond);
258 extern int __gthread_cond_broadcast (__gthread_cond_t *cond);
260 extern int __gthread_cond_wait (__gthread_cond_t *cond,
261 __gthread_mutex_t *mutex);
263 extern int __gthread_cond_wait_recursive (__gthread_cond_t *cond,
264 __gthread_recursive_mutex_t *mutex);
266 #endif
268 /* ----------------------- C++0x thread support ------------------------- */
270 /* We do not support C++0x threads on that VxWorks 653, which we can
271 recognize by VTHREADS being defined. */
273 #if _VXWORKS_MAJOR_GE(6) && !defined(VTHREADS)
275 #define __GTHREADS_CXX0X 1
277 #include <limits.h>
278 #include <time.h>
279 #include <tickLib.h>
280 #include <sysLib.h>
281 #include <version.h>
283 typedef struct
285 TASK_ID task_id;
286 void *return_value;
288 /* This mutex is used to block in join() while the return value is
289 unavailable. */
290 __gthread_mutex_t return_value_available;
292 /* Before freeing the structure in the task wrapper, we need to wait until
293 join() or detach() are called on that thread. */
294 __gthread_mutex_t delete_ok;
295 } __gthread_tcb;
297 typedef __gthread_tcb *__gthread_t;
299 /* Typedefs specific to different vxworks versions. */
300 #if _VXWORKS_PRE(6,9)
301 typedef int _Vx_usr_arg_t;
302 #define TASK_ID_NULL ((TASK_ID)NULL)
303 #define SEM_ID_NULL ((SEM_ID)NULL)
304 #endif
306 typedef struct timespec __gthread_time_t;
308 /* Timed mutex lock declarations. */
310 extern int __gthread_mutex_timedlock (__gthread_mutex_t *m,
311 const __gthread_time_t *abs_time);
313 extern int __gthread_recursive_mutex_timedlock
314 (__gthread_recursive_mutex_t *mutex,
315 const __gthread_time_t *abs_timeout);
317 /* Timed condition variable declarations. */
319 extern int __gthread_cond_signal (__gthread_cond_t *cond);
320 extern int __gthread_cond_timedwait (__gthread_cond_t *cond,
321 __gthread_mutex_t *mutex,
322 const __gthread_time_t *abs_timeout);
324 /* gthreads declarations. */
326 extern int __gthread_equal (__gthread_t t1, __gthread_t t2);
327 extern int __gthread_yield (void);
328 extern int __gthread_create (__gthread_t *__threadid,
329 void *(*__func) (void*),
330 void *__args);
331 extern int __gthread_join (__gthread_t thread, void **value_ptr);
332 extern int __gthread_detach (__gthread_t thread);
334 extern __gthread_t __gthread_self (void);
336 #endif /* _VXWORKS_MAJOR_GE(6) && !defined(VTHREADS) */
338 #ifdef __cplusplus
340 #endif
342 #endif /* not _LIBOBJC */
344 #endif /* gthr-vxworks.h */