libgomp.h

Go to the documentation of this file.
00001 /* Copyright (C) 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
00002    Contributed by Richard Henderson <rth@redhat.com>.
00003 
00004    This file is part of the GNU OpenMP Library (libgomp).
00005 
00006    Libgomp is free software; you can redistribute it and/or modify it
00007    under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 3, or (at your option)
00009    any later version.
00010 
00011    Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
00012    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00013    FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
00014    more details.
00015 
00016    Under Section 7 of GPL version 3, you are granted additional
00017    permissions described in the GCC Runtime Library Exception, version
00018    3.1, as published by the Free Software Foundation.
00019 
00020    You should have received a copy of the GNU General Public License and
00021    a copy of the GCC Runtime Library Exception along with this program;
00022    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00023    <http://www.gnu.org/licenses/>.  */
00024 
00025 /* This file contains data types and function declarations that are not
00026    part of the official OpenMP user interface.  There are declarations
00027    in here that are part of the GNU OpenMP ABI, in that the compiler is
00028    required to know about them and use them.
00029 
00030    The convention is that the all caps prefix "GOMP" is used group items
00031    that are part of the external ABI, and the lower case prefix "gomp"
00032    is used group items that are completely private to the library.  */
00033 
00034 #ifndef LIBGOMP_H 
00035 #define LIBGOMP_H 1
00036 
00037 #include "config.h"
00038 #include "gstdint.h"
00039 
00040 #include <pthread.h>
00041 #include <stdbool.h>
00042 
00043 #ifdef HAVE_ATTRIBUTE_VISIBILITY
00044 # pragma GCC visibility push(hidden)
00045 #endif
00046 
00047 #include "sem.h"
00048 #include "mutex.h"
00049 #include "bar.h"
00050 #include "ptrlock.h"
00051 
00052 
00053 /* This structure contains the data to control one work-sharing construct,
00054    either a LOOP (FOR/DO) or a SECTIONS.  */
00055 
00056 enum gomp_schedule_type
00057 {
00058   GFS_RUNTIME,
00059   GFS_STATIC,
00060   GFS_DYNAMIC,
00061   GFS_GUIDED,
00062   GFS_AUTO
00063 };
00064 
00065 struct gomp_work_share
00066 {
00067   /* This member records the SCHEDULE clause to be used for this construct.
00068      The user specification of "runtime" will already have been resolved.
00069      If this is a SECTIONS construct, this value will always be DYNAMIC.  */
00070   enum gomp_schedule_type sched;
00071 
00072   int mode;
00073 
00074   union {
00075     struct {
00076       /* This is the chunk_size argument to the SCHEDULE clause.  */
00077       long chunk_size;
00078 
00079       /* This is the iteration end point.  If this is a SECTIONS construct,
00080      this is the number of contained sections.  */
00081       long end;
00082 
00083       /* This is the iteration step.  If this is a SECTIONS construct, this
00084      is always 1.  */
00085       long incr;
00086     };
00087 
00088     struct {
00089       /* The same as above, but for the unsigned long long loop variants.  */
00090       unsigned long long chunk_size_ull;
00091       unsigned long long end_ull;
00092       unsigned long long incr_ull;
00093     };
00094   };
00095 
00096   /* This is a circular queue that details which threads will be allowed
00097      into the ordered region and in which order.  When a thread allocates
00098      iterations on which it is going to work, it also registers itself at
00099      the end of the array.  When a thread reaches the ordered region, it
00100      checks to see if it is the one at the head of the queue.  If not, it
00101      blocks on its RELEASE semaphore.  */
00102   unsigned *ordered_team_ids;
00103 
00104   /* This is the number of threads that have registered themselves in
00105      the circular queue ordered_team_ids.  */
00106   unsigned ordered_num_used;
00107 
00108   /* This is the team_id of the currently acknowledged owner of the ordered
00109      section, or -1u if the ordered section has not been acknowledged by
00110      any thread.  This is distinguished from the thread that is *allowed*
00111      to take the section next.  */
00112   unsigned ordered_owner;
00113 
00114   /* This is the index into the circular queue ordered_team_ids of the
00115      current thread that's allowed into the ordered reason.  */
00116   unsigned ordered_cur;
00117 
00118   /* This is a chain of allocated gomp_work_share blocks, valid only
00119      in the first gomp_work_share struct in the block.  */
00120   struct gomp_work_share *next_alloc;
00121 
00122   /* The above fields are written once during workshare initialization,
00123      or related to ordered worksharing.  Make sure the following fields
00124      are in a different cache line.  */
00125 
00126   /* This lock protects the update of the following members.  */
00127   gomp_mutex_t lock __attribute__((aligned (64)));
00128 
00129   /* This is the count of the number of threads that have exited the work
00130      share construct.  If the construct was marked nowait, they have moved on
00131      to other work; otherwise they're blocked on a barrier.  The last member
00132      of the team to exit the work share construct must deallocate it.  */
00133   unsigned threads_completed;
00134 
00135   union {
00136     /* This is the next iteration value to be allocated.  In the case of
00137        GFS_STATIC loops, this the iteration start point and never changes.  */
00138     long next;
00139 
00140     /* The same, but with unsigned long long type.  */
00141     unsigned long long next_ull;
00142 
00143     /* This is the returned data structure for SINGLE COPYPRIVATE.  */
00144     void *copyprivate;
00145   };
00146 
00147   union {
00148     /* Link to gomp_work_share struct for next work sharing construct
00149        encountered after this one.  */
00150     gomp_ptrlock_t next_ws;
00151 
00152     /* gomp_work_share structs are chained in the free work share cache
00153        through this.  */
00154     struct gomp_work_share *next_free;
00155   };
00156 
00157   /* If only few threads are in the team, ordered_team_ids can point
00158      to this array which fills the padding at the end of this struct.  */
00159   unsigned inline_ordered_team_ids[0];
00160 };
00161 
00162 /* This structure contains all of the thread-local data associated with 
00163    a thread team.  This is the data that must be saved when a thread
00164    encounters a nested PARALLEL construct.  */
00165 
00166 struct gomp_team_state
00167 {
00168   /* This is the team of which the thread is currently a member.  */
00169   struct gomp_team *team;
00170 
00171   /* This is the work share construct which this thread is currently
00172      processing.  Recall that with NOWAIT, not all threads may be 
00173      processing the same construct.  */
00174   struct gomp_work_share *work_share;
00175 
00176   /* This is the previous work share construct or NULL if there wasn't any.
00177      When all threads are done with the current work sharing construct,
00178      the previous one can be freed.  The current one can't, as its
00179      next_ws field is used.  */
00180   struct gomp_work_share *last_work_share;
00181 
00182   /* This is the ID of this thread within the team.  This value is
00183      guaranteed to be between 0 and N-1, where N is the number of
00184      threads in the team.  */
00185   unsigned team_id;
00186 
00187   /* Nesting level.  */
00188   unsigned level;
00189 
00190   /* Active nesting level.  Only active parallel regions are counted.  */
00191   unsigned active_level;
00192 
00193 #ifdef HAVE_SYNC_BUILTINS
00194   /* Number of single stmts encountered.  */
00195   unsigned long single_count;
00196 #endif
00197 
00198   /* For GFS_RUNTIME loops that resolved to GFS_STATIC, this is the
00199      trip number through the loop.  So first time a particular loop
00200      is encountered this number is 0, the second time through the loop
00201      is 1, etc.  This is unused when the compiler knows in advance that
00202      the loop is statically scheduled.  */
00203   unsigned long static_trip;
00204 };
00205 
00206 /* These are the OpenMP 3.0 Internal Control Variables described in
00207    section 2.3.1.  Those described as having one copy per task are
00208    stored within the structure; those described as having one copy
00209    for the whole program are (naturally) global variables.  */
00210 
00211 struct gomp_task_icv
00212 {
00213   unsigned long nthreads_var;
00214   enum gomp_schedule_type run_sched_var;
00215   int run_sched_modifier;
00216   bool dyn_var;
00217   bool nest_var;
00218 };
00219 
00220 extern struct gomp_task_icv gomp_global_icv;
00221 extern unsigned long gomp_thread_limit_var;
00222 extern unsigned long gomp_remaining_threads_count;
00223 #ifndef HAVE_SYNC_BUILTINS
00224 extern gomp_mutex_t gomp_remaining_threads_lock;
00225 #endif
00226 extern unsigned long gomp_max_active_levels_var;
00227 extern unsigned long long gomp_spin_count_var, gomp_throttled_spin_count_var;
00228 extern unsigned long gomp_available_cpus, gomp_managed_threads;
00229 
00230 enum gomp_task_kind
00231 {
00232   GOMP_TASK_IMPLICIT,
00233   GOMP_TASK_IFFALSE,
00234   GOMP_TASK_WAITING,
00235   GOMP_TASK_TIED
00236 };
00237 
00238 /* This structure describes a "task" to be run by a thread.  */
00239 
00240 struct gomp_task
00241 {
00242   struct gomp_task *parent;
00243   struct gomp_task *children;
00244   struct gomp_task *next_child;
00245   struct gomp_task *prev_child;
00246   struct gomp_task *next_queue;
00247   struct gomp_task *prev_queue;
00248   struct gomp_task_icv icv;
00249   void (*fn) (void *);
00250   void *fn_data;
00251   enum gomp_task_kind kind;
00252   bool in_taskwait;
00253   bool in_tied_task;
00254   gomp_sem_t taskwait_sem;
00255 };
00256 
00257 /* This structure describes a "team" of threads.  These are the threads
00258    that are spawned by a PARALLEL constructs, as well as the work sharing
00259    constructs that the team encounters.  */
00260 
00261 struct gomp_team
00262 {
00263   /* This is the number of threads in the current team.  */
00264   unsigned nthreads;
00265 
00266   /* This is number of gomp_work_share structs that have been allocated
00267      as a block last time.  */
00268   unsigned work_share_chunk;
00269 
00270   /* This is the saved team state that applied to a master thread before
00271      the current thread was created.  */
00272   struct gomp_team_state prev_ts;
00273 
00274   /* This semaphore should be used by the master thread instead of its
00275      "native" semaphore in the thread structure.  Required for nested
00276      parallels, as the master is a member of two teams.  */
00277   gomp_sem_t master_release;
00278 
00279   /* This points to an array with pointers to the release semaphore
00280      of the threads in the team.  */
00281   gomp_sem_t **ordered_release;
00282 
00283   /* List of gomp_work_share structs chained through next_free fields.
00284      This is populated and taken off only by the first thread in the
00285      team encountering a new work sharing construct, in a critical
00286      section.  */
00287   struct gomp_work_share *work_share_list_alloc;
00288 
00289   /* List of gomp_work_share structs freed by free_work_share.  New
00290      entries are atomically added to the start of the list, and
00291      alloc_work_share can safely only move all but the first entry
00292      to work_share_list alloc, as free_work_share can happen concurrently
00293      with alloc_work_share.  */
00294   struct gomp_work_share *work_share_list_free;
00295 
00296 #ifdef HAVE_SYNC_BUILTINS
00297   /* Number of simple single regions encountered by threads in this
00298      team.  */
00299   unsigned long single_count;
00300 #else
00301   /* Mutex protecting addition of workshares to work_share_list_free.  */
00302   gomp_mutex_t work_share_list_free_lock;
00303 #endif
00304 
00305   /* This barrier is used for most synchronization of the team.  */
00306   gomp_barrier_t barrier;
00307 
00308   /* Initial work shares, to avoid allocating any gomp_work_share
00309      structs in the common case.  */
00310   struct gomp_work_share work_shares[8];
00311 
00312   gomp_mutex_t task_lock;
00313   struct gomp_task *task_queue;
00314   int task_count;
00315   int task_running_count;
00316 
00317   /* This array contains structures for implicit tasks.  */
00318   struct gomp_task implicit_task[];
00319 };
00320 
00321 /* This structure contains all data that is private to libgomp and is
00322    allocated per thread.  */
00323 
00324 struct gomp_thread
00325 {
00326   /* This is the function that the thread should run upon launch.  */
00327   void (*fn) (void *data);
00328   void *data;
00329 
00330   /* This is the current team state for this thread.  The ts.team member
00331      is NULL only if the thread is idle.  */
00332   struct gomp_team_state ts;
00333 
00334   /* This is the task that the thread is currently executing.  */
00335   struct gomp_task *task;
00336 
00337   /* This semaphore is used for ordered loops.  */
00338   gomp_sem_t release;
00339 
00340   /* user pthread thread pool */
00341   struct gomp_thread_pool *thread_pool;
00342 };
00343 
00344 
00345 struct gomp_thread_pool
00346 {
00347   /* This array manages threads spawned from the top level, which will
00348      return to the idle loop once the current PARALLEL construct ends.  */
00349   struct gomp_thread **threads;
00350   unsigned threads_size;
00351   unsigned threads_used;
00352   struct gomp_team *last_team;
00353 
00354   /* This barrier holds and releases threads waiting in threads.  */
00355   gomp_barrier_t threads_dock;
00356 };
00357 
00358 /* ... and here is that TLS data.  */
00359 
00360 #ifdef HAVE_TLS
00361 extern __thread struct gomp_thread gomp_tls_data;
00362 static inline struct gomp_thread *gomp_thread (void)
00363 {
00364   return &gomp_tls_data;
00365 }
00366 #else
00367 extern pthread_key_t gomp_tls_key;
00368 static inline struct gomp_thread *gomp_thread (void)
00369 {
00370   return pthread_getspecific (gomp_tls_key);
00371 }
00372 #endif
00373 
00374 extern struct gomp_task_icv *gomp_new_icv (void);
00375 
00376 /* Here's how to access the current copy of the ICVs.  */
00377 
00378 static inline struct gomp_task_icv *gomp_icv (bool write)
00379 {
00380   struct gomp_task *task = gomp_thread ()->task;
00381   if (task)
00382     return &task->icv;
00383   else if (write)
00384     return gomp_new_icv ();
00385   else
00386     return &gomp_global_icv;
00387 }
00388 
00389 /* The attributes to be used during thread creation.  */
00390 extern pthread_attr_t gomp_thread_attr;
00391 
00392 /* Other variables.  */
00393 
00394 extern unsigned short *gomp_cpu_affinity;
00395 extern size_t gomp_cpu_affinity_len;
00396 
00397 /* Function prototypes.  */
00398 
00399 /* affinity.c */
00400 
00401 extern void gomp_init_affinity (void);
00402 extern void gomp_init_thread_affinity (pthread_attr_t *);
00403 
00404 /* alloc.c */
00405 
00406 extern void *gomp_malloc (size_t) __attribute__((malloc));
00407 extern void *gomp_malloc_cleared (size_t) __attribute__((malloc));
00408 extern void *gomp_realloc (void *, size_t);
00409 
00410 /* Avoid conflicting prototypes of alloca() in system headers by using
00411    GCC's builtin alloca().  */
00412 #define gomp_alloca(x)  __builtin_alloca(x)
00413 
00414 /* error.c */
00415 
00416 extern void gomp_error (const char *, ...)
00417     __attribute__((format (printf, 1, 2)));
00418 extern void gomp_fatal (const char *, ...)
00419     __attribute__((noreturn, format (printf, 1, 2)));
00420 
00421 /* iter.c */
00422 
00423 extern int gomp_iter_static_next (long *, long *);
00424 extern bool gomp_iter_dynamic_next_locked (long *, long *);
00425 extern bool gomp_iter_guided_next_locked (long *, long *);
00426 
00427 #ifdef HAVE_SYNC_BUILTINS
00428 extern bool gomp_iter_dynamic_next (long *, long *);
00429 extern bool gomp_iter_guided_next (long *, long *);
00430 #endif
00431 
00432 /* iter_ull.c */
00433 
00434 extern int gomp_iter_ull_static_next (unsigned long long *,
00435                       unsigned long long *);
00436 extern bool gomp_iter_ull_dynamic_next_locked (unsigned long long *,
00437                            unsigned long long *);
00438 extern bool gomp_iter_ull_guided_next_locked (unsigned long long *,
00439                           unsigned long long *);
00440 
00441 #if defined HAVE_SYNC_BUILTINS && defined __LP64__
00442 extern bool gomp_iter_ull_dynamic_next (unsigned long long *,
00443                     unsigned long long *);
00444 extern bool gomp_iter_ull_guided_next (unsigned long long *,
00445                        unsigned long long *);
00446 #endif
00447 
00448 /* ordered.c */
00449 
00450 extern void gomp_ordered_first (void);
00451 extern void gomp_ordered_last (void);
00452 extern void gomp_ordered_next (void);
00453 extern void gomp_ordered_static_init (void);
00454 extern void gomp_ordered_static_next (void);
00455 extern void gomp_ordered_sync (void);
00456 
00457 /* parallel.c */
00458 
00459 extern unsigned gomp_resolve_num_threads (unsigned, unsigned);
00460 
00461 /* proc.c (in config/) */
00462 
00463 extern void gomp_init_num_threads (void);
00464 extern unsigned gomp_dynamic_max_threads (void);
00465 
00466 /* task.c */
00467 
00468 extern void gomp_init_task (struct gomp_task *, struct gomp_task *,
00469                 struct gomp_task_icv *);
00470 extern void gomp_end_task (void);
00471 extern void gomp_barrier_handle_tasks (gomp_barrier_state_t);
00472 
00473 static void inline
00474 gomp_finish_task (struct gomp_task *task)
00475 {
00476   gomp_sem_destroy (&task->taskwait_sem);
00477 }
00478 
00479 /* team.c */
00480 
00481 extern struct gomp_team *gomp_new_team (unsigned);
00482 extern void gomp_team_start (void (*) (void *), void *, unsigned,
00483                  struct gomp_team *);
00484 extern void gomp_team_end (void);
00485 
00486 /* work.c */
00487 
00488 extern void gomp_init_work_share (struct gomp_work_share *, bool, unsigned);
00489 extern void gomp_fini_work_share (struct gomp_work_share *);
00490 extern bool gomp_work_share_start (bool);
00491 extern void gomp_work_share_end (void);
00492 extern void gomp_work_share_end_nowait (void);
00493 
00494 static inline void
00495 gomp_work_share_init_done (void)
00496 {
00497   struct gomp_thread *thr = gomp_thread ();
00498   if (__builtin_expect (thr->ts.last_work_share != NULL, 1))
00499     gomp_ptrlock_set (&thr->ts.last_work_share->next_ws, thr->ts.work_share);
00500 }
00501 
00502 #ifdef HAVE_ATTRIBUTE_VISIBILITY
00503 # pragma GCC visibility pop
00504 #endif
00505 
00506 /* Now that we're back to default visibility, include the globals.  */
00507 #include "libgomp_g.h"
00508 
00509 /* Include omp.h by parts.  */
00510 #include "omp-lock.h"
00511 #define _LIBGOMP_OMP_LOCK_DEFINED 1
00512 #include "omp.h.in"
00513 
00514 #if !defined (HAVE_ATTRIBUTE_VISIBILITY) \
00515     || !defined (HAVE_ATTRIBUTE_ALIAS) \
00516     || !defined (HAVE_AS_SYMVER_DIRECTIVE) \
00517     || !defined (PIC) \
00518     || !defined (HAVE_SYMVER_SYMBOL_RENAMING_RUNTIME_SUPPORT)
00519 # undef LIBGOMP_GNU_SYMBOL_VERSIONING
00520 #endif
00521 
00522 #ifdef LIBGOMP_GNU_SYMBOL_VERSIONING
00523 extern void gomp_init_lock_30 (omp_lock_t *) __GOMP_NOTHROW;
00524 extern void gomp_destroy_lock_30 (omp_lock_t *) __GOMP_NOTHROW;
00525 extern void gomp_set_lock_30 (omp_lock_t *) __GOMP_NOTHROW;
00526 extern void gomp_unset_lock_30 (omp_lock_t *) __GOMP_NOTHROW;
00527 extern int gomp_test_lock_30 (omp_lock_t *) __GOMP_NOTHROW;
00528 extern void gomp_init_nest_lock_30 (omp_nest_lock_t *) __GOMP_NOTHROW;
00529 extern void gomp_destroy_nest_lock_30 (omp_nest_lock_t *) __GOMP_NOTHROW;
00530 extern void gomp_set_nest_lock_30 (omp_nest_lock_t *) __GOMP_NOTHROW;
00531 extern void gomp_unset_nest_lock_30 (omp_nest_lock_t *) __GOMP_NOTHROW;
00532 extern int gomp_test_nest_lock_30 (omp_nest_lock_t *) __GOMP_NOTHROW;
00533 
00534 extern void gomp_init_lock_25 (omp_lock_25_t *) __GOMP_NOTHROW;
00535 extern void gomp_destroy_lock_25 (omp_lock_25_t *) __GOMP_NOTHROW;
00536 extern void gomp_set_lock_25 (omp_lock_25_t *) __GOMP_NOTHROW;
00537 extern void gomp_unset_lock_25 (omp_lock_25_t *) __GOMP_NOTHROW;
00538 extern int gomp_test_lock_25 (omp_lock_25_t *) __GOMP_NOTHROW;
00539 extern void gomp_init_nest_lock_25 (omp_nest_lock_25_t *) __GOMP_NOTHROW;
00540 extern void gomp_destroy_nest_lock_25 (omp_nest_lock_25_t *) __GOMP_NOTHROW;
00541 extern void gomp_set_nest_lock_25 (omp_nest_lock_25_t *) __GOMP_NOTHROW;
00542 extern void gomp_unset_nest_lock_25 (omp_nest_lock_25_t *) __GOMP_NOTHROW;
00543 extern int gomp_test_nest_lock_25 (omp_nest_lock_25_t *) __GOMP_NOTHROW;
00544 
00545 # define strong_alias(fn, al) \
00546   extern __typeof (fn) al __attribute__ ((alias (#fn)));
00547 # define omp_lock_symver(fn) \
00548   __asm (".symver g" #fn "_30, " #fn "@@OMP_3.0"); \
00549   __asm (".symver g" #fn "_25, " #fn "@OMP_1.0");
00550 #else
00551 # define gomp_init_lock_30 omp_init_lock
00552 # define gomp_destroy_lock_30 omp_destroy_lock
00553 # define gomp_set_lock_30 omp_set_lock
00554 # define gomp_unset_lock_30 omp_unset_lock
00555 # define gomp_test_lock_30 omp_test_lock
00556 # define gomp_init_nest_lock_30 omp_init_nest_lock
00557 # define gomp_destroy_nest_lock_30 omp_destroy_nest_lock
00558 # define gomp_set_nest_lock_30 omp_set_nest_lock
00559 # define gomp_unset_nest_lock_30 omp_unset_nest_lock
00560 # define gomp_test_nest_lock_30 omp_test_nest_lock
00561 #endif
00562 
00563 #ifdef HAVE_ATTRIBUTE_VISIBILITY
00564 # define attribute_hidden __attribute__ ((visibility ("hidden")))
00565 #else
00566 # define attribute_hidden
00567 #endif
00568 
00569 #ifdef HAVE_ATTRIBUTE_ALIAS
00570 # define ialias(fn) \
00571   extern __typeof (fn) gomp_ialias_##fn \
00572     __attribute__ ((alias (#fn))) attribute_hidden;
00573 #else
00574 # define ialias(fn)
00575 #endif
00576 
00577 #endif /* LIBGOMP_H */

Generated on Fri Apr 5 05:38:10 2013 for Libgomp by  doxygen 1.4.7