Suppress -fstack-protector warning on hppa.
[official-gcc.git] / libgomp / libgomp.h
blob8fc9379d1b3cc90c65d98f3e484dc47c2c9ecd27
1 /* Copyright (C) 2005-2022 Free Software Foundation, Inc.
2 Contributed by Richard Henderson <rth@redhat.com>.
4 This file is part of the GNU Offloading and Multi Processing Library
5 (libgomp).
7 Libgomp is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
12 Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 more details.
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
26 /* This file contains data types and function declarations that are not
27 part of the official OpenACC or OpenMP user interfaces. There are
28 declarations in here that are part of the GNU Offloading and Multi
29 Processing ABI, in that the compiler is required to know about them
30 and use them.
32 The convention is that the all caps prefix "GOMP" is used group items
33 that are part of the external ABI, and the lower case prefix "gomp"
34 is used group items that are completely private to the library. */
36 #ifndef LIBGOMP_H
37 #define LIBGOMP_H 1
39 #ifndef _LIBGOMP_CHECKING_
40 /* Define to 1 to perform internal sanity checks. */
41 #define _LIBGOMP_CHECKING_ 0
42 #endif
44 #include "config.h"
45 #include <stdint.h>
46 #include "libgomp-plugin.h"
47 #include "gomp-constants.h"
49 #ifdef HAVE_PTHREAD_H
50 #include <pthread.h>
51 #endif
52 #include <stdbool.h>
53 #include <stdlib.h>
54 #include <stdarg.h>
56 /* Needed for memset in priority_queue.c. */
57 #if _LIBGOMP_CHECKING_
58 # ifdef STRING_WITH_STRINGS
59 # include <string.h>
60 # include <strings.h>
61 # else
62 # ifdef HAVE_STRING_H
63 # include <string.h>
64 # else
65 # ifdef HAVE_STRINGS_H
66 # include <strings.h>
67 # endif
68 # endif
69 # endif
70 #endif
72 #ifdef HAVE_ATTRIBUTE_VISIBILITY
73 # pragma GCC visibility push(hidden)
74 #endif
76 /* If we were a C++ library, we'd get this from <std/atomic>. */
77 enum memmodel
79 MEMMODEL_RELAXED = 0,
80 MEMMODEL_CONSUME = 1,
81 MEMMODEL_ACQUIRE = 2,
82 MEMMODEL_RELEASE = 3,
83 MEMMODEL_ACQ_REL = 4,
84 MEMMODEL_SEQ_CST = 5
87 /* alloc.c */
89 #if defined(HAVE_ALIGNED_ALLOC) \
90 || defined(HAVE_POSIX_MEMALIGN) \
91 || defined(HAVE_MEMALIGN)
92 /* Defined if gomp_aligned_alloc doesn't use fallback version
93 and free can be used instead of gomp_aligned_free. */
94 #define GOMP_HAVE_EFFICIENT_ALIGNED_ALLOC 1
95 #endif
97 #if defined(GOMP_HAVE_EFFICIENT_ALIGNED_ALLOC) && !defined(__AMDGCN__)
98 #define GOMP_USE_ALIGNED_WORK_SHARES 1
99 #endif
101 extern void *gomp_malloc (size_t) __attribute__((malloc));
102 extern void *gomp_malloc_cleared (size_t) __attribute__((malloc));
103 extern void *gomp_realloc (void *, size_t);
104 extern void *gomp_aligned_alloc (size_t, size_t)
105 __attribute__((malloc, alloc_size (2)));
106 extern void gomp_aligned_free (void *);
108 /* Avoid conflicting prototypes of alloca() in system headers by using
109 GCC's builtin alloca(). */
110 #define gomp_alloca(x) __builtin_alloca(x)
112 /* Optimized allocators for team-specific data that will die with the team. */
114 #ifdef __AMDGCN__
115 /* The arena is initialized in config/gcn/team.c. */
116 #define TEAM_ARENA_SIZE 64*1024 /* Must match the value in plugin-gcn.c. */
117 #define TEAM_ARENA_START 16 /* LDS offset of free pointer. */
118 #define TEAM_ARENA_FREE 24 /* LDS offset of free pointer. */
119 #define TEAM_ARENA_END 32 /* LDS offset of end pointer. */
121 static inline void * __attribute__((malloc))
122 team_malloc (size_t size)
124 /* 4-byte align the size. */
125 size = (size + 3) & ~3;
127 /* Allocate directly from the arena.
128 The compiler does not support DS atomics, yet. */
129 void *result;
130 asm ("ds_add_rtn_u64 %0, %1, %2\n\ts_waitcnt 0"
131 : "=v"(result) : "v"(TEAM_ARENA_FREE), "v"(size), "e"(1L) : "memory");
133 /* Handle OOM. */
134 if (result + size > *(void * __lds *)TEAM_ARENA_END)
136 /* While this is experimental, let's make sure we know when OOM
137 happens. */
138 const char msg[] = "GCN team arena exhausted\n";
139 write (2, msg, sizeof(msg)-1);
141 /* Fall back to using the heap (slowly). */
142 result = gomp_malloc (size);
144 return result;
147 static inline void * __attribute__((malloc))
148 team_malloc_cleared (size_t size)
150 char *result = team_malloc (size);
152 /* Clear the allocated memory. */
153 __builtin_memset (result, 0, size);
155 return result;
158 static inline void
159 team_free (void *ptr)
161 /* The whole arena is freed when the kernel exits.
162 However, if we fell back to using heap then we should free it.
163 It would be better if this function could be a no-op, but at least
164 LDS loads are cheap. */
165 if (ptr < *(void * __lds *)TEAM_ARENA_START
166 || ptr >= *(void * __lds *)TEAM_ARENA_END)
167 free (ptr);
169 #else
170 #define team_malloc(...) gomp_malloc (__VA_ARGS__)
171 #define team_malloc_cleared(...) gomp_malloc_cleared (__VA_ARGS__)
172 #define team_free(...) free (__VA_ARGS__)
173 #endif
175 /* error.c */
177 extern void gomp_vdebug (int, const char *, va_list);
178 extern void gomp_debug (int, const char *, ...)
179 __attribute__ ((format (printf, 2, 3)));
180 #define gomp_vdebug(KIND, FMT, VALIST) \
181 do { \
182 if (__builtin_expect (gomp_debug_var, 0)) \
183 (gomp_vdebug) ((KIND), (FMT), (VALIST)); \
184 } while (0)
185 #define gomp_debug(KIND, ...) \
186 do { \
187 if (__builtin_expect (gomp_debug_var, 0)) \
188 (gomp_debug) ((KIND), __VA_ARGS__); \
189 } while (0)
190 extern void gomp_verror (const char *, va_list);
191 extern void gomp_error (const char *, ...)
192 __attribute__ ((format (printf, 1, 2)));
193 extern void gomp_vfatal (const char *, va_list)
194 __attribute__ ((noreturn));
195 extern void gomp_fatal (const char *, ...)
196 __attribute__ ((noreturn, format (printf, 1, 2)));
198 struct gomp_task;
199 struct gomp_taskgroup;
200 struct htab;
202 #include "priority_queue.h"
203 #include "sem.h"
204 #include "mutex.h"
205 #include "bar.h"
206 #include "simple-bar.h"
207 #include "ptrlock.h"
210 /* This structure contains the data to control one work-sharing construct,
211 either a LOOP (FOR/DO) or a SECTIONS. */
213 enum gomp_schedule_type
215 GFS_RUNTIME,
216 GFS_STATIC,
217 GFS_DYNAMIC,
218 GFS_GUIDED,
219 GFS_AUTO,
220 GFS_MONOTONIC = 0x80000000U
223 struct gomp_doacross_work_share
225 union {
226 /* chunk_size copy, as ws->chunk_size is multiplied by incr for
227 GFS_DYNAMIC. */
228 long chunk_size;
229 /* Likewise, but for ull implementation. */
230 unsigned long long chunk_size_ull;
231 /* For schedule(static,0) this is the number
232 of iterations assigned to the last thread, i.e. number of
233 iterations / number of threads. */
234 long q;
235 /* Likewise, but for ull implementation. */
236 unsigned long long q_ull;
238 /* Size of each array entry (padded to cache line size). */
239 unsigned long elt_sz;
240 /* Number of dimensions in sink vectors. */
241 unsigned int ncounts;
242 /* True if the iterations can be flattened. */
243 bool flattened;
244 /* Actual array (of elt_sz sized units), aligned to cache line size.
245 This is indexed by team_id for GFS_STATIC and outermost iteration
246 / chunk_size for other schedules. */
247 unsigned char *array;
248 /* These two are only used for schedule(static,0). */
249 /* This one is number of iterations % number of threads. */
250 long t;
251 union {
252 /* And this one is cached t * (q + 1). */
253 long boundary;
254 /* Likewise, but for the ull implementation. */
255 unsigned long long boundary_ull;
257 /* Pointer to extra memory if needed for lastprivate(conditional). */
258 void *extra;
259 /* Array of shift counts for each dimension if they can be flattened. */
260 unsigned int shift_counts[];
263 /* Like struct gomp_work_share, but only the 1st cacheline of it plus
264 flexible array at the end.
265 Keep in sync with struct gomp_work_share. */
266 struct gomp_work_share_1st_cacheline
268 enum gomp_schedule_type sched;
269 int mode;
270 union {
271 struct {
272 long chunk_size, end, incr;
274 struct {
275 unsigned long long chunk_size_ull, end_ull, incr_ull;
278 union {
279 unsigned *ordered_team_ids;
280 struct gomp_doacross_work_share *doacross;
282 unsigned ordered_num_used, ordered_owner, ordered_cur;
283 struct gomp_work_share *next_alloc;
284 char pad[];
287 struct gomp_work_share
289 /* This member records the SCHEDULE clause to be used for this construct.
290 The user specification of "runtime" will already have been resolved.
291 If this is a SECTIONS construct, this value will always be DYNAMIC. */
292 enum gomp_schedule_type sched;
294 int mode;
296 union {
297 struct {
298 /* This is the chunk_size argument to the SCHEDULE clause. */
299 long chunk_size;
301 /* This is the iteration end point. If this is a SECTIONS construct,
302 this is the number of contained sections. */
303 long end;
305 /* This is the iteration step. If this is a SECTIONS construct, this
306 is always 1. */
307 long incr;
310 struct {
311 /* The same as above, but for the unsigned long long loop variants. */
312 unsigned long long chunk_size_ull;
313 unsigned long long end_ull;
314 unsigned long long incr_ull;
318 union {
319 /* This is a circular queue that details which threads will be allowed
320 into the ordered region and in which order. When a thread allocates
321 iterations on which it is going to work, it also registers itself at
322 the end of the array. When a thread reaches the ordered region, it
323 checks to see if it is the one at the head of the queue. If not, it
324 blocks on its RELEASE semaphore. */
325 unsigned *ordered_team_ids;
327 /* This is a pointer to DOACROSS work share data. */
328 struct gomp_doacross_work_share *doacross;
331 /* This is the number of threads that have registered themselves in
332 the circular queue ordered_team_ids. */
333 unsigned ordered_num_used;
335 /* This is the team_id of the currently acknowledged owner of the ordered
336 section, or -1u if the ordered section has not been acknowledged by
337 any thread. This is distinguished from the thread that is *allowed*
338 to take the section next. */
339 unsigned ordered_owner;
341 /* This is the index into the circular queue ordered_team_ids of the
342 current thread that's allowed into the ordered reason. */
343 unsigned ordered_cur;
345 /* This is a chain of allocated gomp_work_share blocks, valid only
346 in the first gomp_work_share struct in the block. */
347 struct gomp_work_share *next_alloc;
349 /* The above fields are written once during workshare initialization,
350 or related to ordered worksharing. Make sure the following fields
351 are in a different cache line. */
353 /* This lock protects the update of the following members. */
354 #ifdef GOMP_USE_ALIGNED_WORK_SHARES
355 gomp_mutex_t lock __attribute__((aligned (64)));
356 #else
357 char pad[64 - offsetof (struct gomp_work_share_1st_cacheline, pad)];
358 gomp_mutex_t lock;
359 #endif
361 /* This is the count of the number of threads that have exited the work
362 share construct. If the construct was marked nowait, they have moved on
363 to other work; otherwise they're blocked on a barrier. The last member
364 of the team to exit the work share construct must deallocate it. */
365 unsigned threads_completed;
367 union {
368 /* This is the next iteration value to be allocated. In the case of
369 GFS_STATIC loops, this the iteration start point and never changes. */
370 long next;
372 /* The same, but with unsigned long long type. */
373 unsigned long long next_ull;
375 /* This is the returned data structure for SINGLE COPYPRIVATE. */
376 void *copyprivate;
379 union {
380 /* Link to gomp_work_share struct for next work sharing construct
381 encountered after this one. */
382 gomp_ptrlock_t next_ws;
384 /* gomp_work_share structs are chained in the free work share cache
385 through this. */
386 struct gomp_work_share *next_free;
389 /* Task reductions for this work-sharing construct. */
390 uintptr_t *task_reductions;
392 /* If only few threads are in the team, ordered_team_ids can point
393 to this array which fills the padding at the end of this struct. */
394 unsigned inline_ordered_team_ids[0];
397 extern char gomp_workshare_struct_check1
398 [offsetof (struct gomp_work_share_1st_cacheline, next_alloc)
399 == offsetof (struct gomp_work_share, next_alloc) ? 1 : -1];
400 extern char gomp_workshare_struct_check2
401 [offsetof (struct gomp_work_share, lock) == 64 ? 1 : -1];
403 /* This structure contains all of the thread-local data associated with
404 a thread team. This is the data that must be saved when a thread
405 encounters a nested PARALLEL construct. */
407 struct gomp_team_state
409 /* This is the team of which the thread is currently a member. */
410 struct gomp_team *team;
412 /* This is the work share construct which this thread is currently
413 processing. Recall that with NOWAIT, not all threads may be
414 processing the same construct. */
415 struct gomp_work_share *work_share;
417 /* This is the previous work share construct or NULL if there wasn't any.
418 When all threads are done with the current work sharing construct,
419 the previous one can be freed. The current one can't, as its
420 next_ws field is used. */
421 struct gomp_work_share *last_work_share;
423 /* This is the ID of this thread within the team. This value is
424 guaranteed to be between 0 and N-1, where N is the number of
425 threads in the team. */
426 unsigned team_id;
428 /* Nesting level. */
429 unsigned level;
431 /* Active nesting level. Only active parallel regions are counted. */
432 unsigned active_level;
434 /* Place-partition-var, offset and length into gomp_places_list array. */
435 unsigned place_partition_off;
436 unsigned place_partition_len;
438 /* Def-allocator-var ICV. */
439 uintptr_t def_allocator;
441 #ifdef HAVE_SYNC_BUILTINS
442 /* Number of single stmts encountered. */
443 unsigned long single_count;
444 #endif
446 /* For GFS_RUNTIME loops that resolved to GFS_STATIC, this is the
447 trip number through the loop. So first time a particular loop
448 is encountered this number is 0, the second time through the loop
449 is 1, etc. This is unused when the compiler knows in advance that
450 the loop is statically scheduled. */
451 unsigned long static_trip;
454 struct target_mem_desc;
456 enum gomp_icvs
458 GOMP_ICV_NTEAMS = 1,
459 GOMP_ICV_SCHEDULE = 2,
460 GOMP_ICV_SCHEDULE_CHUNK_SIZE = 3,
461 GOMP_ICV_DYNAMIC = 4,
462 GOMP_ICV_TEAMS_THREAD_LIMIT = 5,
463 GOMP_ICV_THREAD_LIMIT = 6,
464 GOMP_ICV_NTHREADS = 7,
465 GOMP_ICV_NTHREADS_LIST = 8,
466 GOMP_ICV_NTHREADS_LIST_LEN = 9,
467 GOMP_ICV_BIND = 10,
468 GOMP_ICV_BIND_LIST = 11,
469 GOMP_ICV_BIND_LIST_LEN = 12,
470 GOMP_ICV_MAX_ACTIVE_LEVELS = 13,
471 GOMP_ICV_WAIT_POLICY = 14,
472 GOMP_ICV_STACKSIZE = 15,
473 GOMP_ICV_DEFAULT_DEVICE = 16,
474 GOMP_ICV_CANCELLATION = 17,
475 GOMP_ICV_DISPLAY_AFFINITY = 18,
476 GOMP_ICV_TARGET_OFFLOAD = 19,
477 GOMP_ICV_MAX_TASK_PRIORITY = 20,
478 GOMP_ICV_ALLOCATOR = 21
481 enum gomp_device_num
483 GOMP_DEVICE_NUM_FOR_DEV = -1,
484 GOMP_DEVICE_NUM_FOR_ALL = -2,
485 GOMP_DEVICE_NUM_FOR_NO_SUFFIX = -3
488 /* These are the OpenMP 4.0 Internal Control Variables described in
489 section 2.3.1. Those described as having one copy per task are
490 stored within the structure; those described as having one copy
491 for the whole program are (naturally) global variables. */
493 struct gomp_task_icv
495 unsigned long nthreads_var;
496 enum gomp_schedule_type run_sched_var;
497 int run_sched_chunk_size;
498 int default_device_var;
499 unsigned int thread_limit_var;
500 bool dyn_var;
501 unsigned char max_active_levels_var;
502 char bind_var;
503 /* Internal ICV. */
504 struct target_mem_desc *target_data;
507 enum gomp_env_suffix
509 GOMP_ENV_SUFFIX_UNKNOWN = 0,
510 GOMP_ENV_SUFFIX_NONE = 1,
511 GOMP_ENV_SUFFIX_DEV = 2,
512 GOMP_ENV_SUFFIX_ALL = 4,
513 GOMP_ENV_SUFFIX_DEV_X = 8
516 /* Struct that contains all ICVs for which we need to store initial values.
517 Keeping the initial values is needed for omp_display_env. Moreover initial
518 _DEV and _ALL variants of environment variables are also used to determine
519 actually used values for devices and for the host. */
520 struct gomp_initial_icvs
522 unsigned long *nthreads_var_list;
523 char *bind_var_list;
524 unsigned long nthreads_var;
525 unsigned long nthreads_var_list_len;
526 unsigned long bind_var_list_len;
527 unsigned long stacksize;
528 int run_sched_chunk_size;
529 int default_device_var;
530 int nteams_var;
531 int teams_thread_limit_var;
532 int wait_policy;
533 unsigned int thread_limit_var;
534 enum gomp_schedule_type run_sched_var;
535 bool dyn_var;
536 unsigned char max_active_levels_var;
537 char bind_var;
540 struct gomp_default_icv
542 unsigned long nthreads_var;
543 enum gomp_schedule_type run_sched_var;
544 int run_sched_chunk_size;
545 int default_device_var;
546 unsigned int thread_limit_var;
547 int nteams_var;
548 int teams_thread_limit_var;
549 bool dyn_var;
550 unsigned char max_active_levels_var;
551 char bind_var;
554 /* DEVICE_NUM "-1" is reserved for "_DEV" icvs.
555 DEVICE_NUM "-2" is reserved for "_ALL" icvs.
556 DEVICE_NUM "-3" is reserved for ICVs without suffix.
557 Non-negative DEVICE_NUM is for "_DEV_X" icvs. */
558 struct gomp_icv_list
560 int device_num;
561 uint32_t flags;
562 struct gomp_initial_icvs icvs;
563 struct gomp_icv_list *next;
566 struct gomp_offload_icvs
568 int device_num;
569 int default_device;
570 int nteams;
571 int teams_thread_limit;
574 struct gomp_offload_icv_list
576 int device_num;
577 struct gomp_offload_icvs icvs;
578 struct gomp_offload_icv_list *next;
581 enum gomp_target_offload_t
583 GOMP_TARGET_OFFLOAD_DEFAULT,
584 GOMP_TARGET_OFFLOAD_MANDATORY,
585 GOMP_TARGET_OFFLOAD_DISABLED
588 #define gomp_supported_active_levels UCHAR_MAX
590 extern struct gomp_task_icv gomp_global_icv;
591 #ifndef HAVE_SYNC_BUILTINS
592 extern gomp_mutex_t gomp_managed_threads_lock;
593 #endif
594 extern bool gomp_cancel_var;
595 extern enum gomp_target_offload_t gomp_target_offload_var;
596 extern int gomp_max_task_priority_var;
597 extern unsigned long long gomp_spin_count_var, gomp_throttled_spin_count_var;
598 extern unsigned long gomp_available_cpus, gomp_managed_threads;
599 extern unsigned long *gomp_nthreads_var_list, gomp_nthreads_var_list_len;
600 extern char *gomp_bind_var_list;
601 extern unsigned long gomp_bind_var_list_len;
602 extern void **gomp_places_list;
603 extern unsigned long gomp_places_list_len;
604 extern unsigned int gomp_num_teams_var;
605 extern int gomp_nteams_var;
606 extern int gomp_teams_thread_limit_var;
607 extern int gomp_debug_var;
608 extern bool gomp_display_affinity_var;
609 extern char *gomp_affinity_format_var;
610 extern size_t gomp_affinity_format_len;
611 extern uintptr_t gomp_def_allocator;
612 extern const struct gomp_default_icv gomp_default_icv_values;
613 extern struct gomp_icv_list *gomp_initial_icv_list;
614 extern struct gomp_offload_icv_list *gomp_offload_icv_list;
615 extern int goacc_device_num;
616 extern char *goacc_device_type;
617 extern int goacc_default_dims[GOMP_DIM_MAX];
619 enum gomp_task_kind
621 /* Implicit task. */
622 GOMP_TASK_IMPLICIT,
623 /* Undeferred task. */
624 GOMP_TASK_UNDEFERRED,
625 /* Task created by GOMP_task and waiting to be run. */
626 GOMP_TASK_WAITING,
627 /* Task currently executing or scheduled and about to execute. */
628 GOMP_TASK_TIED,
629 /* Used for target tasks that have vars mapped and async run started,
630 but not yet completed. Once that completes, they will be readded
631 into the queues as GOMP_TASK_WAITING in order to perform the var
632 unmapping. */
633 GOMP_TASK_ASYNC_RUNNING,
634 /* Task that has finished executing but is waiting for its
635 completion event to be fulfilled. */
636 GOMP_TASK_DETACHED
639 struct gomp_task_depend_entry
641 /* Address of dependency. */
642 void *addr;
643 struct gomp_task_depend_entry *next;
644 struct gomp_task_depend_entry *prev;
645 /* Task that provides the dependency in ADDR. */
646 struct gomp_task *task;
647 /* Depend entry is of type "IN" (1) or "INOUTSET" (2). */
648 unsigned char is_in;
649 bool redundant;
650 bool redundant_out;
653 struct gomp_dependers_vec
655 size_t n_elem;
656 size_t allocated;
657 struct gomp_task *elem[];
660 /* Used when in GOMP_taskwait or in gomp_task_maybe_wait_for_dependencies. */
662 struct gomp_taskwait
664 bool in_taskwait;
665 bool in_depend_wait;
666 /* Number of tasks we are waiting for. */
667 size_t n_depend;
668 gomp_sem_t taskwait_sem;
671 /* This structure describes a "task" to be run by a thread. */
673 struct gomp_task
675 /* Parent of this task. */
676 struct gomp_task *parent;
677 /* Children of this task. */
678 struct priority_queue children_queue;
679 /* Taskgroup this task belongs in. */
680 struct gomp_taskgroup *taskgroup;
681 /* Tasks that depend on this task. */
682 struct gomp_dependers_vec *dependers;
683 struct htab *depend_hash;
684 struct gomp_taskwait *taskwait;
685 /* Last depend({,in}out:omp_all_memory) child if any. */
686 struct gomp_task *depend_all_memory;
687 /* Number of items in DEPEND. */
688 size_t depend_count;
689 /* Number of tasks this task depends on. Once this counter reaches
690 0, we have no unsatisfied dependencies, and this task can be put
691 into the various queues to be scheduled. */
692 size_t num_dependees;
694 union {
695 /* Valid only if deferred_p is false. */
696 gomp_sem_t *completion_sem;
697 /* Valid only if deferred_p is true. Set to the team that executes the
698 task if the task is detached and the completion event has yet to be
699 fulfilled. */
700 struct gomp_team *detach_team;
702 bool deferred_p;
704 /* Priority of this task. */
705 int priority;
706 /* The priority node for this task in each of the different queues.
707 We put this here to avoid allocating space for each priority
708 node. Then we play offsetof() games to convert between pnode[]
709 entries and the gomp_task in which they reside. */
710 struct priority_node pnode[3];
712 struct gomp_task_icv icv;
713 void (*fn) (void *);
714 void *fn_data;
715 enum gomp_task_kind kind;
716 bool in_tied_task;
717 bool final_task;
718 bool copy_ctors_done;
719 /* Set for undeferred tasks with unsatisfied dependencies which
720 block further execution of their parent until the dependencies
721 are satisfied. */
722 bool parent_depends_on;
723 /* Dependencies provided and/or needed for this task. DEPEND_COUNT
724 is the number of items available. */
725 struct gomp_task_depend_entry depend[];
728 /* This structure describes a single #pragma omp taskgroup. */
730 struct gomp_taskgroup
732 struct gomp_taskgroup *prev;
733 /* Queue of tasks that belong in this taskgroup. */
734 struct priority_queue taskgroup_queue;
735 uintptr_t *reductions;
736 bool in_taskgroup_wait;
737 bool cancelled;
738 bool workshare;
739 gomp_sem_t taskgroup_sem;
740 size_t num_children;
743 /* Various state of OpenMP async offloading tasks. */
744 enum gomp_target_task_state
746 GOMP_TARGET_TASK_DATA,
747 GOMP_TARGET_TASK_BEFORE_MAP,
748 GOMP_TARGET_TASK_FALLBACK,
749 GOMP_TARGET_TASK_READY_TO_RUN,
750 GOMP_TARGET_TASK_RUNNING,
751 GOMP_TARGET_TASK_FINISHED
754 /* This structure describes a target task. */
756 struct gomp_target_task
758 struct gomp_device_descr *devicep;
759 void (*fn) (void *);
760 size_t mapnum;
761 size_t *sizes;
762 unsigned short *kinds;
763 unsigned int flags;
764 enum gomp_target_task_state state;
765 struct target_mem_desc *tgt;
766 struct gomp_task *task;
767 struct gomp_team *team;
768 /* Device-specific target arguments. */
769 void **args;
770 void *hostaddrs[];
773 /* This structure describes a "team" of threads. These are the threads
774 that are spawned by a PARALLEL constructs, as well as the work sharing
775 constructs that the team encounters. */
777 struct gomp_team
779 /* This is the number of threads in the current team. */
780 unsigned nthreads;
782 /* This is number of gomp_work_share structs that have been allocated
783 as a block last time. */
784 unsigned work_share_chunk;
786 /* This is the saved team state that applied to a master thread before
787 the current thread was created. */
788 struct gomp_team_state prev_ts;
790 /* This semaphore should be used by the master thread instead of its
791 "native" semaphore in the thread structure. Required for nested
792 parallels, as the master is a member of two teams. */
793 gomp_sem_t master_release;
795 /* This points to an array with pointers to the release semaphore
796 of the threads in the team. */
797 gomp_sem_t **ordered_release;
799 /* List of work shares on which gomp_fini_work_share hasn't been
800 called yet. If the team hasn't been cancelled, this should be
801 equal to each thr->ts.work_share, but otherwise it can be a possibly
802 long list of workshares. */
803 struct gomp_work_share *work_shares_to_free;
805 /* List of gomp_work_share structs chained through next_free fields.
806 This is populated and taken off only by the first thread in the
807 team encountering a new work sharing construct, in a critical
808 section. */
809 struct gomp_work_share *work_share_list_alloc;
811 /* List of gomp_work_share structs freed by free_work_share. New
812 entries are atomically added to the start of the list, and
813 alloc_work_share can safely only move all but the first entry
814 to work_share_list alloc, as free_work_share can happen concurrently
815 with alloc_work_share. */
816 struct gomp_work_share *work_share_list_free;
818 #ifdef HAVE_SYNC_BUILTINS
819 /* Number of simple single regions encountered by threads in this
820 team. */
821 unsigned long single_count;
822 #else
823 /* Mutex protecting addition of workshares to work_share_list_free. */
824 gomp_mutex_t work_share_list_free_lock;
825 #endif
827 /* This barrier is used for most synchronization of the team. */
828 gomp_barrier_t barrier;
830 /* Initial work shares, to avoid allocating any gomp_work_share
831 structs in the common case. */
832 struct gomp_work_share work_shares[8];
834 gomp_mutex_t task_lock;
835 /* Scheduled tasks. */
836 struct priority_queue task_queue;
837 /* Number of all GOMP_TASK_{WAITING,TIED} tasks in the team. */
838 unsigned int task_count;
839 /* Number of GOMP_TASK_WAITING tasks currently waiting to be scheduled. */
840 unsigned int task_queued_count;
841 /* Number of GOMP_TASK_{WAITING,TIED} tasks currently running
842 directly in gomp_barrier_handle_tasks; tasks spawned
843 from e.g. GOMP_taskwait or GOMP_taskgroup_end don't count, even when
844 that is called from a task run from gomp_barrier_handle_tasks.
845 task_running_count should be always <= team->nthreads,
846 and if current task isn't in_tied_task, then it will be
847 even < team->nthreads. */
848 unsigned int task_running_count;
849 int work_share_cancelled;
850 int team_cancelled;
852 /* Number of tasks waiting for their completion event to be fulfilled. */
853 unsigned int task_detach_count;
855 /* This array contains structures for implicit tasks. */
856 struct gomp_task implicit_task[];
859 /* This structure contains all data that is private to libgomp and is
860 allocated per thread. */
862 struct gomp_thread
864 /* This is the function that the thread should run upon launch. */
865 void (*fn) (void *data);
866 void *data;
868 /* This is the current team state for this thread. The ts.team member
869 is NULL only if the thread is idle. */
870 struct gomp_team_state ts;
872 /* This is the task that the thread is currently executing. */
873 struct gomp_task *task;
875 /* This semaphore is used for ordered loops. */
876 gomp_sem_t release;
878 /* Place this thread is bound to plus one, or zero if not bound
879 to any place. */
880 unsigned int place;
882 /* User pthread thread pool */
883 struct gomp_thread_pool *thread_pool;
885 #ifdef LIBGOMP_USE_PTHREADS
886 /* omp_get_num_teams () - 1. */
887 unsigned int num_teams;
889 /* omp_get_team_num (). */
890 unsigned int team_num;
891 #endif
893 #if defined(LIBGOMP_USE_PTHREADS) \
894 && (!defined(HAVE_TLS) \
895 || !defined(__GLIBC__) \
896 || !defined(USING_INITIAL_EXEC_TLS))
897 /* pthread_t of the thread containing this gomp_thread.
898 On Linux when using initial-exec TLS,
899 (typeof (pthread_t)) gomp_thread () - pthread_self ()
900 is constant in all threads, so we can optimize and not
901 store it. */
902 #define GOMP_NEEDS_THREAD_HANDLE 1
903 pthread_t handle;
904 #endif
908 struct gomp_thread_pool
910 /* This array manages threads spawned from the top level, which will
911 return to the idle loop once the current PARALLEL construct ends. */
912 struct gomp_thread **threads;
913 unsigned threads_size;
914 unsigned threads_used;
915 /* The last team is used for non-nested teams to delay their destruction to
916 make sure all the threads in the team move on to the pool's barrier before
917 the team's barrier is destroyed. */
918 struct gomp_team *last_team;
919 /* Number of threads running in this contention group. */
920 unsigned long threads_busy;
922 /* This barrier holds and releases threads waiting in thread pools. */
923 gomp_simple_barrier_t threads_dock;
926 enum gomp_cancel_kind
928 GOMP_CANCEL_PARALLEL = 1,
929 GOMP_CANCEL_LOOP = 2,
930 GOMP_CANCEL_FOR = GOMP_CANCEL_LOOP,
931 GOMP_CANCEL_DO = GOMP_CANCEL_LOOP,
932 GOMP_CANCEL_SECTIONS = 4,
933 GOMP_CANCEL_TASKGROUP = 8
936 /* ... and here is that TLS data. */
938 #if defined __nvptx__
939 extern struct gomp_thread *nvptx_thrs __attribute__((shared));
940 static inline struct gomp_thread *gomp_thread (void)
942 int tid;
943 asm ("mov.u32 %0, %%tid.y;" : "=r" (tid));
944 return nvptx_thrs + tid;
946 #elif defined __AMDGCN__
947 static inline struct gomp_thread *gcn_thrs (void)
949 /* The value is at the bottom of LDS. */
950 struct gomp_thread * __lds *thrs = (struct gomp_thread * __lds *)4;
951 return *thrs;
953 static inline void set_gcn_thrs (struct gomp_thread *val)
955 /* The value is at the bottom of LDS. */
956 struct gomp_thread * __lds *thrs = (struct gomp_thread * __lds *)4;
957 *thrs = val;
959 static inline struct gomp_thread *gomp_thread (void)
961 int tid = __builtin_gcn_dim_pos(1);
962 return gcn_thrs () + tid;
964 #elif defined HAVE_TLS || defined USE_EMUTLS
965 extern __thread struct gomp_thread gomp_tls_data;
966 static inline struct gomp_thread *gomp_thread (void)
968 return &gomp_tls_data;
970 #else
971 extern pthread_key_t gomp_tls_key;
972 static inline struct gomp_thread *gomp_thread (void)
974 return pthread_getspecific (gomp_tls_key);
976 #endif
978 extern struct gomp_task_icv *gomp_new_icv (void);
980 /* Here's how to access the current copy of the ICVs. */
982 static inline struct gomp_task_icv *gomp_icv (bool write)
984 struct gomp_task *task = gomp_thread ()->task;
985 if (task)
986 return &task->icv;
987 else if (write)
988 return gomp_new_icv ();
989 else
990 return &gomp_global_icv;
993 #ifdef LIBGOMP_USE_PTHREADS
994 /* The attributes to be used during thread creation. */
995 extern pthread_attr_t gomp_thread_attr;
997 extern pthread_key_t gomp_thread_destructor;
998 #endif
1000 /* Function prototypes. */
1002 /* affinity.c */
1004 extern void gomp_init_affinity (void);
1005 #ifdef LIBGOMP_USE_PTHREADS
1006 extern void gomp_init_thread_affinity (pthread_attr_t *, unsigned int);
1007 #endif
1008 extern void **gomp_affinity_alloc (unsigned long, bool);
1009 extern void gomp_affinity_init_place (void *);
1010 extern bool gomp_affinity_add_cpus (void *, unsigned long, unsigned long,
1011 long, bool);
1012 extern bool gomp_affinity_remove_cpu (void *, unsigned long);
1013 extern bool gomp_affinity_copy_place (void *, void *, long);
1014 extern bool gomp_affinity_same_place (void *, void *);
1015 extern bool gomp_affinity_finalize_place_list (bool);
1016 extern bool gomp_affinity_init_level (int, unsigned long, bool);
1017 extern void gomp_affinity_print_place (void *);
1018 extern void gomp_get_place_proc_ids_8 (int, int64_t *);
1019 extern void gomp_display_affinity_place (char *, size_t, size_t *, int);
1021 /* affinity-fmt.c */
1023 extern bool gomp_print_string (const char *str, size_t len);
1024 extern void gomp_set_affinity_format (const char *, size_t);
1025 extern void gomp_display_string (char *, size_t, size_t *, const char *,
1026 size_t);
1027 #ifdef LIBGOMP_USE_PTHREADS
1028 typedef pthread_t gomp_thread_handle;
1029 #else
1030 typedef struct {} gomp_thread_handle;
1031 #endif
1032 extern size_t gomp_display_affinity (char *, size_t, const char *,
1033 gomp_thread_handle,
1034 struct gomp_team_state *, unsigned int);
1035 extern void gomp_display_affinity_thread (gomp_thread_handle,
1036 struct gomp_team_state *,
1037 unsigned int) __attribute__((cold));
1039 /* env.c */
1041 extern struct gomp_icv_list *gomp_get_initial_icv_item (int dev_num);
1042 extern bool gomp_get_icv_flag (uint32_t value, enum gomp_icvs icv);
1044 /* iter.c */
1046 extern int gomp_iter_static_next (long *, long *);
1047 extern bool gomp_iter_dynamic_next_locked (long *, long *);
1048 extern bool gomp_iter_guided_next_locked (long *, long *);
1050 #ifdef HAVE_SYNC_BUILTINS
1051 extern bool gomp_iter_dynamic_next (long *, long *);
1052 extern bool gomp_iter_guided_next (long *, long *);
1053 #endif
1055 /* iter_ull.c */
1057 extern int gomp_iter_ull_static_next (unsigned long long *,
1058 unsigned long long *);
1059 extern bool gomp_iter_ull_dynamic_next_locked (unsigned long long *,
1060 unsigned long long *);
1061 extern bool gomp_iter_ull_guided_next_locked (unsigned long long *,
1062 unsigned long long *);
1064 #if defined HAVE_SYNC_BUILTINS && defined __LP64__
1065 extern bool gomp_iter_ull_dynamic_next (unsigned long long *,
1066 unsigned long long *);
1067 extern bool gomp_iter_ull_guided_next (unsigned long long *,
1068 unsigned long long *);
1069 #endif
1071 /* ordered.c */
1073 extern void gomp_ordered_first (void);
1074 extern void gomp_ordered_last (void);
1075 extern void gomp_ordered_next (void);
1076 extern void gomp_ordered_static_init (void);
1077 extern void gomp_ordered_static_next (void);
1078 extern void gomp_ordered_sync (void);
1079 extern void gomp_doacross_init (unsigned, long *, long, size_t);
1080 extern void gomp_doacross_ull_init (unsigned, unsigned long long *,
1081 unsigned long long, size_t);
1083 /* parallel.c */
1085 extern unsigned gomp_resolve_num_threads (unsigned, unsigned);
1087 /* proc.c (in config/) */
1089 extern void gomp_init_num_threads (void);
1090 extern unsigned gomp_dynamic_max_threads (void);
1092 /* task.c */
1094 extern void gomp_init_task (struct gomp_task *, struct gomp_task *,
1095 struct gomp_task_icv *);
1096 extern void gomp_end_task (void);
1097 extern void gomp_barrier_handle_tasks (gomp_barrier_state_t);
1098 extern void gomp_task_maybe_wait_for_dependencies (void **);
1099 extern bool gomp_create_target_task (struct gomp_device_descr *,
1100 void (*) (void *), size_t, void **,
1101 size_t *, unsigned short *, unsigned int,
1102 void **, void **,
1103 enum gomp_target_task_state);
1104 extern struct gomp_taskgroup *gomp_parallel_reduction_register (uintptr_t *,
1105 unsigned);
1106 extern void gomp_workshare_taskgroup_start (void);
1107 extern void gomp_workshare_task_reduction_register (uintptr_t *, uintptr_t *);
1109 static void inline
1110 gomp_finish_task (struct gomp_task *task)
1112 if (__builtin_expect (task->depend_hash != NULL, 0))
1113 free (task->depend_hash);
1116 /* team.c */
1118 extern struct gomp_team *gomp_new_team (unsigned);
1119 extern void gomp_team_start (void (*) (void *), void *, unsigned,
1120 unsigned, struct gomp_team *,
1121 struct gomp_taskgroup *);
1122 extern void gomp_team_end (void);
1123 extern void gomp_free_thread (void *);
1124 extern int gomp_pause_host (void);
1126 /* target.c */
1128 extern void gomp_init_targets_once (void);
1129 extern int gomp_get_num_devices (void);
1130 extern bool gomp_target_task_fn (void *);
1131 extern void gomp_target_rev (uint64_t, uint64_t, uint64_t, uint64_t, uint64_t,
1132 int,
1133 void (*) (void *, const void *, size_t, void *),
1134 void (*) (void *, const void *, size_t, void *),
1135 void *);
1137 /* Splay tree definitions. */
1138 typedef struct splay_tree_node_s *splay_tree_node;
1139 typedef struct splay_tree_s *splay_tree;
1140 typedef struct splay_tree_key_s *splay_tree_key;
1142 struct target_var_desc {
1143 /* Splay key. */
1144 splay_tree_key key;
1145 /* True if data should be copied from device to host at the end. */
1146 bool copy_from;
1147 /* True if data always should be copied from device to host at the end. */
1148 bool always_copy_from;
1149 /* True if this is for OpenACC 'attach'. */
1150 bool is_attach;
1151 /* If GOMP_MAP_TO_PSET had a NULL pointer; used for Fortran descriptors,
1152 which were initially unallocated. */
1153 bool has_null_ptr_assoc;
1154 /* Relative offset against key host_start. */
1155 uintptr_t offset;
1156 /* Actual length. */
1157 uintptr_t length;
1160 struct target_mem_desc;
1162 /* Special value for refcount - mask to indicate existence of special
1163 values. Right now we allocate 3 bits. */
1164 #define REFCOUNT_SPECIAL (~(uintptr_t) 0x7)
1166 /* Special value for refcount - infinity. */
1167 #define REFCOUNT_INFINITY (REFCOUNT_SPECIAL | 0)
1168 /* Special value for refcount - tgt_offset contains target address of the
1169 artificial pointer to "omp declare target link" object. */
1170 #define REFCOUNT_LINK (REFCOUNT_SPECIAL | 1)
1172 /* Special value for refcount - structure element sibling list items.
1173 All such key refounts have REFCOUNT_STRUCTELEM bits set, with _FLAG_FIRST
1174 and _FLAG_LAST indicating first and last in the created sibling sequence. */
1175 #define REFCOUNT_STRUCTELEM (REFCOUNT_SPECIAL | 4)
1176 #define REFCOUNT_STRUCTELEM_P(V) \
1177 (((V) & REFCOUNT_STRUCTELEM) == REFCOUNT_STRUCTELEM)
1178 /* The first leading key with _FLAG_FIRST set houses the actual reference count
1179 in the structelem_refcount field. Other siblings point to this counter value
1180 through its structelem_refcount_ptr field. */
1181 #define REFCOUNT_STRUCTELEM_FLAG_FIRST (1)
1182 /* The last key in the sibling sequence has this set. This is required to
1183 indicate the sequence boundary, when we remove the structure sibling list
1184 from the map. */
1185 #define REFCOUNT_STRUCTELEM_FLAG_LAST (2)
1187 #define REFCOUNT_STRUCTELEM_FIRST_P(V) \
1188 (REFCOUNT_STRUCTELEM_P (V) && ((V) & REFCOUNT_STRUCTELEM_FLAG_FIRST))
1189 #define REFCOUNT_STRUCTELEM_LAST_P(V) \
1190 (REFCOUNT_STRUCTELEM_P (V) && ((V) & REFCOUNT_STRUCTELEM_FLAG_LAST))
1192 /* Special offset values. */
1193 #define OFFSET_INLINED (~(uintptr_t) 0)
1194 #define OFFSET_POINTER (~(uintptr_t) 1)
1195 #define OFFSET_STRUCT (~(uintptr_t) 2)
1197 /* Auxiliary structure for infrequently-used or API-specific data. */
1199 struct splay_tree_aux {
1200 /* Pointer to the original mapping of "omp declare target link" object. */
1201 splay_tree_key link_key;
1202 /* For a block with attached pointers, the attachment counters for each.
1203 Only used for OpenACC. */
1204 uintptr_t *attach_count;
1207 struct splay_tree_key_s {
1208 /* Address of the host object. */
1209 uintptr_t host_start;
1210 /* Address immediately after the host object. */
1211 uintptr_t host_end;
1212 /* Descriptor of the target memory. */
1213 struct target_mem_desc *tgt;
1214 /* Offset from tgt->tgt_start to the start of the target object. */
1215 uintptr_t tgt_offset;
1216 /* Reference count. */
1217 uintptr_t refcount;
1218 union {
1219 /* Dynamic reference count. */
1220 uintptr_t dynamic_refcount;
1222 /* Unified reference count for structure element siblings, this is used
1223 when REFCOUNT_STRUCTELEM_FIRST_P(k->refcount) == true, the first sibling
1224 in a structure element sibling list item sequence. */
1225 uintptr_t structelem_refcount;
1227 /* When REFCOUNT_STRUCTELEM_P (k->refcount) == true, this field points
1228 into the (above) structelem_refcount field of the _FIRST splay_tree_key,
1229 the first key in the created sequence. All structure element siblings
1230 share a single refcount in this manner. Since these two fields won't be
1231 used at the same time, they are stashed in a union. */
1232 uintptr_t *structelem_refcount_ptr;
1234 struct splay_tree_aux *aux;
1237 /* The comparison function. */
1239 static inline int
1240 splay_compare (splay_tree_key x, splay_tree_key y)
1242 if (x->host_start == x->host_end
1243 && y->host_start == y->host_end)
1244 return 0;
1245 if (x->host_end <= y->host_start)
1246 return -1;
1247 if (x->host_start >= y->host_end)
1248 return 1;
1249 return 0;
1252 #include "splay-tree.h"
1254 /* Reverse offload splay-tree handling (functions only). */
1256 struct reverse_splay_tree_key_s {
1257 /* Address of the device object. */
1258 uint64_t dev;
1259 splay_tree_key k;
1262 typedef struct reverse_splay_tree_node_s *reverse_splay_tree_node;
1263 typedef struct reverse_splay_tree_s *reverse_splay_tree;
1264 typedef struct reverse_splay_tree_key_s *reverse_splay_tree_key;
1266 static inline int
1267 reverse_splay_compare (reverse_splay_tree_key x, reverse_splay_tree_key y)
1269 if (x->dev < y->dev)
1270 return -1;
1271 if (x->dev > y->dev)
1272 return 1;
1273 return 0;
1276 #define splay_tree_prefix reverse
1277 #include "splay-tree.h"
1279 struct target_mem_desc {
1280 /* Reference count. */
1281 uintptr_t refcount;
1282 /* All the splay nodes allocated together. */
1283 splay_tree_node array;
1284 /* Likewise for the reverse lookup device->host for reverse offload. */
1285 reverse_splay_tree_node rev_array;
1286 /* Start of the target region. */
1287 uintptr_t tgt_start;
1288 /* End of the targer region. */
1289 uintptr_t tgt_end;
1290 /* Handle to free. */
1291 void *to_free;
1292 /* Previous target_mem_desc. */
1293 struct target_mem_desc *prev;
1294 /* Number of items in following list. */
1295 size_t list_count;
1297 /* Corresponding target device descriptor. */
1298 struct gomp_device_descr *device_descr;
1300 /* List of target items to remove (or decrease refcount)
1301 at the end of region. */
1302 struct target_var_desc list[];
1306 typedef struct acc_dispatch_t
1308 /* Execute. */
1309 __typeof (GOMP_OFFLOAD_openacc_exec) *exec_func;
1311 /* Create/destroy TLS data. */
1312 __typeof (GOMP_OFFLOAD_openacc_create_thread_data) *create_thread_data_func;
1313 __typeof (GOMP_OFFLOAD_openacc_destroy_thread_data)
1314 *destroy_thread_data_func;
1316 struct {
1317 /* Once created and put into the "active" list, asyncqueues are then never
1318 destructed and removed from the "active" list, other than if the TODO
1319 device is shut down. */
1320 gomp_mutex_t lock;
1321 int nasyncqueue;
1322 struct goacc_asyncqueue **asyncqueue;
1323 struct goacc_asyncqueue_list *active;
1325 __typeof (GOMP_OFFLOAD_openacc_async_construct) *construct_func;
1326 __typeof (GOMP_OFFLOAD_openacc_async_destruct) *destruct_func;
1327 __typeof (GOMP_OFFLOAD_openacc_async_test) *test_func;
1328 __typeof (GOMP_OFFLOAD_openacc_async_synchronize) *synchronize_func;
1329 __typeof (GOMP_OFFLOAD_openacc_async_serialize) *serialize_func;
1330 __typeof (GOMP_OFFLOAD_openacc_async_queue_callback) *queue_callback_func;
1332 __typeof (GOMP_OFFLOAD_openacc_async_exec) *exec_func;
1333 __typeof (GOMP_OFFLOAD_openacc_async_dev2host) *dev2host_func;
1334 __typeof (GOMP_OFFLOAD_openacc_async_host2dev) *host2dev_func;
1335 } async;
1337 __typeof (GOMP_OFFLOAD_openacc_get_property) *get_property_func;
1339 /* NVIDIA target specific routines. */
1340 struct {
1341 __typeof (GOMP_OFFLOAD_openacc_cuda_get_current_device)
1342 *get_current_device_func;
1343 __typeof (GOMP_OFFLOAD_openacc_cuda_get_current_context)
1344 *get_current_context_func;
1345 __typeof (GOMP_OFFLOAD_openacc_cuda_get_stream) *get_stream_func;
1346 __typeof (GOMP_OFFLOAD_openacc_cuda_set_stream) *set_stream_func;
1347 } cuda;
1348 } acc_dispatch_t;
1350 /* Various state of the accelerator device. */
1351 enum gomp_device_state
1353 GOMP_DEVICE_UNINITIALIZED,
1354 GOMP_DEVICE_INITIALIZED,
1355 GOMP_DEVICE_FINALIZED
1358 /* This structure describes accelerator device.
1359 It contains name of the corresponding libgomp plugin, function handlers for
1360 interaction with the device, ID-number of the device, and information about
1361 mapped memory. */
1362 struct gomp_device_descr
1364 /* Immutable data, which is only set during initialization, and which is not
1365 guarded by the lock. */
1367 /* The name of the device. */
1368 const char *name;
1370 /* Capabilities of device (supports OpenACC, OpenMP). */
1371 unsigned int capabilities;
1373 /* This is the ID number of device among devices of the same type. */
1374 int target_id;
1376 /* This is the TYPE of device. */
1377 enum offload_target_type type;
1379 /* Function handlers. */
1380 __typeof (GOMP_OFFLOAD_get_name) *get_name_func;
1381 __typeof (GOMP_OFFLOAD_get_caps) *get_caps_func;
1382 __typeof (GOMP_OFFLOAD_get_type) *get_type_func;
1383 __typeof (GOMP_OFFLOAD_get_num_devices) *get_num_devices_func;
1384 __typeof (GOMP_OFFLOAD_init_device) *init_device_func;
1385 __typeof (GOMP_OFFLOAD_fini_device) *fini_device_func;
1386 __typeof (GOMP_OFFLOAD_version) *version_func;
1387 __typeof (GOMP_OFFLOAD_load_image) *load_image_func;
1388 __typeof (GOMP_OFFLOAD_unload_image) *unload_image_func;
1389 __typeof (GOMP_OFFLOAD_alloc) *alloc_func;
1390 __typeof (GOMP_OFFLOAD_free) *free_func;
1391 __typeof (GOMP_OFFLOAD_dev2host) *dev2host_func;
1392 __typeof (GOMP_OFFLOAD_host2dev) *host2dev_func;
1393 __typeof (GOMP_OFFLOAD_dev2dev) *dev2dev_func;
1394 __typeof (GOMP_OFFLOAD_can_run) *can_run_func;
1395 __typeof (GOMP_OFFLOAD_run) *run_func;
1396 __typeof (GOMP_OFFLOAD_async_run) *async_run_func;
1398 /* Splay tree containing information about mapped memory regions. */
1399 struct splay_tree_s mem_map;
1400 struct reverse_splay_tree_s mem_map_rev;
1402 /* Mutex for the mutable data. */
1403 gomp_mutex_t lock;
1405 /* Current state of the device. OpenACC allows to move from INITIALIZED state
1406 back to UNINITIALIZED state. OpenMP allows only to move from INITIALIZED
1407 to FINALIZED state (at program shutdown). */
1408 enum gomp_device_state state;
1410 /* OpenACC-specific data and functions. */
1411 /* This is mutable because of its mutable target_data member. */
1412 acc_dispatch_t openacc;
1415 /* Kind of the pragma, for which gomp_map_vars () is called. */
1416 enum gomp_map_vars_kind
1418 GOMP_MAP_VARS_OPENACC = 1,
1419 GOMP_MAP_VARS_TARGET = 2,
1420 GOMP_MAP_VARS_DATA = 4,
1421 GOMP_MAP_VARS_ENTER_DATA = 8
1424 extern void gomp_acc_declare_allocate (bool, size_t, void **, size_t *,
1425 unsigned short *);
1426 struct gomp_coalesce_buf;
1427 extern void gomp_copy_host2dev (struct gomp_device_descr *,
1428 struct goacc_asyncqueue *, void *, const void *,
1429 size_t, bool, struct gomp_coalesce_buf *);
1430 extern void gomp_copy_dev2host (struct gomp_device_descr *,
1431 struct goacc_asyncqueue *, void *, const void *,
1432 size_t);
1433 extern uintptr_t gomp_map_val (struct target_mem_desc *, void **, size_t);
1434 extern void gomp_attach_pointer (struct gomp_device_descr *,
1435 struct goacc_asyncqueue *, splay_tree,
1436 splay_tree_key, uintptr_t, size_t,
1437 struct gomp_coalesce_buf *, bool);
1438 extern void gomp_detach_pointer (struct gomp_device_descr *,
1439 struct goacc_asyncqueue *, splay_tree_key,
1440 uintptr_t, bool, struct gomp_coalesce_buf *);
1441 extern struct target_mem_desc *goacc_map_vars (struct gomp_device_descr *,
1442 struct goacc_asyncqueue *,
1443 size_t, void **, void **,
1444 size_t *, void *, bool,
1445 enum gomp_map_vars_kind);
1446 extern void goacc_unmap_vars (struct target_mem_desc *, bool,
1447 struct goacc_asyncqueue *);
1448 extern void gomp_init_device (struct gomp_device_descr *);
1449 extern bool gomp_fini_device (struct gomp_device_descr *);
1450 extern void gomp_unload_device (struct gomp_device_descr *);
1451 extern bool gomp_remove_var (struct gomp_device_descr *, splay_tree_key);
1452 extern void gomp_remove_var_async (struct gomp_device_descr *, splay_tree_key,
1453 struct goacc_asyncqueue *);
1455 /* work.c */
1457 extern void gomp_init_work_share (struct gomp_work_share *, size_t, unsigned);
1458 extern void gomp_fini_work_share (struct gomp_work_share *);
1459 extern bool gomp_work_share_start (size_t);
1460 extern void gomp_work_share_end (void);
1461 extern bool gomp_work_share_end_cancel (void);
1462 extern void gomp_work_share_end_nowait (void);
1464 static inline void
1465 gomp_work_share_init_done (void)
1467 struct gomp_thread *thr = gomp_thread ();
1468 if (__builtin_expect (thr->ts.last_work_share != NULL, 1))
1469 gomp_ptrlock_set (&thr->ts.last_work_share->next_ws, thr->ts.work_share);
1472 #ifdef HAVE_ATTRIBUTE_VISIBILITY
1473 # pragma GCC visibility pop
1474 #endif
1476 /* Now that we're back to default visibility, include the globals. */
1477 #include "libgomp_g.h"
1479 /* Include omp.h by parts. */
1480 #include "omp-lock.h"
1481 #define _LIBGOMP_OMP_LOCK_DEFINED 1
1482 #include "omp.h.in"
1484 #if !defined (HAVE_ATTRIBUTE_VISIBILITY) \
1485 || !defined (HAVE_ATTRIBUTE_ALIAS) \
1486 || !defined (HAVE_AS_SYMVER_DIRECTIVE) \
1487 || !defined (PIC) \
1488 || !defined (HAVE_SYMVER_SYMBOL_RENAMING_RUNTIME_SUPPORT)
1489 # undef LIBGOMP_GNU_SYMBOL_VERSIONING
1490 #endif
1492 #ifdef LIBGOMP_GNU_SYMBOL_VERSIONING
1493 extern void gomp_init_lock_30 (omp_lock_t *) __GOMP_NOTHROW;
1494 extern void gomp_destroy_lock_30 (omp_lock_t *) __GOMP_NOTHROW;
1495 extern void gomp_set_lock_30 (omp_lock_t *) __GOMP_NOTHROW;
1496 extern void gomp_unset_lock_30 (omp_lock_t *) __GOMP_NOTHROW;
1497 extern int gomp_test_lock_30 (omp_lock_t *) __GOMP_NOTHROW;
1498 extern void gomp_init_nest_lock_30 (omp_nest_lock_t *) __GOMP_NOTHROW;
1499 extern void gomp_destroy_nest_lock_30 (omp_nest_lock_t *) __GOMP_NOTHROW;
1500 extern void gomp_set_nest_lock_30 (omp_nest_lock_t *) __GOMP_NOTHROW;
1501 extern void gomp_unset_nest_lock_30 (omp_nest_lock_t *) __GOMP_NOTHROW;
1502 extern int gomp_test_nest_lock_30 (omp_nest_lock_t *) __GOMP_NOTHROW;
1504 extern void gomp_init_lock_25 (omp_lock_25_t *) __GOMP_NOTHROW;
1505 extern void gomp_destroy_lock_25 (omp_lock_25_t *) __GOMP_NOTHROW;
1506 extern void gomp_set_lock_25 (omp_lock_25_t *) __GOMP_NOTHROW;
1507 extern void gomp_unset_lock_25 (omp_lock_25_t *) __GOMP_NOTHROW;
1508 extern int gomp_test_lock_25 (omp_lock_25_t *) __GOMP_NOTHROW;
1509 extern void gomp_init_nest_lock_25 (omp_nest_lock_25_t *) __GOMP_NOTHROW;
1510 extern void gomp_destroy_nest_lock_25 (omp_nest_lock_25_t *) __GOMP_NOTHROW;
1511 extern void gomp_set_nest_lock_25 (omp_nest_lock_25_t *) __GOMP_NOTHROW;
1512 extern void gomp_unset_nest_lock_25 (omp_nest_lock_25_t *) __GOMP_NOTHROW;
1513 extern int gomp_test_nest_lock_25 (omp_nest_lock_25_t *) __GOMP_NOTHROW;
1515 # define omp_lock_symver(fn) \
1516 __asm (".symver g" #fn "_30, " #fn "@@OMP_3.0"); \
1517 __asm (".symver g" #fn "_25, " #fn "@OMP_1.0");
1518 #else
1519 # define gomp_init_lock_30 omp_init_lock
1520 # define gomp_destroy_lock_30 omp_destroy_lock
1521 # define gomp_set_lock_30 omp_set_lock
1522 # define gomp_unset_lock_30 omp_unset_lock
1523 # define gomp_test_lock_30 omp_test_lock
1524 # define gomp_init_nest_lock_30 omp_init_nest_lock
1525 # define gomp_destroy_nest_lock_30 omp_destroy_nest_lock
1526 # define gomp_set_nest_lock_30 omp_set_nest_lock
1527 # define gomp_unset_nest_lock_30 omp_unset_nest_lock
1528 # define gomp_test_nest_lock_30 omp_test_nest_lock
1529 #endif
1531 #ifdef HAVE_ATTRIBUTE_VISIBILITY
1532 # define attribute_hidden __attribute__ ((visibility ("hidden")))
1533 #else
1534 # define attribute_hidden
1535 #endif
1537 #if __GNUC__ >= 9
1538 # define HAVE_ATTRIBUTE_COPY
1539 #endif
1541 #ifdef HAVE_ATTRIBUTE_COPY
1542 # define attribute_copy(arg) __attribute__ ((copy (arg)))
1543 #else
1544 # define attribute_copy(arg)
1545 #endif
1547 #ifdef HAVE_ATTRIBUTE_ALIAS
1548 # define strong_alias(fn, al) \
1549 extern __typeof (fn) al __attribute__ ((alias (#fn))) attribute_copy (fn);
1551 # define ialias_ulp ialias_str1(__USER_LABEL_PREFIX__)
1552 # define ialias_str1(x) ialias_str2(x)
1553 # define ialias_str2(x) #x
1554 # define ialias(fn) \
1555 extern __typeof (fn) gomp_ialias_##fn \
1556 __attribute__ ((alias (#fn))) attribute_hidden attribute_copy (fn);
1557 # define ialias_redirect(fn) \
1558 extern __typeof (fn) fn __asm__ (ialias_ulp "gomp_ialias_" #fn) attribute_hidden;
1559 # define ialias_call(fn) gomp_ialias_ ## fn
1560 #else
1561 # define ialias(fn)
1562 # define ialias_redirect(fn)
1563 # define ialias_call(fn) fn
1564 #endif
1566 /* Helper function for priority_node_to_task() and
1567 task_to_priority_node().
1569 Return the offset from a task to its priority_node entry. The
1570 priority_node entry is has a type of TYPE. */
1572 static inline size_t
1573 priority_queue_offset (enum priority_queue_type type)
1575 return offsetof (struct gomp_task, pnode[(int) type]);
1578 /* Return the task associated with a priority NODE of type TYPE. */
1580 static inline struct gomp_task *
1581 priority_node_to_task (enum priority_queue_type type,
1582 struct priority_node *node)
1584 return (struct gomp_task *) ((char *) node - priority_queue_offset (type));
1587 /* Return the priority node of type TYPE for a given TASK. */
1589 static inline struct priority_node *
1590 task_to_priority_node (enum priority_queue_type type,
1591 struct gomp_task *task)
1593 return (struct priority_node *) ((char *) task
1594 + priority_queue_offset (type));
1597 #ifdef LIBGOMP_USE_PTHREADS
1598 static inline gomp_thread_handle
1599 gomp_thread_self (void)
1601 return pthread_self ();
1604 static inline gomp_thread_handle
1605 gomp_thread_to_pthread_t (struct gomp_thread *thr)
1607 struct gomp_thread *this_thr = gomp_thread ();
1608 if (thr == this_thr)
1609 return pthread_self ();
1610 #ifdef GOMP_NEEDS_THREAD_HANDLE
1611 return thr->handle;
1612 #else
1613 /* On Linux with initial-exec TLS, the pthread_t of the thread containing
1614 thr can be computed from thr, this_thr and pthread_self (),
1615 as the distance between this_thr and pthread_self () is constant. */
1616 return pthread_self () + ((uintptr_t) thr - (uintptr_t) this_thr);
1617 #endif
1619 #else
1620 static inline gomp_thread_handle
1621 gomp_thread_self (void)
1623 return (gomp_thread_handle) {};
1626 static inline gomp_thread_handle
1627 gomp_thread_to_pthread_t (struct gomp_thread *thr)
1629 (void) thr;
1630 return gomp_thread_self ();
1632 #endif
1634 #endif /* LIBGOMP_H */