sections.c revision 1.1.1.4
1492SN/A/* Copyright (C) 2005-2016 Free Software Foundation, Inc.
21345Sihse   Contributed by Richard Henderson <rth@redhat.com>.
3492SN/A
4492SN/A   This file is part of the GNU Offloading and Multi Processing Library
5492SN/A   (libgomp).
6492SN/A
7492SN/A   Libgomp is free software; you can redistribute it and/or modify it
8492SN/A   under the terms of the GNU General Public License as published by
9492SN/A   the Free Software Foundation; either version 3, or (at your option)
10492SN/A   any later version.
11492SN/A
12492SN/A   Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
13492SN/A   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14492SN/A   FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15492SN/A   more details.
16492SN/A
17492SN/A   Under Section 7 of GPL version 3, you are granted additional
18492SN/A   permissions described in the GCC Runtime Library Exception, version
19492SN/A   3.1, as published by the Free Software Foundation.
20492SN/A
21492SN/A   You should have received a copy of the GNU General Public License and
22492SN/A   a copy of the GCC Runtime Library Exception along with this program;
23492SN/A   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24492SN/A   <http://www.gnu.org/licenses/>.  */
25492SN/A
261120Schegar/* This file handles the SECTIONS construct.  */
271120Schegar
281120Schegar#include "libgomp.h"
291410Sihse
301120Schegar
311120Schegar/* Initialize the given work share construct from the given arguments.  */
321120Schegar
33492SN/Astatic inline void
341410Sihsegomp_sections_init (struct gomp_work_share *ws, unsigned count)
351410Sihse{
361410Sihse  ws->sched = GFS_DYNAMIC;
371410Sihse  ws->chunk_size = 1;
38492SN/A  ws->end = count + 1L;
39492SN/A  ws->incr = 1;
40492SN/A  ws->next = 1;
411410Sihse#ifdef HAVE_SYNC_BUILTINS
421120Schegar  /* Prepare things to make each iteration faster.  */
43837SN/A  if (sizeof (long) > sizeof (unsigned))
44910Sihse    ws->mode = 1;
451131Serikj  else
46492SN/A    {
471120Schegar      struct gomp_thread *thr = gomp_thread ();
481236Sihse      struct gomp_team *team = thr->ts.team;
491120Schegar      long nthreads = team ? team->nthreads : 1;
501120Schegar
511120Schegar      ws->mode = ((nthreads | ws->end)
52968Sihse		  < 1UL << (sizeof (long) * __CHAR_BIT__ / 2 - 1));
53968Sihse    }
54492SN/A#else
551120Schegar  ws->mode = 0;
561120Schegar#endif
571120Schegar}
581120Schegar
591120Schegar/* This routine is called when first encountering a sections construct
601120Schegar   that is not bound directly to a parallel construct.  The first thread
611120Schegar   that arrives will create the work-share construct; subsequent threads
621120Schegar   will see the construct exists and allocate work from it.
631120Schegar
641120Schegar   COUNT is the number of sections in this construct.
651120Schegar
661120Schegar   Returns the 1-based section number for this thread to perform, or 0 if
671120Schegar   all work was assigned to other threads prior to this thread's arrival.  */
681120Schegar
691223Schegarunsigned
701223SchegarGOMP_sections_start (unsigned count)
711223Schegar{
721120Schegar  struct gomp_thread *thr = gomp_thread ();
731120Schegar  long s, e, ret;
741120Schegar
751120Schegar  if (gomp_work_share_start (false))
761120Schegar    {
771120Schegar      gomp_sections_init (thr->ts.work_share, count);
781600Snaoto      gomp_work_share_init_done ();
791600Snaoto    }
801600Snaoto
811223Schegar#ifdef HAVE_SYNC_BUILTINS
821120Schegar  if (gomp_iter_dynamic_next (&s, &e))
831120Schegar    ret = s;
841659Serikj  else
851600Snaoto    ret = 0;
861120Schegar#else
871120Schegar  gomp_mutex_lock (&thr->ts.work_share->lock);
881120Schegar  if (gomp_iter_dynamic_next_locked (&s, &e))
891120Schegar    ret = s;
901120Schegar  else
911120Schegar    ret = 0;
92492SN/A  gomp_mutex_unlock (&thr->ts.work_share->lock);
931120Schegar#endif
941120Schegar
951120Schegar  return ret;
961223Schegar}
97492SN/A
981120Schegar/* This routine is called when the thread completes processing of the
991120Schegar   section currently assigned to it.  If the work-share construct is
1001223Schegar   bound directly to a parallel construct, then the construct may have
1011223Schegar   been set up before the parallel.  In which case, this may be the
1021223Schegar   first iteration for the thread.
1031223Schegar
1041223Schegar   Returns the 1-based section number for this thread to perform, or 0 if
1051223Schegar   all work was assigned to other threads prior to this thread's arrival.  */
106492SN/A
1071223Schegarunsigned
1081223SchegarGOMP_sections_next (void)
1091223Schegar{
1101695Stwisti  long s, e, ret;
111557SN/A
1121120Schegar#ifdef HAVE_SYNC_BUILTINS
1131120Schegar  if (gomp_iter_dynamic_next (&s, &e))
1141120Schegar    ret = s;
1151120Schegar  else
1161223Schegar    ret = 0;
1171223Schegar#else
1181223Schegar  struct gomp_thread *thr = gomp_thread ();
1191223Schegar
1201223Schegar  gomp_mutex_lock (&thr->ts.work_share->lock);
1211223Schegar  if (gomp_iter_dynamic_next_locked (&s, &e))
1221120Schegar    ret = s;
1231120Schegar  else
1241120Schegar    ret = 0;
1251120Schegar  gomp_mutex_unlock (&thr->ts.work_share->lock);
1261120Schegar#endif
1271223Schegar
1281223Schegar  return ret;
1291223Schegar}
1301223Schegar
1311223Schegar/* This routine pre-initializes a work-share construct to avoid one
1321695Stwisti   synchronization once we get into the loop.  */
1331695Stwisti
1341120Schegarvoid
1351120SchegarGOMP_parallel_sections_start (void (*fn) (void *), void *data,
136607SN/A			      unsigned num_threads, unsigned count)
1371120Schegar{
1381120Schegar  struct gomp_team *team;
1391120Schegar
1401120Schegar  num_threads = gomp_resolve_num_threads (num_threads, count);
141492SN/A  team = gomp_new_team (num_threads);
1421120Schegar  gomp_sections_init (&team->work_shares[0], count);
1431120Schegar  gomp_team_start (fn, data, num_threads, 0, team);
1441120Schegar}
1451550Serikj
1461120Schegarialias_redirect (GOMP_parallel_end)
1471120Schegar
1481120Schegarvoid
1491120SchegarGOMP_parallel_sections (void (*fn) (void *), void *data,
1501120Schegar			unsigned num_threads, unsigned count, unsigned flags)
1511120Schegar{
1521120Schegar  struct gomp_team *team;
1531120Schegar
1541120Schegar  num_threads = gomp_resolve_num_threads (num_threads, count);
155492SN/A  team = gomp_new_team (num_threads);
1561120Schegar  gomp_sections_init (&team->work_shares[0], count);
1571120Schegar  gomp_team_start (fn, data, num_threads, flags, team);
1581120Schegar  fn (data);
1591120Schegar  GOMP_parallel_end ();
1601223Schegar}
1611223Schegar
1621223Schegar/* The GOMP_section_end* routines are called after the thread is told
1631223Schegar   that all sections are complete.  The first two versions synchronize
1641223Schegar   all threads; the nowait version does not.  */
1651120Schegar
1661120Schegarvoid
1671120SchegarGOMP_sections_end (void)
1681120Schegar{
1691120Schegar  gomp_work_share_end ();
1701223Schegar}
1711223Schegar
1721223Schegarbool
1731223SchegarGOMP_sections_end_cancel (void)
1741223Schegar{
1751223Schegar  return gomp_work_share_end_cancel ();
176492SN/A}
1771223Schegar
178492SN/Avoid
1791120SchegarGOMP_sections_end_nowait (void)
1801120Schegar{
1811223Schegar  gomp_work_share_end_nowait ();
1821223Schegar}
1831223Schegar