Mercurial > hg > CbC > CbC_gcc
comparison libgomp/parallel.c @ 0:a06113de4d67
first commit
author | kent <kent@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 17 Jul 2009 14:47:48 +0900 |
parents | |
children | f6334be47118 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a06113de4d67 |
---|---|
1 /* Copyright (C) 2005, 2007, 2008, 2009 Free Software Foundation, Inc. | |
2 Contributed by Richard Henderson <rth@redhat.com>. | |
3 | |
4 This file is part of the GNU OpenMP Library (libgomp). | |
5 | |
6 Libgomp is free software; you can redistribute it and/or modify it | |
7 under the terms of the GNU General Public License as published by | |
8 the Free Software Foundation; either version 3, or (at your option) | |
9 any later version. | |
10 | |
11 Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY | |
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
13 FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
14 more details. | |
15 | |
16 Under Section 7 of GPL version 3, you are granted additional | |
17 permissions described in the GCC Runtime Library Exception, version | |
18 3.1, as published by the Free Software Foundation. | |
19 | |
20 You should have received a copy of the GNU General Public License and | |
21 a copy of the GCC Runtime Library Exception along with this program; | |
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
23 <http://www.gnu.org/licenses/>. */ | |
24 | |
25 /* This file handles the (bare) PARALLEL construct. */ | |
26 | |
27 #include "libgomp.h" | |
28 #include <limits.h> | |
29 | |
30 | |
31 /* Determine the number of threads to be launched for a PARALLEL construct. | |
32 This algorithm is explicitly described in OpenMP 3.0 section 2.4.1. | |
33 SPECIFIED is a combination of the NUM_THREADS clause and the IF clause. | |
34 If the IF clause is false, SPECIFIED is forced to 1. When NUM_THREADS | |
35 is not present, SPECIFIED is 0. */ | |
36 | |
37 unsigned | |
38 gomp_resolve_num_threads (unsigned specified, unsigned count) | |
39 { | |
40 struct gomp_thread *thread = gomp_thread(); | |
41 struct gomp_task_icv *icv; | |
42 unsigned threads_requested, max_num_threads, num_threads; | |
43 unsigned long remaining; | |
44 | |
45 icv = gomp_icv (false); | |
46 | |
47 if (specified == 1) | |
48 return 1; | |
49 else if (thread->ts.active_level >= 1 && !icv->nest_var) | |
50 return 1; | |
51 else if (thread->ts.active_level >= gomp_max_active_levels_var) | |
52 return 1; | |
53 | |
54 /* If NUM_THREADS not specified, use nthreads_var. */ | |
55 if (specified == 0) | |
56 threads_requested = icv->nthreads_var; | |
57 else | |
58 threads_requested = specified; | |
59 | |
60 max_num_threads = threads_requested; | |
61 | |
62 /* If dynamic threads are enabled, bound the number of threads | |
63 that we launch. */ | |
64 if (icv->dyn_var) | |
65 { | |
66 unsigned dyn = gomp_dynamic_max_threads (); | |
67 if (dyn < max_num_threads) | |
68 max_num_threads = dyn; | |
69 | |
70 /* Optimization for parallel sections. */ | |
71 if (count && count < max_num_threads) | |
72 max_num_threads = count; | |
73 } | |
74 | |
75 /* ULONG_MAX stands for infinity. */ | |
76 if (__builtin_expect (gomp_thread_limit_var == ULONG_MAX, 1) | |
77 || max_num_threads == 1) | |
78 return max_num_threads; | |
79 | |
80 #ifdef HAVE_SYNC_BUILTINS | |
81 do | |
82 { | |
83 remaining = gomp_remaining_threads_count; | |
84 num_threads = max_num_threads; | |
85 if (num_threads > remaining) | |
86 num_threads = remaining + 1; | |
87 } | |
88 while (__sync_val_compare_and_swap (&gomp_remaining_threads_count, | |
89 remaining, remaining - num_threads + 1) | |
90 != remaining); | |
91 #else | |
92 gomp_mutex_lock (&gomp_remaining_threads_lock); | |
93 num_threads = max_num_threads; | |
94 remaining = gomp_remaining_threads_count; | |
95 if (num_threads > remaining) | |
96 num_threads = remaining + 1; | |
97 gomp_remaining_threads_count -= num_threads - 1; | |
98 gomp_mutex_unlock (&gomp_remaining_threads_lock); | |
99 #endif | |
100 | |
101 return num_threads; | |
102 } | |
103 | |
104 void | |
105 GOMP_parallel_start (void (*fn) (void *), void *data, unsigned num_threads) | |
106 { | |
107 num_threads = gomp_resolve_num_threads (num_threads, 0); | |
108 gomp_team_start (fn, data, num_threads, gomp_new_team (num_threads)); | |
109 } | |
110 | |
111 void | |
112 GOMP_parallel_end (void) | |
113 { | |
114 if (__builtin_expect (gomp_thread_limit_var != ULONG_MAX, 0)) | |
115 { | |
116 struct gomp_thread *thr = gomp_thread (); | |
117 struct gomp_team *team = thr->ts.team; | |
118 if (team && team->nthreads > 1) | |
119 { | |
120 #ifdef HAVE_SYNC_BUILTINS | |
121 __sync_fetch_and_add (&gomp_remaining_threads_count, | |
122 1UL - team->nthreads); | |
123 #else | |
124 gomp_mutex_lock (&gomp_remaining_threads_lock); | |
125 gomp_remaining_threads_count -= team->nthreads - 1; | |
126 #endif | |
127 } | |
128 } | |
129 gomp_team_end (); | |
130 } | |
131 | |
132 | |
133 /* The public OpenMP API for thread and team related inquiries. */ | |
134 | |
135 int | |
136 omp_get_num_threads (void) | |
137 { | |
138 struct gomp_team *team = gomp_thread ()->ts.team; | |
139 return team ? team->nthreads : 1; | |
140 } | |
141 | |
142 int | |
143 omp_get_thread_num (void) | |
144 { | |
145 return gomp_thread ()->ts.team_id; | |
146 } | |
147 | |
148 /* This wasn't right for OpenMP 2.5. Active region used to be non-zero | |
149 when the IF clause doesn't evaluate to false, starting with OpenMP 3.0 | |
150 it is non-zero with more than one thread in the team. */ | |
151 | |
152 int | |
153 omp_in_parallel (void) | |
154 { | |
155 return gomp_thread ()->ts.active_level > 0; | |
156 } | |
157 | |
158 int | |
159 omp_get_level (void) | |
160 { | |
161 return gomp_thread ()->ts.level; | |
162 } | |
163 | |
164 int | |
165 omp_get_ancestor_thread_num (int level) | |
166 { | |
167 struct gomp_team_state *ts = &gomp_thread ()->ts; | |
168 if (level < 0 || level > ts->level) | |
169 return -1; | |
170 for (level = ts->level - level; level > 0; --level) | |
171 ts = &ts->team->prev_ts; | |
172 return ts->team_id; | |
173 } | |
174 | |
175 int | |
176 omp_get_team_size (int level) | |
177 { | |
178 struct gomp_team_state *ts = &gomp_thread ()->ts; | |
179 if (level < 0 || level > ts->level) | |
180 return -1; | |
181 for (level = ts->level - level; level > 0; --level) | |
182 ts = &ts->team->prev_ts; | |
183 if (ts->team == NULL) | |
184 return 1; | |
185 else | |
186 return ts->team->nthreads; | |
187 } | |
188 | |
189 int | |
190 omp_get_active_level (void) | |
191 { | |
192 return gomp_thread ()->ts.active_level; | |
193 } | |
194 | |
195 ialias (omp_get_num_threads) | |
196 ialias (omp_get_thread_num) | |
197 ialias (omp_in_parallel) | |
198 ialias (omp_get_level) | |
199 ialias (omp_get_ancestor_thread_num) | |
200 ialias (omp_get_team_size) | |
201 ialias (omp_get_active_level) |