111
|
1 /* Copyright (C) 2005-2017 Free Software Foundation, Inc.
|
0
|
2 Contributed by Richard Henderson <rth@redhat.com>.
|
|
3
|
111
|
4 This file is part of the GNU Offloading and Multi Processing Library
|
|
5 (libgomp).
|
0
|
6
|
|
7 Libgomp is free software; you can redistribute it and/or modify it
|
|
8 under the terms of the GNU General Public License as published by
|
|
9 the Free Software Foundation; either version 3, or (at your option)
|
|
10 any later version.
|
|
11
|
|
12 Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
14 FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
15 more details.
|
|
16
|
|
17 Under Section 7 of GPL version 3, you are granted additional
|
|
18 permissions described in the GCC Runtime Library Exception, version
|
|
19 3.1, as published by the Free Software Foundation.
|
|
20
|
|
21 You should have received a copy of the GNU General Public License and
|
|
22 a copy of the GCC Runtime Library Exception along with this program;
|
|
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
|
24 <http://www.gnu.org/licenses/>. */
|
|
25
|
|
26 /* This file handles the SINGLE construct. */
|
|
27
|
|
28 #include "libgomp.h"
|
|
29
|
|
30
|
|
31 /* This routine is called when first encountering a SINGLE construct that
|
|
32 doesn't have a COPYPRIVATE clause. Returns true if this is the thread
|
|
33 that should execute the clause. */
|
|
34
|
|
35 bool
|
|
36 GOMP_single_start (void)
|
|
37 {
|
|
38 #ifdef HAVE_SYNC_BUILTINS
|
|
39 struct gomp_thread *thr = gomp_thread ();
|
|
40 struct gomp_team *team = thr->ts.team;
|
|
41 unsigned long single_count;
|
|
42
|
|
43 if (__builtin_expect (team == NULL, 0))
|
|
44 return true;
|
|
45
|
|
46 single_count = thr->ts.single_count++;
|
|
47 return __sync_bool_compare_and_swap (&team->single_count, single_count,
|
|
48 single_count + 1L);
|
|
49 #else
|
|
50 bool ret = gomp_work_share_start (false);
|
|
51 if (ret)
|
|
52 gomp_work_share_init_done ();
|
|
53 gomp_work_share_end_nowait ();
|
|
54 return ret;
|
|
55 #endif
|
|
56 }
|
|
57
|
|
58 /* This routine is called when first encountering a SINGLE construct that
|
|
59 does have a COPYPRIVATE clause. Returns NULL if this is the thread
|
|
60 that should execute the clause; otherwise the return value is pointer
|
|
61 given to GOMP_single_copy_end by the thread that did execute the clause. */
|
|
62
|
|
63 void *
|
|
64 GOMP_single_copy_start (void)
|
|
65 {
|
|
66 struct gomp_thread *thr = gomp_thread ();
|
|
67
|
|
68 bool first;
|
|
69 void *ret;
|
|
70
|
|
71 first = gomp_work_share_start (false);
|
|
72
|
|
73 if (first)
|
|
74 {
|
|
75 gomp_work_share_init_done ();
|
|
76 ret = NULL;
|
|
77 }
|
|
78 else
|
|
79 {
|
|
80 gomp_team_barrier_wait (&thr->ts.team->barrier);
|
|
81
|
|
82 ret = thr->ts.work_share->copyprivate;
|
|
83 gomp_work_share_end_nowait ();
|
|
84 }
|
|
85
|
|
86 return ret;
|
|
87 }
|
|
88
|
|
89 /* This routine is called when the thread that entered a SINGLE construct
|
|
90 with a COPYPRIVATE clause gets to the end of the construct. */
|
|
91
|
|
92 void
|
|
93 GOMP_single_copy_end (void *data)
|
|
94 {
|
|
95 struct gomp_thread *thr = gomp_thread ();
|
|
96 struct gomp_team *team = thr->ts.team;
|
|
97
|
|
98 if (team != NULL)
|
|
99 {
|
|
100 thr->ts.work_share->copyprivate = data;
|
|
101 gomp_team_barrier_wait (&team->barrier);
|
|
102 }
|
|
103
|
|
104 gomp_work_share_end_nowait ();
|
|
105 }
|