1*8feb0f0bSmrg /* Copyright (C) 2005-2020 Free Software Foundation, Inc.
21debfc3dSmrg Contributed by Richard Henderson <rth@redhat.com>.
31debfc3dSmrg
41debfc3dSmrg This file is part of the GNU Offloading and Multi Processing Library
51debfc3dSmrg (libgomp).
61debfc3dSmrg
71debfc3dSmrg Libgomp is free software; you can redistribute it and/or modify it
81debfc3dSmrg under the terms of the GNU General Public License as published by
91debfc3dSmrg the Free Software Foundation; either version 3, or (at your option)
101debfc3dSmrg any later version.
111debfc3dSmrg
121debfc3dSmrg Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
131debfc3dSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
141debfc3dSmrg FOR A PARTICULAR PURPOSE. See the GNU General Public License for
151debfc3dSmrg more details.
161debfc3dSmrg
171debfc3dSmrg Under Section 7 of GPL version 3, you are granted additional
181debfc3dSmrg permissions described in the GCC Runtime Library Exception, version
191debfc3dSmrg 3.1, as published by the Free Software Foundation.
201debfc3dSmrg
211debfc3dSmrg You should have received a copy of the GNU General Public License and
221debfc3dSmrg a copy of the GCC Runtime Library Exception along with this program;
231debfc3dSmrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
241debfc3dSmrg <http://www.gnu.org/licenses/>. */
251debfc3dSmrg
261debfc3dSmrg /* This file handles the SINGLE construct. */
271debfc3dSmrg
281debfc3dSmrg #include "libgomp.h"
291debfc3dSmrg
301debfc3dSmrg
311debfc3dSmrg /* This routine is called when first encountering a SINGLE construct that
321debfc3dSmrg doesn't have a COPYPRIVATE clause. Returns true if this is the thread
331debfc3dSmrg that should execute the clause. */
341debfc3dSmrg
351debfc3dSmrg bool
GOMP_single_start(void)361debfc3dSmrg GOMP_single_start (void)
371debfc3dSmrg {
381debfc3dSmrg #ifdef HAVE_SYNC_BUILTINS
391debfc3dSmrg struct gomp_thread *thr = gomp_thread ();
401debfc3dSmrg struct gomp_team *team = thr->ts.team;
411debfc3dSmrg unsigned long single_count;
421debfc3dSmrg
431debfc3dSmrg if (__builtin_expect (team == NULL, 0))
441debfc3dSmrg return true;
451debfc3dSmrg
461debfc3dSmrg single_count = thr->ts.single_count++;
471debfc3dSmrg return __sync_bool_compare_and_swap (&team->single_count, single_count,
481debfc3dSmrg single_count + 1L);
491debfc3dSmrg #else
50c0a68be4Smrg bool ret = gomp_work_share_start (0);
511debfc3dSmrg if (ret)
521debfc3dSmrg gomp_work_share_init_done ();
531debfc3dSmrg gomp_work_share_end_nowait ();
541debfc3dSmrg return ret;
551debfc3dSmrg #endif
561debfc3dSmrg }
571debfc3dSmrg
581debfc3dSmrg /* This routine is called when first encountering a SINGLE construct that
591debfc3dSmrg does have a COPYPRIVATE clause. Returns NULL if this is the thread
601debfc3dSmrg that should execute the clause; otherwise the return value is pointer
611debfc3dSmrg given to GOMP_single_copy_end by the thread that did execute the clause. */
621debfc3dSmrg
631debfc3dSmrg void *
GOMP_single_copy_start(void)641debfc3dSmrg GOMP_single_copy_start (void)
651debfc3dSmrg {
661debfc3dSmrg struct gomp_thread *thr = gomp_thread ();
671debfc3dSmrg
681debfc3dSmrg bool first;
691debfc3dSmrg void *ret;
701debfc3dSmrg
71c0a68be4Smrg first = gomp_work_share_start (0);
721debfc3dSmrg
731debfc3dSmrg if (first)
741debfc3dSmrg {
751debfc3dSmrg gomp_work_share_init_done ();
761debfc3dSmrg ret = NULL;
771debfc3dSmrg }
781debfc3dSmrg else
791debfc3dSmrg {
801debfc3dSmrg gomp_team_barrier_wait (&thr->ts.team->barrier);
811debfc3dSmrg
821debfc3dSmrg ret = thr->ts.work_share->copyprivate;
831debfc3dSmrg gomp_work_share_end_nowait ();
841debfc3dSmrg }
851debfc3dSmrg
861debfc3dSmrg return ret;
871debfc3dSmrg }
881debfc3dSmrg
891debfc3dSmrg /* This routine is called when the thread that entered a SINGLE construct
901debfc3dSmrg with a COPYPRIVATE clause gets to the end of the construct. */
911debfc3dSmrg
921debfc3dSmrg void
GOMP_single_copy_end(void * data)931debfc3dSmrg GOMP_single_copy_end (void *data)
941debfc3dSmrg {
951debfc3dSmrg struct gomp_thread *thr = gomp_thread ();
961debfc3dSmrg struct gomp_team *team = thr->ts.team;
971debfc3dSmrg
981debfc3dSmrg if (team != NULL)
991debfc3dSmrg {
1001debfc3dSmrg thr->ts.work_share->copyprivate = data;
1011debfc3dSmrg gomp_team_barrier_wait (&team->barrier);
1021debfc3dSmrg }
1031debfc3dSmrg
1041debfc3dSmrg gomp_work_share_end_nowait ();
1051debfc3dSmrg }
106