team.c revision 1.1.1.4 1 1.1.1.4 mrg /* Copyright (C) 2005-2016 Free Software Foundation, Inc.
2 1.1 mrg Contributed by Richard Henderson <rth (at) redhat.com>.
3 1.1 mrg
4 1.1.1.3 mrg This file is part of the GNU Offloading and Multi Processing Library
5 1.1.1.3 mrg (libgomp).
6 1.1 mrg
7 1.1 mrg Libgomp is free software; you can redistribute it and/or modify it
8 1.1 mrg under the terms of the GNU General Public License as published by
9 1.1 mrg the Free Software Foundation; either version 3, or (at your option)
10 1.1 mrg any later version.
11 1.1 mrg
12 1.1 mrg Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
13 1.1 mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 1.1 mrg FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 1.1 mrg more details.
16 1.1 mrg
17 1.1 mrg Under Section 7 of GPL version 3, you are granted additional
18 1.1 mrg permissions described in the GCC Runtime Library Exception, version
19 1.1 mrg 3.1, as published by the Free Software Foundation.
20 1.1 mrg
21 1.1 mrg You should have received a copy of the GNU General Public License and
22 1.1 mrg a copy of the GCC Runtime Library Exception along with this program;
23 1.1 mrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 1.1 mrg <http://www.gnu.org/licenses/>. */
25 1.1 mrg
26 1.1 mrg /* This file handles the maintainence of threads in response to team
27 1.1 mrg creation and termination. */
28 1.1 mrg
29 1.1 mrg #include "libgomp.h"
30 1.1.1.4 mrg #include "pool.h"
31 1.1 mrg #include <stdlib.h>
32 1.1 mrg #include <string.h>
33 1.1 mrg
34 1.1 mrg /* This attribute contains PTHREAD_CREATE_DETACHED. */
35 1.1 mrg pthread_attr_t gomp_thread_attr;
36 1.1 mrg
37 1.1 mrg /* This key is for the thread destructor. */
38 1.1 mrg pthread_key_t gomp_thread_destructor;
39 1.1 mrg
40 1.1 mrg
41 1.1 mrg /* This is the libgomp per-thread data structure. */
42 1.1.1.3 mrg #if defined HAVE_TLS || defined USE_EMUTLS
43 1.1 mrg __thread struct gomp_thread gomp_tls_data;
44 1.1 mrg #else
45 1.1 mrg pthread_key_t gomp_tls_key;
46 1.1 mrg #endif
47 1.1 mrg
48 1.1 mrg
49 1.1 mrg /* This structure is used to communicate across pthread_create. */
50 1.1 mrg
51 1.1 mrg struct gomp_thread_start_data
52 1.1 mrg {
53 1.1 mrg void (*fn) (void *);
54 1.1 mrg void *fn_data;
55 1.1 mrg struct gomp_team_state ts;
56 1.1 mrg struct gomp_task *task;
57 1.1 mrg struct gomp_thread_pool *thread_pool;
58 1.1.1.3 mrg unsigned int place;
59 1.1 mrg bool nested;
60 1.1 mrg };
61 1.1 mrg
62 1.1 mrg
63 1.1 mrg /* This function is a pthread_create entry point. This contains the idle
64 1.1 mrg loop in which a thread waits to be called up to become part of a team. */
65 1.1 mrg
66 1.1 mrg static void *
67 1.1 mrg gomp_thread_start (void *xdata)
68 1.1 mrg {
69 1.1 mrg struct gomp_thread_start_data *data = xdata;
70 1.1 mrg struct gomp_thread *thr;
71 1.1 mrg struct gomp_thread_pool *pool;
72 1.1 mrg void (*local_fn) (void *);
73 1.1 mrg void *local_data;
74 1.1 mrg
75 1.1.1.3 mrg #if defined HAVE_TLS || defined USE_EMUTLS
76 1.1 mrg thr = &gomp_tls_data;
77 1.1 mrg #else
78 1.1 mrg struct gomp_thread local_thr;
79 1.1 mrg thr = &local_thr;
80 1.1 mrg pthread_setspecific (gomp_tls_key, thr);
81 1.1 mrg #endif
82 1.1 mrg gomp_sem_init (&thr->release, 0);
83 1.1 mrg
84 1.1 mrg /* Extract what we need from data. */
85 1.1 mrg local_fn = data->fn;
86 1.1 mrg local_data = data->fn_data;
87 1.1 mrg thr->thread_pool = data->thread_pool;
88 1.1 mrg thr->ts = data->ts;
89 1.1 mrg thr->task = data->task;
90 1.1.1.3 mrg thr->place = data->place;
91 1.1 mrg
92 1.1 mrg thr->ts.team->ordered_release[thr->ts.team_id] = &thr->release;
93 1.1 mrg
94 1.1 mrg /* Make thread pool local. */
95 1.1 mrg pool = thr->thread_pool;
96 1.1 mrg
97 1.1 mrg if (data->nested)
98 1.1 mrg {
99 1.1 mrg struct gomp_team *team = thr->ts.team;
100 1.1 mrg struct gomp_task *task = thr->task;
101 1.1 mrg
102 1.1 mrg gomp_barrier_wait (&team->barrier);
103 1.1 mrg
104 1.1 mrg local_fn (local_data);
105 1.1.1.3 mrg gomp_team_barrier_wait_final (&team->barrier);
106 1.1 mrg gomp_finish_task (task);
107 1.1 mrg gomp_barrier_wait_last (&team->barrier);
108 1.1 mrg }
109 1.1 mrg else
110 1.1 mrg {
111 1.1 mrg pool->threads[thr->ts.team_id] = thr;
112 1.1 mrg
113 1.1 mrg gomp_barrier_wait (&pool->threads_dock);
114 1.1 mrg do
115 1.1 mrg {
116 1.1 mrg struct gomp_team *team = thr->ts.team;
117 1.1 mrg struct gomp_task *task = thr->task;
118 1.1 mrg
119 1.1 mrg local_fn (local_data);
120 1.1.1.3 mrg gomp_team_barrier_wait_final (&team->barrier);
121 1.1 mrg gomp_finish_task (task);
122 1.1 mrg
123 1.1 mrg gomp_barrier_wait (&pool->threads_dock);
124 1.1 mrg
125 1.1 mrg local_fn = thr->fn;
126 1.1 mrg local_data = thr->data;
127 1.1 mrg thr->fn = NULL;
128 1.1 mrg }
129 1.1 mrg while (local_fn);
130 1.1 mrg }
131 1.1 mrg
132 1.1 mrg gomp_sem_destroy (&thr->release);
133 1.1.1.3 mrg thr->thread_pool = NULL;
134 1.1.1.3 mrg thr->task = NULL;
135 1.1 mrg return NULL;
136 1.1 mrg }
137 1.1 mrg
138 1.1.1.4 mrg static inline struct gomp_team *
139 1.1.1.4 mrg get_last_team (unsigned nthreads)
140 1.1.1.4 mrg {
141 1.1.1.4 mrg struct gomp_thread *thr = gomp_thread ();
142 1.1.1.4 mrg if (thr->ts.team == NULL)
143 1.1.1.4 mrg {
144 1.1.1.4 mrg struct gomp_thread_pool *pool = gomp_get_thread_pool (thr, nthreads);
145 1.1.1.4 mrg struct gomp_team *last_team = pool->last_team;
146 1.1.1.4 mrg if (last_team != NULL && last_team->nthreads == nthreads)
147 1.1.1.4 mrg {
148 1.1.1.4 mrg pool->last_team = NULL;
149 1.1.1.4 mrg return last_team;
150 1.1.1.4 mrg }
151 1.1.1.4 mrg }
152 1.1.1.4 mrg return NULL;
153 1.1.1.4 mrg }
154 1.1 mrg
155 1.1 mrg /* Create a new team data structure. */
156 1.1 mrg
157 1.1 mrg struct gomp_team *
158 1.1 mrg gomp_new_team (unsigned nthreads)
159 1.1 mrg {
160 1.1 mrg struct gomp_team *team;
161 1.1 mrg int i;
162 1.1 mrg
163 1.1.1.4 mrg team = get_last_team (nthreads);
164 1.1.1.4 mrg if (team == NULL)
165 1.1.1.4 mrg {
166 1.1.1.4 mrg size_t extra = sizeof (team->ordered_release[0])
167 1.1.1.4 mrg + sizeof (team->implicit_task[0]);
168 1.1.1.4 mrg team = gomp_malloc (sizeof (*team) + nthreads * extra);
169 1.1.1.4 mrg
170 1.1.1.4 mrg #ifndef HAVE_SYNC_BUILTINS
171 1.1.1.4 mrg gomp_mutex_init (&team->work_share_list_free_lock);
172 1.1.1.4 mrg #endif
173 1.1.1.4 mrg gomp_barrier_init (&team->barrier, nthreads);
174 1.1.1.4 mrg gomp_mutex_init (&team->task_lock);
175 1.1.1.4 mrg
176 1.1.1.4 mrg team->nthreads = nthreads;
177 1.1.1.4 mrg }
178 1.1 mrg
179 1.1 mrg team->work_share_chunk = 8;
180 1.1 mrg #ifdef HAVE_SYNC_BUILTINS
181 1.1 mrg team->single_count = 0;
182 1.1 mrg #endif
183 1.1.1.3 mrg team->work_shares_to_free = &team->work_shares[0];
184 1.1 mrg gomp_init_work_share (&team->work_shares[0], false, nthreads);
185 1.1 mrg team->work_shares[0].next_alloc = NULL;
186 1.1 mrg team->work_share_list_free = NULL;
187 1.1 mrg team->work_share_list_alloc = &team->work_shares[1];
188 1.1 mrg for (i = 1; i < 7; i++)
189 1.1 mrg team->work_shares[i].next_free = &team->work_shares[i + 1];
190 1.1 mrg team->work_shares[i].next_free = NULL;
191 1.1 mrg
192 1.1 mrg gomp_sem_init (&team->master_release, 0);
193 1.1 mrg team->ordered_release = (void *) &team->implicit_task[nthreads];
194 1.1 mrg team->ordered_release[0] = &team->master_release;
195 1.1 mrg
196 1.1.1.4 mrg priority_queue_init (&team->task_queue);
197 1.1 mrg team->task_count = 0;
198 1.1.1.3 mrg team->task_queued_count = 0;
199 1.1 mrg team->task_running_count = 0;
200 1.1.1.3 mrg team->work_share_cancelled = 0;
201 1.1.1.3 mrg team->team_cancelled = 0;
202 1.1 mrg
203 1.1 mrg return team;
204 1.1 mrg }
205 1.1 mrg
206 1.1 mrg
207 1.1 mrg /* Free a team data structure. */
208 1.1 mrg
209 1.1 mrg static void
210 1.1 mrg free_team (struct gomp_team *team)
211 1.1 mrg {
212 1.1.1.4 mrg #ifndef HAVE_SYNC_BUILTINS
213 1.1.1.4 mrg gomp_mutex_destroy (&team->work_share_list_free_lock);
214 1.1.1.4 mrg #endif
215 1.1 mrg gomp_barrier_destroy (&team->barrier);
216 1.1 mrg gomp_mutex_destroy (&team->task_lock);
217 1.1.1.4 mrg priority_queue_free (&team->task_queue);
218 1.1 mrg free (team);
219 1.1 mrg }
220 1.1 mrg
221 1.1 mrg static void
222 1.1 mrg gomp_free_pool_helper (void *thread_pool)
223 1.1 mrg {
224 1.1.1.3 mrg struct gomp_thread *thr = gomp_thread ();
225 1.1 mrg struct gomp_thread_pool *pool
226 1.1 mrg = (struct gomp_thread_pool *) thread_pool;
227 1.1 mrg gomp_barrier_wait_last (&pool->threads_dock);
228 1.1.1.3 mrg gomp_sem_destroy (&thr->release);
229 1.1.1.3 mrg thr->thread_pool = NULL;
230 1.1.1.3 mrg thr->task = NULL;
231 1.1 mrg pthread_exit (NULL);
232 1.1 mrg }
233 1.1 mrg
234 1.1 mrg /* Free a thread pool and release its threads. */
235 1.1 mrg
236 1.1.1.3 mrg void
237 1.1 mrg gomp_free_thread (void *arg __attribute__((unused)))
238 1.1 mrg {
239 1.1 mrg struct gomp_thread *thr = gomp_thread ();
240 1.1 mrg struct gomp_thread_pool *pool = thr->thread_pool;
241 1.1 mrg if (pool)
242 1.1 mrg {
243 1.1 mrg if (pool->threads_used > 0)
244 1.1 mrg {
245 1.1 mrg int i;
246 1.1 mrg for (i = 1; i < pool->threads_used; i++)
247 1.1 mrg {
248 1.1 mrg struct gomp_thread *nthr = pool->threads[i];
249 1.1 mrg nthr->fn = gomp_free_pool_helper;
250 1.1 mrg nthr->data = pool;
251 1.1 mrg }
252 1.1 mrg /* This barrier undocks threads docked on pool->threads_dock. */
253 1.1 mrg gomp_barrier_wait (&pool->threads_dock);
254 1.1 mrg /* And this waits till all threads have called gomp_barrier_wait_last
255 1.1 mrg in gomp_free_pool_helper. */
256 1.1 mrg gomp_barrier_wait (&pool->threads_dock);
257 1.1 mrg /* Now it is safe to destroy the barrier and free the pool. */
258 1.1 mrg gomp_barrier_destroy (&pool->threads_dock);
259 1.1.1.2 mrg
260 1.1.1.2 mrg #ifdef HAVE_SYNC_BUILTINS
261 1.1.1.2 mrg __sync_fetch_and_add (&gomp_managed_threads,
262 1.1.1.2 mrg 1L - pool->threads_used);
263 1.1.1.2 mrg #else
264 1.1.1.3 mrg gomp_mutex_lock (&gomp_managed_threads_lock);
265 1.1.1.2 mrg gomp_managed_threads -= pool->threads_used - 1L;
266 1.1.1.3 mrg gomp_mutex_unlock (&gomp_managed_threads_lock);
267 1.1.1.2 mrg #endif
268 1.1 mrg }
269 1.1 mrg free (pool->threads);
270 1.1 mrg if (pool->last_team)
271 1.1 mrg free_team (pool->last_team);
272 1.1 mrg free (pool);
273 1.1 mrg thr->thread_pool = NULL;
274 1.1 mrg }
275 1.1.1.4 mrg if (thr->ts.level == 0 && __builtin_expect (thr->ts.team != NULL, 0))
276 1.1.1.4 mrg gomp_team_end ();
277 1.1 mrg if (thr->task != NULL)
278 1.1 mrg {
279 1.1 mrg struct gomp_task *task = thr->task;
280 1.1 mrg gomp_end_task ();
281 1.1 mrg free (task);
282 1.1 mrg }
283 1.1 mrg }
284 1.1 mrg
285 1.1 mrg /* Launch a team. */
286 1.1 mrg
287 1.1 mrg void
288 1.1 mrg gomp_team_start (void (*fn) (void *), void *data, unsigned nthreads,
289 1.1.1.3 mrg unsigned flags, struct gomp_team *team)
290 1.1 mrg {
291 1.1 mrg struct gomp_thread_start_data *start_data;
292 1.1 mrg struct gomp_thread *thr, *nthr;
293 1.1 mrg struct gomp_task *task;
294 1.1 mrg struct gomp_task_icv *icv;
295 1.1 mrg bool nested;
296 1.1 mrg struct gomp_thread_pool *pool;
297 1.1 mrg unsigned i, n, old_threads_used = 0;
298 1.1 mrg pthread_attr_t thread_attr, *attr;
299 1.1.1.2 mrg unsigned long nthreads_var;
300 1.1.1.3 mrg char bind, bind_var;
301 1.1.1.3 mrg unsigned int s = 0, rest = 0, p = 0, k = 0;
302 1.1.1.3 mrg unsigned int affinity_count = 0;
303 1.1.1.3 mrg struct gomp_thread **affinity_thr = NULL;
304 1.1 mrg
305 1.1 mrg thr = gomp_thread ();
306 1.1.1.4 mrg nested = thr->ts.level;
307 1.1 mrg pool = thr->thread_pool;
308 1.1 mrg task = thr->task;
309 1.1 mrg icv = task ? &task->icv : &gomp_global_icv;
310 1.1.1.3 mrg if (__builtin_expect (gomp_places_list != NULL, 0) && thr->place == 0)
311 1.1.1.3 mrg gomp_init_affinity ();
312 1.1 mrg
313 1.1 mrg /* Always save the previous state, even if this isn't a nested team.
314 1.1 mrg In particular, we should save any work share state from an outer
315 1.1 mrg orphaned work share construct. */
316 1.1 mrg team->prev_ts = thr->ts;
317 1.1 mrg
318 1.1 mrg thr->ts.team = team;
319 1.1 mrg thr->ts.team_id = 0;
320 1.1 mrg ++thr->ts.level;
321 1.1 mrg if (nthreads > 1)
322 1.1 mrg ++thr->ts.active_level;
323 1.1 mrg thr->ts.work_share = &team->work_shares[0];
324 1.1 mrg thr->ts.last_work_share = NULL;
325 1.1 mrg #ifdef HAVE_SYNC_BUILTINS
326 1.1 mrg thr->ts.single_count = 0;
327 1.1 mrg #endif
328 1.1 mrg thr->ts.static_trip = 0;
329 1.1 mrg thr->task = &team->implicit_task[0];
330 1.1.1.2 mrg nthreads_var = icv->nthreads_var;
331 1.1.1.2 mrg if (__builtin_expect (gomp_nthreads_var_list != NULL, 0)
332 1.1.1.2 mrg && thr->ts.level < gomp_nthreads_var_list_len)
333 1.1.1.2 mrg nthreads_var = gomp_nthreads_var_list[thr->ts.level];
334 1.1.1.3 mrg bind_var = icv->bind_var;
335 1.1.1.3 mrg if (bind_var != omp_proc_bind_false && (flags & 7) != omp_proc_bind_false)
336 1.1.1.3 mrg bind_var = flags & 7;
337 1.1.1.3 mrg bind = bind_var;
338 1.1.1.3 mrg if (__builtin_expect (gomp_bind_var_list != NULL, 0)
339 1.1.1.3 mrg && thr->ts.level < gomp_bind_var_list_len)
340 1.1.1.3 mrg bind_var = gomp_bind_var_list[thr->ts.level];
341 1.1 mrg gomp_init_task (thr->task, task, icv);
342 1.1.1.2 mrg team->implicit_task[0].icv.nthreads_var = nthreads_var;
343 1.1.1.3 mrg team->implicit_task[0].icv.bind_var = bind_var;
344 1.1 mrg
345 1.1 mrg if (nthreads == 1)
346 1.1 mrg return;
347 1.1 mrg
348 1.1 mrg i = 1;
349 1.1 mrg
350 1.1.1.3 mrg if (__builtin_expect (gomp_places_list != NULL, 0))
351 1.1.1.3 mrg {
352 1.1.1.3 mrg /* Depending on chosen proc_bind model, set subpartition
353 1.1.1.3 mrg for the master thread and initialize helper variables
354 1.1.1.3 mrg P and optionally S, K and/or REST used by later place
355 1.1.1.3 mrg computation for each additional thread. */
356 1.1.1.3 mrg p = thr->place - 1;
357 1.1.1.3 mrg switch (bind)
358 1.1.1.3 mrg {
359 1.1.1.3 mrg case omp_proc_bind_true:
360 1.1.1.3 mrg case omp_proc_bind_close:
361 1.1.1.3 mrg if (nthreads > thr->ts.place_partition_len)
362 1.1.1.3 mrg {
363 1.1.1.3 mrg /* T > P. S threads will be placed in each place,
364 1.1.1.3 mrg and the final REM threads placed one by one
365 1.1.1.3 mrg into the already occupied places. */
366 1.1.1.3 mrg s = nthreads / thr->ts.place_partition_len;
367 1.1.1.3 mrg rest = nthreads % thr->ts.place_partition_len;
368 1.1.1.3 mrg }
369 1.1.1.3 mrg else
370 1.1.1.3 mrg s = 1;
371 1.1.1.3 mrg k = 1;
372 1.1.1.3 mrg break;
373 1.1.1.3 mrg case omp_proc_bind_master:
374 1.1.1.3 mrg /* Each thread will be bound to master's place. */
375 1.1.1.3 mrg break;
376 1.1.1.3 mrg case omp_proc_bind_spread:
377 1.1.1.3 mrg if (nthreads <= thr->ts.place_partition_len)
378 1.1.1.3 mrg {
379 1.1.1.3 mrg /* T <= P. Each subpartition will have in between s
380 1.1.1.3 mrg and s+1 places (subpartitions starting at or
381 1.1.1.3 mrg after rest will have s places, earlier s+1 places),
382 1.1.1.3 mrg each thread will be bound to the first place in
383 1.1.1.3 mrg its subpartition (except for the master thread
384 1.1.1.3 mrg that can be bound to another place in its
385 1.1.1.3 mrg subpartition). */
386 1.1.1.3 mrg s = thr->ts.place_partition_len / nthreads;
387 1.1.1.3 mrg rest = thr->ts.place_partition_len % nthreads;
388 1.1.1.3 mrg rest = (s + 1) * rest + thr->ts.place_partition_off;
389 1.1.1.3 mrg if (p < rest)
390 1.1.1.3 mrg {
391 1.1.1.3 mrg p -= (p - thr->ts.place_partition_off) % (s + 1);
392 1.1.1.3 mrg thr->ts.place_partition_len = s + 1;
393 1.1.1.3 mrg }
394 1.1.1.3 mrg else
395 1.1.1.3 mrg {
396 1.1.1.3 mrg p -= (p - rest) % s;
397 1.1.1.3 mrg thr->ts.place_partition_len = s;
398 1.1.1.3 mrg }
399 1.1.1.3 mrg thr->ts.place_partition_off = p;
400 1.1.1.3 mrg }
401 1.1.1.3 mrg else
402 1.1.1.3 mrg {
403 1.1.1.3 mrg /* T > P. Each subpartition will have just a single
404 1.1.1.3 mrg place and we'll place between s and s+1
405 1.1.1.3 mrg threads into each subpartition. */
406 1.1.1.3 mrg s = nthreads / thr->ts.place_partition_len;
407 1.1.1.3 mrg rest = nthreads % thr->ts.place_partition_len;
408 1.1.1.3 mrg thr->ts.place_partition_off = p;
409 1.1.1.3 mrg thr->ts.place_partition_len = 1;
410 1.1.1.3 mrg k = 1;
411 1.1.1.3 mrg }
412 1.1.1.3 mrg break;
413 1.1.1.3 mrg }
414 1.1.1.3 mrg }
415 1.1.1.3 mrg else
416 1.1.1.3 mrg bind = omp_proc_bind_false;
417 1.1.1.3 mrg
418 1.1 mrg /* We only allow the reuse of idle threads for non-nested PARALLEL
419 1.1 mrg regions. This appears to be implied by the semantics of
420 1.1 mrg threadprivate variables, but perhaps that's reading too much into
421 1.1 mrg things. Certainly it does prevent any locking problems, since
422 1.1 mrg only the initial program thread will modify gomp_threads. */
423 1.1 mrg if (!nested)
424 1.1 mrg {
425 1.1 mrg old_threads_used = pool->threads_used;
426 1.1 mrg
427 1.1 mrg if (nthreads <= old_threads_used)
428 1.1 mrg n = nthreads;
429 1.1 mrg else if (old_threads_used == 0)
430 1.1 mrg {
431 1.1 mrg n = 0;
432 1.1 mrg gomp_barrier_init (&pool->threads_dock, nthreads);
433 1.1 mrg }
434 1.1 mrg else
435 1.1 mrg {
436 1.1 mrg n = old_threads_used;
437 1.1 mrg
438 1.1 mrg /* Increase the barrier threshold to make sure all new
439 1.1 mrg threads arrive before the team is released. */
440 1.1 mrg gomp_barrier_reinit (&pool->threads_dock, nthreads);
441 1.1 mrg }
442 1.1 mrg
443 1.1 mrg /* Not true yet, but soon will be. We're going to release all
444 1.1 mrg threads from the dock, and those that aren't part of the
445 1.1 mrg team will exit. */
446 1.1 mrg pool->threads_used = nthreads;
447 1.1 mrg
448 1.1.1.3 mrg /* If necessary, expand the size of the gomp_threads array. It is
449 1.1.1.3 mrg expected that changes in the number of threads are rare, thus we
450 1.1.1.3 mrg make no effort to expand gomp_threads_size geometrically. */
451 1.1.1.3 mrg if (nthreads >= pool->threads_size)
452 1.1.1.3 mrg {
453 1.1.1.3 mrg pool->threads_size = nthreads + 1;
454 1.1.1.3 mrg pool->threads
455 1.1.1.3 mrg = gomp_realloc (pool->threads,
456 1.1.1.3 mrg pool->threads_size
457 1.1.1.3 mrg * sizeof (struct gomp_thread_data *));
458 1.1.1.3 mrg }
459 1.1.1.3 mrg
460 1.1 mrg /* Release existing idle threads. */
461 1.1 mrg for (; i < n; ++i)
462 1.1 mrg {
463 1.1.1.3 mrg unsigned int place_partition_off = thr->ts.place_partition_off;
464 1.1.1.3 mrg unsigned int place_partition_len = thr->ts.place_partition_len;
465 1.1.1.3 mrg unsigned int place = 0;
466 1.1.1.3 mrg if (__builtin_expect (gomp_places_list != NULL, 0))
467 1.1.1.3 mrg {
468 1.1.1.3 mrg switch (bind)
469 1.1.1.3 mrg {
470 1.1.1.3 mrg case omp_proc_bind_true:
471 1.1.1.3 mrg case omp_proc_bind_close:
472 1.1.1.3 mrg if (k == s)
473 1.1.1.3 mrg {
474 1.1.1.3 mrg ++p;
475 1.1.1.3 mrg if (p == (team->prev_ts.place_partition_off
476 1.1.1.3 mrg + team->prev_ts.place_partition_len))
477 1.1.1.3 mrg p = team->prev_ts.place_partition_off;
478 1.1.1.3 mrg k = 1;
479 1.1.1.3 mrg if (i == nthreads - rest)
480 1.1.1.3 mrg s = 1;
481 1.1.1.3 mrg }
482 1.1.1.3 mrg else
483 1.1.1.3 mrg ++k;
484 1.1.1.3 mrg break;
485 1.1.1.3 mrg case omp_proc_bind_master:
486 1.1.1.3 mrg break;
487 1.1.1.3 mrg case omp_proc_bind_spread:
488 1.1.1.3 mrg if (k == 0)
489 1.1.1.3 mrg {
490 1.1.1.3 mrg /* T <= P. */
491 1.1.1.3 mrg if (p < rest)
492 1.1.1.3 mrg p += s + 1;
493 1.1.1.3 mrg else
494 1.1.1.3 mrg p += s;
495 1.1.1.3 mrg if (p == (team->prev_ts.place_partition_off
496 1.1.1.3 mrg + team->prev_ts.place_partition_len))
497 1.1.1.3 mrg p = team->prev_ts.place_partition_off;
498 1.1.1.3 mrg place_partition_off = p;
499 1.1.1.3 mrg if (p < rest)
500 1.1.1.3 mrg place_partition_len = s + 1;
501 1.1.1.3 mrg else
502 1.1.1.3 mrg place_partition_len = s;
503 1.1.1.3 mrg }
504 1.1.1.3 mrg else
505 1.1.1.3 mrg {
506 1.1.1.3 mrg /* T > P. */
507 1.1.1.3 mrg if (k == s)
508 1.1.1.3 mrg {
509 1.1.1.3 mrg ++p;
510 1.1.1.3 mrg if (p == (team->prev_ts.place_partition_off
511 1.1.1.3 mrg + team->prev_ts.place_partition_len))
512 1.1.1.3 mrg p = team->prev_ts.place_partition_off;
513 1.1.1.3 mrg k = 1;
514 1.1.1.3 mrg if (i == nthreads - rest)
515 1.1.1.3 mrg s = 1;
516 1.1.1.3 mrg }
517 1.1.1.3 mrg else
518 1.1.1.3 mrg ++k;
519 1.1.1.3 mrg place_partition_off = p;
520 1.1.1.3 mrg place_partition_len = 1;
521 1.1.1.3 mrg }
522 1.1.1.3 mrg break;
523 1.1.1.3 mrg }
524 1.1.1.3 mrg if (affinity_thr != NULL
525 1.1.1.3 mrg || (bind != omp_proc_bind_true
526 1.1.1.3 mrg && pool->threads[i]->place != p + 1)
527 1.1.1.3 mrg || pool->threads[i]->place <= place_partition_off
528 1.1.1.3 mrg || pool->threads[i]->place > (place_partition_off
529 1.1.1.3 mrg + place_partition_len))
530 1.1.1.3 mrg {
531 1.1.1.3 mrg unsigned int l;
532 1.1.1.3 mrg if (affinity_thr == NULL)
533 1.1.1.3 mrg {
534 1.1.1.3 mrg unsigned int j;
535 1.1.1.3 mrg
536 1.1.1.3 mrg if (team->prev_ts.place_partition_len > 64)
537 1.1.1.3 mrg affinity_thr
538 1.1.1.3 mrg = gomp_malloc (team->prev_ts.place_partition_len
539 1.1.1.3 mrg * sizeof (struct gomp_thread *));
540 1.1.1.3 mrg else
541 1.1.1.3 mrg affinity_thr
542 1.1.1.3 mrg = gomp_alloca (team->prev_ts.place_partition_len
543 1.1.1.3 mrg * sizeof (struct gomp_thread *));
544 1.1.1.3 mrg memset (affinity_thr, '\0',
545 1.1.1.3 mrg team->prev_ts.place_partition_len
546 1.1.1.3 mrg * sizeof (struct gomp_thread *));
547 1.1.1.3 mrg for (j = i; j < old_threads_used; j++)
548 1.1.1.3 mrg {
549 1.1.1.3 mrg if (pool->threads[j]->place
550 1.1.1.3 mrg > team->prev_ts.place_partition_off
551 1.1.1.3 mrg && (pool->threads[j]->place
552 1.1.1.3 mrg <= (team->prev_ts.place_partition_off
553 1.1.1.3 mrg + team->prev_ts.place_partition_len)))
554 1.1.1.3 mrg {
555 1.1.1.3 mrg l = pool->threads[j]->place - 1
556 1.1.1.3 mrg - team->prev_ts.place_partition_off;
557 1.1.1.3 mrg pool->threads[j]->data = affinity_thr[l];
558 1.1.1.3 mrg affinity_thr[l] = pool->threads[j];
559 1.1.1.3 mrg }
560 1.1.1.3 mrg pool->threads[j] = NULL;
561 1.1.1.3 mrg }
562 1.1.1.3 mrg if (nthreads > old_threads_used)
563 1.1.1.3 mrg memset (&pool->threads[old_threads_used],
564 1.1.1.3 mrg '\0', ((nthreads - old_threads_used)
565 1.1.1.3 mrg * sizeof (struct gomp_thread *)));
566 1.1.1.3 mrg n = nthreads;
567 1.1.1.3 mrg affinity_count = old_threads_used - i;
568 1.1.1.3 mrg }
569 1.1.1.3 mrg if (affinity_count == 0)
570 1.1.1.3 mrg break;
571 1.1.1.3 mrg l = p;
572 1.1.1.3 mrg if (affinity_thr[l - team->prev_ts.place_partition_off]
573 1.1.1.3 mrg == NULL)
574 1.1.1.3 mrg {
575 1.1.1.3 mrg if (bind != omp_proc_bind_true)
576 1.1.1.3 mrg continue;
577 1.1.1.3 mrg for (l = place_partition_off;
578 1.1.1.3 mrg l < place_partition_off + place_partition_len;
579 1.1.1.3 mrg l++)
580 1.1.1.3 mrg if (affinity_thr[l - team->prev_ts.place_partition_off]
581 1.1.1.3 mrg != NULL)
582 1.1.1.3 mrg break;
583 1.1.1.3 mrg if (l == place_partition_off + place_partition_len)
584 1.1.1.3 mrg continue;
585 1.1.1.3 mrg }
586 1.1.1.3 mrg nthr = affinity_thr[l - team->prev_ts.place_partition_off];
587 1.1.1.3 mrg affinity_thr[l - team->prev_ts.place_partition_off]
588 1.1.1.3 mrg = (struct gomp_thread *) nthr->data;
589 1.1.1.3 mrg affinity_count--;
590 1.1.1.3 mrg pool->threads[i] = nthr;
591 1.1.1.3 mrg }
592 1.1.1.3 mrg else
593 1.1.1.3 mrg nthr = pool->threads[i];
594 1.1.1.3 mrg place = p + 1;
595 1.1.1.3 mrg }
596 1.1.1.3 mrg else
597 1.1.1.3 mrg nthr = pool->threads[i];
598 1.1 mrg nthr->ts.team = team;
599 1.1 mrg nthr->ts.work_share = &team->work_shares[0];
600 1.1 mrg nthr->ts.last_work_share = NULL;
601 1.1 mrg nthr->ts.team_id = i;
602 1.1 mrg nthr->ts.level = team->prev_ts.level + 1;
603 1.1 mrg nthr->ts.active_level = thr->ts.active_level;
604 1.1.1.3 mrg nthr->ts.place_partition_off = place_partition_off;
605 1.1.1.3 mrg nthr->ts.place_partition_len = place_partition_len;
606 1.1 mrg #ifdef HAVE_SYNC_BUILTINS
607 1.1 mrg nthr->ts.single_count = 0;
608 1.1 mrg #endif
609 1.1 mrg nthr->ts.static_trip = 0;
610 1.1 mrg nthr->task = &team->implicit_task[i];
611 1.1.1.3 mrg nthr->place = place;
612 1.1 mrg gomp_init_task (nthr->task, task, icv);
613 1.1.1.2 mrg team->implicit_task[i].icv.nthreads_var = nthreads_var;
614 1.1.1.3 mrg team->implicit_task[i].icv.bind_var = bind_var;
615 1.1 mrg nthr->fn = fn;
616 1.1 mrg nthr->data = data;
617 1.1 mrg team->ordered_release[i] = &nthr->release;
618 1.1 mrg }
619 1.1 mrg
620 1.1.1.3 mrg if (__builtin_expect (affinity_thr != NULL, 0))
621 1.1.1.3 mrg {
622 1.1.1.3 mrg /* If AFFINITY_THR is non-NULL just because we had to
623 1.1.1.3 mrg permute some threads in the pool, but we've managed
624 1.1.1.3 mrg to find exactly as many old threads as we'd find
625 1.1.1.3 mrg without affinity, we don't need to handle this
626 1.1.1.3 mrg specially anymore. */
627 1.1.1.3 mrg if (nthreads <= old_threads_used
628 1.1.1.3 mrg ? (affinity_count == old_threads_used - nthreads)
629 1.1.1.3 mrg : (i == old_threads_used))
630 1.1.1.3 mrg {
631 1.1.1.3 mrg if (team->prev_ts.place_partition_len > 64)
632 1.1.1.3 mrg free (affinity_thr);
633 1.1.1.3 mrg affinity_thr = NULL;
634 1.1.1.3 mrg affinity_count = 0;
635 1.1.1.3 mrg }
636 1.1.1.3 mrg else
637 1.1.1.3 mrg {
638 1.1.1.3 mrg i = 1;
639 1.1.1.3 mrg /* We are going to compute the places/subpartitions
640 1.1.1.3 mrg again from the beginning. So, we need to reinitialize
641 1.1.1.3 mrg vars modified by the switch (bind) above inside
642 1.1.1.3 mrg of the loop, to the state they had after the initial
643 1.1.1.3 mrg switch (bind). */
644 1.1.1.3 mrg switch (bind)
645 1.1.1.3 mrg {
646 1.1.1.3 mrg case omp_proc_bind_true:
647 1.1.1.3 mrg case omp_proc_bind_close:
648 1.1.1.3 mrg if (nthreads > thr->ts.place_partition_len)
649 1.1.1.3 mrg /* T > P. S has been changed, so needs
650 1.1.1.3 mrg to be recomputed. */
651 1.1.1.3 mrg s = nthreads / thr->ts.place_partition_len;
652 1.1.1.3 mrg k = 1;
653 1.1.1.3 mrg p = thr->place - 1;
654 1.1.1.3 mrg break;
655 1.1.1.3 mrg case omp_proc_bind_master:
656 1.1.1.3 mrg /* No vars have been changed. */
657 1.1.1.3 mrg break;
658 1.1.1.3 mrg case omp_proc_bind_spread:
659 1.1.1.3 mrg p = thr->ts.place_partition_off;
660 1.1.1.3 mrg if (k != 0)
661 1.1.1.3 mrg {
662 1.1.1.3 mrg /* T > P. */
663 1.1.1.3 mrg s = nthreads / team->prev_ts.place_partition_len;
664 1.1.1.3 mrg k = 1;
665 1.1.1.3 mrg }
666 1.1.1.3 mrg break;
667 1.1.1.3 mrg }
668 1.1.1.3 mrg
669 1.1.1.3 mrg /* Increase the barrier threshold to make sure all new
670 1.1.1.3 mrg threads and all the threads we're going to let die
671 1.1.1.3 mrg arrive before the team is released. */
672 1.1.1.3 mrg if (affinity_count)
673 1.1.1.3 mrg gomp_barrier_reinit (&pool->threads_dock,
674 1.1.1.3 mrg nthreads + affinity_count);
675 1.1.1.3 mrg }
676 1.1.1.3 mrg }
677 1.1.1.3 mrg
678 1.1 mrg if (i == nthreads)
679 1.1 mrg goto do_release;
680 1.1 mrg
681 1.1 mrg }
682 1.1 mrg
683 1.1.1.3 mrg if (__builtin_expect (nthreads + affinity_count > old_threads_used, 0))
684 1.1 mrg {
685 1.1.1.3 mrg long diff = (long) (nthreads + affinity_count) - (long) old_threads_used;
686 1.1 mrg
687 1.1 mrg if (old_threads_used == 0)
688 1.1 mrg --diff;
689 1.1 mrg
690 1.1 mrg #ifdef HAVE_SYNC_BUILTINS
691 1.1 mrg __sync_fetch_and_add (&gomp_managed_threads, diff);
692 1.1 mrg #else
693 1.1.1.3 mrg gomp_mutex_lock (&gomp_managed_threads_lock);
694 1.1 mrg gomp_managed_threads += diff;
695 1.1.1.3 mrg gomp_mutex_unlock (&gomp_managed_threads_lock);
696 1.1 mrg #endif
697 1.1 mrg }
698 1.1 mrg
699 1.1 mrg attr = &gomp_thread_attr;
700 1.1.1.3 mrg if (__builtin_expect (gomp_places_list != NULL, 0))
701 1.1 mrg {
702 1.1 mrg size_t stacksize;
703 1.1 mrg pthread_attr_init (&thread_attr);
704 1.1 mrg pthread_attr_setdetachstate (&thread_attr, PTHREAD_CREATE_DETACHED);
705 1.1 mrg if (! pthread_attr_getstacksize (&gomp_thread_attr, &stacksize))
706 1.1 mrg pthread_attr_setstacksize (&thread_attr, stacksize);
707 1.1 mrg attr = &thread_attr;
708 1.1 mrg }
709 1.1 mrg
710 1.1 mrg start_data = gomp_alloca (sizeof (struct gomp_thread_start_data)
711 1.1 mrg * (nthreads-i));
712 1.1 mrg
713 1.1 mrg /* Launch new threads. */
714 1.1.1.3 mrg for (; i < nthreads; ++i)
715 1.1 mrg {
716 1.1 mrg pthread_t pt;
717 1.1 mrg int err;
718 1.1 mrg
719 1.1.1.3 mrg start_data->ts.place_partition_off = thr->ts.place_partition_off;
720 1.1.1.3 mrg start_data->ts.place_partition_len = thr->ts.place_partition_len;
721 1.1.1.3 mrg start_data->place = 0;
722 1.1.1.3 mrg if (__builtin_expect (gomp_places_list != NULL, 0))
723 1.1.1.3 mrg {
724 1.1.1.3 mrg switch (bind)
725 1.1.1.3 mrg {
726 1.1.1.3 mrg case omp_proc_bind_true:
727 1.1.1.3 mrg case omp_proc_bind_close:
728 1.1.1.3 mrg if (k == s)
729 1.1.1.3 mrg {
730 1.1.1.3 mrg ++p;
731 1.1.1.3 mrg if (p == (team->prev_ts.place_partition_off
732 1.1.1.3 mrg + team->prev_ts.place_partition_len))
733 1.1.1.3 mrg p = team->prev_ts.place_partition_off;
734 1.1.1.3 mrg k = 1;
735 1.1.1.3 mrg if (i == nthreads - rest)
736 1.1.1.3 mrg s = 1;
737 1.1.1.3 mrg }
738 1.1.1.3 mrg else
739 1.1.1.3 mrg ++k;
740 1.1.1.3 mrg break;
741 1.1.1.3 mrg case omp_proc_bind_master:
742 1.1.1.3 mrg break;
743 1.1.1.3 mrg case omp_proc_bind_spread:
744 1.1.1.3 mrg if (k == 0)
745 1.1.1.3 mrg {
746 1.1.1.3 mrg /* T <= P. */
747 1.1.1.3 mrg if (p < rest)
748 1.1.1.3 mrg p += s + 1;
749 1.1.1.3 mrg else
750 1.1.1.3 mrg p += s;
751 1.1.1.3 mrg if (p == (team->prev_ts.place_partition_off
752 1.1.1.3 mrg + team->prev_ts.place_partition_len))
753 1.1.1.3 mrg p = team->prev_ts.place_partition_off;
754 1.1.1.3 mrg start_data->ts.place_partition_off = p;
755 1.1.1.3 mrg if (p < rest)
756 1.1.1.3 mrg start_data->ts.place_partition_len = s + 1;
757 1.1.1.3 mrg else
758 1.1.1.3 mrg start_data->ts.place_partition_len = s;
759 1.1.1.3 mrg }
760 1.1.1.3 mrg else
761 1.1.1.3 mrg {
762 1.1.1.3 mrg /* T > P. */
763 1.1.1.3 mrg if (k == s)
764 1.1.1.3 mrg {
765 1.1.1.3 mrg ++p;
766 1.1.1.3 mrg if (p == (team->prev_ts.place_partition_off
767 1.1.1.3 mrg + team->prev_ts.place_partition_len))
768 1.1.1.3 mrg p = team->prev_ts.place_partition_off;
769 1.1.1.3 mrg k = 1;
770 1.1.1.3 mrg if (i == nthreads - rest)
771 1.1.1.3 mrg s = 1;
772 1.1.1.3 mrg }
773 1.1.1.3 mrg else
774 1.1.1.3 mrg ++k;
775 1.1.1.3 mrg start_data->ts.place_partition_off = p;
776 1.1.1.3 mrg start_data->ts.place_partition_len = 1;
777 1.1.1.3 mrg }
778 1.1.1.3 mrg break;
779 1.1.1.3 mrg }
780 1.1.1.3 mrg start_data->place = p + 1;
781 1.1.1.3 mrg if (affinity_thr != NULL && pool->threads[i] != NULL)
782 1.1.1.3 mrg continue;
783 1.1.1.3 mrg gomp_init_thread_affinity (attr, p);
784 1.1.1.3 mrg }
785 1.1.1.3 mrg
786 1.1 mrg start_data->fn = fn;
787 1.1 mrg start_data->fn_data = data;
788 1.1 mrg start_data->ts.team = team;
789 1.1 mrg start_data->ts.work_share = &team->work_shares[0];
790 1.1 mrg start_data->ts.last_work_share = NULL;
791 1.1 mrg start_data->ts.team_id = i;
792 1.1 mrg start_data->ts.level = team->prev_ts.level + 1;
793 1.1 mrg start_data->ts.active_level = thr->ts.active_level;
794 1.1 mrg #ifdef HAVE_SYNC_BUILTINS
795 1.1 mrg start_data->ts.single_count = 0;
796 1.1 mrg #endif
797 1.1 mrg start_data->ts.static_trip = 0;
798 1.1 mrg start_data->task = &team->implicit_task[i];
799 1.1 mrg gomp_init_task (start_data->task, task, icv);
800 1.1.1.2 mrg team->implicit_task[i].icv.nthreads_var = nthreads_var;
801 1.1.1.3 mrg team->implicit_task[i].icv.bind_var = bind_var;
802 1.1 mrg start_data->thread_pool = pool;
803 1.1 mrg start_data->nested = nested;
804 1.1 mrg
805 1.1.1.4 mrg attr = gomp_adjust_thread_attr (attr, &thread_attr);
806 1.1.1.3 mrg err = pthread_create (&pt, attr, gomp_thread_start, start_data++);
807 1.1 mrg if (err != 0)
808 1.1 mrg gomp_fatal ("Thread creation failed: %s", strerror (err));
809 1.1 mrg }
810 1.1 mrg
811 1.1.1.4 mrg if (__builtin_expect (attr == &thread_attr, 0))
812 1.1 mrg pthread_attr_destroy (&thread_attr);
813 1.1 mrg
814 1.1 mrg do_release:
815 1.1 mrg gomp_barrier_wait (nested ? &team->barrier : &pool->threads_dock);
816 1.1 mrg
817 1.1 mrg /* Decrease the barrier threshold to match the number of threads
818 1.1 mrg that should arrive back at the end of this team. The extra
819 1.1 mrg threads should be exiting. Note that we arrange for this test
820 1.1.1.3 mrg to never be true for nested teams. If AFFINITY_COUNT is non-zero,
821 1.1.1.3 mrg the barrier as well as gomp_managed_threads was temporarily
822 1.1.1.3 mrg set to NTHREADS + AFFINITY_COUNT. For NTHREADS < OLD_THREADS_COUNT,
823 1.1.1.3 mrg AFFINITY_COUNT if non-zero will be always at least
824 1.1.1.3 mrg OLD_THREADS_COUNT - NTHREADS. */
825 1.1.1.3 mrg if (__builtin_expect (nthreads < old_threads_used, 0)
826 1.1.1.3 mrg || __builtin_expect (affinity_count, 0))
827 1.1 mrg {
828 1.1 mrg long diff = (long) nthreads - (long) old_threads_used;
829 1.1 mrg
830 1.1.1.3 mrg if (affinity_count)
831 1.1.1.3 mrg diff = -affinity_count;
832 1.1.1.3 mrg
833 1.1 mrg gomp_barrier_reinit (&pool->threads_dock, nthreads);
834 1.1 mrg
835 1.1 mrg #ifdef HAVE_SYNC_BUILTINS
836 1.1 mrg __sync_fetch_and_add (&gomp_managed_threads, diff);
837 1.1 mrg #else
838 1.1.1.3 mrg gomp_mutex_lock (&gomp_managed_threads_lock);
839 1.1 mrg gomp_managed_threads += diff;
840 1.1.1.3 mrg gomp_mutex_unlock (&gomp_managed_threads_lock);
841 1.1 mrg #endif
842 1.1 mrg }
843 1.1.1.3 mrg if (__builtin_expect (affinity_thr != NULL, 0)
844 1.1.1.3 mrg && team->prev_ts.place_partition_len > 64)
845 1.1.1.3 mrg free (affinity_thr);
846 1.1 mrg }
847 1.1 mrg
848 1.1 mrg
849 1.1 mrg /* Terminate the current team. This is only to be called by the master
850 1.1 mrg thread. We assume that we must wait for the other threads. */
851 1.1 mrg
852 1.1 mrg void
853 1.1 mrg gomp_team_end (void)
854 1.1 mrg {
855 1.1 mrg struct gomp_thread *thr = gomp_thread ();
856 1.1 mrg struct gomp_team *team = thr->ts.team;
857 1.1 mrg
858 1.1.1.3 mrg /* This barrier handles all pending explicit threads.
859 1.1.1.3 mrg As #pragma omp cancel parallel might get awaited count in
860 1.1.1.3 mrg team->barrier in a inconsistent state, we need to use a different
861 1.1.1.3 mrg counter here. */
862 1.1.1.3 mrg gomp_team_barrier_wait_final (&team->barrier);
863 1.1.1.3 mrg if (__builtin_expect (team->team_cancelled, 0))
864 1.1.1.3 mrg {
865 1.1.1.3 mrg struct gomp_work_share *ws = team->work_shares_to_free;
866 1.1.1.3 mrg do
867 1.1.1.3 mrg {
868 1.1.1.3 mrg struct gomp_work_share *next_ws = gomp_ptrlock_get (&ws->next_ws);
869 1.1.1.3 mrg if (next_ws == NULL)
870 1.1.1.3 mrg gomp_ptrlock_set (&ws->next_ws, ws);
871 1.1.1.3 mrg gomp_fini_work_share (ws);
872 1.1.1.3 mrg ws = next_ws;
873 1.1.1.3 mrg }
874 1.1.1.3 mrg while (ws != NULL);
875 1.1.1.3 mrg }
876 1.1.1.3 mrg else
877 1.1.1.3 mrg gomp_fini_work_share (thr->ts.work_share);
878 1.1 mrg
879 1.1 mrg gomp_end_task ();
880 1.1 mrg thr->ts = team->prev_ts;
881 1.1 mrg
882 1.1 mrg if (__builtin_expect (thr->ts.team != NULL, 0))
883 1.1 mrg {
884 1.1 mrg #ifdef HAVE_SYNC_BUILTINS
885 1.1 mrg __sync_fetch_and_add (&gomp_managed_threads, 1L - team->nthreads);
886 1.1 mrg #else
887 1.1.1.3 mrg gomp_mutex_lock (&gomp_managed_threads_lock);
888 1.1 mrg gomp_managed_threads -= team->nthreads - 1L;
889 1.1.1.3 mrg gomp_mutex_unlock (&gomp_managed_threads_lock);
890 1.1 mrg #endif
891 1.1 mrg /* This barrier has gomp_barrier_wait_last counterparts
892 1.1 mrg and ensures the team can be safely destroyed. */
893 1.1 mrg gomp_barrier_wait (&team->barrier);
894 1.1 mrg }
895 1.1 mrg
896 1.1 mrg if (__builtin_expect (team->work_shares[0].next_alloc != NULL, 0))
897 1.1 mrg {
898 1.1 mrg struct gomp_work_share *ws = team->work_shares[0].next_alloc;
899 1.1 mrg do
900 1.1 mrg {
901 1.1 mrg struct gomp_work_share *next_ws = ws->next_alloc;
902 1.1 mrg free (ws);
903 1.1 mrg ws = next_ws;
904 1.1 mrg }
905 1.1 mrg while (ws != NULL);
906 1.1 mrg }
907 1.1 mrg gomp_sem_destroy (&team->master_release);
908 1.1 mrg
909 1.1 mrg if (__builtin_expect (thr->ts.team != NULL, 0)
910 1.1 mrg || __builtin_expect (team->nthreads == 1, 0))
911 1.1 mrg free_team (team);
912 1.1 mrg else
913 1.1 mrg {
914 1.1 mrg struct gomp_thread_pool *pool = thr->thread_pool;
915 1.1 mrg if (pool->last_team)
916 1.1 mrg free_team (pool->last_team);
917 1.1 mrg pool->last_team = team;
918 1.1.1.4 mrg gomp_release_thread_pool (pool);
919 1.1 mrg }
920 1.1 mrg }
921 1.1 mrg
922 1.1 mrg
923 1.1 mrg /* Constructors for this file. */
924 1.1 mrg
925 1.1 mrg static void __attribute__((constructor))
926 1.1 mrg initialize_team (void)
927 1.1 mrg {
928 1.1.1.3 mrg #if !defined HAVE_TLS && !defined USE_EMUTLS
929 1.1 mrg static struct gomp_thread initial_thread_tls_data;
930 1.1 mrg
931 1.1 mrg pthread_key_create (&gomp_tls_key, NULL);
932 1.1 mrg pthread_setspecific (gomp_tls_key, &initial_thread_tls_data);
933 1.1 mrg #endif
934 1.1 mrg
935 1.1 mrg if (pthread_key_create (&gomp_thread_destructor, gomp_free_thread) != 0)
936 1.1 mrg gomp_fatal ("could not create thread pool destructor.");
937 1.1 mrg }
938 1.1 mrg
939 1.1 mrg static void __attribute__((destructor))
940 1.1 mrg team_destructor (void)
941 1.1 mrg {
942 1.1 mrg /* Without this dlclose on libgomp could lead to subsequent
943 1.1 mrg crashes. */
944 1.1 mrg pthread_key_delete (gomp_thread_destructor);
945 1.1 mrg }
946 1.1 mrg
947 1.1 mrg struct gomp_task_icv *
948 1.1 mrg gomp_new_icv (void)
949 1.1 mrg {
950 1.1 mrg struct gomp_thread *thr = gomp_thread ();
951 1.1 mrg struct gomp_task *task = gomp_malloc (sizeof (struct gomp_task));
952 1.1 mrg gomp_init_task (task, NULL, &gomp_global_icv);
953 1.1 mrg thr->task = task;
954 1.1 mrg pthread_setspecific (gomp_thread_destructor, thr);
955 1.1 mrg return &task->icv;
956 1.1 mrg }
957