1 /* Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011 2 Free Software Foundation, Inc. 3 Contributed by Richard Henderson <rth@redhat.com>. 4 5 This file is part of the GNU OpenMP Library (libgomp). 6 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. 11 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. 16 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. 20 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/>. */ 25 26 /* This file contains data types and function declarations that are not 27 part of the official OpenMP user interface. There are declarations 28 in here that are part of the GNU OpenMP ABI, in that the compiler is 29 required to know about them and use them. 30 31 The convention is that the all caps prefix "GOMP" is used group items 32 that are part of the external ABI, and the lower case prefix "gomp" 33 is used group items that are completely private to the library. */ 34 35 #ifndef LIBGOMP_H 36 #define LIBGOMP_H 1 37 38 #include "config.h" 39 #include "gstdint.h" 40 41 #include <pthread.h> 42 #include <stdbool.h> 43 44 #ifdef HAVE_ATTRIBUTE_VISIBILITY 45 # pragma GCC visibility push(hidden) 46 #endif 47 48 /* If we were a C++ library, we'd get this from <std/atomic>. */ 49 enum memmodel 50 { 51 MEMMODEL_RELAXED = 0, 52 MEMMODEL_CONSUME = 1, 53 MEMMODEL_ACQUIRE = 2, 54 MEMMODEL_RELEASE = 3, 55 MEMMODEL_ACQ_REL = 4, 56 MEMMODEL_SEQ_CST = 5 57 }; 58 59 #include "sem.h" 60 #include "mutex.h" 61 #include "bar.h" 62 #include "ptrlock.h" 63 64 65 /* This structure contains the data to control one work-sharing construct, 66 either a LOOP (FOR/DO) or a SECTIONS. */ 67 68 enum gomp_schedule_type 69 { 70 GFS_RUNTIME, 71 GFS_STATIC, 72 GFS_DYNAMIC, 73 GFS_GUIDED, 74 GFS_AUTO 75 }; 76 77 struct gomp_work_share 78 { 79 /* This member records the SCHEDULE clause to be used for this construct. 80 The user specification of "runtime" will already have been resolved. 81 If this is a SECTIONS construct, this value will always be DYNAMIC. */ 82 enum gomp_schedule_type sched; 83 84 int mode; 85 86 union { 87 struct { 88 /* This is the chunk_size argument to the SCHEDULE clause. */ 89 long chunk_size; 90 91 /* This is the iteration end point. If this is a SECTIONS construct, 92 this is the number of contained sections. */ 93 long end; 94 95 /* This is the iteration step. If this is a SECTIONS construct, this 96 is always 1. */ 97 long incr; 98 }; 99 100 struct { 101 /* The same as above, but for the unsigned long long loop variants. */ 102 unsigned long long chunk_size_ull; 103 unsigned long long end_ull; 104 unsigned long long incr_ull; 105 }; 106 }; 107 108 /* This is a circular queue that details which threads will be allowed 109 into the ordered region and in which order. When a thread allocates 110 iterations on which it is going to work, it also registers itself at 111 the end of the array. When a thread reaches the ordered region, it 112 checks to see if it is the one at the head of the queue. If not, it 113 blocks on its RELEASE semaphore. */ 114 unsigned *ordered_team_ids; 115 116 /* This is the number of threads that have registered themselves in 117 the circular queue ordered_team_ids. */ 118 unsigned ordered_num_used; 119 120 /* This is the team_id of the currently acknowledged owner of the ordered 121 section, or -1u if the ordered section has not been acknowledged by 122 any thread. This is distinguished from the thread that is *allowed* 123 to take the section next. */ 124 unsigned ordered_owner; 125 126 /* This is the index into the circular queue ordered_team_ids of the 127 current thread that's allowed into the ordered reason. */ 128 unsigned ordered_cur; 129 130 /* This is a chain of allocated gomp_work_share blocks, valid only 131 in the first gomp_work_share struct in the block. */ 132 struct gomp_work_share *next_alloc; 133 134 /* The above fields are written once during workshare initialization, 135 or related to ordered worksharing. Make sure the following fields 136 are in a different cache line. */ 137 138 /* This lock protects the update of the following members. */ 139 gomp_mutex_t lock __attribute__((aligned (64))); 140 141 /* This is the count of the number of threads that have exited the work 142 share construct. If the construct was marked nowait, they have moved on 143 to other work; otherwise they're blocked on a barrier. The last member 144 of the team to exit the work share construct must deallocate it. */ 145 unsigned threads_completed; 146 147 union { 148 /* This is the next iteration value to be allocated. In the case of 149 GFS_STATIC loops, this the iteration start point and never changes. */ 150 long next; 151 152 /* The same, but with unsigned long long type. */ 153 unsigned long long next_ull; 154 155 /* This is the returned data structure for SINGLE COPYPRIVATE. */ 156 void *copyprivate; 157 }; 158 159 union { 160 /* Link to gomp_work_share struct for next work sharing construct 161 encountered after this one. */ 162 gomp_ptrlock_t next_ws; 163 164 /* gomp_work_share structs are chained in the free work share cache 165 through this. */ 166 struct gomp_work_share *next_free; 167 }; 168 169 /* If only few threads are in the team, ordered_team_ids can point 170 to this array which fills the padding at the end of this struct. */ 171 unsigned inline_ordered_team_ids[0]; 172 }; 173 174 /* This structure contains all of the thread-local data associated with 175 a thread team. This is the data that must be saved when a thread 176 encounters a nested PARALLEL construct. */ 177 178 struct gomp_team_state 179 { 180 /* This is the team of which the thread is currently a member. */ 181 struct gomp_team *team; 182 183 /* This is the work share construct which this thread is currently 184 processing. Recall that with NOWAIT, not all threads may be 185 processing the same construct. */ 186 struct gomp_work_share *work_share; 187 188 /* This is the previous work share construct or NULL if there wasn't any. 189 When all threads are done with the current work sharing construct, 190 the previous one can be freed. The current one can't, as its 191 next_ws field is used. */ 192 struct gomp_work_share *last_work_share; 193 194 /* This is the ID of this thread within the team. This value is 195 guaranteed to be between 0 and N-1, where N is the number of 196 threads in the team. */ 197 unsigned team_id; 198 199 /* Nesting level. */ 200 unsigned level; 201 202 /* Active nesting level. Only active parallel regions are counted. */ 203 unsigned active_level; 204 205 #ifdef HAVE_SYNC_BUILTINS 206 /* Number of single stmts encountered. */ 207 unsigned long single_count; 208 #endif 209 210 /* For GFS_RUNTIME loops that resolved to GFS_STATIC, this is the 211 trip number through the loop. So first time a particular loop 212 is encountered this number is 0, the second time through the loop 213 is 1, etc. This is unused when the compiler knows in advance that 214 the loop is statically scheduled. */ 215 unsigned long static_trip; 216 }; 217 218 /* These are the OpenMP 3.0 Internal Control Variables described in 219 section 2.3.1. Those described as having one copy per task are 220 stored within the structure; those described as having one copy 221 for the whole program are (naturally) global variables. */ 222 223 struct gomp_task_icv 224 { 225 unsigned long nthreads_var; 226 enum gomp_schedule_type run_sched_var; 227 int run_sched_modifier; 228 bool dyn_var; 229 bool nest_var; 230 }; 231 232 extern struct gomp_task_icv gomp_global_icv; 233 extern unsigned long gomp_thread_limit_var; 234 extern unsigned long gomp_remaining_threads_count; 235 #ifndef HAVE_SYNC_BUILTINS 236 extern gomp_mutex_t gomp_remaining_threads_lock; 237 #endif 238 extern unsigned long gomp_max_active_levels_var; 239 extern unsigned long long gomp_spin_count_var, gomp_throttled_spin_count_var; 240 extern unsigned long gomp_available_cpus, gomp_managed_threads; 241 extern unsigned long *gomp_nthreads_var_list, gomp_nthreads_var_list_len; 242 243 enum gomp_task_kind 244 { 245 GOMP_TASK_IMPLICIT, 246 GOMP_TASK_IFFALSE, 247 GOMP_TASK_WAITING, 248 GOMP_TASK_TIED 249 }; 250 251 /* This structure describes a "task" to be run by a thread. */ 252 253 struct gomp_task 254 { 255 struct gomp_task *parent; 256 struct gomp_task *children; 257 struct gomp_task *next_child; 258 struct gomp_task *prev_child; 259 struct gomp_task *next_queue; 260 struct gomp_task *prev_queue; 261 struct gomp_task_icv icv; 262 void (*fn) (void *); 263 void *fn_data; 264 enum gomp_task_kind kind; 265 bool in_taskwait; 266 bool in_tied_task; 267 bool final_task; 268 gomp_sem_t taskwait_sem; 269 }; 270 271 /* This structure describes a "team" of threads. These are the threads 272 that are spawned by a PARALLEL constructs, as well as the work sharing 273 constructs that the team encounters. */ 274 275 struct gomp_team 276 { 277 /* This is the number of threads in the current team. */ 278 unsigned nthreads; 279 280 /* This is number of gomp_work_share structs that have been allocated 281 as a block last time. */ 282 unsigned work_share_chunk; 283 284 /* This is the saved team state that applied to a master thread before 285 the current thread was created. */ 286 struct gomp_team_state prev_ts; 287 288 /* This semaphore should be used by the master thread instead of its 289 "native" semaphore in the thread structure. Required for nested 290 parallels, as the master is a member of two teams. */ 291 gomp_sem_t master_release; 292 293 /* This points to an array with pointers to the release semaphore 294 of the threads in the team. */ 295 gomp_sem_t **ordered_release; 296 297 /* List of gomp_work_share structs chained through next_free fields. 298 This is populated and taken off only by the first thread in the 299 team encountering a new work sharing construct, in a critical 300 section. */ 301 struct gomp_work_share *work_share_list_alloc; 302 303 /* List of gomp_work_share structs freed by free_work_share. New 304 entries are atomically added to the start of the list, and 305 alloc_work_share can safely only move all but the first entry 306 to work_share_list alloc, as free_work_share can happen concurrently 307 with alloc_work_share. */ 308 struct gomp_work_share *work_share_list_free; 309 310 #ifdef HAVE_SYNC_BUILTINS 311 /* Number of simple single regions encountered by threads in this 312 team. */ 313 unsigned long single_count; 314 #else 315 /* Mutex protecting addition of workshares to work_share_list_free. */ 316 gomp_mutex_t work_share_list_free_lock; 317 #endif 318 319 /* This barrier is used for most synchronization of the team. */ 320 gomp_barrier_t barrier; 321 322 /* Initial work shares, to avoid allocating any gomp_work_share 323 structs in the common case. */ 324 struct gomp_work_share work_shares[8]; 325 326 gomp_mutex_t task_lock; 327 struct gomp_task *task_queue; 328 int task_count; 329 int task_running_count; 330 331 /* This array contains structures for implicit tasks. */ 332 struct gomp_task implicit_task[]; 333 }; 334 335 /* This structure contains all data that is private to libgomp and is 336 allocated per thread. */ 337 338 struct gomp_thread 339 { 340 /* This is the function that the thread should run upon launch. */ 341 void (*fn) (void *data); 342 void *data; 343 344 /* This is the current team state for this thread. The ts.team member 345 is NULL only if the thread is idle. */ 346 struct gomp_team_state ts; 347 348 /* This is the task that the thread is currently executing. */ 349 struct gomp_task *task; 350 351 /* This semaphore is used for ordered loops. */ 352 gomp_sem_t release; 353 354 /* user pthread thread pool */ 355 struct gomp_thread_pool *thread_pool; 356 }; 357 358 359 struct gomp_thread_pool 360 { 361 /* This array manages threads spawned from the top level, which will 362 return to the idle loop once the current PARALLEL construct ends. */ 363 struct gomp_thread **threads; 364 unsigned threads_size; 365 unsigned threads_used; 366 struct gomp_team *last_team; 367 368 /* This barrier holds and releases threads waiting in threads. */ 369 gomp_barrier_t threads_dock; 370 }; 371 372 /* ... and here is that TLS data. */ 373 374 #ifdef HAVE_TLS 375 extern __thread struct gomp_thread gomp_tls_data; 376 static inline struct gomp_thread *gomp_thread (void) 377 { 378 return &gomp_tls_data; 379 } 380 #else 381 extern pthread_key_t gomp_tls_key; 382 static inline struct gomp_thread *gomp_thread (void) 383 { 384 return pthread_getspecific (gomp_tls_key); 385 } 386 #endif 387 388 extern struct gomp_task_icv *gomp_new_icv (void); 389 390 /* Here's how to access the current copy of the ICVs. */ 391 392 static inline struct gomp_task_icv *gomp_icv (bool write) 393 { 394 struct gomp_task *task = gomp_thread ()->task; 395 if (task) 396 return &task->icv; 397 else if (write) 398 return gomp_new_icv (); 399 else 400 return &gomp_global_icv; 401 } 402 403 /* The attributes to be used during thread creation. */ 404 extern pthread_attr_t gomp_thread_attr; 405 406 /* Other variables. */ 407 408 extern unsigned short *gomp_cpu_affinity; 409 extern size_t gomp_cpu_affinity_len; 410 411 /* Function prototypes. */ 412 413 /* affinity.c */ 414 415 extern void gomp_init_affinity (void); 416 extern void gomp_init_thread_affinity (pthread_attr_t *); 417 418 /* alloc.c */ 419 420 extern void *gomp_malloc (size_t) __attribute__((malloc)); 421 extern void *gomp_malloc_cleared (size_t) __attribute__((malloc)); 422 extern void *gomp_realloc (void *, size_t); 423 424 /* Avoid conflicting prototypes of alloca() in system headers by using 425 GCC's builtin alloca(). */ 426 #define gomp_alloca(x) __builtin_alloca(x) 427 428 /* error.c */ 429 430 extern void gomp_error (const char *, ...) 431 __attribute__((format (printf, 1, 2))); 432 extern void gomp_fatal (const char *, ...) 433 __attribute__((noreturn, format (printf, 1, 2))); 434 435 /* iter.c */ 436 437 extern int gomp_iter_static_next (long *, long *); 438 extern bool gomp_iter_dynamic_next_locked (long *, long *); 439 extern bool gomp_iter_guided_next_locked (long *, long *); 440 441 #ifdef HAVE_SYNC_BUILTINS 442 extern bool gomp_iter_dynamic_next (long *, long *); 443 extern bool gomp_iter_guided_next (long *, long *); 444 #endif 445 446 /* iter_ull.c */ 447 448 extern int gomp_iter_ull_static_next (unsigned long long *, 449 unsigned long long *); 450 extern bool gomp_iter_ull_dynamic_next_locked (unsigned long long *, 451 unsigned long long *); 452 extern bool gomp_iter_ull_guided_next_locked (unsigned long long *, 453 unsigned long long *); 454 455 #if defined HAVE_SYNC_BUILTINS && defined __LP64__ 456 extern bool gomp_iter_ull_dynamic_next (unsigned long long *, 457 unsigned long long *); 458 extern bool gomp_iter_ull_guided_next (unsigned long long *, 459 unsigned long long *); 460 #endif 461 462 /* ordered.c */ 463 464 extern void gomp_ordered_first (void); 465 extern void gomp_ordered_last (void); 466 extern void gomp_ordered_next (void); 467 extern void gomp_ordered_static_init (void); 468 extern void gomp_ordered_static_next (void); 469 extern void gomp_ordered_sync (void); 470 471 /* parallel.c */ 472 473 extern unsigned gomp_resolve_num_threads (unsigned, unsigned); 474 475 /* proc.c (in config/) */ 476 477 extern void gomp_init_num_threads (void); 478 extern unsigned gomp_dynamic_max_threads (void); 479 480 /* task.c */ 481 482 extern void gomp_init_task (struct gomp_task *, struct gomp_task *, 483 struct gomp_task_icv *); 484 extern void gomp_end_task (void); 485 extern void gomp_barrier_handle_tasks (gomp_barrier_state_t); 486 487 static void inline 488 gomp_finish_task (struct gomp_task *task) 489 { 490 gomp_sem_destroy (&task->taskwait_sem); 491 } 492 493 /* team.c */ 494 495 extern struct gomp_team *gomp_new_team (unsigned); 496 extern void gomp_team_start (void (*) (void *), void *, unsigned, 497 struct gomp_team *); 498 extern void gomp_team_end (void); 499 500 /* work.c */ 501 502 extern void gomp_init_work_share (struct gomp_work_share *, bool, unsigned); 503 extern void gomp_fini_work_share (struct gomp_work_share *); 504 extern bool gomp_work_share_start (bool); 505 extern void gomp_work_share_end (void); 506 extern void gomp_work_share_end_nowait (void); 507 508 static inline void 509 gomp_work_share_init_done (void) 510 { 511 struct gomp_thread *thr = gomp_thread (); 512 if (__builtin_expect (thr->ts.last_work_share != NULL, 1)) 513 gomp_ptrlock_set (&thr->ts.last_work_share->next_ws, thr->ts.work_share); 514 } 515 516 #ifdef HAVE_ATTRIBUTE_VISIBILITY 517 # pragma GCC visibility pop 518 #endif 519 520 /* Now that we're back to default visibility, include the globals. */ 521 #include "libgomp_g.h" 522 523 /* Include omp.h by parts. */ 524 #include "omp-lock.h" 525 #define _LIBGOMP_OMP_LOCK_DEFINED 1 526 #include "omp.h.in" 527 528 #if !defined (HAVE_ATTRIBUTE_VISIBILITY) \ 529 || !defined (HAVE_ATTRIBUTE_ALIAS) \ 530 || !defined (HAVE_AS_SYMVER_DIRECTIVE) \ 531 || !defined (PIC) \ 532 || !defined (HAVE_SYMVER_SYMBOL_RENAMING_RUNTIME_SUPPORT) 533 # undef LIBGOMP_GNU_SYMBOL_VERSIONING 534 #endif 535 536 #ifdef LIBGOMP_GNU_SYMBOL_VERSIONING 537 extern void gomp_init_lock_30 (omp_lock_t *) __GOMP_NOTHROW; 538 extern void gomp_destroy_lock_30 (omp_lock_t *) __GOMP_NOTHROW; 539 extern void gomp_set_lock_30 (omp_lock_t *) __GOMP_NOTHROW; 540 extern void gomp_unset_lock_30 (omp_lock_t *) __GOMP_NOTHROW; 541 extern int gomp_test_lock_30 (omp_lock_t *) __GOMP_NOTHROW; 542 extern void gomp_init_nest_lock_30 (omp_nest_lock_t *) __GOMP_NOTHROW; 543 extern void gomp_destroy_nest_lock_30 (omp_nest_lock_t *) __GOMP_NOTHROW; 544 extern void gomp_set_nest_lock_30 (omp_nest_lock_t *) __GOMP_NOTHROW; 545 extern void gomp_unset_nest_lock_30 (omp_nest_lock_t *) __GOMP_NOTHROW; 546 extern int gomp_test_nest_lock_30 (omp_nest_lock_t *) __GOMP_NOTHROW; 547 548 extern void gomp_init_lock_25 (omp_lock_25_t *) __GOMP_NOTHROW; 549 extern void gomp_destroy_lock_25 (omp_lock_25_t *) __GOMP_NOTHROW; 550 extern void gomp_set_lock_25 (omp_lock_25_t *) __GOMP_NOTHROW; 551 extern void gomp_unset_lock_25 (omp_lock_25_t *) __GOMP_NOTHROW; 552 extern int gomp_test_lock_25 (omp_lock_25_t *) __GOMP_NOTHROW; 553 extern void gomp_init_nest_lock_25 (omp_nest_lock_25_t *) __GOMP_NOTHROW; 554 extern void gomp_destroy_nest_lock_25 (omp_nest_lock_25_t *) __GOMP_NOTHROW; 555 extern void gomp_set_nest_lock_25 (omp_nest_lock_25_t *) __GOMP_NOTHROW; 556 extern void gomp_unset_nest_lock_25 (omp_nest_lock_25_t *) __GOMP_NOTHROW; 557 extern int gomp_test_nest_lock_25 (omp_nest_lock_25_t *) __GOMP_NOTHROW; 558 559 # define strong_alias(fn, al) \ 560 extern __typeof (fn) al __attribute__ ((alias (#fn))); 561 # define omp_lock_symver(fn) \ 562 __asm (".symver g" #fn "_30, " #fn "@@OMP_3.0"); \ 563 __asm (".symver g" #fn "_25, " #fn "@OMP_1.0"); 564 #else 565 # define gomp_init_lock_30 omp_init_lock 566 # define gomp_destroy_lock_30 omp_destroy_lock 567 # define gomp_set_lock_30 omp_set_lock 568 # define gomp_unset_lock_30 omp_unset_lock 569 # define gomp_test_lock_30 omp_test_lock 570 # define gomp_init_nest_lock_30 omp_init_nest_lock 571 # define gomp_destroy_nest_lock_30 omp_destroy_nest_lock 572 # define gomp_set_nest_lock_30 omp_set_nest_lock 573 # define gomp_unset_nest_lock_30 omp_unset_nest_lock 574 # define gomp_test_nest_lock_30 omp_test_nest_lock 575 #endif 576 577 #ifdef HAVE_ATTRIBUTE_VISIBILITY 578 # define attribute_hidden __attribute__ ((visibility ("hidden"))) 579 #else 580 # define attribute_hidden 581 #endif 582 583 #ifdef HAVE_ATTRIBUTE_ALIAS 584 # define ialias(fn) \ 585 extern __typeof (fn) gomp_ialias_##fn \ 586 __attribute__ ((alias (#fn))) attribute_hidden; 587 #else 588 # define ialias(fn) 589 #endif 590 591 #endif /* LIBGOMP_H */ 592