sections.c

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 handles the SECTIONS construct.  */
00026 
00027 #include "libgomp.h"
00028 
00029 
00030 /* Initialize the given work share construct from the given arguments.  */
00031 
00032 static inline void
00033 gomp_sections_init (struct gomp_work_share *ws, unsigned count)
00034 {
00035   ws->sched = GFS_DYNAMIC;
00036   ws->chunk_size = 1;
00037   ws->end = count + 1L;
00038   ws->incr = 1;
00039   ws->next = 1;
00040 #ifdef HAVE_SYNC_BUILTINS
00041   /* Prepare things to make each iteration faster.  */
00042   if (sizeof (long) > sizeof (unsigned))
00043     ws->mode = 1;
00044   else
00045     {
00046       struct gomp_thread *thr = gomp_thread ();
00047       struct gomp_team *team = thr->ts.team;
00048       long nthreads = team ? team->nthreads : 1;
00049 
00050       ws->mode = ((nthreads | ws->end)
00051           < 1UL << (sizeof (long) * __CHAR_BIT__ / 2 - 1));
00052     }
00053 #else
00054   ws->mode = 0;
00055 #endif
00056 }
00057 
00058 /* This routine is called when first encountering a sections construct
00059    that is not bound directly to a parallel construct.  The first thread 
00060    that arrives will create the work-share construct; subsequent threads
00061    will see the construct exists and allocate work from it.
00062 
00063    COUNT is the number of sections in this construct.
00064 
00065    Returns the 1-based section number for this thread to perform, or 0 if
00066    all work was assigned to other threads prior to this thread's arrival.  */
00067 
00068 unsigned
00069 GOMP_sections_start (unsigned count)
00070 {
00071   struct gomp_thread *thr = gomp_thread ();
00072   long s, e, ret;
00073 
00074   if (gomp_work_share_start (false))
00075     {
00076       gomp_sections_init (thr->ts.work_share, count);
00077       gomp_work_share_init_done ();
00078     }
00079 
00080 #ifdef HAVE_SYNC_BUILTINS
00081   if (gomp_iter_dynamic_next (&s, &e))
00082     ret = s;
00083   else
00084     ret = 0;
00085 #else
00086   gomp_mutex_lock (&thr->ts.work_share->lock);
00087   if (gomp_iter_dynamic_next_locked (&s, &e))
00088     ret = s;
00089   else
00090     ret = 0;
00091   gomp_mutex_unlock (&thr->ts.work_share->lock);
00092 #endif
00093 
00094   return ret;
00095 }
00096 
00097 /* This routine is called when the thread completes processing of the
00098    section currently assigned to it.  If the work-share construct is
00099    bound directly to a parallel construct, then the construct may have
00100    been set up before the parallel.  In which case, this may be the
00101    first iteration for the thread.
00102 
00103    Returns the 1-based section number for this thread to perform, or 0 if
00104    all work was assigned to other threads prior to this thread's arrival.  */
00105 
00106 unsigned
00107 GOMP_sections_next (void)
00108 {
00109   long s, e, ret;
00110 
00111 #ifdef HAVE_SYNC_BUILTINS
00112   if (gomp_iter_dynamic_next (&s, &e))
00113     ret = s;
00114   else
00115     ret = 0;
00116 #else
00117   struct gomp_thread *thr = gomp_thread ();
00118 
00119   gomp_mutex_lock (&thr->ts.work_share->lock);
00120   if (gomp_iter_dynamic_next_locked (&s, &e))
00121     ret = s;
00122   else
00123     ret = 0;
00124   gomp_mutex_unlock (&thr->ts.work_share->lock);
00125 #endif
00126 
00127   return ret;
00128 }
00129 
00130 /* This routine pre-initializes a work-share construct to avoid one
00131    synchronization once we get into the loop.  */
00132 
00133 void
00134 GOMP_parallel_sections_start (void (*fn) (void *), void *data,
00135                   unsigned num_threads, unsigned count)
00136 {
00137   struct gomp_team *team;
00138 
00139   num_threads = gomp_resolve_num_threads (num_threads, count);
00140   team = gomp_new_team (num_threads);
00141   gomp_sections_init (&team->work_shares[0], count);
00142   gomp_team_start (fn, data, num_threads, team);
00143 }
00144 
00145 /* The GOMP_section_end* routines are called after the thread is told
00146    that all sections are complete.  This first version synchronizes
00147    all threads; the nowait version does not.  */
00148 
00149 void
00150 GOMP_sections_end (void)
00151 {
00152   gomp_work_share_end ();
00153 }
00154 
00155 void
00156 GOMP_sections_end_nowait (void)
00157 {
00158   gomp_work_share_end_nowait ();
00159 }

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