1 1.1.1.12 mrg /* Copyright (C) 2005-2024 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.1.10 mrg /* This file handles the maintenance 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.1.5 mrg #ifdef LIBGOMP_USE_PTHREADS 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.1.11 mrg unsigned int num_teams; 60 1.1.1.11 mrg unsigned int team_num; 61 1.1 mrg bool nested; 62 1.1.1.9 mrg pthread_t handle; 63 1.1 mrg }; 64 1.1 mrg 65 1.1 mrg 66 1.1 mrg /* This function is a pthread_create entry point. This contains the idle 67 1.1 mrg loop in which a thread waits to be called up to become part of a team. */ 68 1.1 mrg 69 1.1 mrg static void * 70 1.1 mrg gomp_thread_start (void *xdata) 71 1.1 mrg { 72 1.1 mrg struct gomp_thread_start_data *data = xdata; 73 1.1 mrg struct gomp_thread *thr; 74 1.1 mrg struct gomp_thread_pool *pool; 75 1.1 mrg void (*local_fn) (void *); 76 1.1 mrg void *local_data; 77 1.1 mrg 78 1.1.1.3 mrg #if defined HAVE_TLS || defined USE_EMUTLS 79 1.1 mrg thr = &gomp_tls_data; 80 1.1 mrg #else 81 1.1 mrg struct gomp_thread local_thr; 82 1.1 mrg thr = &local_thr; 83 1.1 mrg #endif 84 1.1 mrg gomp_sem_init (&thr->release, 0); 85 1.1 mrg 86 1.1 mrg /* Extract what we need from data. */ 87 1.1 mrg local_fn = data->fn; 88 1.1 mrg local_data = data->fn_data; 89 1.1 mrg thr->thread_pool = data->thread_pool; 90 1.1 mrg thr->ts = data->ts; 91 1.1 mrg thr->task = data->task; 92 1.1.1.3 mrg thr->place = data->place; 93 1.1.1.11 mrg thr->num_teams = data->num_teams; 94 1.1.1.11 mrg thr->team_num = data->team_num; 95 1.1.1.9 mrg #ifdef GOMP_NEEDS_THREAD_HANDLE 96 1.1.1.9 mrg thr->handle = data->handle; 97 1.1.1.9 mrg #endif 98 1.1.1.11 mrg #if !(defined HAVE_TLS || defined USE_EMUTLS) 99 1.1.1.11 mrg pthread_setspecific (gomp_tls_key, thr); 100 1.1.1.11 mrg #endif 101 1.1 mrg 102 1.1 mrg thr->ts.team->ordered_release[thr->ts.team_id] = &thr->release; 103 1.1 mrg 104 1.1 mrg /* Make thread pool local. */ 105 1.1 mrg pool = thr->thread_pool; 106 1.1 mrg 107 1.1 mrg if (data->nested) 108 1.1 mrg { 109 1.1 mrg struct gomp_team *team = thr->ts.team; 110 1.1 mrg struct gomp_task *task = thr->task; 111 1.1 mrg 112 1.1 mrg gomp_barrier_wait (&team->barrier); 113 1.1 mrg 114 1.1 mrg local_fn (local_data); 115 1.1.1.3 mrg gomp_team_barrier_wait_final (&team->barrier); 116 1.1 mrg gomp_finish_task (task); 117 1.1 mrg gomp_barrier_wait_last (&team->barrier); 118 1.1 mrg } 119 1.1 mrg else 120 1.1 mrg { 121 1.1 mrg pool->threads[thr->ts.team_id] = thr; 122 1.1 mrg 123 1.1.1.5 mrg gomp_simple_barrier_wait (&pool->threads_dock); 124 1.1 mrg do 125 1.1 mrg { 126 1.1 mrg struct gomp_team *team = thr->ts.team; 127 1.1 mrg struct gomp_task *task = thr->task; 128 1.1 mrg 129 1.1 mrg local_fn (local_data); 130 1.1.1.3 mrg gomp_team_barrier_wait_final (&team->barrier); 131 1.1 mrg gomp_finish_task (task); 132 1.1 mrg 133 1.1.1.5 mrg gomp_simple_barrier_wait (&pool->threads_dock); 134 1.1 mrg 135 1.1 mrg local_fn = thr->fn; 136 1.1 mrg local_data = thr->data; 137 1.1 mrg thr->fn = NULL; 138 1.1 mrg } 139 1.1 mrg while (local_fn); 140 1.1 mrg } 141 1.1 mrg 142 1.1 mrg gomp_sem_destroy (&thr->release); 143 1.1.1.9 mrg pthread_detach (pthread_self ()); 144 1.1.1.3 mrg thr->thread_pool = NULL; 145 1.1.1.3 mrg thr->task = NULL; 146 1.1 mrg return NULL; 147 1.1 mrg } 148 1.1.1.5 mrg #endif 149 1.1 mrg 150 1.1.1.4 mrg static inline struct gomp_team * 151 1.1.1.4 mrg get_last_team (unsigned nthreads) 152 1.1.1.4 mrg { 153 1.1.1.4 mrg struct gomp_thread *thr = gomp_thread (); 154 1.1.1.4 mrg if (thr->ts.team == NULL) 155 1.1.1.4 mrg { 156 1.1.1.4 mrg struct gomp_thread_pool *pool = gomp_get_thread_pool (thr, nthreads); 157 1.1.1.4 mrg struct gomp_team *last_team = pool->last_team; 158 1.1.1.4 mrg if (last_team != NULL && last_team->nthreads == nthreads) 159 1.1.1.4 mrg { 160 1.1.1.4 mrg pool->last_team = NULL; 161 1.1.1.4 mrg return last_team; 162 1.1.1.4 mrg } 163 1.1.1.4 mrg } 164 1.1.1.4 mrg return NULL; 165 1.1.1.4 mrg } 166 1.1 mrg 167 1.1 mrg /* Create a new team data structure. */ 168 1.1 mrg 169 1.1 mrg struct gomp_team * 170 1.1 mrg gomp_new_team (unsigned nthreads) 171 1.1 mrg { 172 1.1 mrg struct gomp_team *team; 173 1.1 mrg int i; 174 1.1 mrg 175 1.1.1.4 mrg team = get_last_team (nthreads); 176 1.1.1.4 mrg if (team == NULL) 177 1.1.1.4 mrg { 178 1.1.1.4 mrg size_t extra = sizeof (team->ordered_release[0]) 179 1.1.1.4 mrg + sizeof (team->implicit_task[0]); 180 1.1.1.11 mrg #ifdef GOMP_USE_ALIGNED_WORK_SHARES 181 1.1.1.11 mrg team = gomp_aligned_alloc (__alignof (struct gomp_team), 182 1.1.1.11 mrg sizeof (*team) + nthreads * extra); 183 1.1.1.11 mrg #else 184 1.1.1.10 mrg team = team_malloc (sizeof (*team) + nthreads * extra); 185 1.1.1.11 mrg #endif 186 1.1.1.4 mrg 187 1.1.1.4 mrg #ifndef HAVE_SYNC_BUILTINS 188 1.1.1.4 mrg gomp_mutex_init (&team->work_share_list_free_lock); 189 1.1.1.4 mrg #endif 190 1.1.1.4 mrg gomp_barrier_init (&team->barrier, nthreads); 191 1.1.1.4 mrg gomp_mutex_init (&team->task_lock); 192 1.1.1.4 mrg 193 1.1.1.4 mrg team->nthreads = nthreads; 194 1.1.1.4 mrg } 195 1.1 mrg 196 1.1 mrg team->work_share_chunk = 8; 197 1.1 mrg #ifdef HAVE_SYNC_BUILTINS 198 1.1 mrg team->single_count = 0; 199 1.1 mrg #endif 200 1.1.1.3 mrg team->work_shares_to_free = &team->work_shares[0]; 201 1.1.1.9 mrg gomp_init_work_share (&team->work_shares[0], 0, nthreads); 202 1.1 mrg team->work_shares[0].next_alloc = NULL; 203 1.1 mrg team->work_share_list_free = NULL; 204 1.1 mrg team->work_share_list_alloc = &team->work_shares[1]; 205 1.1 mrg for (i = 1; i < 7; i++) 206 1.1 mrg team->work_shares[i].next_free = &team->work_shares[i + 1]; 207 1.1 mrg team->work_shares[i].next_free = NULL; 208 1.1 mrg 209 1.1 mrg gomp_sem_init (&team->master_release, 0); 210 1.1 mrg team->ordered_release = (void *) &team->implicit_task[nthreads]; 211 1.1 mrg team->ordered_release[0] = &team->master_release; 212 1.1 mrg 213 1.1.1.4 mrg priority_queue_init (&team->task_queue); 214 1.1 mrg team->task_count = 0; 215 1.1.1.3 mrg team->task_queued_count = 0; 216 1.1 mrg team->task_running_count = 0; 217 1.1.1.3 mrg team->work_share_cancelled = 0; 218 1.1.1.3 mrg team->team_cancelled = 0; 219 1.1 mrg 220 1.1.1.11 mrg team->task_detach_count = 0; 221 1.1.1.11 mrg 222 1.1 mrg return team; 223 1.1 mrg } 224 1.1 mrg 225 1.1 mrg 226 1.1 mrg /* Free a team data structure. */ 227 1.1 mrg 228 1.1 mrg static void 229 1.1 mrg free_team (struct gomp_team *team) 230 1.1 mrg { 231 1.1.1.4 mrg #ifndef HAVE_SYNC_BUILTINS 232 1.1.1.4 mrg gomp_mutex_destroy (&team->work_share_list_free_lock); 233 1.1.1.4 mrg #endif 234 1.1 mrg gomp_barrier_destroy (&team->barrier); 235 1.1 mrg gomp_mutex_destroy (&team->task_lock); 236 1.1.1.4 mrg priority_queue_free (&team->task_queue); 237 1.1.1.10 mrg team_free (team); 238 1.1 mrg } 239 1.1 mrg 240 1.1 mrg static void 241 1.1 mrg gomp_free_pool_helper (void *thread_pool) 242 1.1 mrg { 243 1.1.1.3 mrg struct gomp_thread *thr = gomp_thread (); 244 1.1 mrg struct gomp_thread_pool *pool 245 1.1 mrg = (struct gomp_thread_pool *) thread_pool; 246 1.1.1.5 mrg gomp_simple_barrier_wait_last (&pool->threads_dock); 247 1.1.1.3 mrg gomp_sem_destroy (&thr->release); 248 1.1.1.3 mrg thr->thread_pool = NULL; 249 1.1.1.3 mrg thr->task = NULL; 250 1.1.1.5 mrg #ifdef LIBGOMP_USE_PTHREADS 251 1.1.1.9 mrg pthread_detach (pthread_self ()); 252 1.1 mrg pthread_exit (NULL); 253 1.1.1.5 mrg #elif defined(__nvptx__) 254 1.1.1.5 mrg asm ("exit;"); 255 1.1.1.10 mrg #elif defined(__AMDGCN__) 256 1.1.1.12 mrg asm ("s_endpgm"); 257 1.1.1.5 mrg #else 258 1.1.1.5 mrg #error gomp_free_pool_helper must terminate the thread 259 1.1.1.5 mrg #endif 260 1.1 mrg } 261 1.1 mrg 262 1.1 mrg /* Free a thread pool and release its threads. */ 263 1.1 mrg 264 1.1.1.3 mrg void 265 1.1 mrg gomp_free_thread (void *arg __attribute__((unused))) 266 1.1 mrg { 267 1.1 mrg struct gomp_thread *thr = gomp_thread (); 268 1.1 mrg struct gomp_thread_pool *pool = thr->thread_pool; 269 1.1 mrg if (pool) 270 1.1 mrg { 271 1.1 mrg if (pool->threads_used > 0) 272 1.1 mrg { 273 1.1 mrg int i; 274 1.1 mrg for (i = 1; i < pool->threads_used; i++) 275 1.1 mrg { 276 1.1 mrg struct gomp_thread *nthr = pool->threads[i]; 277 1.1 mrg nthr->fn = gomp_free_pool_helper; 278 1.1 mrg nthr->data = pool; 279 1.1 mrg } 280 1.1 mrg /* This barrier undocks threads docked on pool->threads_dock. */ 281 1.1.1.5 mrg gomp_simple_barrier_wait (&pool->threads_dock); 282 1.1 mrg /* And this waits till all threads have called gomp_barrier_wait_last 283 1.1 mrg in gomp_free_pool_helper. */ 284 1.1.1.5 mrg gomp_simple_barrier_wait (&pool->threads_dock); 285 1.1 mrg /* Now it is safe to destroy the barrier and free the pool. */ 286 1.1.1.5 mrg gomp_simple_barrier_destroy (&pool->threads_dock); 287 1.1.1.2 mrg 288 1.1.1.2 mrg #ifdef HAVE_SYNC_BUILTINS 289 1.1.1.2 mrg __sync_fetch_and_add (&gomp_managed_threads, 290 1.1.1.2 mrg 1L - pool->threads_used); 291 1.1.1.2 mrg #else 292 1.1.1.3 mrg gomp_mutex_lock (&gomp_managed_threads_lock); 293 1.1.1.2 mrg gomp_managed_threads -= pool->threads_used - 1L; 294 1.1.1.3 mrg gomp_mutex_unlock (&gomp_managed_threads_lock); 295 1.1.1.2 mrg #endif 296 1.1 mrg } 297 1.1 mrg if (pool->last_team) 298 1.1 mrg free_team (pool->last_team); 299 1.1.1.5 mrg #ifndef __nvptx__ 300 1.1.1.10 mrg team_free (pool->threads); 301 1.1.1.10 mrg team_free (pool); 302 1.1.1.5 mrg #endif 303 1.1 mrg thr->thread_pool = NULL; 304 1.1 mrg } 305 1.1.1.4 mrg if (thr->ts.level == 0 && __builtin_expect (thr->ts.team != NULL, 0)) 306 1.1.1.4 mrg gomp_team_end (); 307 1.1 mrg if (thr->task != NULL) 308 1.1 mrg { 309 1.1 mrg struct gomp_task *task = thr->task; 310 1.1 mrg gomp_end_task (); 311 1.1 mrg free (task); 312 1.1 mrg } 313 1.1 mrg } 314 1.1 mrg 315 1.1 mrg /* Launch a team. */ 316 1.1 mrg 317 1.1.1.5 mrg #ifdef LIBGOMP_USE_PTHREADS 318 1.1 mrg void 319 1.1 mrg gomp_team_start (void (*fn) (void *), void *data, unsigned nthreads, 320 1.1.1.9 mrg unsigned flags, struct gomp_team *team, 321 1.1.1.9 mrg struct gomp_taskgroup *taskgroup) 322 1.1 mrg { 323 1.1.1.11 mrg struct gomp_thread_start_data *start_data = NULL; 324 1.1 mrg struct gomp_thread *thr, *nthr; 325 1.1 mrg struct gomp_task *task; 326 1.1 mrg struct gomp_task_icv *icv; 327 1.1 mrg bool nested; 328 1.1 mrg struct gomp_thread_pool *pool; 329 1.1 mrg unsigned i, n, old_threads_used = 0; 330 1.1 mrg pthread_attr_t thread_attr, *attr; 331 1.1.1.2 mrg unsigned long nthreads_var; 332 1.1.1.3 mrg char bind, bind_var; 333 1.1.1.3 mrg unsigned int s = 0, rest = 0, p = 0, k = 0; 334 1.1.1.3 mrg unsigned int affinity_count = 0; 335 1.1.1.3 mrg struct gomp_thread **affinity_thr = NULL; 336 1.1.1.9 mrg bool force_display = false; 337 1.1 mrg 338 1.1 mrg thr = gomp_thread (); 339 1.1.1.4 mrg nested = thr->ts.level; 340 1.1 mrg pool = thr->thread_pool; 341 1.1 mrg task = thr->task; 342 1.1 mrg icv = task ? &task->icv : &gomp_global_icv; 343 1.1.1.3 mrg if (__builtin_expect (gomp_places_list != NULL, 0) && thr->place == 0) 344 1.1.1.9 mrg { 345 1.1.1.9 mrg gomp_init_affinity (); 346 1.1.1.9 mrg if (__builtin_expect (gomp_display_affinity_var, 0) && nthreads == 1) 347 1.1.1.9 mrg gomp_display_affinity_thread (gomp_thread_self (), &thr->ts, 348 1.1.1.9 mrg thr->place); 349 1.1.1.9 mrg } 350 1.1 mrg 351 1.1 mrg /* Always save the previous state, even if this isn't a nested team. 352 1.1 mrg In particular, we should save any work share state from an outer 353 1.1 mrg orphaned work share construct. */ 354 1.1 mrg team->prev_ts = thr->ts; 355 1.1 mrg 356 1.1 mrg thr->ts.team = team; 357 1.1 mrg thr->ts.team_id = 0; 358 1.1 mrg ++thr->ts.level; 359 1.1 mrg if (nthreads > 1) 360 1.1 mrg ++thr->ts.active_level; 361 1.1 mrg thr->ts.work_share = &team->work_shares[0]; 362 1.1 mrg thr->ts.last_work_share = NULL; 363 1.1 mrg #ifdef HAVE_SYNC_BUILTINS 364 1.1 mrg thr->ts.single_count = 0; 365 1.1 mrg #endif 366 1.1 mrg thr->ts.static_trip = 0; 367 1.1 mrg thr->task = &team->implicit_task[0]; 368 1.1.1.9 mrg #ifdef GOMP_NEEDS_THREAD_HANDLE 369 1.1.1.9 mrg thr->handle = pthread_self (); 370 1.1.1.9 mrg #endif 371 1.1.1.2 mrg nthreads_var = icv->nthreads_var; 372 1.1.1.2 mrg if (__builtin_expect (gomp_nthreads_var_list != NULL, 0) 373 1.1.1.2 mrg && thr->ts.level < gomp_nthreads_var_list_len) 374 1.1.1.2 mrg nthreads_var = gomp_nthreads_var_list[thr->ts.level]; 375 1.1.1.3 mrg bind_var = icv->bind_var; 376 1.1.1.3 mrg if (bind_var != omp_proc_bind_false && (flags & 7) != omp_proc_bind_false) 377 1.1.1.3 mrg bind_var = flags & 7; 378 1.1.1.3 mrg bind = bind_var; 379 1.1.1.3 mrg if (__builtin_expect (gomp_bind_var_list != NULL, 0) 380 1.1.1.3 mrg && thr->ts.level < gomp_bind_var_list_len) 381 1.1.1.3 mrg bind_var = gomp_bind_var_list[thr->ts.level]; 382 1.1 mrg gomp_init_task (thr->task, task, icv); 383 1.1.1.9 mrg thr->task->taskgroup = taskgroup; 384 1.1.1.2 mrg team->implicit_task[0].icv.nthreads_var = nthreads_var; 385 1.1.1.3 mrg team->implicit_task[0].icv.bind_var = bind_var; 386 1.1 mrg 387 1.1 mrg if (nthreads == 1) 388 1.1 mrg return; 389 1.1 mrg 390 1.1 mrg i = 1; 391 1.1 mrg 392 1.1.1.3 mrg if (__builtin_expect (gomp_places_list != NULL, 0)) 393 1.1.1.3 mrg { 394 1.1.1.3 mrg /* Depending on chosen proc_bind model, set subpartition 395 1.1.1.3 mrg for the master thread and initialize helper variables 396 1.1.1.3 mrg P and optionally S, K and/or REST used by later place 397 1.1.1.3 mrg computation for each additional thread. */ 398 1.1.1.3 mrg p = thr->place - 1; 399 1.1.1.3 mrg switch (bind) 400 1.1.1.3 mrg { 401 1.1.1.3 mrg case omp_proc_bind_true: 402 1.1.1.3 mrg case omp_proc_bind_close: 403 1.1.1.3 mrg if (nthreads > thr->ts.place_partition_len) 404 1.1.1.3 mrg { 405 1.1.1.3 mrg /* T > P. S threads will be placed in each place, 406 1.1.1.3 mrg and the final REM threads placed one by one 407 1.1.1.3 mrg into the already occupied places. */ 408 1.1.1.3 mrg s = nthreads / thr->ts.place_partition_len; 409 1.1.1.3 mrg rest = nthreads % thr->ts.place_partition_len; 410 1.1.1.3 mrg } 411 1.1.1.3 mrg else 412 1.1.1.3 mrg s = 1; 413 1.1.1.3 mrg k = 1; 414 1.1.1.3 mrg break; 415 1.1.1.3 mrg case omp_proc_bind_master: 416 1.1.1.3 mrg /* Each thread will be bound to master's place. */ 417 1.1.1.3 mrg break; 418 1.1.1.3 mrg case omp_proc_bind_spread: 419 1.1.1.3 mrg if (nthreads <= thr->ts.place_partition_len) 420 1.1.1.3 mrg { 421 1.1.1.3 mrg /* T <= P. Each subpartition will have in between s 422 1.1.1.3 mrg and s+1 places (subpartitions starting at or 423 1.1.1.3 mrg after rest will have s places, earlier s+1 places), 424 1.1.1.3 mrg each thread will be bound to the first place in 425 1.1.1.3 mrg its subpartition (except for the master thread 426 1.1.1.3 mrg that can be bound to another place in its 427 1.1.1.3 mrg subpartition). */ 428 1.1.1.3 mrg s = thr->ts.place_partition_len / nthreads; 429 1.1.1.3 mrg rest = thr->ts.place_partition_len % nthreads; 430 1.1.1.3 mrg rest = (s + 1) * rest + thr->ts.place_partition_off; 431 1.1.1.3 mrg if (p < rest) 432 1.1.1.3 mrg { 433 1.1.1.3 mrg p -= (p - thr->ts.place_partition_off) % (s + 1); 434 1.1.1.3 mrg thr->ts.place_partition_len = s + 1; 435 1.1.1.3 mrg } 436 1.1.1.3 mrg else 437 1.1.1.3 mrg { 438 1.1.1.3 mrg p -= (p - rest) % s; 439 1.1.1.3 mrg thr->ts.place_partition_len = s; 440 1.1.1.3 mrg } 441 1.1.1.3 mrg thr->ts.place_partition_off = p; 442 1.1.1.3 mrg } 443 1.1.1.3 mrg else 444 1.1.1.3 mrg { 445 1.1.1.3 mrg /* T > P. Each subpartition will have just a single 446 1.1.1.3 mrg place and we'll place between s and s+1 447 1.1.1.3 mrg threads into each subpartition. */ 448 1.1.1.3 mrg s = nthreads / thr->ts.place_partition_len; 449 1.1.1.3 mrg rest = nthreads % thr->ts.place_partition_len; 450 1.1.1.3 mrg thr->ts.place_partition_off = p; 451 1.1.1.3 mrg thr->ts.place_partition_len = 1; 452 1.1.1.3 mrg k = 1; 453 1.1.1.3 mrg } 454 1.1.1.3 mrg break; 455 1.1.1.3 mrg } 456 1.1.1.3 mrg } 457 1.1.1.3 mrg else 458 1.1.1.3 mrg bind = omp_proc_bind_false; 459 1.1.1.3 mrg 460 1.1 mrg /* We only allow the reuse of idle threads for non-nested PARALLEL 461 1.1 mrg regions. This appears to be implied by the semantics of 462 1.1 mrg threadprivate variables, but perhaps that's reading too much into 463 1.1 mrg things. Certainly it does prevent any locking problems, since 464 1.1 mrg only the initial program thread will modify gomp_threads. */ 465 1.1 mrg if (!nested) 466 1.1 mrg { 467 1.1 mrg old_threads_used = pool->threads_used; 468 1.1 mrg 469 1.1 mrg if (nthreads <= old_threads_used) 470 1.1 mrg n = nthreads; 471 1.1 mrg else if (old_threads_used == 0) 472 1.1 mrg { 473 1.1 mrg n = 0; 474 1.1.1.5 mrg gomp_simple_barrier_init (&pool->threads_dock, nthreads); 475 1.1 mrg } 476 1.1 mrg else 477 1.1 mrg { 478 1.1 mrg n = old_threads_used; 479 1.1 mrg 480 1.1 mrg /* Increase the barrier threshold to make sure all new 481 1.1 mrg threads arrive before the team is released. */ 482 1.1.1.5 mrg gomp_simple_barrier_reinit (&pool->threads_dock, nthreads); 483 1.1 mrg } 484 1.1 mrg 485 1.1 mrg /* Not true yet, but soon will be. We're going to release all 486 1.1 mrg threads from the dock, and those that aren't part of the 487 1.1 mrg team will exit. */ 488 1.1 mrg pool->threads_used = nthreads; 489 1.1 mrg 490 1.1.1.3 mrg /* If necessary, expand the size of the gomp_threads array. It is 491 1.1.1.3 mrg expected that changes in the number of threads are rare, thus we 492 1.1.1.3 mrg make no effort to expand gomp_threads_size geometrically. */ 493 1.1.1.3 mrg if (nthreads >= pool->threads_size) 494 1.1.1.3 mrg { 495 1.1.1.3 mrg pool->threads_size = nthreads + 1; 496 1.1.1.3 mrg pool->threads 497 1.1.1.3 mrg = gomp_realloc (pool->threads, 498 1.1.1.3 mrg pool->threads_size 499 1.1.1.9 mrg * sizeof (struct gomp_thread *)); 500 1.1.1.9 mrg /* Add current (master) thread to threads[]. */ 501 1.1.1.9 mrg pool->threads[0] = thr; 502 1.1.1.3 mrg } 503 1.1.1.3 mrg 504 1.1 mrg /* Release existing idle threads. */ 505 1.1 mrg for (; i < n; ++i) 506 1.1 mrg { 507 1.1.1.3 mrg unsigned int place_partition_off = thr->ts.place_partition_off; 508 1.1.1.3 mrg unsigned int place_partition_len = thr->ts.place_partition_len; 509 1.1.1.3 mrg unsigned int place = 0; 510 1.1.1.3 mrg if (__builtin_expect (gomp_places_list != NULL, 0)) 511 1.1.1.3 mrg { 512 1.1.1.3 mrg switch (bind) 513 1.1.1.3 mrg { 514 1.1.1.3 mrg case omp_proc_bind_true: 515 1.1.1.3 mrg case omp_proc_bind_close: 516 1.1.1.3 mrg if (k == s) 517 1.1.1.3 mrg { 518 1.1.1.3 mrg ++p; 519 1.1.1.3 mrg if (p == (team->prev_ts.place_partition_off 520 1.1.1.3 mrg + team->prev_ts.place_partition_len)) 521 1.1.1.3 mrg p = team->prev_ts.place_partition_off; 522 1.1.1.3 mrg k = 1; 523 1.1.1.3 mrg if (i == nthreads - rest) 524 1.1.1.3 mrg s = 1; 525 1.1.1.3 mrg } 526 1.1.1.3 mrg else 527 1.1.1.3 mrg ++k; 528 1.1.1.3 mrg break; 529 1.1.1.3 mrg case omp_proc_bind_master: 530 1.1.1.3 mrg break; 531 1.1.1.3 mrg case omp_proc_bind_spread: 532 1.1.1.3 mrg if (k == 0) 533 1.1.1.3 mrg { 534 1.1.1.3 mrg /* T <= P. */ 535 1.1.1.3 mrg if (p < rest) 536 1.1.1.3 mrg p += s + 1; 537 1.1.1.3 mrg else 538 1.1.1.3 mrg p += s; 539 1.1.1.3 mrg if (p == (team->prev_ts.place_partition_off 540 1.1.1.3 mrg + team->prev_ts.place_partition_len)) 541 1.1.1.3 mrg p = team->prev_ts.place_partition_off; 542 1.1.1.3 mrg place_partition_off = p; 543 1.1.1.3 mrg if (p < rest) 544 1.1.1.3 mrg place_partition_len = s + 1; 545 1.1.1.3 mrg else 546 1.1.1.3 mrg place_partition_len = s; 547 1.1.1.3 mrg } 548 1.1.1.3 mrg else 549 1.1.1.3 mrg { 550 1.1.1.3 mrg /* T > P. */ 551 1.1.1.3 mrg if (k == s) 552 1.1.1.3 mrg { 553 1.1.1.3 mrg ++p; 554 1.1.1.3 mrg if (p == (team->prev_ts.place_partition_off 555 1.1.1.3 mrg + team->prev_ts.place_partition_len)) 556 1.1.1.3 mrg p = team->prev_ts.place_partition_off; 557 1.1.1.3 mrg k = 1; 558 1.1.1.3 mrg if (i == nthreads - rest) 559 1.1.1.3 mrg s = 1; 560 1.1.1.3 mrg } 561 1.1.1.3 mrg else 562 1.1.1.3 mrg ++k; 563 1.1.1.3 mrg place_partition_off = p; 564 1.1.1.3 mrg place_partition_len = 1; 565 1.1.1.3 mrg } 566 1.1.1.3 mrg break; 567 1.1.1.3 mrg } 568 1.1.1.3 mrg if (affinity_thr != NULL 569 1.1.1.3 mrg || (bind != omp_proc_bind_true 570 1.1.1.3 mrg && pool->threads[i]->place != p + 1) 571 1.1.1.3 mrg || pool->threads[i]->place <= place_partition_off 572 1.1.1.3 mrg || pool->threads[i]->place > (place_partition_off 573 1.1.1.3 mrg + place_partition_len)) 574 1.1.1.3 mrg { 575 1.1.1.3 mrg unsigned int l; 576 1.1.1.9 mrg force_display = true; 577 1.1.1.3 mrg if (affinity_thr == NULL) 578 1.1.1.3 mrg { 579 1.1.1.3 mrg unsigned int j; 580 1.1.1.3 mrg 581 1.1.1.3 mrg if (team->prev_ts.place_partition_len > 64) 582 1.1.1.3 mrg affinity_thr 583 1.1.1.3 mrg = gomp_malloc (team->prev_ts.place_partition_len 584 1.1.1.3 mrg * sizeof (struct gomp_thread *)); 585 1.1.1.3 mrg else 586 1.1.1.3 mrg affinity_thr 587 1.1.1.3 mrg = gomp_alloca (team->prev_ts.place_partition_len 588 1.1.1.3 mrg * sizeof (struct gomp_thread *)); 589 1.1.1.3 mrg memset (affinity_thr, '\0', 590 1.1.1.3 mrg team->prev_ts.place_partition_len 591 1.1.1.3 mrg * sizeof (struct gomp_thread *)); 592 1.1.1.3 mrg for (j = i; j < old_threads_used; j++) 593 1.1.1.3 mrg { 594 1.1.1.3 mrg if (pool->threads[j]->place 595 1.1.1.3 mrg > team->prev_ts.place_partition_off 596 1.1.1.3 mrg && (pool->threads[j]->place 597 1.1.1.3 mrg <= (team->prev_ts.place_partition_off 598 1.1.1.3 mrg + team->prev_ts.place_partition_len))) 599 1.1.1.3 mrg { 600 1.1.1.3 mrg l = pool->threads[j]->place - 1 601 1.1.1.3 mrg - team->prev_ts.place_partition_off; 602 1.1.1.3 mrg pool->threads[j]->data = affinity_thr[l]; 603 1.1.1.3 mrg affinity_thr[l] = pool->threads[j]; 604 1.1.1.3 mrg } 605 1.1.1.3 mrg pool->threads[j] = NULL; 606 1.1.1.3 mrg } 607 1.1.1.3 mrg if (nthreads > old_threads_used) 608 1.1.1.3 mrg memset (&pool->threads[old_threads_used], 609 1.1.1.3 mrg '\0', ((nthreads - old_threads_used) 610 1.1.1.3 mrg * sizeof (struct gomp_thread *))); 611 1.1.1.3 mrg n = nthreads; 612 1.1.1.3 mrg affinity_count = old_threads_used - i; 613 1.1.1.3 mrg } 614 1.1.1.3 mrg if (affinity_count == 0) 615 1.1.1.3 mrg break; 616 1.1.1.3 mrg l = p; 617 1.1.1.3 mrg if (affinity_thr[l - team->prev_ts.place_partition_off] 618 1.1.1.3 mrg == NULL) 619 1.1.1.3 mrg { 620 1.1.1.3 mrg if (bind != omp_proc_bind_true) 621 1.1.1.3 mrg continue; 622 1.1.1.3 mrg for (l = place_partition_off; 623 1.1.1.3 mrg l < place_partition_off + place_partition_len; 624 1.1.1.3 mrg l++) 625 1.1.1.3 mrg if (affinity_thr[l - team->prev_ts.place_partition_off] 626 1.1.1.3 mrg != NULL) 627 1.1.1.3 mrg break; 628 1.1.1.3 mrg if (l == place_partition_off + place_partition_len) 629 1.1.1.3 mrg continue; 630 1.1.1.3 mrg } 631 1.1.1.3 mrg nthr = affinity_thr[l - team->prev_ts.place_partition_off]; 632 1.1.1.3 mrg affinity_thr[l - team->prev_ts.place_partition_off] 633 1.1.1.3 mrg = (struct gomp_thread *) nthr->data; 634 1.1.1.3 mrg affinity_count--; 635 1.1.1.3 mrg pool->threads[i] = nthr; 636 1.1.1.3 mrg } 637 1.1.1.3 mrg else 638 1.1.1.3 mrg nthr = pool->threads[i]; 639 1.1.1.3 mrg place = p + 1; 640 1.1.1.3 mrg } 641 1.1.1.3 mrg else 642 1.1.1.3 mrg nthr = pool->threads[i]; 643 1.1 mrg nthr->ts.team = team; 644 1.1 mrg nthr->ts.work_share = &team->work_shares[0]; 645 1.1 mrg nthr->ts.last_work_share = NULL; 646 1.1 mrg nthr->ts.team_id = i; 647 1.1 mrg nthr->ts.level = team->prev_ts.level + 1; 648 1.1 mrg nthr->ts.active_level = thr->ts.active_level; 649 1.1.1.3 mrg nthr->ts.place_partition_off = place_partition_off; 650 1.1.1.3 mrg nthr->ts.place_partition_len = place_partition_len; 651 1.1.1.11 mrg nthr->ts.def_allocator = thr->ts.def_allocator; 652 1.1 mrg #ifdef HAVE_SYNC_BUILTINS 653 1.1 mrg nthr->ts.single_count = 0; 654 1.1 mrg #endif 655 1.1 mrg nthr->ts.static_trip = 0; 656 1.1.1.11 mrg nthr->num_teams = thr->num_teams; 657 1.1.1.11 mrg nthr->team_num = thr->team_num; 658 1.1 mrg nthr->task = &team->implicit_task[i]; 659 1.1.1.3 mrg nthr->place = place; 660 1.1 mrg gomp_init_task (nthr->task, task, icv); 661 1.1.1.2 mrg team->implicit_task[i].icv.nthreads_var = nthreads_var; 662 1.1.1.3 mrg team->implicit_task[i].icv.bind_var = bind_var; 663 1.1.1.9 mrg nthr->task->taskgroup = taskgroup; 664 1.1 mrg nthr->fn = fn; 665 1.1 mrg nthr->data = data; 666 1.1 mrg team->ordered_release[i] = &nthr->release; 667 1.1 mrg } 668 1.1 mrg 669 1.1.1.3 mrg if (__builtin_expect (affinity_thr != NULL, 0)) 670 1.1.1.3 mrg { 671 1.1.1.3 mrg /* If AFFINITY_THR is non-NULL just because we had to 672 1.1.1.3 mrg permute some threads in the pool, but we've managed 673 1.1.1.3 mrg to find exactly as many old threads as we'd find 674 1.1.1.3 mrg without affinity, we don't need to handle this 675 1.1.1.3 mrg specially anymore. */ 676 1.1.1.3 mrg if (nthreads <= old_threads_used 677 1.1.1.3 mrg ? (affinity_count == old_threads_used - nthreads) 678 1.1.1.3 mrg : (i == old_threads_used)) 679 1.1.1.3 mrg { 680 1.1.1.3 mrg if (team->prev_ts.place_partition_len > 64) 681 1.1.1.3 mrg free (affinity_thr); 682 1.1.1.3 mrg affinity_thr = NULL; 683 1.1.1.3 mrg affinity_count = 0; 684 1.1.1.3 mrg } 685 1.1.1.3 mrg else 686 1.1.1.3 mrg { 687 1.1.1.3 mrg i = 1; 688 1.1.1.3 mrg /* We are going to compute the places/subpartitions 689 1.1.1.3 mrg again from the beginning. So, we need to reinitialize 690 1.1.1.3 mrg vars modified by the switch (bind) above inside 691 1.1.1.3 mrg of the loop, to the state they had after the initial 692 1.1.1.3 mrg switch (bind). */ 693 1.1.1.3 mrg switch (bind) 694 1.1.1.3 mrg { 695 1.1.1.3 mrg case omp_proc_bind_true: 696 1.1.1.3 mrg case omp_proc_bind_close: 697 1.1.1.3 mrg if (nthreads > thr->ts.place_partition_len) 698 1.1.1.3 mrg /* T > P. S has been changed, so needs 699 1.1.1.3 mrg to be recomputed. */ 700 1.1.1.3 mrg s = nthreads / thr->ts.place_partition_len; 701 1.1.1.3 mrg k = 1; 702 1.1.1.3 mrg p = thr->place - 1; 703 1.1.1.3 mrg break; 704 1.1.1.3 mrg case omp_proc_bind_master: 705 1.1.1.3 mrg /* No vars have been changed. */ 706 1.1.1.3 mrg break; 707 1.1.1.3 mrg case omp_proc_bind_spread: 708 1.1.1.3 mrg p = thr->ts.place_partition_off; 709 1.1.1.3 mrg if (k != 0) 710 1.1.1.3 mrg { 711 1.1.1.3 mrg /* T > P. */ 712 1.1.1.3 mrg s = nthreads / team->prev_ts.place_partition_len; 713 1.1.1.3 mrg k = 1; 714 1.1.1.3 mrg } 715 1.1.1.3 mrg break; 716 1.1.1.3 mrg } 717 1.1.1.3 mrg 718 1.1.1.3 mrg /* Increase the barrier threshold to make sure all new 719 1.1.1.3 mrg threads and all the threads we're going to let die 720 1.1.1.3 mrg arrive before the team is released. */ 721 1.1.1.3 mrg if (affinity_count) 722 1.1.1.5 mrg gomp_simple_barrier_reinit (&pool->threads_dock, 723 1.1.1.5 mrg nthreads + affinity_count); 724 1.1.1.3 mrg } 725 1.1.1.3 mrg } 726 1.1.1.3 mrg 727 1.1 mrg if (i == nthreads) 728 1.1 mrg goto do_release; 729 1.1 mrg 730 1.1 mrg } 731 1.1 mrg 732 1.1.1.3 mrg if (__builtin_expect (nthreads + affinity_count > old_threads_used, 0)) 733 1.1 mrg { 734 1.1.1.3 mrg long diff = (long) (nthreads + affinity_count) - (long) old_threads_used; 735 1.1 mrg 736 1.1 mrg if (old_threads_used == 0) 737 1.1 mrg --diff; 738 1.1 mrg 739 1.1 mrg #ifdef HAVE_SYNC_BUILTINS 740 1.1 mrg __sync_fetch_and_add (&gomp_managed_threads, diff); 741 1.1 mrg #else 742 1.1.1.3 mrg gomp_mutex_lock (&gomp_managed_threads_lock); 743 1.1 mrg gomp_managed_threads += diff; 744 1.1.1.3 mrg gomp_mutex_unlock (&gomp_managed_threads_lock); 745 1.1 mrg #endif 746 1.1 mrg } 747 1.1 mrg 748 1.1 mrg attr = &gomp_thread_attr; 749 1.1.1.3 mrg if (__builtin_expect (gomp_places_list != NULL, 0)) 750 1.1 mrg { 751 1.1 mrg size_t stacksize; 752 1.1 mrg pthread_attr_init (&thread_attr); 753 1.1 mrg if (! pthread_attr_getstacksize (&gomp_thread_attr, &stacksize)) 754 1.1 mrg pthread_attr_setstacksize (&thread_attr, stacksize); 755 1.1 mrg attr = &thread_attr; 756 1.1 mrg } 757 1.1 mrg 758 1.1.1.12 mrg if (i >= nthreads) 759 1.1.1.12 mrg __builtin_unreachable (); 760 1.1 mrg start_data = gomp_alloca (sizeof (struct gomp_thread_start_data) 761 1.1.1.9 mrg * (nthreads - i)); 762 1.1 mrg 763 1.1 mrg /* Launch new threads. */ 764 1.1.1.3 mrg for (; i < nthreads; ++i) 765 1.1 mrg { 766 1.1 mrg int err; 767 1.1 mrg 768 1.1.1.3 mrg start_data->ts.place_partition_off = thr->ts.place_partition_off; 769 1.1.1.3 mrg start_data->ts.place_partition_len = thr->ts.place_partition_len; 770 1.1.1.3 mrg start_data->place = 0; 771 1.1.1.3 mrg if (__builtin_expect (gomp_places_list != NULL, 0)) 772 1.1.1.3 mrg { 773 1.1.1.3 mrg switch (bind) 774 1.1.1.3 mrg { 775 1.1.1.3 mrg case omp_proc_bind_true: 776 1.1.1.3 mrg case omp_proc_bind_close: 777 1.1.1.3 mrg if (k == s) 778 1.1.1.3 mrg { 779 1.1.1.3 mrg ++p; 780 1.1.1.3 mrg if (p == (team->prev_ts.place_partition_off 781 1.1.1.3 mrg + team->prev_ts.place_partition_len)) 782 1.1.1.3 mrg p = team->prev_ts.place_partition_off; 783 1.1.1.3 mrg k = 1; 784 1.1.1.3 mrg if (i == nthreads - rest) 785 1.1.1.3 mrg s = 1; 786 1.1.1.3 mrg } 787 1.1.1.3 mrg else 788 1.1.1.3 mrg ++k; 789 1.1.1.3 mrg break; 790 1.1.1.3 mrg case omp_proc_bind_master: 791 1.1.1.3 mrg break; 792 1.1.1.3 mrg case omp_proc_bind_spread: 793 1.1.1.3 mrg if (k == 0) 794 1.1.1.3 mrg { 795 1.1.1.3 mrg /* T <= P. */ 796 1.1.1.3 mrg if (p < rest) 797 1.1.1.3 mrg p += s + 1; 798 1.1.1.3 mrg else 799 1.1.1.3 mrg p += s; 800 1.1.1.3 mrg if (p == (team->prev_ts.place_partition_off 801 1.1.1.3 mrg + team->prev_ts.place_partition_len)) 802 1.1.1.3 mrg p = team->prev_ts.place_partition_off; 803 1.1.1.3 mrg start_data->ts.place_partition_off = p; 804 1.1.1.3 mrg if (p < rest) 805 1.1.1.3 mrg start_data->ts.place_partition_len = s + 1; 806 1.1.1.3 mrg else 807 1.1.1.3 mrg start_data->ts.place_partition_len = s; 808 1.1.1.3 mrg } 809 1.1.1.3 mrg else 810 1.1.1.3 mrg { 811 1.1.1.3 mrg /* T > P. */ 812 1.1.1.3 mrg if (k == s) 813 1.1.1.3 mrg { 814 1.1.1.3 mrg ++p; 815 1.1.1.3 mrg if (p == (team->prev_ts.place_partition_off 816 1.1.1.3 mrg + team->prev_ts.place_partition_len)) 817 1.1.1.3 mrg p = team->prev_ts.place_partition_off; 818 1.1.1.3 mrg k = 1; 819 1.1.1.3 mrg if (i == nthreads - rest) 820 1.1.1.3 mrg s = 1; 821 1.1.1.3 mrg } 822 1.1.1.3 mrg else 823 1.1.1.3 mrg ++k; 824 1.1.1.3 mrg start_data->ts.place_partition_off = p; 825 1.1.1.3 mrg start_data->ts.place_partition_len = 1; 826 1.1.1.3 mrg } 827 1.1.1.3 mrg break; 828 1.1.1.3 mrg } 829 1.1.1.3 mrg start_data->place = p + 1; 830 1.1.1.3 mrg if (affinity_thr != NULL && pool->threads[i] != NULL) 831 1.1.1.3 mrg continue; 832 1.1.1.3 mrg gomp_init_thread_affinity (attr, p); 833 1.1.1.3 mrg } 834 1.1.1.3 mrg 835 1.1 mrg start_data->fn = fn; 836 1.1 mrg start_data->fn_data = data; 837 1.1 mrg start_data->ts.team = team; 838 1.1 mrg start_data->ts.work_share = &team->work_shares[0]; 839 1.1 mrg start_data->ts.last_work_share = NULL; 840 1.1 mrg start_data->ts.team_id = i; 841 1.1 mrg start_data->ts.level = team->prev_ts.level + 1; 842 1.1 mrg start_data->ts.active_level = thr->ts.active_level; 843 1.1.1.11 mrg start_data->ts.def_allocator = thr->ts.def_allocator; 844 1.1 mrg #ifdef HAVE_SYNC_BUILTINS 845 1.1 mrg start_data->ts.single_count = 0; 846 1.1 mrg #endif 847 1.1 mrg start_data->ts.static_trip = 0; 848 1.1.1.11 mrg start_data->num_teams = thr->num_teams; 849 1.1.1.11 mrg start_data->team_num = thr->team_num; 850 1.1 mrg start_data->task = &team->implicit_task[i]; 851 1.1 mrg gomp_init_task (start_data->task, task, icv); 852 1.1.1.2 mrg team->implicit_task[i].icv.nthreads_var = nthreads_var; 853 1.1.1.3 mrg team->implicit_task[i].icv.bind_var = bind_var; 854 1.1.1.9 mrg start_data->task->taskgroup = taskgroup; 855 1.1 mrg start_data->thread_pool = pool; 856 1.1 mrg start_data->nested = nested; 857 1.1 mrg 858 1.1.1.4 mrg attr = gomp_adjust_thread_attr (attr, &thread_attr); 859 1.1.1.9 mrg err = pthread_create (&start_data->handle, attr, gomp_thread_start, 860 1.1.1.9 mrg start_data); 861 1.1.1.9 mrg start_data++; 862 1.1 mrg if (err != 0) 863 1.1 mrg gomp_fatal ("Thread creation failed: %s", strerror (err)); 864 1.1 mrg } 865 1.1 mrg 866 1.1.1.4 mrg if (__builtin_expect (attr == &thread_attr, 0)) 867 1.1 mrg pthread_attr_destroy (&thread_attr); 868 1.1 mrg 869 1.1 mrg do_release: 870 1.1.1.5 mrg if (nested) 871 1.1.1.5 mrg gomp_barrier_wait (&team->barrier); 872 1.1.1.5 mrg else 873 1.1.1.5 mrg gomp_simple_barrier_wait (&pool->threads_dock); 874 1.1 mrg 875 1.1 mrg /* Decrease the barrier threshold to match the number of threads 876 1.1 mrg that should arrive back at the end of this team. The extra 877 1.1 mrg threads should be exiting. Note that we arrange for this test 878 1.1.1.3 mrg to never be true for nested teams. If AFFINITY_COUNT is non-zero, 879 1.1.1.3 mrg the barrier as well as gomp_managed_threads was temporarily 880 1.1.1.3 mrg set to NTHREADS + AFFINITY_COUNT. For NTHREADS < OLD_THREADS_COUNT, 881 1.1.1.3 mrg AFFINITY_COUNT if non-zero will be always at least 882 1.1.1.3 mrg OLD_THREADS_COUNT - NTHREADS. */ 883 1.1.1.3 mrg if (__builtin_expect (nthreads < old_threads_used, 0) 884 1.1.1.3 mrg || __builtin_expect (affinity_count, 0)) 885 1.1 mrg { 886 1.1 mrg long diff = (long) nthreads - (long) old_threads_used; 887 1.1 mrg 888 1.1.1.3 mrg if (affinity_count) 889 1.1.1.3 mrg diff = -affinity_count; 890 1.1.1.3 mrg 891 1.1.1.5 mrg gomp_simple_barrier_reinit (&pool->threads_dock, nthreads); 892 1.1 mrg 893 1.1 mrg #ifdef HAVE_SYNC_BUILTINS 894 1.1 mrg __sync_fetch_and_add (&gomp_managed_threads, diff); 895 1.1 mrg #else 896 1.1.1.3 mrg gomp_mutex_lock (&gomp_managed_threads_lock); 897 1.1 mrg gomp_managed_threads += diff; 898 1.1.1.3 mrg gomp_mutex_unlock (&gomp_managed_threads_lock); 899 1.1 mrg #endif 900 1.1 mrg } 901 1.1.1.9 mrg if (__builtin_expect (gomp_display_affinity_var, 0)) 902 1.1.1.9 mrg { 903 1.1.1.9 mrg if (nested 904 1.1.1.9 mrg || nthreads != old_threads_used 905 1.1.1.9 mrg || force_display) 906 1.1.1.9 mrg { 907 1.1.1.9 mrg gomp_display_affinity_thread (gomp_thread_self (), &thr->ts, 908 1.1.1.9 mrg thr->place); 909 1.1.1.9 mrg if (nested) 910 1.1.1.9 mrg { 911 1.1.1.9 mrg start_data -= nthreads - 1; 912 1.1.1.9 mrg for (i = 1; i < nthreads; ++i) 913 1.1.1.9 mrg { 914 1.1.1.9 mrg gomp_display_affinity_thread ( 915 1.1.1.9 mrg #ifdef LIBGOMP_USE_PTHREADS 916 1.1.1.9 mrg start_data->handle, 917 1.1.1.9 mrg #else 918 1.1.1.9 mrg gomp_thread_self (), 919 1.1.1.9 mrg #endif 920 1.1.1.9 mrg &start_data->ts, 921 1.1.1.9 mrg start_data->place); 922 1.1.1.9 mrg start_data++; 923 1.1.1.9 mrg } 924 1.1.1.9 mrg } 925 1.1.1.9 mrg else 926 1.1.1.9 mrg { 927 1.1.1.9 mrg for (i = 1; i < nthreads; ++i) 928 1.1.1.9 mrg { 929 1.1.1.9 mrg gomp_thread_handle handle 930 1.1.1.9 mrg = gomp_thread_to_pthread_t (pool->threads[i]); 931 1.1.1.9 mrg gomp_display_affinity_thread (handle, &pool->threads[i]->ts, 932 1.1.1.9 mrg pool->threads[i]->place); 933 1.1.1.9 mrg } 934 1.1.1.9 mrg } 935 1.1.1.9 mrg } 936 1.1.1.9 mrg } 937 1.1.1.3 mrg if (__builtin_expect (affinity_thr != NULL, 0) 938 1.1.1.3 mrg && team->prev_ts.place_partition_len > 64) 939 1.1.1.3 mrg free (affinity_thr); 940 1.1 mrg } 941 1.1.1.5 mrg #endif 942 1.1 mrg 943 1.1 mrg 944 1.1 mrg /* Terminate the current team. This is only to be called by the master 945 1.1 mrg thread. We assume that we must wait for the other threads. */ 946 1.1 mrg 947 1.1 mrg void 948 1.1 mrg gomp_team_end (void) 949 1.1 mrg { 950 1.1 mrg struct gomp_thread *thr = gomp_thread (); 951 1.1 mrg struct gomp_team *team = thr->ts.team; 952 1.1 mrg 953 1.1.1.3 mrg /* This barrier handles all pending explicit threads. 954 1.1.1.3 mrg As #pragma omp cancel parallel might get awaited count in 955 1.1.1.3 mrg team->barrier in a inconsistent state, we need to use a different 956 1.1.1.3 mrg counter here. */ 957 1.1.1.3 mrg gomp_team_barrier_wait_final (&team->barrier); 958 1.1.1.3 mrg if (__builtin_expect (team->team_cancelled, 0)) 959 1.1.1.3 mrg { 960 1.1.1.3 mrg struct gomp_work_share *ws = team->work_shares_to_free; 961 1.1.1.3 mrg do 962 1.1.1.3 mrg { 963 1.1.1.3 mrg struct gomp_work_share *next_ws = gomp_ptrlock_get (&ws->next_ws); 964 1.1.1.3 mrg if (next_ws == NULL) 965 1.1.1.3 mrg gomp_ptrlock_set (&ws->next_ws, ws); 966 1.1.1.3 mrg gomp_fini_work_share (ws); 967 1.1.1.3 mrg ws = next_ws; 968 1.1.1.3 mrg } 969 1.1.1.3 mrg while (ws != NULL); 970 1.1.1.3 mrg } 971 1.1.1.3 mrg else 972 1.1.1.3 mrg gomp_fini_work_share (thr->ts.work_share); 973 1.1 mrg 974 1.1 mrg gomp_end_task (); 975 1.1 mrg thr->ts = team->prev_ts; 976 1.1 mrg 977 1.1.1.9 mrg if (__builtin_expect (thr->ts.level != 0, 0)) 978 1.1 mrg { 979 1.1 mrg #ifdef HAVE_SYNC_BUILTINS 980 1.1 mrg __sync_fetch_and_add (&gomp_managed_threads, 1L - team->nthreads); 981 1.1 mrg #else 982 1.1.1.3 mrg gomp_mutex_lock (&gomp_managed_threads_lock); 983 1.1 mrg gomp_managed_threads -= team->nthreads - 1L; 984 1.1.1.3 mrg gomp_mutex_unlock (&gomp_managed_threads_lock); 985 1.1 mrg #endif 986 1.1 mrg /* This barrier has gomp_barrier_wait_last counterparts 987 1.1 mrg and ensures the team can be safely destroyed. */ 988 1.1 mrg gomp_barrier_wait (&team->barrier); 989 1.1 mrg } 990 1.1 mrg 991 1.1 mrg if (__builtin_expect (team->work_shares[0].next_alloc != NULL, 0)) 992 1.1 mrg { 993 1.1 mrg struct gomp_work_share *ws = team->work_shares[0].next_alloc; 994 1.1 mrg do 995 1.1 mrg { 996 1.1 mrg struct gomp_work_share *next_ws = ws->next_alloc; 997 1.1 mrg free (ws); 998 1.1 mrg ws = next_ws; 999 1.1 mrg } 1000 1.1 mrg while (ws != NULL); 1001 1.1 mrg } 1002 1.1 mrg gomp_sem_destroy (&team->master_release); 1003 1.1 mrg 1004 1.1 mrg if (__builtin_expect (thr->ts.team != NULL, 0) 1005 1.1 mrg || __builtin_expect (team->nthreads == 1, 0)) 1006 1.1 mrg free_team (team); 1007 1.1 mrg else 1008 1.1 mrg { 1009 1.1 mrg struct gomp_thread_pool *pool = thr->thread_pool; 1010 1.1 mrg if (pool->last_team) 1011 1.1 mrg free_team (pool->last_team); 1012 1.1 mrg pool->last_team = team; 1013 1.1.1.4 mrg gomp_release_thread_pool (pool); 1014 1.1 mrg } 1015 1.1 mrg } 1016 1.1 mrg 1017 1.1.1.5 mrg #ifdef LIBGOMP_USE_PTHREADS 1018 1.1 mrg 1019 1.1 mrg /* Constructors for this file. */ 1020 1.1 mrg 1021 1.1 mrg static void __attribute__((constructor)) 1022 1.1 mrg initialize_team (void) 1023 1.1 mrg { 1024 1.1.1.3 mrg #if !defined HAVE_TLS && !defined USE_EMUTLS 1025 1.1 mrg static struct gomp_thread initial_thread_tls_data; 1026 1.1 mrg 1027 1.1 mrg pthread_key_create (&gomp_tls_key, NULL); 1028 1.1 mrg pthread_setspecific (gomp_tls_key, &initial_thread_tls_data); 1029 1.1 mrg #endif 1030 1.1 mrg 1031 1.1 mrg if (pthread_key_create (&gomp_thread_destructor, gomp_free_thread) != 0) 1032 1.1 mrg gomp_fatal ("could not create thread pool destructor."); 1033 1.1 mrg } 1034 1.1 mrg 1035 1.1 mrg static void __attribute__((destructor)) 1036 1.1 mrg team_destructor (void) 1037 1.1 mrg { 1038 1.1 mrg /* Without this dlclose on libgomp could lead to subsequent 1039 1.1 mrg crashes. */ 1040 1.1 mrg pthread_key_delete (gomp_thread_destructor); 1041 1.1 mrg } 1042 1.1.1.9 mrg 1043 1.1.1.9 mrg /* Similar to gomp_free_pool_helper, but don't detach itself, 1044 1.1.1.9 mrg gomp_pause_host will pthread_join those threads. */ 1045 1.1.1.9 mrg 1046 1.1.1.9 mrg static void 1047 1.1.1.9 mrg gomp_pause_pool_helper (void *thread_pool) 1048 1.1.1.9 mrg { 1049 1.1.1.9 mrg struct gomp_thread *thr = gomp_thread (); 1050 1.1.1.9 mrg struct gomp_thread_pool *pool 1051 1.1.1.9 mrg = (struct gomp_thread_pool *) thread_pool; 1052 1.1.1.9 mrg gomp_simple_barrier_wait_last (&pool->threads_dock); 1053 1.1.1.9 mrg gomp_sem_destroy (&thr->release); 1054 1.1.1.9 mrg thr->thread_pool = NULL; 1055 1.1.1.9 mrg thr->task = NULL; 1056 1.1.1.9 mrg pthread_exit (NULL); 1057 1.1.1.9 mrg } 1058 1.1.1.9 mrg 1059 1.1.1.9 mrg /* Free a thread pool and release its threads. Return non-zero on 1060 1.1.1.9 mrg failure. */ 1061 1.1.1.9 mrg 1062 1.1.1.9 mrg int 1063 1.1.1.9 mrg gomp_pause_host (void) 1064 1.1.1.9 mrg { 1065 1.1.1.9 mrg struct gomp_thread *thr = gomp_thread (); 1066 1.1.1.9 mrg struct gomp_thread_pool *pool = thr->thread_pool; 1067 1.1.1.9 mrg if (thr->ts.level) 1068 1.1.1.9 mrg return -1; 1069 1.1.1.9 mrg if (pool) 1070 1.1.1.9 mrg { 1071 1.1.1.9 mrg if (pool->threads_used > 0) 1072 1.1.1.9 mrg { 1073 1.1.1.9 mrg int i; 1074 1.1.1.9 mrg pthread_t *thrs 1075 1.1.1.9 mrg = gomp_alloca (sizeof (pthread_t) * pool->threads_used); 1076 1.1.1.9 mrg for (i = 1; i < pool->threads_used; i++) 1077 1.1.1.9 mrg { 1078 1.1.1.9 mrg struct gomp_thread *nthr = pool->threads[i]; 1079 1.1.1.9 mrg nthr->fn = gomp_pause_pool_helper; 1080 1.1.1.9 mrg nthr->data = pool; 1081 1.1.1.9 mrg thrs[i] = gomp_thread_to_pthread_t (nthr); 1082 1.1.1.9 mrg } 1083 1.1.1.9 mrg /* This barrier undocks threads docked on pool->threads_dock. */ 1084 1.1.1.9 mrg gomp_simple_barrier_wait (&pool->threads_dock); 1085 1.1.1.9 mrg /* And this waits till all threads have called gomp_barrier_wait_last 1086 1.1.1.9 mrg in gomp_pause_pool_helper. */ 1087 1.1.1.9 mrg gomp_simple_barrier_wait (&pool->threads_dock); 1088 1.1.1.9 mrg /* Now it is safe to destroy the barrier and free the pool. */ 1089 1.1.1.9 mrg gomp_simple_barrier_destroy (&pool->threads_dock); 1090 1.1.1.9 mrg 1091 1.1.1.9 mrg #ifdef HAVE_SYNC_BUILTINS 1092 1.1.1.9 mrg __sync_fetch_and_add (&gomp_managed_threads, 1093 1.1.1.9 mrg 1L - pool->threads_used); 1094 1.1.1.9 mrg #else 1095 1.1.1.9 mrg gomp_mutex_lock (&gomp_managed_threads_lock); 1096 1.1.1.9 mrg gomp_managed_threads -= pool->threads_used - 1L; 1097 1.1.1.9 mrg gomp_mutex_unlock (&gomp_managed_threads_lock); 1098 1.1.1.9 mrg #endif 1099 1.1.1.9 mrg for (i = 1; i < pool->threads_used; i++) 1100 1.1.1.9 mrg pthread_join (thrs[i], NULL); 1101 1.1.1.9 mrg } 1102 1.1.1.9 mrg if (pool->last_team) 1103 1.1.1.9 mrg free_team (pool->last_team); 1104 1.1.1.9 mrg #ifndef __nvptx__ 1105 1.1.1.10 mrg team_free (pool->threads); 1106 1.1.1.10 mrg team_free (pool); 1107 1.1.1.9 mrg #endif 1108 1.1.1.9 mrg thr->thread_pool = NULL; 1109 1.1.1.9 mrg } 1110 1.1.1.9 mrg return 0; 1111 1.1.1.9 mrg } 1112 1.1.1.5 mrg #endif 1113 1.1 mrg 1114 1.1 mrg struct gomp_task_icv * 1115 1.1 mrg gomp_new_icv (void) 1116 1.1 mrg { 1117 1.1 mrg struct gomp_thread *thr = gomp_thread (); 1118 1.1 mrg struct gomp_task *task = gomp_malloc (sizeof (struct gomp_task)); 1119 1.1 mrg gomp_init_task (task, NULL, &gomp_global_icv); 1120 1.1 mrg thr->task = task; 1121 1.1.1.5 mrg #ifdef LIBGOMP_USE_PTHREADS 1122 1.1 mrg pthread_setspecific (gomp_thread_destructor, thr); 1123 1.1.1.5 mrg #endif 1124 1.1 mrg return &task->icv; 1125 1.1 mrg } 1126