Home | History | Annotate | Line # | Download | only in libgomp
      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