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