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