Home | History | Annotate | Line # | Download | only in libgomp
      1  1.1.1.14  mrg /* Copyright (C) 2007-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 tasks in response to task
     27       1.1  mrg    creation and termination.  */
     28       1.1  mrg 
     29       1.1  mrg #include "libgomp.h"
     30       1.1  mrg #include <stdlib.h>
     31       1.1  mrg #include <string.h>
     32  1.1.1.13  mrg #include <assert.h>
     33   1.1.1.4  mrg #include "gomp-constants.h"
     34       1.1  mrg 
     35   1.1.1.3  mrg typedef struct gomp_task_depend_entry *hash_entry_type;
     36   1.1.1.3  mrg 
     37   1.1.1.3  mrg static inline void *
     38   1.1.1.3  mrg htab_alloc (size_t size)
     39   1.1.1.3  mrg {
     40   1.1.1.3  mrg   return gomp_malloc (size);
     41   1.1.1.3  mrg }
     42   1.1.1.3  mrg 
     43   1.1.1.3  mrg static inline void
     44   1.1.1.3  mrg htab_free (void *ptr)
     45   1.1.1.3  mrg {
     46   1.1.1.3  mrg   free (ptr);
     47   1.1.1.3  mrg }
     48   1.1.1.3  mrg 
     49   1.1.1.3  mrg #include "hashtab.h"
     50   1.1.1.3  mrg 
     51   1.1.1.3  mrg static inline hashval_t
     52   1.1.1.3  mrg htab_hash (hash_entry_type element)
     53   1.1.1.3  mrg {
     54   1.1.1.3  mrg   return hash_pointer (element->addr);
     55   1.1.1.3  mrg }
     56   1.1.1.3  mrg 
     57   1.1.1.3  mrg static inline bool
     58   1.1.1.3  mrg htab_eq (hash_entry_type x, hash_entry_type y)
     59   1.1.1.3  mrg {
     60   1.1.1.3  mrg   return x->addr == y->addr;
     61   1.1.1.3  mrg }
     62       1.1  mrg 
     63       1.1  mrg /* Create a new task data structure.  */
     64       1.1  mrg 
     65       1.1  mrg void
     66       1.1  mrg gomp_init_task (struct gomp_task *task, struct gomp_task *parent_task,
     67       1.1  mrg 		struct gomp_task_icv *prev_icv)
     68       1.1  mrg {
     69   1.1.1.4  mrg   /* It would seem that using memset here would be a win, but it turns
     70   1.1.1.4  mrg      out that partially filling gomp_task allows us to keep the
     71   1.1.1.4  mrg      overhead of task creation low.  In the nqueens-1.c test, for a
     72   1.1.1.4  mrg      sufficiently large N, we drop the overhead from 5-6% to 1%.
     73   1.1.1.4  mrg 
     74   1.1.1.4  mrg      Note, the nqueens-1.c test in serial mode is a good test to
     75   1.1.1.4  mrg      benchmark the overhead of creating tasks as there are millions of
     76   1.1.1.4  mrg      tiny tasks created that all run undeferred.  */
     77       1.1  mrg   task->parent = parent_task;
     78  1.1.1.13  mrg   priority_queue_init (&task->children_queue);
     79  1.1.1.13  mrg   task->taskgroup = NULL;
     80  1.1.1.13  mrg   task->dependers = NULL;
     81  1.1.1.13  mrg   task->depend_hash = NULL;
     82  1.1.1.13  mrg   task->taskwait = NULL;
     83  1.1.1.14  mrg   task->depend_all_memory = NULL;
     84  1.1.1.13  mrg   task->depend_count = 0;
     85  1.1.1.13  mrg   task->completion_sem = NULL;
     86  1.1.1.13  mrg   task->deferred_p = false;
     87       1.1  mrg   task->icv = *prev_icv;
     88       1.1  mrg   task->kind = GOMP_TASK_IMPLICIT;
     89       1.1  mrg   task->in_tied_task = false;
     90   1.1.1.2  mrg   task->final_task = false;
     91   1.1.1.3  mrg   task->copy_ctors_done = false;
     92   1.1.1.3  mrg   task->parent_depends_on = false;
     93       1.1  mrg }
     94       1.1  mrg 
     95       1.1  mrg /* Clean up a task, after completing it.  */
     96       1.1  mrg 
     97       1.1  mrg void
     98       1.1  mrg gomp_end_task (void)
     99       1.1  mrg {
    100       1.1  mrg   struct gomp_thread *thr = gomp_thread ();
    101       1.1  mrg   struct gomp_task *task = thr->task;
    102       1.1  mrg 
    103       1.1  mrg   gomp_finish_task (task);
    104       1.1  mrg   thr->task = task->parent;
    105       1.1  mrg }
    106       1.1  mrg 
    107   1.1.1.4  mrg /* Clear the parent field of every task in LIST.  */
    108   1.1.1.4  mrg 
    109       1.1  mrg static inline void
    110   1.1.1.4  mrg gomp_clear_parent_in_list (struct priority_list *list)
    111       1.1  mrg {
    112   1.1.1.4  mrg   struct priority_node *p = list->tasks;
    113   1.1.1.4  mrg   if (p)
    114       1.1  mrg     do
    115       1.1  mrg       {
    116   1.1.1.4  mrg 	priority_node_to_task (PQ_CHILDREN, p)->parent = NULL;
    117   1.1.1.4  mrg 	p = p->next;
    118       1.1  mrg       }
    119   1.1.1.4  mrg     while (p != list->tasks);
    120   1.1.1.4  mrg }
    121   1.1.1.4  mrg 
    122   1.1.1.4  mrg /* Splay tree version of gomp_clear_parent_in_list.
    123   1.1.1.4  mrg 
    124   1.1.1.4  mrg    Clear the parent field of every task in NODE within SP, and free
    125   1.1.1.4  mrg    the node when done.  */
    126   1.1.1.4  mrg 
    127   1.1.1.4  mrg static void
    128   1.1.1.4  mrg gomp_clear_parent_in_tree (prio_splay_tree sp, prio_splay_tree_node node)
    129   1.1.1.4  mrg {
    130   1.1.1.4  mrg   if (!node)
    131   1.1.1.4  mrg     return;
    132   1.1.1.4  mrg   prio_splay_tree_node left = node->left, right = node->right;
    133   1.1.1.4  mrg   gomp_clear_parent_in_list (&node->key.l);
    134   1.1.1.4  mrg #if _LIBGOMP_CHECKING_
    135   1.1.1.4  mrg   memset (node, 0xaf, sizeof (*node));
    136   1.1.1.4  mrg #endif
    137   1.1.1.4  mrg   /* No need to remove the node from the tree.  We're nuking
    138   1.1.1.4  mrg      everything, so just free the nodes and our caller can clear the
    139   1.1.1.4  mrg      entire splay tree.  */
    140   1.1.1.4  mrg   free (node);
    141   1.1.1.4  mrg   gomp_clear_parent_in_tree (sp, left);
    142   1.1.1.4  mrg   gomp_clear_parent_in_tree (sp, right);
    143   1.1.1.4  mrg }
    144   1.1.1.4  mrg 
    145   1.1.1.4  mrg /* Clear the parent field of every task in Q and remove every task
    146   1.1.1.4  mrg    from Q.  */
    147   1.1.1.4  mrg 
    148   1.1.1.4  mrg static inline void
    149   1.1.1.4  mrg gomp_clear_parent (struct priority_queue *q)
    150   1.1.1.4  mrg {
    151   1.1.1.4  mrg   if (priority_queue_multi_p (q))
    152   1.1.1.4  mrg     {
    153   1.1.1.4  mrg       gomp_clear_parent_in_tree (&q->t, q->t.root);
    154   1.1.1.4  mrg       /* All the nodes have been cleared in gomp_clear_parent_in_tree.
    155   1.1.1.4  mrg 	 No need to remove anything.  We can just nuke everything.  */
    156   1.1.1.4  mrg       q->t.root = NULL;
    157   1.1.1.4  mrg     }
    158   1.1.1.4  mrg   else
    159   1.1.1.4  mrg     gomp_clear_parent_in_list (&q->l);
    160       1.1  mrg }
    161       1.1  mrg 
    162   1.1.1.4  mrg /* Helper function for GOMP_task and gomp_create_target_task.
    163   1.1.1.4  mrg 
    164   1.1.1.4  mrg    For a TASK with in/out dependencies, fill in the various dependency
    165   1.1.1.4  mrg    queues.  PARENT is the parent of said task.  DEPEND is as in
    166   1.1.1.4  mrg    GOMP_task.  */
    167   1.1.1.4  mrg 
    168   1.1.1.4  mrg static void
    169   1.1.1.4  mrg gomp_task_handle_depend (struct gomp_task *task, struct gomp_task *parent,
    170   1.1.1.4  mrg 			 void **depend)
    171   1.1.1.4  mrg {
    172   1.1.1.4  mrg   size_t ndepend = (uintptr_t) depend[0];
    173   1.1.1.4  mrg   size_t i;
    174   1.1.1.4  mrg   hash_entry_type ent;
    175  1.1.1.14  mrg   bool all_memory = false;
    176   1.1.1.4  mrg 
    177   1.1.1.9  mrg   if (ndepend)
    178   1.1.1.9  mrg     {
    179   1.1.1.9  mrg       /* depend[0] is total # */
    180   1.1.1.9  mrg       size_t nout = (uintptr_t) depend[1]; /* # of out: and inout: */
    181   1.1.1.9  mrg       /* ndepend - nout is # of in: */
    182   1.1.1.9  mrg       for (i = 0; i < ndepend; i++)
    183   1.1.1.9  mrg 	{
    184   1.1.1.9  mrg 	  task->depend[i].addr = depend[2 + i];
    185   1.1.1.9  mrg 	  task->depend[i].is_in = i >= nout;
    186  1.1.1.14  mrg 	  all_memory |= i < nout && depend[2 + i] == NULL;
    187   1.1.1.9  mrg 	}
    188   1.1.1.9  mrg     }
    189   1.1.1.9  mrg   else
    190   1.1.1.9  mrg     {
    191   1.1.1.9  mrg       ndepend = (uintptr_t) depend[1]; /* total # */
    192   1.1.1.9  mrg       size_t nout = (uintptr_t) depend[2]; /* # of out: and inout: */
    193   1.1.1.9  mrg       size_t nmutexinoutset = (uintptr_t) depend[3]; /* # of mutexinoutset: */
    194   1.1.1.9  mrg       /* For now we treat mutexinoutset like out, which is compliant, but
    195   1.1.1.9  mrg 	 inefficient.  */
    196   1.1.1.9  mrg       size_t nin = (uintptr_t) depend[4]; /* # of in: */
    197   1.1.1.9  mrg       /* ndepend - nout - nmutexinoutset - nin is # of depobjs */
    198   1.1.1.9  mrg       size_t normal = nout + nmutexinoutset + nin;
    199   1.1.1.9  mrg       size_t n = 0;
    200  1.1.1.14  mrg       bool has_in = false;
    201   1.1.1.9  mrg       for (i = normal; i < ndepend; i++)
    202   1.1.1.9  mrg 	{
    203   1.1.1.9  mrg 	  void **d = (void **) (uintptr_t) depend[5 + i];
    204   1.1.1.9  mrg 	  switch ((uintptr_t) d[1])
    205   1.1.1.9  mrg 	    {
    206   1.1.1.9  mrg 	    case GOMP_DEPEND_OUT:
    207   1.1.1.9  mrg 	    case GOMP_DEPEND_INOUT:
    208  1.1.1.14  mrg 	      all_memory |= d[0] == NULL;
    209  1.1.1.14  mrg 	      break;
    210   1.1.1.9  mrg 	    case GOMP_DEPEND_MUTEXINOUTSET:
    211   1.1.1.9  mrg 	      break;
    212   1.1.1.9  mrg 	    case GOMP_DEPEND_IN:
    213  1.1.1.14  mrg 	    case GOMP_DEPEND_INOUTSET:
    214  1.1.1.14  mrg 	      has_in = true;
    215   1.1.1.9  mrg 	      continue;
    216   1.1.1.9  mrg 	    default:
    217   1.1.1.9  mrg 	      gomp_fatal ("unknown omp_depend_t dependence type %d",
    218   1.1.1.9  mrg 			  (int) (uintptr_t) d[1]);
    219   1.1.1.9  mrg 	    }
    220   1.1.1.9  mrg 	  task->depend[n].addr = d[0];
    221   1.1.1.9  mrg 	  task->depend[n++].is_in = 0;
    222   1.1.1.9  mrg 	}
    223   1.1.1.9  mrg       for (i = 0; i < normal; i++)
    224   1.1.1.9  mrg 	{
    225   1.1.1.9  mrg 	  task->depend[n].addr = depend[5 + i];
    226   1.1.1.9  mrg 	  task->depend[n++].is_in = i >= nout + nmutexinoutset;
    227   1.1.1.9  mrg 	}
    228  1.1.1.14  mrg       if (has_in)
    229  1.1.1.14  mrg 	for (i = normal; i < ndepend; i++)
    230  1.1.1.14  mrg 	  {
    231  1.1.1.14  mrg 	    void **d = (void **) (uintptr_t) depend[5 + i];
    232  1.1.1.14  mrg 	    if ((uintptr_t) d[1] != GOMP_DEPEND_IN
    233  1.1.1.14  mrg 		&& (uintptr_t) d[1] != GOMP_DEPEND_INOUTSET)
    234  1.1.1.14  mrg 	      continue;
    235  1.1.1.14  mrg 	    task->depend[n].addr = d[0];
    236  1.1.1.14  mrg 	    task->depend[n++].is_in
    237  1.1.1.14  mrg 	      = 1 + ((uintptr_t) d[1] == GOMP_DEPEND_INOUTSET);
    238  1.1.1.14  mrg 	  }
    239  1.1.1.14  mrg     }
    240  1.1.1.14  mrg   task->num_dependees = 0;
    241  1.1.1.14  mrg   if (__builtin_expect (parent->depend_all_memory && ndepend, false))
    242  1.1.1.14  mrg     {
    243  1.1.1.14  mrg       struct gomp_task *tsk = parent->depend_all_memory;
    244  1.1.1.14  mrg       if (tsk->dependers == NULL)
    245   1.1.1.9  mrg 	{
    246  1.1.1.14  mrg 	  tsk->dependers
    247  1.1.1.14  mrg 	    = gomp_malloc (sizeof (struct gomp_dependers_vec)
    248  1.1.1.14  mrg 			   + 6 * sizeof (struct gomp_task *));
    249  1.1.1.14  mrg 	  tsk->dependers->n_elem = 1;
    250  1.1.1.14  mrg 	  tsk->dependers->allocated = 6;
    251  1.1.1.14  mrg 	  tsk->dependers->elem[0] = task;
    252   1.1.1.9  mrg 	}
    253  1.1.1.14  mrg       else
    254  1.1.1.14  mrg 	{
    255  1.1.1.14  mrg 	  if (tsk->dependers->n_elem == tsk->dependers->allocated)
    256  1.1.1.14  mrg 	    {
    257  1.1.1.14  mrg 	      tsk->dependers->allocated
    258  1.1.1.14  mrg 		= tsk->dependers->allocated * 2 + 2;
    259  1.1.1.14  mrg 	      tsk->dependers
    260  1.1.1.14  mrg 		= gomp_realloc (tsk->dependers,
    261  1.1.1.14  mrg 				sizeof (struct gomp_dependers_vec)
    262  1.1.1.14  mrg 				+ (tsk->dependers->allocated
    263  1.1.1.14  mrg 				   * sizeof (struct gomp_task *)));
    264  1.1.1.14  mrg 	    }
    265  1.1.1.14  mrg 	  tsk->dependers->elem[tsk->dependers->n_elem++] = task;
    266  1.1.1.14  mrg 	}
    267  1.1.1.14  mrg       task->num_dependees++;
    268  1.1.1.14  mrg     }
    269  1.1.1.14  mrg   if (__builtin_expect (all_memory, false))
    270  1.1.1.14  mrg     {
    271  1.1.1.14  mrg       /* A task with depend(inout: omp_all_memory) depends on all previous
    272  1.1.1.14  mrg 	 sibling tasks which have any dependencies and all later sibling
    273  1.1.1.14  mrg 	 tasks which have any dependencies depend on it.  */
    274  1.1.1.14  mrg       task->depend_count = 1;
    275  1.1.1.14  mrg       task->depend[0].addr = NULL;
    276  1.1.1.14  mrg       task->depend[0].next = NULL;
    277  1.1.1.14  mrg       task->depend[0].prev = NULL;
    278  1.1.1.14  mrg       task->depend[0].task = task;
    279  1.1.1.14  mrg       task->depend[0].redundant = true;
    280  1.1.1.14  mrg       task->depend[0].redundant_out = false;
    281  1.1.1.14  mrg       if (parent->depend_hash)
    282  1.1.1.14  mrg 	{
    283  1.1.1.14  mrg 	  /* Inlined htab_traverse + htab_clear.  All newer siblings can
    284  1.1.1.14  mrg 	     just depend on this task.  Add dependencies on all previous
    285  1.1.1.14  mrg 	     sibling tasks with dependencies and make them redundant and
    286  1.1.1.14  mrg 	     clear the hash table.  */
    287  1.1.1.14  mrg 	  hash_entry_type *slot = &parent->depend_hash->entries[0];
    288  1.1.1.14  mrg 	  hash_entry_type *end = slot + htab_size (parent->depend_hash);
    289  1.1.1.14  mrg 	  for (; slot != end; ++slot)
    290  1.1.1.14  mrg 	    {
    291  1.1.1.14  mrg 	      if (*slot == HTAB_EMPTY_ENTRY)
    292  1.1.1.14  mrg 		continue;
    293  1.1.1.14  mrg 	      if (*slot != HTAB_DELETED_ENTRY)
    294  1.1.1.14  mrg 		{
    295  1.1.1.14  mrg 		  for (ent = *slot; ent; ent = ent->next)
    296  1.1.1.14  mrg 		    {
    297  1.1.1.14  mrg 		      struct gomp_task *tsk = ent->task;
    298  1.1.1.14  mrg 
    299  1.1.1.14  mrg 		      if (ent->redundant_out)
    300  1.1.1.14  mrg 			break;
    301  1.1.1.14  mrg 
    302  1.1.1.14  mrg 		      ent->redundant = true;
    303  1.1.1.14  mrg 		      if (tsk->dependers == NULL)
    304  1.1.1.14  mrg 			{
    305  1.1.1.14  mrg 			  tsk->dependers
    306  1.1.1.14  mrg 			    = gomp_malloc (sizeof (struct gomp_dependers_vec)
    307  1.1.1.14  mrg 					   + 6 * sizeof (struct gomp_task *));
    308  1.1.1.14  mrg 			  tsk->dependers->n_elem = 1;
    309  1.1.1.14  mrg 			  tsk->dependers->allocated = 6;
    310  1.1.1.14  mrg 			  tsk->dependers->elem[0] = task;
    311  1.1.1.14  mrg 			  task->num_dependees++;
    312  1.1.1.14  mrg 			  continue;
    313  1.1.1.14  mrg 			}
    314  1.1.1.14  mrg 		      /* We already have some other dependency on tsk from
    315  1.1.1.14  mrg 			 earlier depend clause.  */
    316  1.1.1.14  mrg 		      else if (tsk->dependers->n_elem
    317  1.1.1.14  mrg 			       && (tsk->dependers->elem[tsk->dependers->n_elem
    318  1.1.1.14  mrg 							- 1] == task))
    319  1.1.1.14  mrg 			continue;
    320  1.1.1.14  mrg 		      else if (tsk->dependers->n_elem
    321  1.1.1.14  mrg 			       == tsk->dependers->allocated)
    322  1.1.1.14  mrg 			{
    323  1.1.1.14  mrg 			  tsk->dependers->allocated
    324  1.1.1.14  mrg 			    = tsk->dependers->allocated * 2 + 2;
    325  1.1.1.14  mrg 			  tsk->dependers
    326  1.1.1.14  mrg 			    = gomp_realloc (tsk->dependers,
    327  1.1.1.14  mrg 					    sizeof (struct gomp_dependers_vec)
    328  1.1.1.14  mrg 					    + (tsk->dependers->allocated
    329  1.1.1.14  mrg 					       * sizeof (struct gomp_task *)));
    330  1.1.1.14  mrg 			}
    331  1.1.1.14  mrg 		      tsk->dependers->elem[tsk->dependers->n_elem++] = task;
    332  1.1.1.14  mrg 		      task->num_dependees++;
    333  1.1.1.14  mrg 		    }
    334  1.1.1.14  mrg 		  while (ent)
    335  1.1.1.14  mrg 		    {
    336  1.1.1.14  mrg 		      ent->redundant = true;
    337  1.1.1.14  mrg 		      ent = ent->next;
    338  1.1.1.14  mrg 		    }
    339  1.1.1.14  mrg 		}
    340  1.1.1.14  mrg 	      *slot = HTAB_EMPTY_ENTRY;
    341  1.1.1.14  mrg 	    }
    342  1.1.1.14  mrg 	  if (htab_size (parent->depend_hash) <= 32)
    343  1.1.1.14  mrg 	    {
    344  1.1.1.14  mrg 	      parent->depend_hash->n_elements = 0;
    345  1.1.1.14  mrg 	      parent->depend_hash->n_deleted = 0;
    346  1.1.1.14  mrg 	    }
    347  1.1.1.14  mrg 	  else
    348  1.1.1.14  mrg 	    {
    349  1.1.1.14  mrg 	      /* Shrink the hash table if it would be too large.
    350  1.1.1.14  mrg 		 We don't want to walk e.g. megabytes of empty hash
    351  1.1.1.14  mrg 		 table for every depend(inout: omp_all_memory).  */
    352  1.1.1.14  mrg 	      free (parent->depend_hash);
    353  1.1.1.14  mrg 	      parent->depend_hash = htab_create (12);
    354  1.1.1.14  mrg 	    }
    355  1.1.1.14  mrg 	}
    356  1.1.1.14  mrg       parent->depend_all_memory = task;
    357  1.1.1.14  mrg       return;
    358   1.1.1.9  mrg     }
    359   1.1.1.4  mrg   task->depend_count = ndepend;
    360   1.1.1.4  mrg   if (parent->depend_hash == NULL)
    361   1.1.1.4  mrg     parent->depend_hash = htab_create (2 * ndepend > 12 ? 2 * ndepend : 12);
    362   1.1.1.4  mrg   for (i = 0; i < ndepend; i++)
    363   1.1.1.4  mrg     {
    364   1.1.1.4  mrg       task->depend[i].next = NULL;
    365   1.1.1.4  mrg       task->depend[i].prev = NULL;
    366   1.1.1.4  mrg       task->depend[i].task = task;
    367   1.1.1.4  mrg       task->depend[i].redundant = false;
    368   1.1.1.4  mrg       task->depend[i].redundant_out = false;
    369   1.1.1.4  mrg 
    370   1.1.1.4  mrg       hash_entry_type *slot = htab_find_slot (&parent->depend_hash,
    371   1.1.1.4  mrg 					      &task->depend[i], INSERT);
    372   1.1.1.4  mrg       hash_entry_type out = NULL, last = NULL;
    373   1.1.1.4  mrg       if (*slot)
    374   1.1.1.4  mrg 	{
    375   1.1.1.4  mrg 	  /* If multiple depends on the same task are the same, all but the
    376   1.1.1.4  mrg 	     first one are redundant.  As inout/out come first, if any of them
    377   1.1.1.4  mrg 	     is inout/out, it will win, which is the right semantics.  */
    378   1.1.1.4  mrg 	  if ((*slot)->task == task)
    379   1.1.1.4  mrg 	    {
    380   1.1.1.4  mrg 	      task->depend[i].redundant = true;
    381   1.1.1.4  mrg 	      continue;
    382   1.1.1.4  mrg 	    }
    383   1.1.1.4  mrg 	  for (ent = *slot; ent; ent = ent->next)
    384   1.1.1.4  mrg 	    {
    385   1.1.1.4  mrg 	      if (ent->redundant_out)
    386   1.1.1.4  mrg 		break;
    387   1.1.1.4  mrg 
    388   1.1.1.4  mrg 	      last = ent;
    389   1.1.1.4  mrg 
    390  1.1.1.14  mrg 	      /* depend(in:...) doesn't depend on earlier depend(in:...).
    391  1.1.1.14  mrg 		 Similarly depend(inoutset:...) doesn't depend on earlier
    392  1.1.1.14  mrg 		 depend(inoutset:...).  */
    393  1.1.1.14  mrg 	      if (task->depend[i].is_in && task->depend[i].is_in == ent->is_in)
    394   1.1.1.4  mrg 		continue;
    395   1.1.1.4  mrg 
    396   1.1.1.4  mrg 	      if (!ent->is_in)
    397   1.1.1.4  mrg 		out = ent;
    398   1.1.1.4  mrg 
    399   1.1.1.4  mrg 	      struct gomp_task *tsk = ent->task;
    400   1.1.1.4  mrg 	      if (tsk->dependers == NULL)
    401   1.1.1.4  mrg 		{
    402   1.1.1.4  mrg 		  tsk->dependers
    403   1.1.1.4  mrg 		    = gomp_malloc (sizeof (struct gomp_dependers_vec)
    404   1.1.1.4  mrg 				   + 6 * sizeof (struct gomp_task *));
    405   1.1.1.4  mrg 		  tsk->dependers->n_elem = 1;
    406   1.1.1.4  mrg 		  tsk->dependers->allocated = 6;
    407   1.1.1.4  mrg 		  tsk->dependers->elem[0] = task;
    408   1.1.1.4  mrg 		  task->num_dependees++;
    409   1.1.1.4  mrg 		  continue;
    410   1.1.1.4  mrg 		}
    411   1.1.1.4  mrg 	      /* We already have some other dependency on tsk from earlier
    412   1.1.1.4  mrg 		 depend clause.  */
    413   1.1.1.4  mrg 	      else if (tsk->dependers->n_elem
    414   1.1.1.4  mrg 		       && (tsk->dependers->elem[tsk->dependers->n_elem - 1]
    415   1.1.1.4  mrg 			   == task))
    416   1.1.1.4  mrg 		continue;
    417   1.1.1.4  mrg 	      else if (tsk->dependers->n_elem == tsk->dependers->allocated)
    418   1.1.1.4  mrg 		{
    419   1.1.1.4  mrg 		  tsk->dependers->allocated
    420   1.1.1.4  mrg 		    = tsk->dependers->allocated * 2 + 2;
    421   1.1.1.4  mrg 		  tsk->dependers
    422   1.1.1.4  mrg 		    = gomp_realloc (tsk->dependers,
    423   1.1.1.4  mrg 				    sizeof (struct gomp_dependers_vec)
    424   1.1.1.4  mrg 				    + (tsk->dependers->allocated
    425   1.1.1.4  mrg 				       * sizeof (struct gomp_task *)));
    426   1.1.1.4  mrg 		}
    427   1.1.1.4  mrg 	      tsk->dependers->elem[tsk->dependers->n_elem++] = task;
    428   1.1.1.4  mrg 	      task->num_dependees++;
    429   1.1.1.4  mrg 	    }
    430   1.1.1.4  mrg 	  task->depend[i].next = *slot;
    431   1.1.1.4  mrg 	  (*slot)->prev = &task->depend[i];
    432   1.1.1.4  mrg 	}
    433   1.1.1.4  mrg       *slot = &task->depend[i];
    434   1.1.1.4  mrg 
    435   1.1.1.4  mrg       /* There is no need to store more than one depend({,in}out:) task per
    436   1.1.1.4  mrg 	 address in the hash table chain for the purpose of creation of
    437   1.1.1.4  mrg 	 deferred tasks, because each out depends on all earlier outs, thus it
    438   1.1.1.4  mrg 	 is enough to record just the last depend({,in}out:).  For depend(in:),
    439   1.1.1.4  mrg 	 we need to keep all of the previous ones not terminated yet, because
    440   1.1.1.4  mrg 	 a later depend({,in}out:) might need to depend on all of them.  So, if
    441   1.1.1.4  mrg 	 the new task's clause is depend({,in}out:), we know there is at most
    442   1.1.1.4  mrg 	 one other depend({,in}out:) clause in the list (out).  For
    443   1.1.1.4  mrg 	 non-deferred tasks we want to see all outs, so they are moved to the
    444   1.1.1.4  mrg 	 end of the chain, after first redundant_out entry all following
    445   1.1.1.4  mrg 	 entries should be redundant_out.  */
    446   1.1.1.4  mrg       if (!task->depend[i].is_in && out)
    447   1.1.1.4  mrg 	{
    448   1.1.1.4  mrg 	  if (out != last)
    449   1.1.1.4  mrg 	    {
    450   1.1.1.4  mrg 	      out->next->prev = out->prev;
    451   1.1.1.4  mrg 	      out->prev->next = out->next;
    452   1.1.1.4  mrg 	      out->next = last->next;
    453   1.1.1.4  mrg 	      out->prev = last;
    454   1.1.1.4  mrg 	      last->next = out;
    455   1.1.1.4  mrg 	      if (out->next)
    456   1.1.1.4  mrg 		out->next->prev = out;
    457   1.1.1.4  mrg 	    }
    458   1.1.1.4  mrg 	  out->redundant_out = true;
    459   1.1.1.4  mrg 	}
    460   1.1.1.4  mrg     }
    461   1.1.1.4  mrg }
    462   1.1.1.3  mrg 
    463  1.1.1.14  mrg /* Body of empty task like taskwait nowait depend.  */
    464  1.1.1.14  mrg 
    465  1.1.1.14  mrg static void
    466  1.1.1.14  mrg empty_task (void *data __attribute__((unused)))
    467  1.1.1.14  mrg {
    468  1.1.1.14  mrg }
    469  1.1.1.14  mrg 
    470  1.1.1.14  mrg static void gomp_task_run_post_handle_depend_hash (struct gomp_task *);
    471  1.1.1.14  mrg static inline size_t gomp_task_run_post_handle_depend (struct gomp_task *,
    472  1.1.1.14  mrg 						       struct gomp_team *);
    473  1.1.1.14  mrg 
    474       1.1  mrg /* Called when encountering an explicit task directive.  If IF_CLAUSE is
    475       1.1  mrg    false, then we must not delay in executing the task.  If UNTIED is true,
    476   1.1.1.4  mrg    then the task may be executed by any member of the team.
    477   1.1.1.4  mrg 
    478   1.1.1.4  mrg    DEPEND is an array containing:
    479   1.1.1.9  mrg      if depend[0] is non-zero, then:
    480   1.1.1.4  mrg 	depend[0]: number of depend elements.
    481   1.1.1.9  mrg 	depend[1]: number of depend elements of type "out/inout".
    482   1.1.1.9  mrg 	depend[2..N+1]: address of [1..N]th depend element.
    483   1.1.1.9  mrg      otherwise, when depend[0] is zero, then:
    484   1.1.1.9  mrg 	depend[1]: number of depend elements.
    485   1.1.1.9  mrg 	depend[2]: number of depend elements of type "out/inout".
    486   1.1.1.9  mrg 	depend[3]: number of depend elements of type "mutexinoutset".
    487   1.1.1.9  mrg 	depend[4]: number of depend elements of type "in".
    488   1.1.1.9  mrg 	depend[5..4+depend[2]+depend[3]+depend[4]]: address of depend elements
    489   1.1.1.9  mrg 	depend[5+depend[2]+depend[3]+depend[4]..4+depend[1]]: address of
    490   1.1.1.9  mrg 		   omp_depend_t objects.  */
    491       1.1  mrg 
    492       1.1  mrg void
    493       1.1  mrg GOMP_task (void (*fn) (void *), void *data, void (*cpyfn) (void *, void *),
    494   1.1.1.3  mrg 	   long arg_size, long arg_align, bool if_clause, unsigned flags,
    495  1.1.1.13  mrg 	   void **depend, int priority_arg, void *detach)
    496       1.1  mrg {
    497       1.1  mrg   struct gomp_thread *thr = gomp_thread ();
    498       1.1  mrg   struct gomp_team *team = thr->ts.team;
    499  1.1.1.13  mrg   int priority = 0;
    500       1.1  mrg 
    501       1.1  mrg #ifdef HAVE_BROKEN_POSIX_SEMAPHORES
    502       1.1  mrg   /* If pthread_mutex_* is used for omp_*lock*, then each task must be
    503       1.1  mrg      tied to one thread all the time.  This means UNTIED tasks must be
    504       1.1  mrg      tied and if CPYFN is non-NULL IF(0) must be forced, as CPYFN
    505       1.1  mrg      might be running on different thread than FN.  */
    506       1.1  mrg   if (cpyfn)
    507       1.1  mrg     if_clause = false;
    508   1.1.1.4  mrg   flags &= ~GOMP_TASK_FLAG_UNTIED;
    509       1.1  mrg #endif
    510       1.1  mrg 
    511   1.1.1.3  mrg   /* If parallel or taskgroup has been cancelled, don't start new tasks.  */
    512   1.1.1.9  mrg   if (__builtin_expect (gomp_cancel_var, 0) && team)
    513   1.1.1.9  mrg     {
    514   1.1.1.9  mrg       if (gomp_team_barrier_cancelled (&team->barrier))
    515   1.1.1.9  mrg 	return;
    516   1.1.1.9  mrg       if (thr->task->taskgroup)
    517   1.1.1.9  mrg 	{
    518   1.1.1.9  mrg 	  if (thr->task->taskgroup->cancelled)
    519   1.1.1.9  mrg 	    return;
    520   1.1.1.9  mrg 	  if (thr->task->taskgroup->workshare
    521   1.1.1.9  mrg 	      && thr->task->taskgroup->prev
    522   1.1.1.9  mrg 	      && thr->task->taskgroup->prev->cancelled)
    523   1.1.1.9  mrg 	    return;
    524   1.1.1.9  mrg 	}
    525   1.1.1.9  mrg     }
    526   1.1.1.3  mrg 
    527  1.1.1.13  mrg   if (__builtin_expect ((flags & GOMP_TASK_FLAG_PRIORITY) != 0, 0))
    528  1.1.1.13  mrg     {
    529  1.1.1.13  mrg       priority = priority_arg;
    530  1.1.1.13  mrg       if (priority > gomp_max_task_priority_var)
    531  1.1.1.13  mrg 	priority = gomp_max_task_priority_var;
    532  1.1.1.13  mrg     }
    533   1.1.1.4  mrg 
    534       1.1  mrg   if (!if_clause || team == NULL
    535   1.1.1.2  mrg       || (thr->task && thr->task->final_task)
    536       1.1  mrg       || team->task_count > 64 * team->nthreads)
    537       1.1  mrg     {
    538       1.1  mrg       struct gomp_task task;
    539  1.1.1.13  mrg       gomp_sem_t completion_sem;
    540       1.1  mrg 
    541   1.1.1.3  mrg       /* If there are depend clauses and earlier deferred sibling tasks
    542   1.1.1.3  mrg 	 with depend clauses, check if there isn't a dependency.  If there
    543   1.1.1.3  mrg 	 is, we need to wait for them.  There is no need to handle
    544   1.1.1.3  mrg 	 depend clauses for non-deferred tasks other than this, because
    545   1.1.1.3  mrg 	 the parent task is suspended until the child task finishes and thus
    546   1.1.1.3  mrg 	 it can't start further child tasks.  */
    547   1.1.1.4  mrg       if ((flags & GOMP_TASK_FLAG_DEPEND)
    548   1.1.1.4  mrg 	  && thr->task && thr->task->depend_hash)
    549   1.1.1.3  mrg 	gomp_task_maybe_wait_for_dependencies (depend);
    550   1.1.1.3  mrg 
    551       1.1  mrg       gomp_init_task (&task, thr->task, gomp_icv (false));
    552   1.1.1.4  mrg       task.kind = GOMP_TASK_UNDEFERRED;
    553   1.1.1.4  mrg       task.final_task = (thr->task && thr->task->final_task)
    554   1.1.1.4  mrg 			|| (flags & GOMP_TASK_FLAG_FINAL);
    555   1.1.1.4  mrg       task.priority = priority;
    556  1.1.1.13  mrg 
    557  1.1.1.13  mrg       if ((flags & GOMP_TASK_FLAG_DETACH) != 0)
    558  1.1.1.13  mrg 	{
    559  1.1.1.13  mrg 	  gomp_sem_init (&completion_sem, 0);
    560  1.1.1.13  mrg 	  task.completion_sem = &completion_sem;
    561  1.1.1.13  mrg 	  *(void **) detach = &task;
    562  1.1.1.13  mrg 	  if (data)
    563  1.1.1.13  mrg 	    *(void **) data = &task;
    564  1.1.1.13  mrg 
    565  1.1.1.13  mrg 	  gomp_debug (0, "Thread %d: new event: %p\n",
    566  1.1.1.13  mrg 		      thr->ts.team_id, &task);
    567  1.1.1.13  mrg 	}
    568  1.1.1.13  mrg 
    569       1.1  mrg       if (thr->task)
    570   1.1.1.3  mrg 	{
    571   1.1.1.3  mrg 	  task.in_tied_task = thr->task->in_tied_task;
    572   1.1.1.3  mrg 	  task.taskgroup = thr->task->taskgroup;
    573   1.1.1.3  mrg 	}
    574       1.1  mrg       thr->task = &task;
    575       1.1  mrg       if (__builtin_expect (cpyfn != NULL, 0))
    576       1.1  mrg 	{
    577       1.1  mrg 	  char buf[arg_size + arg_align - 1];
    578       1.1  mrg 	  char *arg = (char *) (((uintptr_t) buf + arg_align - 1)
    579       1.1  mrg 				& ~(uintptr_t) (arg_align - 1));
    580       1.1  mrg 	  cpyfn (arg, data);
    581       1.1  mrg 	  fn (arg);
    582       1.1  mrg 	}
    583       1.1  mrg       else
    584       1.1  mrg 	fn (data);
    585  1.1.1.13  mrg 
    586  1.1.1.13  mrg       if ((flags & GOMP_TASK_FLAG_DETACH) != 0)
    587  1.1.1.13  mrg 	{
    588  1.1.1.13  mrg 	  gomp_sem_wait (&completion_sem);
    589  1.1.1.13  mrg 	  gomp_sem_destroy (&completion_sem);
    590  1.1.1.13  mrg 	}
    591  1.1.1.13  mrg 
    592   1.1.1.2  mrg       /* Access to "children" is normally done inside a task_lock
    593   1.1.1.2  mrg 	 mutex region, but the only way this particular task.children
    594   1.1.1.2  mrg 	 can be set is if this thread's task work function (fn)
    595   1.1.1.2  mrg 	 creates children.  So since the setter is *this* thread, we
    596   1.1.1.2  mrg 	 need no barriers here when testing for non-NULL.  We can have
    597   1.1.1.2  mrg 	 task.children set by the current thread then changed by a
    598   1.1.1.2  mrg 	 child thread, but seeing a stale non-NULL value is not a
    599   1.1.1.2  mrg 	 problem.  Once past the task_lock acquisition, this thread
    600   1.1.1.2  mrg 	 will see the real value of task.children.  */
    601   1.1.1.4  mrg       if (!priority_queue_empty_p (&task.children_queue, MEMMODEL_RELAXED))
    602       1.1  mrg 	{
    603       1.1  mrg 	  gomp_mutex_lock (&team->task_lock);
    604   1.1.1.4  mrg 	  gomp_clear_parent (&task.children_queue);
    605       1.1  mrg 	  gomp_mutex_unlock (&team->task_lock);
    606       1.1  mrg 	}
    607       1.1  mrg       gomp_end_task ();
    608       1.1  mrg     }
    609       1.1  mrg   else
    610       1.1  mrg     {
    611       1.1  mrg       struct gomp_task *task;
    612       1.1  mrg       struct gomp_task *parent = thr->task;
    613   1.1.1.3  mrg       struct gomp_taskgroup *taskgroup = parent->taskgroup;
    614       1.1  mrg       char *arg;
    615       1.1  mrg       bool do_wake;
    616   1.1.1.3  mrg       size_t depend_size = 0;
    617       1.1  mrg 
    618   1.1.1.4  mrg       if (flags & GOMP_TASK_FLAG_DEPEND)
    619   1.1.1.9  mrg 	depend_size = ((uintptr_t) (depend[0] ? depend[0] : depend[1])
    620   1.1.1.3  mrg 		       * sizeof (struct gomp_task_depend_entry));
    621   1.1.1.3  mrg       task = gomp_malloc (sizeof (*task) + depend_size
    622   1.1.1.3  mrg 			  + arg_size + arg_align - 1);
    623   1.1.1.3  mrg       arg = (char *) (((uintptr_t) (task + 1) + depend_size + arg_align - 1)
    624       1.1  mrg 		      & ~(uintptr_t) (arg_align - 1));
    625       1.1  mrg       gomp_init_task (task, parent, gomp_icv (false));
    626   1.1.1.4  mrg       task->priority = priority;
    627   1.1.1.4  mrg       task->kind = GOMP_TASK_UNDEFERRED;
    628       1.1  mrg       task->in_tied_task = parent->in_tied_task;
    629   1.1.1.3  mrg       task->taskgroup = taskgroup;
    630  1.1.1.13  mrg       task->deferred_p = true;
    631  1.1.1.13  mrg       if ((flags & GOMP_TASK_FLAG_DETACH) != 0)
    632  1.1.1.13  mrg 	{
    633  1.1.1.13  mrg 	  task->detach_team = team;
    634  1.1.1.13  mrg 
    635  1.1.1.13  mrg 	  *(void **) detach = task;
    636  1.1.1.13  mrg 	  if (data)
    637  1.1.1.13  mrg 	    *(void **) data = task;
    638  1.1.1.13  mrg 
    639  1.1.1.13  mrg 	  gomp_debug (0, "Thread %d: new event: %p\n", thr->ts.team_id, task);
    640  1.1.1.13  mrg 	}
    641       1.1  mrg       thr->task = task;
    642       1.1  mrg       if (cpyfn)
    643   1.1.1.3  mrg 	{
    644   1.1.1.3  mrg 	  cpyfn (arg, data);
    645   1.1.1.3  mrg 	  task->copy_ctors_done = true;
    646   1.1.1.3  mrg 	}
    647       1.1  mrg       else
    648       1.1  mrg 	memcpy (arg, data, arg_size);
    649       1.1  mrg       thr->task = parent;
    650       1.1  mrg       task->kind = GOMP_TASK_WAITING;
    651       1.1  mrg       task->fn = fn;
    652       1.1  mrg       task->fn_data = arg;
    653   1.1.1.4  mrg       task->final_task = (flags & GOMP_TASK_FLAG_FINAL) >> 1;
    654       1.1  mrg       gomp_mutex_lock (&team->task_lock);
    655   1.1.1.3  mrg       /* If parallel or taskgroup has been cancelled, don't start new
    656   1.1.1.3  mrg 	 tasks.  */
    657   1.1.1.9  mrg       if (__builtin_expect (gomp_cancel_var, 0)
    658   1.1.1.9  mrg 	  && !task->copy_ctors_done)
    659   1.1.1.3  mrg 	{
    660   1.1.1.9  mrg 	  if (gomp_team_barrier_cancelled (&team->barrier))
    661   1.1.1.9  mrg 	    {
    662   1.1.1.9  mrg 	    do_cancel:
    663   1.1.1.9  mrg 	      gomp_mutex_unlock (&team->task_lock);
    664   1.1.1.9  mrg 	      gomp_finish_task (task);
    665   1.1.1.9  mrg 	      free (task);
    666   1.1.1.9  mrg 	      return;
    667   1.1.1.9  mrg 	    }
    668   1.1.1.9  mrg 	  if (taskgroup)
    669   1.1.1.9  mrg 	    {
    670   1.1.1.9  mrg 	      if (taskgroup->cancelled)
    671   1.1.1.9  mrg 		goto do_cancel;
    672   1.1.1.9  mrg 	      if (taskgroup->workshare
    673   1.1.1.9  mrg 		  && taskgroup->prev
    674   1.1.1.9  mrg 		  && taskgroup->prev->cancelled)
    675   1.1.1.9  mrg 		goto do_cancel;
    676   1.1.1.9  mrg 	    }
    677   1.1.1.3  mrg 	}
    678   1.1.1.3  mrg       if (taskgroup)
    679   1.1.1.3  mrg 	taskgroup->num_children++;
    680   1.1.1.3  mrg       if (depend_size)
    681   1.1.1.3  mrg 	{
    682   1.1.1.4  mrg 	  gomp_task_handle_depend (task, parent, depend);
    683   1.1.1.3  mrg 	  if (task->num_dependees)
    684   1.1.1.3  mrg 	    {
    685   1.1.1.4  mrg 	      /* Tasks that depend on other tasks are not put into the
    686   1.1.1.4  mrg 		 various waiting queues, so we are done for now.  Said
    687   1.1.1.4  mrg 		 tasks are instead put into the queues via
    688   1.1.1.4  mrg 		 gomp_task_run_post_handle_dependers() after their
    689   1.1.1.4  mrg 		 dependencies have been satisfied.  After which, they
    690   1.1.1.4  mrg 		 can be picked up by the various scheduling
    691   1.1.1.4  mrg 		 points.  */
    692   1.1.1.3  mrg 	      gomp_mutex_unlock (&team->task_lock);
    693   1.1.1.3  mrg 	      return;
    694   1.1.1.3  mrg 	    }
    695  1.1.1.14  mrg 	  /* Check for taskwait nowait depend which doesn't need to wait for
    696  1.1.1.14  mrg 	     anything.  */
    697  1.1.1.14  mrg 	  if (__builtin_expect (fn == empty_task, 0))
    698  1.1.1.14  mrg 	    {
    699  1.1.1.14  mrg 	      if (taskgroup)
    700  1.1.1.14  mrg 		taskgroup->num_children--;
    701  1.1.1.14  mrg 	      gomp_task_run_post_handle_depend_hash (task);
    702  1.1.1.14  mrg 	      gomp_mutex_unlock (&team->task_lock);
    703  1.1.1.14  mrg 	      gomp_finish_task (task);
    704  1.1.1.14  mrg 	      free (task);
    705  1.1.1.14  mrg 	      return;
    706  1.1.1.14  mrg 	    }
    707   1.1.1.3  mrg 	}
    708   1.1.1.4  mrg 
    709   1.1.1.4  mrg       priority_queue_insert (PQ_CHILDREN, &parent->children_queue,
    710   1.1.1.4  mrg 			     task, priority,
    711   1.1.1.4  mrg 			     PRIORITY_INSERT_BEGIN,
    712   1.1.1.4  mrg 			     /*adjust_parent_depends_on=*/false,
    713   1.1.1.4  mrg 			     task->parent_depends_on);
    714   1.1.1.3  mrg       if (taskgroup)
    715   1.1.1.4  mrg 	priority_queue_insert (PQ_TASKGROUP, &taskgroup->taskgroup_queue,
    716   1.1.1.4  mrg 			       task, priority,
    717   1.1.1.4  mrg 			       PRIORITY_INSERT_BEGIN,
    718   1.1.1.4  mrg 			       /*adjust_parent_depends_on=*/false,
    719   1.1.1.4  mrg 			       task->parent_depends_on);
    720   1.1.1.4  mrg 
    721   1.1.1.4  mrg       priority_queue_insert (PQ_TEAM, &team->task_queue,
    722   1.1.1.4  mrg 			     task, priority,
    723   1.1.1.4  mrg 			     PRIORITY_INSERT_END,
    724   1.1.1.4  mrg 			     /*adjust_parent_depends_on=*/false,
    725   1.1.1.4  mrg 			     task->parent_depends_on);
    726   1.1.1.4  mrg 
    727       1.1  mrg       ++team->task_count;
    728   1.1.1.3  mrg       ++team->task_queued_count;
    729       1.1  mrg       gomp_team_barrier_set_task_pending (&team->barrier);
    730       1.1  mrg       do_wake = team->task_running_count + !parent->in_tied_task
    731       1.1  mrg 		< team->nthreads;
    732       1.1  mrg       gomp_mutex_unlock (&team->task_lock);
    733       1.1  mrg       if (do_wake)
    734       1.1  mrg 	gomp_team_barrier_wake (&team->barrier, 1);
    735       1.1  mrg     }
    736       1.1  mrg }
    737       1.1  mrg 
    738  1.1.1.14  mrg ialias (GOMP_task)
    739   1.1.1.4  mrg ialias (GOMP_taskgroup_start)
    740   1.1.1.4  mrg ialias (GOMP_taskgroup_end)
    741   1.1.1.9  mrg ialias (GOMP_taskgroup_reduction_register)
    742   1.1.1.4  mrg 
    743   1.1.1.4  mrg #define TYPE long
    744   1.1.1.4  mrg #define UTYPE unsigned long
    745   1.1.1.4  mrg #define TYPE_is_long 1
    746   1.1.1.4  mrg #include "taskloop.c"
    747   1.1.1.4  mrg #undef TYPE
    748   1.1.1.4  mrg #undef UTYPE
    749   1.1.1.4  mrg #undef TYPE_is_long
    750   1.1.1.4  mrg 
    751   1.1.1.4  mrg #define TYPE unsigned long long
    752   1.1.1.4  mrg #define UTYPE TYPE
    753   1.1.1.4  mrg #define GOMP_taskloop GOMP_taskloop_ull
    754   1.1.1.4  mrg #include "taskloop.c"
    755   1.1.1.4  mrg #undef TYPE
    756   1.1.1.4  mrg #undef UTYPE
    757   1.1.1.4  mrg #undef GOMP_taskloop
    758   1.1.1.4  mrg 
    759   1.1.1.4  mrg static void inline
    760   1.1.1.4  mrg priority_queue_move_task_first (enum priority_queue_type type,
    761   1.1.1.4  mrg 				struct priority_queue *head,
    762   1.1.1.4  mrg 				struct gomp_task *task)
    763   1.1.1.4  mrg {
    764   1.1.1.4  mrg #if _LIBGOMP_CHECKING_
    765   1.1.1.4  mrg   if (!priority_queue_task_in_queue_p (type, head, task))
    766   1.1.1.4  mrg     gomp_fatal ("Attempt to move first missing task %p", task);
    767   1.1.1.4  mrg #endif
    768   1.1.1.4  mrg   struct priority_list *list;
    769   1.1.1.4  mrg   if (priority_queue_multi_p (head))
    770   1.1.1.4  mrg     {
    771   1.1.1.4  mrg       list = priority_queue_lookup_priority (head, task->priority);
    772   1.1.1.4  mrg #if _LIBGOMP_CHECKING_
    773   1.1.1.4  mrg       if (!list)
    774   1.1.1.4  mrg 	gomp_fatal ("Unable to find priority %d", task->priority);
    775   1.1.1.4  mrg #endif
    776   1.1.1.4  mrg     }
    777   1.1.1.4  mrg   else
    778   1.1.1.4  mrg     list = &head->l;
    779   1.1.1.4  mrg   priority_list_remove (list, task_to_priority_node (type, task), 0);
    780   1.1.1.4  mrg   priority_list_insert (type, list, task, task->priority,
    781   1.1.1.4  mrg 			PRIORITY_INSERT_BEGIN, type == PQ_CHILDREN,
    782   1.1.1.4  mrg 			task->parent_depends_on);
    783   1.1.1.4  mrg }
    784   1.1.1.4  mrg 
    785   1.1.1.4  mrg /* Actual body of GOMP_PLUGIN_target_task_completion that is executed
    786   1.1.1.4  mrg    with team->task_lock held, or is executed in the thread that called
    787   1.1.1.4  mrg    gomp_target_task_fn if GOMP_PLUGIN_target_task_completion has been
    788   1.1.1.4  mrg    run before it acquires team->task_lock.  */
    789   1.1.1.4  mrg 
    790   1.1.1.4  mrg static void
    791   1.1.1.4  mrg gomp_target_task_completion (struct gomp_team *team, struct gomp_task *task)
    792   1.1.1.3  mrg {
    793   1.1.1.4  mrg   struct gomp_task *parent = task->parent;
    794   1.1.1.3  mrg   if (parent)
    795   1.1.1.4  mrg     priority_queue_move_task_first (PQ_CHILDREN, &parent->children_queue,
    796   1.1.1.4  mrg 				    task);
    797   1.1.1.4  mrg 
    798   1.1.1.4  mrg   struct gomp_taskgroup *taskgroup = task->taskgroup;
    799   1.1.1.4  mrg   if (taskgroup)
    800   1.1.1.4  mrg     priority_queue_move_task_first (PQ_TASKGROUP, &taskgroup->taskgroup_queue,
    801   1.1.1.4  mrg 				    task);
    802   1.1.1.4  mrg 
    803   1.1.1.4  mrg   priority_queue_insert (PQ_TEAM, &team->task_queue, task, task->priority,
    804   1.1.1.4  mrg 			 PRIORITY_INSERT_BEGIN, false,
    805   1.1.1.4  mrg 			 task->parent_depends_on);
    806   1.1.1.4  mrg   task->kind = GOMP_TASK_WAITING;
    807   1.1.1.4  mrg   if (parent && parent->taskwait)
    808   1.1.1.3  mrg     {
    809   1.1.1.4  mrg       if (parent->taskwait->in_taskwait)
    810   1.1.1.4  mrg 	{
    811   1.1.1.4  mrg 	  /* One more task has had its dependencies met.
    812   1.1.1.4  mrg 	     Inform any waiters.  */
    813   1.1.1.4  mrg 	  parent->taskwait->in_taskwait = false;
    814   1.1.1.4  mrg 	  gomp_sem_post (&parent->taskwait->taskwait_sem);
    815   1.1.1.4  mrg 	}
    816   1.1.1.4  mrg       else if (parent->taskwait->in_depend_wait)
    817   1.1.1.4  mrg 	{
    818   1.1.1.4  mrg 	  /* One more task has had its dependencies met.
    819   1.1.1.4  mrg 	     Inform any waiters.  */
    820   1.1.1.4  mrg 	  parent->taskwait->in_depend_wait = false;
    821   1.1.1.4  mrg 	  gomp_sem_post (&parent->taskwait->taskwait_sem);
    822   1.1.1.3  mrg 	}
    823   1.1.1.3  mrg     }
    824   1.1.1.4  mrg   if (taskgroup && taskgroup->in_taskgroup_wait)
    825   1.1.1.4  mrg     {
    826   1.1.1.4  mrg       /* One more task has had its dependencies met.
    827   1.1.1.4  mrg 	 Inform any waiters.  */
    828   1.1.1.4  mrg       taskgroup->in_taskgroup_wait = false;
    829   1.1.1.4  mrg       gomp_sem_post (&taskgroup->taskgroup_sem);
    830   1.1.1.4  mrg     }
    831   1.1.1.4  mrg 
    832   1.1.1.4  mrg   ++team->task_queued_count;
    833   1.1.1.4  mrg   gomp_team_barrier_set_task_pending (&team->barrier);
    834   1.1.1.4  mrg   /* I'm afraid this can't be done after releasing team->task_lock,
    835   1.1.1.4  mrg      as gomp_target_task_completion is run from unrelated thread and
    836   1.1.1.4  mrg      therefore in between gomp_mutex_unlock and gomp_team_barrier_wake
    837   1.1.1.4  mrg      the team could be gone already.  */
    838   1.1.1.4  mrg   if (team->nthreads > team->task_running_count)
    839   1.1.1.4  mrg     gomp_team_barrier_wake (&team->barrier, 1);
    840   1.1.1.4  mrg }
    841   1.1.1.4  mrg 
    842   1.1.1.4  mrg /* Signal that a target task TTASK has completed the asynchronously
    843   1.1.1.4  mrg    running phase and should be requeued as a task to handle the
    844   1.1.1.4  mrg    variable unmapping.  */
    845   1.1.1.4  mrg 
    846   1.1.1.4  mrg void
    847   1.1.1.4  mrg GOMP_PLUGIN_target_task_completion (void *data)
    848   1.1.1.4  mrg {
    849   1.1.1.4  mrg   struct gomp_target_task *ttask = (struct gomp_target_task *) data;
    850   1.1.1.4  mrg   struct gomp_task *task = ttask->task;
    851   1.1.1.4  mrg   struct gomp_team *team = ttask->team;
    852   1.1.1.4  mrg 
    853   1.1.1.4  mrg   gomp_mutex_lock (&team->task_lock);
    854   1.1.1.4  mrg   if (ttask->state == GOMP_TARGET_TASK_READY_TO_RUN)
    855   1.1.1.4  mrg     {
    856   1.1.1.4  mrg       ttask->state = GOMP_TARGET_TASK_FINISHED;
    857   1.1.1.4  mrg       gomp_mutex_unlock (&team->task_lock);
    858   1.1.1.4  mrg       return;
    859   1.1.1.4  mrg     }
    860   1.1.1.4  mrg   ttask->state = GOMP_TARGET_TASK_FINISHED;
    861   1.1.1.4  mrg   gomp_target_task_completion (team, task);
    862   1.1.1.4  mrg   gomp_mutex_unlock (&team->task_lock);
    863   1.1.1.4  mrg }
    864   1.1.1.4  mrg 
    865   1.1.1.4  mrg /* Called for nowait target tasks.  */
    866   1.1.1.4  mrg 
    867   1.1.1.4  mrg bool
    868   1.1.1.4  mrg gomp_create_target_task (struct gomp_device_descr *devicep,
    869   1.1.1.4  mrg 			 void (*fn) (void *), size_t mapnum, void **hostaddrs,
    870   1.1.1.4  mrg 			 size_t *sizes, unsigned short *kinds,
    871   1.1.1.4  mrg 			 unsigned int flags, void **depend, void **args,
    872   1.1.1.4  mrg 			 enum gomp_target_task_state state)
    873   1.1.1.4  mrg {
    874   1.1.1.4  mrg   struct gomp_thread *thr = gomp_thread ();
    875   1.1.1.4  mrg   struct gomp_team *team = thr->ts.team;
    876   1.1.1.4  mrg 
    877   1.1.1.4  mrg   /* If parallel or taskgroup has been cancelled, don't start new tasks.  */
    878   1.1.1.9  mrg   if (__builtin_expect (gomp_cancel_var, 0) && team)
    879   1.1.1.9  mrg     {
    880   1.1.1.9  mrg       if (gomp_team_barrier_cancelled (&team->barrier))
    881   1.1.1.9  mrg 	return true;
    882   1.1.1.9  mrg       if (thr->task->taskgroup)
    883   1.1.1.9  mrg 	{
    884   1.1.1.9  mrg 	  if (thr->task->taskgroup->cancelled)
    885   1.1.1.9  mrg 	    return true;
    886   1.1.1.9  mrg 	  if (thr->task->taskgroup->workshare
    887   1.1.1.9  mrg 	      && thr->task->taskgroup->prev
    888   1.1.1.9  mrg 	      && thr->task->taskgroup->prev->cancelled)
    889   1.1.1.9  mrg 	    return true;
    890   1.1.1.9  mrg 	}
    891   1.1.1.9  mrg     }
    892   1.1.1.4  mrg 
    893   1.1.1.4  mrg   struct gomp_target_task *ttask;
    894   1.1.1.4  mrg   struct gomp_task *task;
    895   1.1.1.4  mrg   struct gomp_task *parent = thr->task;
    896   1.1.1.4  mrg   struct gomp_taskgroup *taskgroup = parent->taskgroup;
    897   1.1.1.4  mrg   bool do_wake;
    898   1.1.1.4  mrg   size_t depend_size = 0;
    899   1.1.1.4  mrg   uintptr_t depend_cnt = 0;
    900   1.1.1.4  mrg   size_t tgt_align = 0, tgt_size = 0;
    901  1.1.1.13  mrg   uintptr_t args_cnt = 0;
    902   1.1.1.4  mrg 
    903   1.1.1.4  mrg   if (depend != NULL)
    904   1.1.1.4  mrg     {
    905   1.1.1.9  mrg       depend_cnt = (uintptr_t) (depend[0] ? depend[0] : depend[1]);
    906   1.1.1.4  mrg       depend_size = depend_cnt * sizeof (struct gomp_task_depend_entry);
    907   1.1.1.4  mrg     }
    908   1.1.1.4  mrg   if (fn)
    909   1.1.1.3  mrg     {
    910   1.1.1.4  mrg       /* GOMP_MAP_FIRSTPRIVATE need to be copied first, as they are
    911   1.1.1.4  mrg 	 firstprivate on the target task.  */
    912   1.1.1.4  mrg       size_t i;
    913   1.1.1.4  mrg       for (i = 0; i < mapnum; i++)
    914   1.1.1.4  mrg 	if ((kinds[i] & 0xff) == GOMP_MAP_FIRSTPRIVATE)
    915   1.1.1.4  mrg 	  {
    916   1.1.1.4  mrg 	    size_t align = (size_t) 1 << (kinds[i] >> 8);
    917   1.1.1.4  mrg 	    if (tgt_align < align)
    918   1.1.1.4  mrg 	      tgt_align = align;
    919   1.1.1.4  mrg 	    tgt_size = (tgt_size + align - 1) & ~(align - 1);
    920   1.1.1.4  mrg 	    tgt_size += sizes[i];
    921   1.1.1.4  mrg 	  }
    922   1.1.1.4  mrg       if (tgt_align)
    923   1.1.1.4  mrg 	tgt_size += tgt_align - 1;
    924   1.1.1.3  mrg       else
    925   1.1.1.4  mrg 	tgt_size = 0;
    926  1.1.1.13  mrg       if (args)
    927  1.1.1.13  mrg 	{
    928  1.1.1.13  mrg 	  void **cargs = args;
    929  1.1.1.13  mrg 	  while (*cargs)
    930  1.1.1.13  mrg 	    {
    931  1.1.1.13  mrg 	      intptr_t id = (intptr_t) *cargs++;
    932  1.1.1.13  mrg 	      if (id & GOMP_TARGET_ARG_SUBSEQUENT_PARAM)
    933  1.1.1.13  mrg 		cargs++;
    934  1.1.1.13  mrg 	    }
    935  1.1.1.13  mrg 	  args_cnt = cargs + 1 - args;
    936  1.1.1.13  mrg 	}
    937   1.1.1.4  mrg     }
    938   1.1.1.4  mrg 
    939   1.1.1.4  mrg   task = gomp_malloc (sizeof (*task) + depend_size
    940   1.1.1.4  mrg 		      + sizeof (*ttask)
    941  1.1.1.13  mrg 		      + args_cnt * sizeof (void *)
    942   1.1.1.4  mrg 		      + mapnum * (sizeof (void *) + sizeof (size_t)
    943   1.1.1.4  mrg 				  + sizeof (unsigned short))
    944   1.1.1.4  mrg 		      + tgt_size);
    945   1.1.1.4  mrg   gomp_init_task (task, parent, gomp_icv (false));
    946   1.1.1.4  mrg   task->priority = 0;
    947   1.1.1.4  mrg   task->kind = GOMP_TASK_WAITING;
    948   1.1.1.4  mrg   task->in_tied_task = parent->in_tied_task;
    949   1.1.1.4  mrg   task->taskgroup = taskgroup;
    950   1.1.1.4  mrg   ttask = (struct gomp_target_task *) &task->depend[depend_cnt];
    951   1.1.1.4  mrg   ttask->devicep = devicep;
    952   1.1.1.4  mrg   ttask->fn = fn;
    953   1.1.1.4  mrg   ttask->mapnum = mapnum;
    954   1.1.1.4  mrg   memcpy (ttask->hostaddrs, hostaddrs, mapnum * sizeof (void *));
    955  1.1.1.13  mrg   if (args_cnt)
    956  1.1.1.13  mrg     {
    957  1.1.1.13  mrg       ttask->args = (void **) &ttask->hostaddrs[mapnum];
    958  1.1.1.13  mrg       memcpy (ttask->args, args, args_cnt * sizeof (void *));
    959  1.1.1.13  mrg       ttask->sizes = (size_t *) &ttask->args[args_cnt];
    960  1.1.1.13  mrg     }
    961  1.1.1.13  mrg   else
    962  1.1.1.13  mrg     {
    963  1.1.1.13  mrg       ttask->args = args;
    964  1.1.1.13  mrg       ttask->sizes = (size_t *) &ttask->hostaddrs[mapnum];
    965  1.1.1.13  mrg     }
    966   1.1.1.4  mrg   memcpy (ttask->sizes, sizes, mapnum * sizeof (size_t));
    967   1.1.1.4  mrg   ttask->kinds = (unsigned short *) &ttask->sizes[mapnum];
    968   1.1.1.4  mrg   memcpy (ttask->kinds, kinds, mapnum * sizeof (unsigned short));
    969   1.1.1.4  mrg   if (tgt_align)
    970   1.1.1.4  mrg     {
    971   1.1.1.4  mrg       char *tgt = (char *) &ttask->kinds[mapnum];
    972   1.1.1.4  mrg       size_t i;
    973   1.1.1.4  mrg       uintptr_t al = (uintptr_t) tgt & (tgt_align - 1);
    974   1.1.1.4  mrg       if (al)
    975   1.1.1.4  mrg 	tgt += tgt_align - al;
    976   1.1.1.4  mrg       tgt_size = 0;
    977   1.1.1.4  mrg       for (i = 0; i < mapnum; i++)
    978   1.1.1.4  mrg 	if ((kinds[i] & 0xff) == GOMP_MAP_FIRSTPRIVATE)
    979   1.1.1.4  mrg 	  {
    980   1.1.1.4  mrg 	    size_t align = (size_t) 1 << (kinds[i] >> 8);
    981   1.1.1.4  mrg 	    tgt_size = (tgt_size + align - 1) & ~(align - 1);
    982   1.1.1.4  mrg 	    memcpy (tgt + tgt_size, hostaddrs[i], sizes[i]);
    983   1.1.1.4  mrg 	    ttask->hostaddrs[i] = tgt + tgt_size;
    984   1.1.1.4  mrg 	    tgt_size = tgt_size + sizes[i];
    985   1.1.1.4  mrg 	  }
    986   1.1.1.4  mrg     }
    987   1.1.1.4  mrg   ttask->flags = flags;
    988   1.1.1.4  mrg   ttask->state = state;
    989   1.1.1.4  mrg   ttask->task = task;
    990   1.1.1.4  mrg   ttask->team = team;
    991   1.1.1.4  mrg   task->fn = NULL;
    992   1.1.1.4  mrg   task->fn_data = ttask;
    993   1.1.1.4  mrg   task->final_task = 0;
    994   1.1.1.4  mrg   gomp_mutex_lock (&team->task_lock);
    995   1.1.1.4  mrg   /* If parallel or taskgroup has been cancelled, don't start new tasks.  */
    996   1.1.1.9  mrg   if (__builtin_expect (gomp_cancel_var, 0))
    997   1.1.1.4  mrg     {
    998   1.1.1.9  mrg       if (gomp_team_barrier_cancelled (&team->barrier))
    999   1.1.1.9  mrg 	{
   1000   1.1.1.9  mrg 	do_cancel:
   1001   1.1.1.9  mrg 	  gomp_mutex_unlock (&team->task_lock);
   1002   1.1.1.9  mrg 	  gomp_finish_task (task);
   1003   1.1.1.9  mrg 	  free (task);
   1004   1.1.1.9  mrg 	  return true;
   1005   1.1.1.9  mrg 	}
   1006   1.1.1.9  mrg       if (taskgroup)
   1007   1.1.1.9  mrg 	{
   1008   1.1.1.9  mrg 	  if (taskgroup->cancelled)
   1009   1.1.1.9  mrg 	    goto do_cancel;
   1010   1.1.1.9  mrg 	  if (taskgroup->workshare
   1011   1.1.1.9  mrg 	      && taskgroup->prev
   1012   1.1.1.9  mrg 	      && taskgroup->prev->cancelled)
   1013   1.1.1.9  mrg 	    goto do_cancel;
   1014   1.1.1.9  mrg 	}
   1015   1.1.1.4  mrg     }
   1016   1.1.1.4  mrg   if (depend_size)
   1017   1.1.1.4  mrg     {
   1018   1.1.1.4  mrg       gomp_task_handle_depend (task, parent, depend);
   1019   1.1.1.4  mrg       if (task->num_dependees)
   1020   1.1.1.4  mrg 	{
   1021   1.1.1.4  mrg 	  if (taskgroup)
   1022   1.1.1.4  mrg 	    taskgroup->num_children++;
   1023   1.1.1.4  mrg 	  gomp_mutex_unlock (&team->task_lock);
   1024   1.1.1.4  mrg 	  return true;
   1025   1.1.1.4  mrg 	}
   1026   1.1.1.4  mrg     }
   1027   1.1.1.4  mrg   if (state == GOMP_TARGET_TASK_DATA)
   1028   1.1.1.4  mrg     {
   1029   1.1.1.4  mrg       gomp_task_run_post_handle_depend_hash (task);
   1030   1.1.1.4  mrg       gomp_mutex_unlock (&team->task_lock);
   1031   1.1.1.4  mrg       gomp_finish_task (task);
   1032   1.1.1.4  mrg       free (task);
   1033   1.1.1.4  mrg       return false;
   1034   1.1.1.3  mrg     }
   1035   1.1.1.4  mrg   if (taskgroup)
   1036   1.1.1.4  mrg     taskgroup->num_children++;
   1037   1.1.1.4  mrg   /* For async offloading, if we don't need to wait for dependencies,
   1038   1.1.1.4  mrg      run the gomp_target_task_fn right away, essentially schedule the
   1039   1.1.1.4  mrg      mapping part of the task in the current thread.  */
   1040   1.1.1.4  mrg   if (devicep != NULL
   1041   1.1.1.4  mrg       && (devicep->capabilities & GOMP_OFFLOAD_CAP_OPENMP_400))
   1042   1.1.1.4  mrg     {
   1043   1.1.1.4  mrg       priority_queue_insert (PQ_CHILDREN, &parent->children_queue, task, 0,
   1044   1.1.1.4  mrg 			     PRIORITY_INSERT_END,
   1045   1.1.1.4  mrg 			     /*adjust_parent_depends_on=*/false,
   1046   1.1.1.4  mrg 			     task->parent_depends_on);
   1047   1.1.1.4  mrg       if (taskgroup)
   1048   1.1.1.4  mrg 	priority_queue_insert (PQ_TASKGROUP, &taskgroup->taskgroup_queue,
   1049   1.1.1.4  mrg 			       task, 0, PRIORITY_INSERT_END,
   1050   1.1.1.4  mrg 			       /*adjust_parent_depends_on=*/false,
   1051   1.1.1.4  mrg 			       task->parent_depends_on);
   1052   1.1.1.4  mrg       task->pnode[PQ_TEAM].next = NULL;
   1053   1.1.1.4  mrg       task->pnode[PQ_TEAM].prev = NULL;
   1054   1.1.1.4  mrg       task->kind = GOMP_TASK_TIED;
   1055   1.1.1.4  mrg       ++team->task_count;
   1056   1.1.1.4  mrg       gomp_mutex_unlock (&team->task_lock);
   1057   1.1.1.4  mrg 
   1058   1.1.1.4  mrg       thr->task = task;
   1059   1.1.1.4  mrg       gomp_target_task_fn (task->fn_data);
   1060   1.1.1.4  mrg       thr->task = parent;
   1061   1.1.1.4  mrg 
   1062   1.1.1.4  mrg       gomp_mutex_lock (&team->task_lock);
   1063   1.1.1.4  mrg       task->kind = GOMP_TASK_ASYNC_RUNNING;
   1064   1.1.1.4  mrg       /* If GOMP_PLUGIN_target_task_completion has run already
   1065   1.1.1.4  mrg 	 in between gomp_target_task_fn and the mutex lock,
   1066   1.1.1.4  mrg 	 perform the requeuing here.  */
   1067   1.1.1.4  mrg       if (ttask->state == GOMP_TARGET_TASK_FINISHED)
   1068   1.1.1.4  mrg 	gomp_target_task_completion (team, task);
   1069   1.1.1.4  mrg       else
   1070   1.1.1.4  mrg 	ttask->state = GOMP_TARGET_TASK_RUNNING;
   1071   1.1.1.4  mrg       gomp_mutex_unlock (&team->task_lock);
   1072   1.1.1.4  mrg       return true;
   1073   1.1.1.4  mrg     }
   1074   1.1.1.4  mrg   priority_queue_insert (PQ_CHILDREN, &parent->children_queue, task, 0,
   1075   1.1.1.4  mrg 			 PRIORITY_INSERT_BEGIN,
   1076   1.1.1.4  mrg 			 /*adjust_parent_depends_on=*/false,
   1077   1.1.1.4  mrg 			 task->parent_depends_on);
   1078   1.1.1.4  mrg   if (taskgroup)
   1079   1.1.1.4  mrg     priority_queue_insert (PQ_TASKGROUP, &taskgroup->taskgroup_queue, task, 0,
   1080   1.1.1.4  mrg 			   PRIORITY_INSERT_BEGIN,
   1081   1.1.1.4  mrg 			   /*adjust_parent_depends_on=*/false,
   1082   1.1.1.4  mrg 			   task->parent_depends_on);
   1083   1.1.1.4  mrg   priority_queue_insert (PQ_TEAM, &team->task_queue, task, 0,
   1084   1.1.1.4  mrg 			 PRIORITY_INSERT_END,
   1085   1.1.1.4  mrg 			 /*adjust_parent_depends_on=*/false,
   1086   1.1.1.4  mrg 			 task->parent_depends_on);
   1087   1.1.1.4  mrg   ++team->task_count;
   1088   1.1.1.4  mrg   ++team->task_queued_count;
   1089   1.1.1.4  mrg   gomp_team_barrier_set_task_pending (&team->barrier);
   1090   1.1.1.4  mrg   do_wake = team->task_running_count + !parent->in_tied_task
   1091   1.1.1.4  mrg 	    < team->nthreads;
   1092   1.1.1.4  mrg   gomp_mutex_unlock (&team->task_lock);
   1093   1.1.1.4  mrg   if (do_wake)
   1094   1.1.1.4  mrg     gomp_team_barrier_wake (&team->barrier, 1);
   1095   1.1.1.4  mrg   return true;
   1096   1.1.1.4  mrg }
   1097   1.1.1.4  mrg 
   1098   1.1.1.4  mrg /* Given a parent_depends_on task in LIST, move it to the front of its
   1099   1.1.1.4  mrg    priority so it is run as soon as possible.
   1100   1.1.1.4  mrg 
   1101   1.1.1.4  mrg    Care is taken to update the list's LAST_PARENT_DEPENDS_ON field.
   1102   1.1.1.4  mrg 
   1103   1.1.1.4  mrg    We rearrange the queue such that all parent_depends_on tasks are
   1104   1.1.1.4  mrg    first, and last_parent_depends_on points to the last such task we
   1105   1.1.1.4  mrg    rearranged.  For example, given the following tasks in a queue
   1106   1.1.1.4  mrg    where PD[123] are the parent_depends_on tasks:
   1107   1.1.1.4  mrg 
   1108   1.1.1.4  mrg 	task->children
   1109   1.1.1.4  mrg 	|
   1110   1.1.1.4  mrg 	V
   1111   1.1.1.4  mrg 	C1 -> C2 -> C3 -> PD1 -> PD2 -> PD3 -> C4
   1112   1.1.1.4  mrg 
   1113   1.1.1.4  mrg 	We rearrange such that:
   1114   1.1.1.4  mrg 
   1115   1.1.1.4  mrg 	task->children
   1116   1.1.1.4  mrg 	|	       +--- last_parent_depends_on
   1117   1.1.1.4  mrg 	|	       |
   1118   1.1.1.4  mrg 	V	       V
   1119   1.1.1.4  mrg 	PD1 -> PD2 -> PD3 -> C1 -> C2 -> C3 -> C4.  */
   1120   1.1.1.4  mrg 
   1121   1.1.1.4  mrg static void inline
   1122   1.1.1.4  mrg priority_list_upgrade_task (struct priority_list *list,
   1123   1.1.1.4  mrg 			    struct priority_node *node)
   1124   1.1.1.4  mrg {
   1125   1.1.1.4  mrg   struct priority_node *last_parent_depends_on
   1126   1.1.1.4  mrg     = list->last_parent_depends_on;
   1127   1.1.1.4  mrg   if (last_parent_depends_on)
   1128   1.1.1.4  mrg     {
   1129   1.1.1.4  mrg       node->prev->next = node->next;
   1130   1.1.1.4  mrg       node->next->prev = node->prev;
   1131   1.1.1.4  mrg       node->prev = last_parent_depends_on;
   1132   1.1.1.4  mrg       node->next = last_parent_depends_on->next;
   1133   1.1.1.4  mrg       node->prev->next = node;
   1134   1.1.1.4  mrg       node->next->prev = node;
   1135   1.1.1.4  mrg     }
   1136   1.1.1.4  mrg   else if (node != list->tasks)
   1137   1.1.1.4  mrg     {
   1138   1.1.1.4  mrg       node->prev->next = node->next;
   1139   1.1.1.4  mrg       node->next->prev = node->prev;
   1140   1.1.1.4  mrg       node->prev = list->tasks->prev;
   1141   1.1.1.4  mrg       node->next = list->tasks;
   1142   1.1.1.4  mrg       list->tasks = node;
   1143   1.1.1.4  mrg       node->prev->next = node;
   1144   1.1.1.4  mrg       node->next->prev = node;
   1145   1.1.1.4  mrg     }
   1146   1.1.1.4  mrg   list->last_parent_depends_on = node;
   1147   1.1.1.4  mrg }
   1148   1.1.1.4  mrg 
   1149   1.1.1.4  mrg /* Given a parent_depends_on TASK in its parent's children_queue, move
   1150   1.1.1.4  mrg    it to the front of its priority so it is run as soon as possible.
   1151   1.1.1.4  mrg 
   1152   1.1.1.4  mrg    PARENT is passed as an optimization.
   1153   1.1.1.4  mrg 
   1154   1.1.1.4  mrg    (This function could be defined in priority_queue.c, but we want it
   1155   1.1.1.4  mrg    inlined, and putting it in priority_queue.h is not an option, given
   1156   1.1.1.4  mrg    that gomp_task has not been properly defined at that point).  */
   1157   1.1.1.4  mrg 
   1158   1.1.1.4  mrg static void inline
   1159   1.1.1.4  mrg priority_queue_upgrade_task (struct gomp_task *task,
   1160   1.1.1.4  mrg 			     struct gomp_task *parent)
   1161   1.1.1.4  mrg {
   1162   1.1.1.4  mrg   struct priority_queue *head = &parent->children_queue;
   1163   1.1.1.4  mrg   struct priority_node *node = &task->pnode[PQ_CHILDREN];
   1164   1.1.1.4  mrg #if _LIBGOMP_CHECKING_
   1165   1.1.1.4  mrg   if (!task->parent_depends_on)
   1166   1.1.1.4  mrg     gomp_fatal ("priority_queue_upgrade_task: task must be a "
   1167   1.1.1.4  mrg 		"parent_depends_on task");
   1168   1.1.1.4  mrg   if (!priority_queue_task_in_queue_p (PQ_CHILDREN, head, task))
   1169   1.1.1.4  mrg     gomp_fatal ("priority_queue_upgrade_task: cannot find task=%p", task);
   1170   1.1.1.4  mrg #endif
   1171   1.1.1.4  mrg   if (priority_queue_multi_p (head))
   1172   1.1.1.4  mrg     {
   1173   1.1.1.4  mrg       struct priority_list *list
   1174   1.1.1.4  mrg 	= priority_queue_lookup_priority (head, task->priority);
   1175   1.1.1.4  mrg       priority_list_upgrade_task (list, node);
   1176   1.1.1.4  mrg     }
   1177   1.1.1.4  mrg   else
   1178   1.1.1.4  mrg     priority_list_upgrade_task (&head->l, node);
   1179   1.1.1.4  mrg }
   1180   1.1.1.4  mrg 
   1181   1.1.1.4  mrg /* Given a CHILD_TASK in LIST that is about to be executed, move it out of
   1182   1.1.1.4  mrg    the way in LIST so that other tasks can be considered for
   1183   1.1.1.4  mrg    execution.  LIST contains tasks of type TYPE.
   1184   1.1.1.4  mrg 
   1185   1.1.1.4  mrg    Care is taken to update the queue's LAST_PARENT_DEPENDS_ON field
   1186   1.1.1.4  mrg    if applicable.  */
   1187   1.1.1.4  mrg 
   1188   1.1.1.4  mrg static void inline
   1189   1.1.1.4  mrg priority_list_downgrade_task (enum priority_queue_type type,
   1190   1.1.1.4  mrg 			      struct priority_list *list,
   1191   1.1.1.4  mrg 			      struct gomp_task *child_task)
   1192   1.1.1.4  mrg {
   1193   1.1.1.4  mrg   struct priority_node *node = task_to_priority_node (type, child_task);
   1194   1.1.1.4  mrg   if (list->tasks == node)
   1195   1.1.1.4  mrg     list->tasks = node->next;
   1196   1.1.1.4  mrg   else if (node->next != list->tasks)
   1197   1.1.1.4  mrg     {
   1198   1.1.1.4  mrg       /* The task in NODE is about to become TIED and TIED tasks
   1199   1.1.1.4  mrg 	 cannot come before WAITING tasks.  If we're about to
   1200   1.1.1.4  mrg 	 leave the queue in such an indeterminate state, rewire
   1201   1.1.1.4  mrg 	 things appropriately.  However, a TIED task at the end is
   1202   1.1.1.4  mrg 	 perfectly fine.  */
   1203   1.1.1.4  mrg       struct gomp_task *next_task = priority_node_to_task (type, node->next);
   1204   1.1.1.4  mrg       if (next_task->kind == GOMP_TASK_WAITING)
   1205   1.1.1.4  mrg 	{
   1206   1.1.1.4  mrg 	  /* Remove from list.  */
   1207   1.1.1.4  mrg 	  node->prev->next = node->next;
   1208   1.1.1.4  mrg 	  node->next->prev = node->prev;
   1209   1.1.1.4  mrg 	  /* Rewire at the end.  */
   1210   1.1.1.4  mrg 	  node->next = list->tasks;
   1211   1.1.1.4  mrg 	  node->prev = list->tasks->prev;
   1212   1.1.1.4  mrg 	  list->tasks->prev->next = node;
   1213   1.1.1.4  mrg 	  list->tasks->prev = node;
   1214   1.1.1.4  mrg 	}
   1215   1.1.1.4  mrg     }
   1216   1.1.1.4  mrg 
   1217   1.1.1.4  mrg   /* If the current task is the last_parent_depends_on for its
   1218   1.1.1.4  mrg      priority, adjust last_parent_depends_on appropriately.  */
   1219   1.1.1.4  mrg   if (__builtin_expect (child_task->parent_depends_on, 0)
   1220   1.1.1.4  mrg       && list->last_parent_depends_on == node)
   1221   1.1.1.4  mrg     {
   1222   1.1.1.4  mrg       struct gomp_task *prev_child = priority_node_to_task (type, node->prev);
   1223   1.1.1.4  mrg       if (node->prev != node
   1224   1.1.1.4  mrg 	  && prev_child->kind == GOMP_TASK_WAITING
   1225   1.1.1.4  mrg 	  && prev_child->parent_depends_on)
   1226   1.1.1.4  mrg 	list->last_parent_depends_on = node->prev;
   1227   1.1.1.4  mrg       else
   1228   1.1.1.4  mrg 	{
   1229   1.1.1.4  mrg 	  /* There are no more parent_depends_on entries waiting
   1230   1.1.1.4  mrg 	     to run, clear the list.  */
   1231   1.1.1.4  mrg 	  list->last_parent_depends_on = NULL;
   1232   1.1.1.4  mrg 	}
   1233   1.1.1.4  mrg     }
   1234   1.1.1.4  mrg }
   1235   1.1.1.4  mrg 
   1236   1.1.1.4  mrg /* Given a TASK in HEAD that is about to be executed, move it out of
   1237   1.1.1.4  mrg    the way so that other tasks can be considered for execution.  HEAD
   1238   1.1.1.4  mrg    contains tasks of type TYPE.
   1239   1.1.1.4  mrg 
   1240   1.1.1.4  mrg    Care is taken to update the queue's LAST_PARENT_DEPENDS_ON field
   1241   1.1.1.4  mrg    if applicable.
   1242   1.1.1.4  mrg 
   1243   1.1.1.4  mrg    (This function could be defined in priority_queue.c, but we want it
   1244   1.1.1.4  mrg    inlined, and putting it in priority_queue.h is not an option, given
   1245   1.1.1.4  mrg    that gomp_task has not been properly defined at that point).  */
   1246   1.1.1.4  mrg 
   1247   1.1.1.4  mrg static void inline
   1248   1.1.1.4  mrg priority_queue_downgrade_task (enum priority_queue_type type,
   1249   1.1.1.4  mrg 			       struct priority_queue *head,
   1250   1.1.1.4  mrg 			       struct gomp_task *task)
   1251   1.1.1.4  mrg {
   1252   1.1.1.4  mrg #if _LIBGOMP_CHECKING_
   1253   1.1.1.4  mrg   if (!priority_queue_task_in_queue_p (type, head, task))
   1254   1.1.1.4  mrg     gomp_fatal ("Attempt to downgrade missing task %p", task);
   1255   1.1.1.4  mrg #endif
   1256   1.1.1.4  mrg   if (priority_queue_multi_p (head))
   1257   1.1.1.4  mrg     {
   1258   1.1.1.4  mrg       struct priority_list *list
   1259   1.1.1.4  mrg 	= priority_queue_lookup_priority (head, task->priority);
   1260   1.1.1.4  mrg       priority_list_downgrade_task (type, list, task);
   1261   1.1.1.4  mrg     }
   1262   1.1.1.4  mrg   else
   1263   1.1.1.4  mrg     priority_list_downgrade_task (type, &head->l, task);
   1264   1.1.1.4  mrg }
   1265   1.1.1.4  mrg 
   1266   1.1.1.4  mrg /* Setup CHILD_TASK to execute.  This is done by setting the task to
   1267   1.1.1.4  mrg    TIED, and updating all relevant queues so that CHILD_TASK is no
   1268   1.1.1.4  mrg    longer chosen for scheduling.  Also, remove CHILD_TASK from the
   1269   1.1.1.4  mrg    overall team task queue entirely.
   1270   1.1.1.4  mrg 
   1271   1.1.1.4  mrg    Return TRUE if task or its containing taskgroup has been
   1272   1.1.1.4  mrg    cancelled.  */
   1273   1.1.1.4  mrg 
   1274   1.1.1.4  mrg static inline bool
   1275   1.1.1.4  mrg gomp_task_run_pre (struct gomp_task *child_task, struct gomp_task *parent,
   1276   1.1.1.4  mrg 		   struct gomp_team *team)
   1277   1.1.1.4  mrg {
   1278   1.1.1.4  mrg #if _LIBGOMP_CHECKING_
   1279   1.1.1.4  mrg   if (child_task->parent)
   1280   1.1.1.4  mrg     priority_queue_verify (PQ_CHILDREN,
   1281   1.1.1.4  mrg 			   &child_task->parent->children_queue, true);
   1282   1.1.1.4  mrg   if (child_task->taskgroup)
   1283   1.1.1.4  mrg     priority_queue_verify (PQ_TASKGROUP,
   1284   1.1.1.4  mrg 			   &child_task->taskgroup->taskgroup_queue, false);
   1285   1.1.1.4  mrg   priority_queue_verify (PQ_TEAM, &team->task_queue, false);
   1286   1.1.1.4  mrg #endif
   1287   1.1.1.4  mrg 
   1288   1.1.1.4  mrg   /* Task is about to go tied, move it out of the way.  */
   1289   1.1.1.4  mrg   if (parent)
   1290   1.1.1.4  mrg     priority_queue_downgrade_task (PQ_CHILDREN, &parent->children_queue,
   1291   1.1.1.4  mrg 				   child_task);
   1292   1.1.1.4  mrg 
   1293   1.1.1.4  mrg   /* Task is about to go tied, move it out of the way.  */
   1294   1.1.1.4  mrg   struct gomp_taskgroup *taskgroup = child_task->taskgroup;
   1295   1.1.1.4  mrg   if (taskgroup)
   1296   1.1.1.4  mrg     priority_queue_downgrade_task (PQ_TASKGROUP, &taskgroup->taskgroup_queue,
   1297   1.1.1.4  mrg 				   child_task);
   1298   1.1.1.4  mrg 
   1299   1.1.1.4  mrg   priority_queue_remove (PQ_TEAM, &team->task_queue, child_task,
   1300   1.1.1.4  mrg 			 MEMMODEL_RELAXED);
   1301   1.1.1.4  mrg   child_task->pnode[PQ_TEAM].next = NULL;
   1302   1.1.1.4  mrg   child_task->pnode[PQ_TEAM].prev = NULL;
   1303   1.1.1.3  mrg   child_task->kind = GOMP_TASK_TIED;
   1304   1.1.1.4  mrg 
   1305   1.1.1.3  mrg   if (--team->task_queued_count == 0)
   1306   1.1.1.3  mrg     gomp_team_barrier_clear_task_pending (&team->barrier);
   1307   1.1.1.9  mrg   if (__builtin_expect (gomp_cancel_var, 0)
   1308   1.1.1.3  mrg       && !child_task->copy_ctors_done)
   1309   1.1.1.9  mrg     {
   1310   1.1.1.9  mrg       if (gomp_team_barrier_cancelled (&team->barrier))
   1311   1.1.1.9  mrg 	return true;
   1312   1.1.1.9  mrg       if (taskgroup)
   1313   1.1.1.9  mrg 	{
   1314   1.1.1.9  mrg 	  if (taskgroup->cancelled)
   1315   1.1.1.9  mrg 	    return true;
   1316   1.1.1.9  mrg 	  if (taskgroup->workshare
   1317   1.1.1.9  mrg 	      && taskgroup->prev
   1318   1.1.1.9  mrg 	      && taskgroup->prev->cancelled)
   1319   1.1.1.9  mrg 	    return true;
   1320   1.1.1.9  mrg 	}
   1321   1.1.1.9  mrg     }
   1322   1.1.1.3  mrg   return false;
   1323   1.1.1.3  mrg }
   1324   1.1.1.3  mrg 
   1325   1.1.1.3  mrg static void
   1326   1.1.1.3  mrg gomp_task_run_post_handle_depend_hash (struct gomp_task *child_task)
   1327   1.1.1.3  mrg {
   1328   1.1.1.3  mrg   struct gomp_task *parent = child_task->parent;
   1329   1.1.1.3  mrg   size_t i;
   1330   1.1.1.3  mrg 
   1331  1.1.1.14  mrg   if (parent->depend_all_memory == child_task)
   1332  1.1.1.14  mrg     parent->depend_all_memory = NULL;
   1333   1.1.1.3  mrg   for (i = 0; i < child_task->depend_count; i++)
   1334   1.1.1.3  mrg     if (!child_task->depend[i].redundant)
   1335   1.1.1.3  mrg       {
   1336   1.1.1.3  mrg 	if (child_task->depend[i].next)
   1337   1.1.1.3  mrg 	  child_task->depend[i].next->prev = child_task->depend[i].prev;
   1338   1.1.1.3  mrg 	if (child_task->depend[i].prev)
   1339   1.1.1.3  mrg 	  child_task->depend[i].prev->next = child_task->depend[i].next;
   1340   1.1.1.3  mrg 	else
   1341   1.1.1.3  mrg 	  {
   1342   1.1.1.3  mrg 	    hash_entry_type *slot
   1343   1.1.1.3  mrg 	      = htab_find_slot (&parent->depend_hash, &child_task->depend[i],
   1344   1.1.1.3  mrg 				NO_INSERT);
   1345   1.1.1.3  mrg 	    if (*slot != &child_task->depend[i])
   1346   1.1.1.3  mrg 	      abort ();
   1347   1.1.1.3  mrg 	    if (child_task->depend[i].next)
   1348   1.1.1.3  mrg 	      *slot = child_task->depend[i].next;
   1349   1.1.1.3  mrg 	    else
   1350   1.1.1.3  mrg 	      htab_clear_slot (parent->depend_hash, slot);
   1351   1.1.1.3  mrg 	  }
   1352   1.1.1.3  mrg       }
   1353   1.1.1.3  mrg }
   1354   1.1.1.3  mrg 
   1355   1.1.1.4  mrg /* After a CHILD_TASK has been run, adjust the dependency queue for
   1356   1.1.1.4  mrg    each task that depends on CHILD_TASK, to record the fact that there
   1357   1.1.1.4  mrg    is one less dependency to worry about.  If a task that depended on
   1358   1.1.1.4  mrg    CHILD_TASK now has no dependencies, place it in the various queues
   1359   1.1.1.4  mrg    so it gets scheduled to run.
   1360   1.1.1.4  mrg 
   1361   1.1.1.4  mrg    TEAM is the team to which CHILD_TASK belongs to.  */
   1362   1.1.1.4  mrg 
   1363   1.1.1.3  mrg static size_t
   1364   1.1.1.3  mrg gomp_task_run_post_handle_dependers (struct gomp_task *child_task,
   1365   1.1.1.3  mrg 				     struct gomp_team *team)
   1366   1.1.1.3  mrg {
   1367   1.1.1.3  mrg   struct gomp_task *parent = child_task->parent;
   1368   1.1.1.3  mrg   size_t i, count = child_task->dependers->n_elem, ret = 0;
   1369   1.1.1.3  mrg   for (i = 0; i < count; i++)
   1370   1.1.1.3  mrg     {
   1371   1.1.1.3  mrg       struct gomp_task *task = child_task->dependers->elem[i];
   1372   1.1.1.4  mrg 
   1373   1.1.1.4  mrg       /* CHILD_TASK satisfies a dependency for TASK.  Keep track of
   1374   1.1.1.4  mrg 	 TASK's remaining dependencies.  Once TASK has no other
   1375  1.1.1.10  mrg 	 dependencies, put it into the various queues so it will get
   1376   1.1.1.4  mrg 	 scheduled for execution.  */
   1377   1.1.1.3  mrg       if (--task->num_dependees != 0)
   1378   1.1.1.3  mrg 	continue;
   1379   1.1.1.3  mrg 
   1380   1.1.1.3  mrg       struct gomp_taskgroup *taskgroup = task->taskgroup;
   1381  1.1.1.14  mrg       if (__builtin_expect (task->fn == empty_task, 0))
   1382  1.1.1.14  mrg 	{
   1383  1.1.1.14  mrg 	  if (!parent)
   1384  1.1.1.14  mrg 	    task->parent = NULL;
   1385  1.1.1.14  mrg 	  else if (__builtin_expect (task->parent_depends_on, 0)
   1386  1.1.1.14  mrg 		   && --parent->taskwait->n_depend == 0
   1387  1.1.1.14  mrg 		   && parent->taskwait->in_depend_wait)
   1388  1.1.1.14  mrg 	    {
   1389  1.1.1.14  mrg 	      parent->taskwait->in_depend_wait = false;
   1390  1.1.1.14  mrg 	      gomp_sem_post (&parent->taskwait->taskwait_sem);
   1391  1.1.1.14  mrg 	    }
   1392  1.1.1.14  mrg 	  if (gomp_task_run_post_handle_depend (task, team))
   1393  1.1.1.14  mrg 	    ++ret;
   1394  1.1.1.14  mrg 	  if (taskgroup)
   1395  1.1.1.14  mrg 	    {
   1396  1.1.1.14  mrg 	      if (taskgroup->num_children > 1)
   1397  1.1.1.14  mrg 		--taskgroup->num_children;
   1398  1.1.1.14  mrg 	      else
   1399  1.1.1.14  mrg 		{
   1400  1.1.1.14  mrg 		  __atomic_store_n (&taskgroup->num_children, 0,
   1401  1.1.1.14  mrg 				    MEMMODEL_RELEASE);
   1402  1.1.1.14  mrg 		  if (taskgroup->in_taskgroup_wait)
   1403  1.1.1.14  mrg 		    {
   1404  1.1.1.14  mrg 		      taskgroup->in_taskgroup_wait = false;
   1405  1.1.1.14  mrg 		      gomp_sem_post (&taskgroup->taskgroup_sem);
   1406  1.1.1.14  mrg 		    }
   1407  1.1.1.14  mrg 		}
   1408  1.1.1.14  mrg 	    }
   1409  1.1.1.14  mrg 	  gomp_finish_task (task);
   1410  1.1.1.14  mrg 	  free (task);
   1411  1.1.1.14  mrg 	  continue;
   1412  1.1.1.14  mrg 	}
   1413   1.1.1.3  mrg       if (parent)
   1414   1.1.1.3  mrg 	{
   1415   1.1.1.4  mrg 	  priority_queue_insert (PQ_CHILDREN, &parent->children_queue,
   1416   1.1.1.4  mrg 				 task, task->priority,
   1417   1.1.1.4  mrg 				 PRIORITY_INSERT_BEGIN,
   1418   1.1.1.4  mrg 				 /*adjust_parent_depends_on=*/true,
   1419   1.1.1.4  mrg 				 task->parent_depends_on);
   1420   1.1.1.3  mrg 	  if (parent->taskwait)
   1421   1.1.1.3  mrg 	    {
   1422   1.1.1.3  mrg 	      if (parent->taskwait->in_taskwait)
   1423   1.1.1.3  mrg 		{
   1424   1.1.1.4  mrg 		  /* One more task has had its dependencies met.
   1425   1.1.1.4  mrg 		     Inform any waiters.  */
   1426   1.1.1.3  mrg 		  parent->taskwait->in_taskwait = false;
   1427   1.1.1.3  mrg 		  gomp_sem_post (&parent->taskwait->taskwait_sem);
   1428   1.1.1.3  mrg 		}
   1429   1.1.1.3  mrg 	      else if (parent->taskwait->in_depend_wait)
   1430   1.1.1.3  mrg 		{
   1431   1.1.1.4  mrg 		  /* One more task has had its dependencies met.
   1432   1.1.1.4  mrg 		     Inform any waiters.  */
   1433   1.1.1.3  mrg 		  parent->taskwait->in_depend_wait = false;
   1434   1.1.1.3  mrg 		  gomp_sem_post (&parent->taskwait->taskwait_sem);
   1435   1.1.1.3  mrg 		}
   1436   1.1.1.3  mrg 	    }
   1437   1.1.1.3  mrg 	}
   1438  1.1.1.11  mrg       else
   1439  1.1.1.11  mrg 	task->parent = NULL;
   1440   1.1.1.3  mrg       if (taskgroup)
   1441   1.1.1.3  mrg 	{
   1442   1.1.1.4  mrg 	  priority_queue_insert (PQ_TASKGROUP, &taskgroup->taskgroup_queue,
   1443   1.1.1.4  mrg 				 task, task->priority,
   1444   1.1.1.4  mrg 				 PRIORITY_INSERT_BEGIN,
   1445   1.1.1.4  mrg 				 /*adjust_parent_depends_on=*/false,
   1446   1.1.1.4  mrg 				 task->parent_depends_on);
   1447   1.1.1.3  mrg 	  if (taskgroup->in_taskgroup_wait)
   1448   1.1.1.3  mrg 	    {
   1449   1.1.1.4  mrg 	      /* One more task has had its dependencies met.
   1450   1.1.1.4  mrg 		 Inform any waiters.  */
   1451   1.1.1.3  mrg 	      taskgroup->in_taskgroup_wait = false;
   1452   1.1.1.3  mrg 	      gomp_sem_post (&taskgroup->taskgroup_sem);
   1453   1.1.1.3  mrg 	    }
   1454   1.1.1.3  mrg 	}
   1455   1.1.1.4  mrg       priority_queue_insert (PQ_TEAM, &team->task_queue,
   1456   1.1.1.4  mrg 			     task, task->priority,
   1457   1.1.1.4  mrg 			     PRIORITY_INSERT_END,
   1458   1.1.1.4  mrg 			     /*adjust_parent_depends_on=*/false,
   1459   1.1.1.4  mrg 			     task->parent_depends_on);
   1460   1.1.1.3  mrg       ++team->task_count;
   1461   1.1.1.3  mrg       ++team->task_queued_count;
   1462   1.1.1.3  mrg       ++ret;
   1463   1.1.1.3  mrg     }
   1464   1.1.1.3  mrg   free (child_task->dependers);
   1465   1.1.1.3  mrg   child_task->dependers = NULL;
   1466   1.1.1.3  mrg   if (ret > 1)
   1467   1.1.1.3  mrg     gomp_team_barrier_set_task_pending (&team->barrier);
   1468   1.1.1.3  mrg   return ret;
   1469   1.1.1.3  mrg }
   1470   1.1.1.3  mrg 
   1471   1.1.1.3  mrg static inline size_t
   1472   1.1.1.3  mrg gomp_task_run_post_handle_depend (struct gomp_task *child_task,
   1473   1.1.1.3  mrg 				  struct gomp_team *team)
   1474   1.1.1.3  mrg {
   1475   1.1.1.3  mrg   if (child_task->depend_count == 0)
   1476   1.1.1.3  mrg     return 0;
   1477   1.1.1.3  mrg 
   1478   1.1.1.3  mrg   /* If parent is gone already, the hash table is freed and nothing
   1479   1.1.1.3  mrg      will use the hash table anymore, no need to remove anything from it.  */
   1480   1.1.1.3  mrg   if (child_task->parent != NULL)
   1481   1.1.1.3  mrg     gomp_task_run_post_handle_depend_hash (child_task);
   1482   1.1.1.3  mrg 
   1483   1.1.1.3  mrg   if (child_task->dependers == NULL)
   1484   1.1.1.3  mrg     return 0;
   1485   1.1.1.3  mrg 
   1486   1.1.1.3  mrg   return gomp_task_run_post_handle_dependers (child_task, team);
   1487   1.1.1.3  mrg }
   1488   1.1.1.3  mrg 
   1489   1.1.1.4  mrg /* Remove CHILD_TASK from its parent.  */
   1490   1.1.1.4  mrg 
   1491   1.1.1.3  mrg static inline void
   1492   1.1.1.3  mrg gomp_task_run_post_remove_parent (struct gomp_task *child_task)
   1493   1.1.1.3  mrg {
   1494   1.1.1.3  mrg   struct gomp_task *parent = child_task->parent;
   1495   1.1.1.3  mrg   if (parent == NULL)
   1496   1.1.1.3  mrg     return;
   1497   1.1.1.4  mrg 
   1498   1.1.1.4  mrg   /* If this was the last task the parent was depending on,
   1499   1.1.1.4  mrg      synchronize with gomp_task_maybe_wait_for_dependencies so it can
   1500   1.1.1.4  mrg      clean up and return.  */
   1501   1.1.1.3  mrg   if (__builtin_expect (child_task->parent_depends_on, 0)
   1502   1.1.1.3  mrg       && --parent->taskwait->n_depend == 0
   1503   1.1.1.3  mrg       && parent->taskwait->in_depend_wait)
   1504   1.1.1.3  mrg     {
   1505   1.1.1.3  mrg       parent->taskwait->in_depend_wait = false;
   1506   1.1.1.3  mrg       gomp_sem_post (&parent->taskwait->taskwait_sem);
   1507   1.1.1.3  mrg     }
   1508   1.1.1.4  mrg 
   1509   1.1.1.4  mrg   if (priority_queue_remove (PQ_CHILDREN, &parent->children_queue,
   1510   1.1.1.4  mrg 			     child_task, MEMMODEL_RELEASE)
   1511   1.1.1.4  mrg       && parent->taskwait && parent->taskwait->in_taskwait)
   1512   1.1.1.3  mrg     {
   1513   1.1.1.4  mrg       parent->taskwait->in_taskwait = false;
   1514   1.1.1.4  mrg       gomp_sem_post (&parent->taskwait->taskwait_sem);
   1515   1.1.1.3  mrg     }
   1516   1.1.1.4  mrg   child_task->pnode[PQ_CHILDREN].next = NULL;
   1517   1.1.1.4  mrg   child_task->pnode[PQ_CHILDREN].prev = NULL;
   1518   1.1.1.3  mrg }
   1519   1.1.1.3  mrg 
   1520   1.1.1.4  mrg /* Remove CHILD_TASK from its taskgroup.  */
   1521   1.1.1.4  mrg 
   1522   1.1.1.3  mrg static inline void
   1523   1.1.1.3  mrg gomp_task_run_post_remove_taskgroup (struct gomp_task *child_task)
   1524   1.1.1.3  mrg {
   1525   1.1.1.3  mrg   struct gomp_taskgroup *taskgroup = child_task->taskgroup;
   1526   1.1.1.3  mrg   if (taskgroup == NULL)
   1527   1.1.1.3  mrg     return;
   1528   1.1.1.4  mrg   bool empty = priority_queue_remove (PQ_TASKGROUP,
   1529   1.1.1.4  mrg 				      &taskgroup->taskgroup_queue,
   1530   1.1.1.4  mrg 				      child_task, MEMMODEL_RELAXED);
   1531   1.1.1.4  mrg   child_task->pnode[PQ_TASKGROUP].next = NULL;
   1532   1.1.1.4  mrg   child_task->pnode[PQ_TASKGROUP].prev = NULL;
   1533   1.1.1.3  mrg   if (taskgroup->num_children > 1)
   1534   1.1.1.3  mrg     --taskgroup->num_children;
   1535   1.1.1.3  mrg   else
   1536   1.1.1.3  mrg     {
   1537   1.1.1.3  mrg       /* We access taskgroup->num_children in GOMP_taskgroup_end
   1538   1.1.1.3  mrg 	 outside of the task lock mutex region, so
   1539   1.1.1.3  mrg 	 need a release barrier here to ensure memory
   1540   1.1.1.3  mrg 	 written by child_task->fn above is flushed
   1541   1.1.1.3  mrg 	 before the NULL is written.  */
   1542   1.1.1.3  mrg       __atomic_store_n (&taskgroup->num_children, 0, MEMMODEL_RELEASE);
   1543   1.1.1.3  mrg     }
   1544   1.1.1.4  mrg   if (empty && taskgroup->in_taskgroup_wait)
   1545   1.1.1.3  mrg     {
   1546   1.1.1.4  mrg       taskgroup->in_taskgroup_wait = false;
   1547   1.1.1.4  mrg       gomp_sem_post (&taskgroup->taskgroup_sem);
   1548   1.1.1.3  mrg     }
   1549   1.1.1.3  mrg }
   1550   1.1.1.3  mrg 
   1551       1.1  mrg void
   1552       1.1  mrg gomp_barrier_handle_tasks (gomp_barrier_state_t state)
   1553       1.1  mrg {
   1554       1.1  mrg   struct gomp_thread *thr = gomp_thread ();
   1555       1.1  mrg   struct gomp_team *team = thr->ts.team;
   1556       1.1  mrg   struct gomp_task *task = thr->task;
   1557       1.1  mrg   struct gomp_task *child_task = NULL;
   1558       1.1  mrg   struct gomp_task *to_free = NULL;
   1559   1.1.1.3  mrg   int do_wake = 0;
   1560       1.1  mrg 
   1561       1.1  mrg   gomp_mutex_lock (&team->task_lock);
   1562       1.1  mrg   if (gomp_barrier_last_thread (state))
   1563       1.1  mrg     {
   1564       1.1  mrg       if (team->task_count == 0)
   1565       1.1  mrg 	{
   1566       1.1  mrg 	  gomp_team_barrier_done (&team->barrier, state);
   1567       1.1  mrg 	  gomp_mutex_unlock (&team->task_lock);
   1568       1.1  mrg 	  gomp_team_barrier_wake (&team->barrier, 0);
   1569       1.1  mrg 	  return;
   1570       1.1  mrg 	}
   1571       1.1  mrg       gomp_team_barrier_set_waiting_for_tasks (&team->barrier);
   1572       1.1  mrg     }
   1573       1.1  mrg 
   1574       1.1  mrg   while (1)
   1575       1.1  mrg     {
   1576   1.1.1.3  mrg       bool cancelled = false;
   1577  1.1.1.13  mrg 
   1578   1.1.1.4  mrg       if (!priority_queue_empty_p (&team->task_queue, MEMMODEL_RELAXED))
   1579       1.1  mrg 	{
   1580   1.1.1.4  mrg 	  bool ignored;
   1581   1.1.1.4  mrg 	  child_task
   1582   1.1.1.4  mrg 	    = priority_queue_next_task (PQ_TEAM, &team->task_queue,
   1583   1.1.1.4  mrg 					PQ_IGNORED, NULL,
   1584   1.1.1.4  mrg 					&ignored);
   1585   1.1.1.3  mrg 	  cancelled = gomp_task_run_pre (child_task, child_task->parent,
   1586   1.1.1.4  mrg 					 team);
   1587   1.1.1.3  mrg 	  if (__builtin_expect (cancelled, 0))
   1588   1.1.1.3  mrg 	    {
   1589   1.1.1.3  mrg 	      if (to_free)
   1590   1.1.1.3  mrg 		{
   1591   1.1.1.3  mrg 		  gomp_finish_task (to_free);
   1592   1.1.1.3  mrg 		  free (to_free);
   1593   1.1.1.3  mrg 		  to_free = NULL;
   1594   1.1.1.3  mrg 		}
   1595   1.1.1.3  mrg 	      goto finish_cancelled;
   1596   1.1.1.3  mrg 	    }
   1597       1.1  mrg 	  team->task_running_count++;
   1598   1.1.1.3  mrg 	  child_task->in_tied_task = true;
   1599       1.1  mrg 	}
   1600  1.1.1.13  mrg       else if (team->task_count == 0
   1601  1.1.1.13  mrg 	       && gomp_team_barrier_waiting_for_tasks (&team->barrier))
   1602  1.1.1.13  mrg 	{
   1603  1.1.1.13  mrg 	  gomp_team_barrier_done (&team->barrier, state);
   1604  1.1.1.13  mrg 	  gomp_mutex_unlock (&team->task_lock);
   1605  1.1.1.13  mrg 	  gomp_team_barrier_wake (&team->barrier, 0);
   1606  1.1.1.13  mrg 	  if (to_free)
   1607  1.1.1.13  mrg 	    {
   1608  1.1.1.13  mrg 	      gomp_finish_task (to_free);
   1609  1.1.1.13  mrg 	      free (to_free);
   1610  1.1.1.13  mrg 	    }
   1611  1.1.1.13  mrg 	  return;
   1612  1.1.1.13  mrg 	}
   1613       1.1  mrg       gomp_mutex_unlock (&team->task_lock);
   1614   1.1.1.3  mrg       if (do_wake)
   1615   1.1.1.3  mrg 	{
   1616   1.1.1.3  mrg 	  gomp_team_barrier_wake (&team->barrier, do_wake);
   1617   1.1.1.3  mrg 	  do_wake = 0;
   1618   1.1.1.3  mrg 	}
   1619       1.1  mrg       if (to_free)
   1620       1.1  mrg 	{
   1621       1.1  mrg 	  gomp_finish_task (to_free);
   1622       1.1  mrg 	  free (to_free);
   1623       1.1  mrg 	  to_free = NULL;
   1624       1.1  mrg 	}
   1625       1.1  mrg       if (child_task)
   1626       1.1  mrg 	{
   1627       1.1  mrg 	  thr->task = child_task;
   1628   1.1.1.4  mrg 	  if (__builtin_expect (child_task->fn == NULL, 0))
   1629   1.1.1.4  mrg 	    {
   1630   1.1.1.4  mrg 	      if (gomp_target_task_fn (child_task->fn_data))
   1631   1.1.1.4  mrg 		{
   1632   1.1.1.4  mrg 		  thr->task = task;
   1633   1.1.1.4  mrg 		  gomp_mutex_lock (&team->task_lock);
   1634   1.1.1.4  mrg 		  child_task->kind = GOMP_TASK_ASYNC_RUNNING;
   1635   1.1.1.4  mrg 		  team->task_running_count--;
   1636   1.1.1.4  mrg 		  struct gomp_target_task *ttask
   1637   1.1.1.4  mrg 		    = (struct gomp_target_task *) child_task->fn_data;
   1638   1.1.1.4  mrg 		  /* If GOMP_PLUGIN_target_task_completion has run already
   1639   1.1.1.4  mrg 		     in between gomp_target_task_fn and the mutex lock,
   1640   1.1.1.4  mrg 		     perform the requeuing here.  */
   1641   1.1.1.4  mrg 		  if (ttask->state == GOMP_TARGET_TASK_FINISHED)
   1642   1.1.1.4  mrg 		    gomp_target_task_completion (team, child_task);
   1643   1.1.1.4  mrg 		  else
   1644   1.1.1.4  mrg 		    ttask->state = GOMP_TARGET_TASK_RUNNING;
   1645   1.1.1.4  mrg 		  child_task = NULL;
   1646   1.1.1.4  mrg 		  continue;
   1647   1.1.1.4  mrg 		}
   1648   1.1.1.4  mrg 	    }
   1649   1.1.1.4  mrg 	  else
   1650   1.1.1.4  mrg 	    child_task->fn (child_task->fn_data);
   1651       1.1  mrg 	  thr->task = task;
   1652       1.1  mrg 	}
   1653       1.1  mrg       else
   1654       1.1  mrg 	return;
   1655       1.1  mrg       gomp_mutex_lock (&team->task_lock);
   1656       1.1  mrg       if (child_task)
   1657       1.1  mrg 	{
   1658  1.1.1.13  mrg 	  if (child_task->detach_team)
   1659  1.1.1.13  mrg 	    {
   1660  1.1.1.13  mrg 	      assert (child_task->detach_team == team);
   1661  1.1.1.13  mrg 	      child_task->kind = GOMP_TASK_DETACHED;
   1662  1.1.1.13  mrg 	      ++team->task_detach_count;
   1663  1.1.1.13  mrg 	      --team->task_running_count;
   1664  1.1.1.13  mrg 	      gomp_debug (0,
   1665  1.1.1.13  mrg 			  "thread %d: task with event %p finished without "
   1666  1.1.1.13  mrg 			  "completion event fulfilled in team barrier\n",
   1667  1.1.1.13  mrg 			  thr->ts.team_id, child_task);
   1668  1.1.1.13  mrg 	      child_task = NULL;
   1669  1.1.1.13  mrg 	      continue;
   1670  1.1.1.13  mrg 	    }
   1671  1.1.1.13  mrg 
   1672   1.1.1.3  mrg 	 finish_cancelled:;
   1673   1.1.1.3  mrg 	  size_t new_tasks
   1674   1.1.1.3  mrg 	    = gomp_task_run_post_handle_depend (child_task, team);
   1675   1.1.1.3  mrg 	  gomp_task_run_post_remove_parent (child_task);
   1676   1.1.1.4  mrg 	  gomp_clear_parent (&child_task->children_queue);
   1677   1.1.1.3  mrg 	  gomp_task_run_post_remove_taskgroup (child_task);
   1678       1.1  mrg 	  to_free = child_task;
   1679   1.1.1.3  mrg 	  if (!cancelled)
   1680   1.1.1.3  mrg 	    team->task_running_count--;
   1681  1.1.1.13  mrg 	  child_task = NULL;
   1682   1.1.1.3  mrg 	  if (new_tasks > 1)
   1683   1.1.1.3  mrg 	    {
   1684   1.1.1.3  mrg 	      do_wake = team->nthreads - team->task_running_count;
   1685   1.1.1.3  mrg 	      if (do_wake > new_tasks)
   1686   1.1.1.3  mrg 		do_wake = new_tasks;
   1687   1.1.1.3  mrg 	    }
   1688  1.1.1.13  mrg 	  --team->task_count;
   1689       1.1  mrg 	}
   1690       1.1  mrg     }
   1691       1.1  mrg }
   1692       1.1  mrg 
   1693   1.1.1.4  mrg /* Called when encountering a taskwait directive.
   1694   1.1.1.4  mrg 
   1695   1.1.1.4  mrg    Wait for all children of the current task.  */
   1696       1.1  mrg 
   1697       1.1  mrg void
   1698       1.1  mrg GOMP_taskwait (void)
   1699       1.1  mrg {
   1700       1.1  mrg   struct gomp_thread *thr = gomp_thread ();
   1701       1.1  mrg   struct gomp_team *team = thr->ts.team;
   1702       1.1  mrg   struct gomp_task *task = thr->task;
   1703       1.1  mrg   struct gomp_task *child_task = NULL;
   1704       1.1  mrg   struct gomp_task *to_free = NULL;
   1705   1.1.1.3  mrg   struct gomp_taskwait taskwait;
   1706   1.1.1.3  mrg   int do_wake = 0;
   1707       1.1  mrg 
   1708   1.1.1.2  mrg   /* The acquire barrier on load of task->children here synchronizes
   1709   1.1.1.3  mrg      with the write of a NULL in gomp_task_run_post_remove_parent.  It is
   1710   1.1.1.2  mrg      not necessary that we synchronize with other non-NULL writes at
   1711   1.1.1.2  mrg      this point, but we must ensure that all writes to memory by a
   1712   1.1.1.2  mrg      child thread task work function are seen before we exit from
   1713   1.1.1.2  mrg      GOMP_taskwait.  */
   1714   1.1.1.2  mrg   if (task == NULL
   1715   1.1.1.4  mrg       || priority_queue_empty_p (&task->children_queue, MEMMODEL_ACQUIRE))
   1716       1.1  mrg     return;
   1717   1.1.1.2  mrg 
   1718   1.1.1.3  mrg   memset (&taskwait, 0, sizeof (taskwait));
   1719   1.1.1.4  mrg   bool child_q = false;
   1720       1.1  mrg   gomp_mutex_lock (&team->task_lock);
   1721       1.1  mrg   while (1)
   1722       1.1  mrg     {
   1723   1.1.1.3  mrg       bool cancelled = false;
   1724   1.1.1.4  mrg       if (priority_queue_empty_p (&task->children_queue, MEMMODEL_RELAXED))
   1725       1.1  mrg 	{
   1726   1.1.1.3  mrg 	  bool destroy_taskwait = task->taskwait != NULL;
   1727   1.1.1.3  mrg 	  task->taskwait = NULL;
   1728       1.1  mrg 	  gomp_mutex_unlock (&team->task_lock);
   1729       1.1  mrg 	  if (to_free)
   1730       1.1  mrg 	    {
   1731       1.1  mrg 	      gomp_finish_task (to_free);
   1732       1.1  mrg 	      free (to_free);
   1733       1.1  mrg 	    }
   1734   1.1.1.3  mrg 	  if (destroy_taskwait)
   1735   1.1.1.3  mrg 	    gomp_sem_destroy (&taskwait.taskwait_sem);
   1736       1.1  mrg 	  return;
   1737       1.1  mrg 	}
   1738   1.1.1.4  mrg       struct gomp_task *next_task
   1739   1.1.1.4  mrg 	= priority_queue_next_task (PQ_CHILDREN, &task->children_queue,
   1740   1.1.1.4  mrg 				    PQ_TEAM, &team->task_queue, &child_q);
   1741   1.1.1.4  mrg       if (next_task->kind == GOMP_TASK_WAITING)
   1742       1.1  mrg 	{
   1743   1.1.1.4  mrg 	  child_task = next_task;
   1744   1.1.1.3  mrg 	  cancelled
   1745   1.1.1.4  mrg 	    = gomp_task_run_pre (child_task, task, team);
   1746   1.1.1.3  mrg 	  if (__builtin_expect (cancelled, 0))
   1747       1.1  mrg 	    {
   1748   1.1.1.3  mrg 	      if (to_free)
   1749   1.1.1.3  mrg 		{
   1750   1.1.1.3  mrg 		  gomp_finish_task (to_free);
   1751   1.1.1.3  mrg 		  free (to_free);
   1752   1.1.1.3  mrg 		  to_free = NULL;
   1753   1.1.1.3  mrg 		}
   1754   1.1.1.3  mrg 	      goto finish_cancelled;
   1755       1.1  mrg 	    }
   1756       1.1  mrg 	}
   1757       1.1  mrg       else
   1758   1.1.1.3  mrg 	{
   1759   1.1.1.4  mrg 	/* All tasks we are waiting for are either running in other
   1760  1.1.1.13  mrg 	   threads, are detached and waiting for the completion event to be
   1761  1.1.1.13  mrg 	   fulfilled, or they are tasks that have not had their
   1762   1.1.1.4  mrg 	   dependencies met (so they're not even in the queue).  Wait
   1763   1.1.1.4  mrg 	   for them.  */
   1764   1.1.1.3  mrg 	  if (task->taskwait == NULL)
   1765   1.1.1.3  mrg 	    {
   1766   1.1.1.3  mrg 	      taskwait.in_depend_wait = false;
   1767   1.1.1.3  mrg 	      gomp_sem_init (&taskwait.taskwait_sem, 0);
   1768   1.1.1.3  mrg 	      task->taskwait = &taskwait;
   1769   1.1.1.3  mrg 	    }
   1770   1.1.1.3  mrg 	  taskwait.in_taskwait = true;
   1771   1.1.1.3  mrg 	}
   1772       1.1  mrg       gomp_mutex_unlock (&team->task_lock);
   1773   1.1.1.3  mrg       if (do_wake)
   1774   1.1.1.3  mrg 	{
   1775   1.1.1.3  mrg 	  gomp_team_barrier_wake (&team->barrier, do_wake);
   1776   1.1.1.3  mrg 	  do_wake = 0;
   1777   1.1.1.3  mrg 	}
   1778       1.1  mrg       if (to_free)
   1779       1.1  mrg 	{
   1780       1.1  mrg 	  gomp_finish_task (to_free);
   1781       1.1  mrg 	  free (to_free);
   1782       1.1  mrg 	  to_free = NULL;
   1783       1.1  mrg 	}
   1784       1.1  mrg       if (child_task)
   1785       1.1  mrg 	{
   1786       1.1  mrg 	  thr->task = child_task;
   1787   1.1.1.4  mrg 	  if (__builtin_expect (child_task->fn == NULL, 0))
   1788   1.1.1.4  mrg 	    {
   1789   1.1.1.4  mrg 	      if (gomp_target_task_fn (child_task->fn_data))
   1790   1.1.1.4  mrg 		{
   1791   1.1.1.4  mrg 		  thr->task = task;
   1792   1.1.1.4  mrg 		  gomp_mutex_lock (&team->task_lock);
   1793   1.1.1.4  mrg 		  child_task->kind = GOMP_TASK_ASYNC_RUNNING;
   1794   1.1.1.4  mrg 		  struct gomp_target_task *ttask
   1795   1.1.1.4  mrg 		    = (struct gomp_target_task *) child_task->fn_data;
   1796   1.1.1.4  mrg 		  /* If GOMP_PLUGIN_target_task_completion has run already
   1797   1.1.1.4  mrg 		     in between gomp_target_task_fn and the mutex lock,
   1798   1.1.1.4  mrg 		     perform the requeuing here.  */
   1799   1.1.1.4  mrg 		  if (ttask->state == GOMP_TARGET_TASK_FINISHED)
   1800   1.1.1.4  mrg 		    gomp_target_task_completion (team, child_task);
   1801   1.1.1.4  mrg 		  else
   1802   1.1.1.4  mrg 		    ttask->state = GOMP_TARGET_TASK_RUNNING;
   1803   1.1.1.4  mrg 		  child_task = NULL;
   1804   1.1.1.4  mrg 		  continue;
   1805   1.1.1.4  mrg 		}
   1806   1.1.1.4  mrg 	    }
   1807   1.1.1.4  mrg 	  else
   1808   1.1.1.4  mrg 	    child_task->fn (child_task->fn_data);
   1809       1.1  mrg 	  thr->task = task;
   1810       1.1  mrg 	}
   1811       1.1  mrg       else
   1812   1.1.1.3  mrg 	gomp_sem_wait (&taskwait.taskwait_sem);
   1813   1.1.1.3  mrg       gomp_mutex_lock (&team->task_lock);
   1814   1.1.1.3  mrg       if (child_task)
   1815       1.1  mrg 	{
   1816  1.1.1.13  mrg 	  if (child_task->detach_team)
   1817  1.1.1.13  mrg 	    {
   1818  1.1.1.13  mrg 	      assert (child_task->detach_team == team);
   1819  1.1.1.13  mrg 	      child_task->kind = GOMP_TASK_DETACHED;
   1820  1.1.1.13  mrg 	      ++team->task_detach_count;
   1821  1.1.1.13  mrg 	      gomp_debug (0,
   1822  1.1.1.13  mrg 			  "thread %d: task with event %p finished without "
   1823  1.1.1.13  mrg 			  "completion event fulfilled in taskwait\n",
   1824  1.1.1.13  mrg 			  thr->ts.team_id, child_task);
   1825  1.1.1.13  mrg 	      child_task = NULL;
   1826  1.1.1.13  mrg 	      continue;
   1827  1.1.1.13  mrg 	    }
   1828  1.1.1.13  mrg 
   1829   1.1.1.3  mrg 	 finish_cancelled:;
   1830   1.1.1.3  mrg 	  size_t new_tasks
   1831   1.1.1.3  mrg 	    = gomp_task_run_post_handle_depend (child_task, team);
   1832   1.1.1.4  mrg 
   1833   1.1.1.4  mrg 	  if (child_q)
   1834   1.1.1.4  mrg 	    {
   1835   1.1.1.4  mrg 	      priority_queue_remove (PQ_CHILDREN, &task->children_queue,
   1836   1.1.1.4  mrg 				     child_task, MEMMODEL_RELAXED);
   1837   1.1.1.4  mrg 	      child_task->pnode[PQ_CHILDREN].next = NULL;
   1838   1.1.1.4  mrg 	      child_task->pnode[PQ_CHILDREN].prev = NULL;
   1839   1.1.1.3  mrg 	    }
   1840   1.1.1.4  mrg 
   1841   1.1.1.4  mrg 	  gomp_clear_parent (&child_task->children_queue);
   1842   1.1.1.4  mrg 
   1843   1.1.1.3  mrg 	  gomp_task_run_post_remove_taskgroup (child_task);
   1844   1.1.1.4  mrg 
   1845   1.1.1.3  mrg 	  to_free = child_task;
   1846   1.1.1.3  mrg 	  child_task = NULL;
   1847   1.1.1.3  mrg 	  team->task_count--;
   1848   1.1.1.3  mrg 	  if (new_tasks > 1)
   1849   1.1.1.3  mrg 	    {
   1850   1.1.1.3  mrg 	      do_wake = team->nthreads - team->task_running_count
   1851   1.1.1.3  mrg 			- !task->in_tied_task;
   1852   1.1.1.3  mrg 	      if (do_wake > new_tasks)
   1853   1.1.1.3  mrg 		do_wake = new_tasks;
   1854   1.1.1.3  mrg 	    }
   1855   1.1.1.3  mrg 	}
   1856   1.1.1.3  mrg     }
   1857   1.1.1.3  mrg }
   1858   1.1.1.3  mrg 
   1859   1.1.1.9  mrg /* Called when encountering a taskwait directive with depend clause(s).
   1860   1.1.1.9  mrg    Wait as if it was an mergeable included task construct with empty body.  */
   1861   1.1.1.9  mrg 
   1862   1.1.1.9  mrg void
   1863   1.1.1.9  mrg GOMP_taskwait_depend (void **depend)
   1864   1.1.1.9  mrg {
   1865   1.1.1.9  mrg   struct gomp_thread *thr = gomp_thread ();
   1866   1.1.1.9  mrg   struct gomp_team *team = thr->ts.team;
   1867   1.1.1.9  mrg 
   1868   1.1.1.9  mrg   /* If parallel or taskgroup has been cancelled, return early.  */
   1869   1.1.1.9  mrg   if (__builtin_expect (gomp_cancel_var, 0) && team)
   1870   1.1.1.9  mrg     {
   1871   1.1.1.9  mrg       if (gomp_team_barrier_cancelled (&team->barrier))
   1872   1.1.1.9  mrg 	return;
   1873   1.1.1.9  mrg       if (thr->task->taskgroup)
   1874   1.1.1.9  mrg 	{
   1875   1.1.1.9  mrg 	  if (thr->task->taskgroup->cancelled)
   1876   1.1.1.9  mrg 	    return;
   1877   1.1.1.9  mrg 	  if (thr->task->taskgroup->workshare
   1878   1.1.1.9  mrg 	      && thr->task->taskgroup->prev
   1879   1.1.1.9  mrg 	      && thr->task->taskgroup->prev->cancelled)
   1880   1.1.1.9  mrg 	    return;
   1881   1.1.1.9  mrg 	}
   1882   1.1.1.9  mrg     }
   1883   1.1.1.9  mrg 
   1884   1.1.1.9  mrg   if (thr->task && thr->task->depend_hash)
   1885   1.1.1.9  mrg     gomp_task_maybe_wait_for_dependencies (depend);
   1886   1.1.1.9  mrg }
   1887   1.1.1.9  mrg 
   1888  1.1.1.14  mrg /* Called when encountering a taskwait directive with nowait and depend
   1889  1.1.1.14  mrg    clause(s).  Create a possibly deferred task construct with empty body.  */
   1890  1.1.1.14  mrg 
   1891  1.1.1.14  mrg void
   1892  1.1.1.14  mrg GOMP_taskwait_depend_nowait (void **depend)
   1893  1.1.1.14  mrg {
   1894  1.1.1.14  mrg   ialias_call (GOMP_task) (empty_task, "", NULL, 0, 1, true,
   1895  1.1.1.14  mrg 			   GOMP_TASK_FLAG_DEPEND, depend, 0, NULL);
   1896  1.1.1.14  mrg }
   1897  1.1.1.14  mrg 
   1898   1.1.1.4  mrg /* An undeferred task is about to run.  Wait for all tasks that this
   1899   1.1.1.4  mrg    undeferred task depends on.
   1900   1.1.1.3  mrg 
   1901   1.1.1.4  mrg    This is done by first putting all known ready dependencies
   1902   1.1.1.4  mrg    (dependencies that have their own dependencies met) at the top of
   1903   1.1.1.4  mrg    the scheduling queues.  Then we iterate through these imminently
   1904   1.1.1.4  mrg    ready tasks (and possibly other high priority tasks), and run them.
   1905   1.1.1.4  mrg    If we run out of ready dependencies to execute, we either wait for
   1906   1.1.1.9  mrg    the remaining dependencies to finish, or wait for them to get
   1907   1.1.1.4  mrg    scheduled so we can run them.
   1908   1.1.1.4  mrg 
   1909   1.1.1.4  mrg    DEPEND is as in GOMP_task.  */
   1910   1.1.1.4  mrg 
   1911   1.1.1.4  mrg void
   1912   1.1.1.3  mrg gomp_task_maybe_wait_for_dependencies (void **depend)
   1913   1.1.1.3  mrg {
   1914   1.1.1.3  mrg   struct gomp_thread *thr = gomp_thread ();
   1915   1.1.1.3  mrg   struct gomp_task *task = thr->task;
   1916   1.1.1.3  mrg   struct gomp_team *team = thr->ts.team;
   1917   1.1.1.3  mrg   struct gomp_task_depend_entry elem, *ent = NULL;
   1918   1.1.1.3  mrg   struct gomp_taskwait taskwait;
   1919   1.1.1.9  mrg   size_t orig_ndepend = (uintptr_t) depend[0];
   1920   1.1.1.3  mrg   size_t nout = (uintptr_t) depend[1];
   1921   1.1.1.9  mrg   size_t ndepend = orig_ndepend;
   1922   1.1.1.9  mrg   size_t normal = ndepend;
   1923   1.1.1.9  mrg   size_t n = 2;
   1924   1.1.1.3  mrg   size_t i;
   1925   1.1.1.3  mrg   size_t num_awaited = 0;
   1926   1.1.1.3  mrg   struct gomp_task *child_task = NULL;
   1927   1.1.1.3  mrg   struct gomp_task *to_free = NULL;
   1928   1.1.1.3  mrg   int do_wake = 0;
   1929   1.1.1.3  mrg 
   1930   1.1.1.9  mrg   if (ndepend == 0)
   1931   1.1.1.9  mrg     {
   1932   1.1.1.9  mrg       ndepend = nout;
   1933   1.1.1.9  mrg       nout = (uintptr_t) depend[2] + (uintptr_t) depend[3];
   1934   1.1.1.9  mrg       normal = nout + (uintptr_t) depend[4];
   1935   1.1.1.9  mrg       n = 5;
   1936   1.1.1.9  mrg     }
   1937   1.1.1.3  mrg   gomp_mutex_lock (&team->task_lock);
   1938  1.1.1.14  mrg   if (__builtin_expect (task->depend_all_memory && ndepend, false))
   1939  1.1.1.14  mrg     {
   1940  1.1.1.14  mrg       struct gomp_task *tsk = task->depend_all_memory;
   1941  1.1.1.14  mrg       if (!tsk->parent_depends_on)
   1942  1.1.1.14  mrg 	{
   1943  1.1.1.14  mrg 	  tsk->parent_depends_on = true;
   1944  1.1.1.14  mrg 	  ++num_awaited;
   1945  1.1.1.14  mrg 	  if (tsk->num_dependees == 0 && tsk->kind == GOMP_TASK_WAITING)
   1946  1.1.1.14  mrg 	    priority_queue_upgrade_task (tsk, task);
   1947  1.1.1.14  mrg 	}
   1948  1.1.1.14  mrg     }
   1949   1.1.1.3  mrg   for (i = 0; i < ndepend; i++)
   1950   1.1.1.3  mrg     {
   1951   1.1.1.9  mrg       elem.addr = depend[i + n];
   1952   1.1.1.9  mrg       elem.is_in = i >= nout;
   1953   1.1.1.9  mrg       if (__builtin_expect (i >= normal, 0))
   1954   1.1.1.9  mrg 	{
   1955   1.1.1.9  mrg 	  void **d = (void **) elem.addr;
   1956   1.1.1.9  mrg 	  switch ((uintptr_t) d[1])
   1957   1.1.1.9  mrg 	    {
   1958   1.1.1.9  mrg 	    case GOMP_DEPEND_IN:
   1959   1.1.1.9  mrg 	      break;
   1960   1.1.1.9  mrg 	    case GOMP_DEPEND_OUT:
   1961   1.1.1.9  mrg 	    case GOMP_DEPEND_INOUT:
   1962   1.1.1.9  mrg 	    case GOMP_DEPEND_MUTEXINOUTSET:
   1963   1.1.1.9  mrg 	      elem.is_in = 0;
   1964   1.1.1.9  mrg 	      break;
   1965  1.1.1.14  mrg 	    case GOMP_DEPEND_INOUTSET:
   1966  1.1.1.14  mrg 	      elem.is_in = 2;
   1967  1.1.1.14  mrg 	      break;
   1968   1.1.1.9  mrg 	    default:
   1969   1.1.1.9  mrg 	      gomp_fatal ("unknown omp_depend_t dependence type %d",
   1970   1.1.1.9  mrg 			  (int) (uintptr_t) d[1]);
   1971   1.1.1.9  mrg 	    }
   1972   1.1.1.9  mrg 	  elem.addr = d[0];
   1973   1.1.1.9  mrg 	}
   1974  1.1.1.14  mrg       if (__builtin_expect (elem.addr == NULL && !elem.is_in, false))
   1975  1.1.1.14  mrg 	{
   1976  1.1.1.14  mrg 	  size_t size = htab_size (task->depend_hash);
   1977  1.1.1.14  mrg 	  if (htab_elements (task->depend_hash) * 8 < size && size > 32)
   1978  1.1.1.14  mrg 	    htab_expand (task->depend_hash);
   1979  1.1.1.14  mrg 
   1980  1.1.1.14  mrg 	  /* depend(inout: omp_all_memory) - depend on all previous
   1981  1.1.1.14  mrg 	     sibling tasks that do have dependencies.  Inlined
   1982  1.1.1.14  mrg 	     htab_traverse.  */
   1983  1.1.1.14  mrg 	  hash_entry_type *slot = &task->depend_hash->entries[0];
   1984  1.1.1.14  mrg 	  hash_entry_type *end = slot + htab_size (task->depend_hash);
   1985  1.1.1.14  mrg 	  for (; slot != end; ++slot)
   1986  1.1.1.14  mrg 	    {
   1987  1.1.1.14  mrg 	      if (*slot == HTAB_EMPTY_ENTRY || *slot == HTAB_DELETED_ENTRY)
   1988  1.1.1.14  mrg 		continue;
   1989  1.1.1.14  mrg 	      for (ent = *slot; ent; ent = ent->next)
   1990  1.1.1.14  mrg 		{
   1991  1.1.1.14  mrg 		  struct gomp_task *tsk = ent->task;
   1992  1.1.1.14  mrg 		  if (!tsk->parent_depends_on)
   1993  1.1.1.14  mrg 		    {
   1994  1.1.1.14  mrg 		      tsk->parent_depends_on = true;
   1995  1.1.1.14  mrg 		      ++num_awaited;
   1996  1.1.1.14  mrg 		      if (tsk->num_dependees == 0
   1997  1.1.1.14  mrg 			  && tsk->kind == GOMP_TASK_WAITING)
   1998  1.1.1.14  mrg 			priority_queue_upgrade_task (tsk, task);
   1999  1.1.1.14  mrg 		    }
   2000  1.1.1.14  mrg 		}
   2001  1.1.1.14  mrg 	    }
   2002  1.1.1.14  mrg 	  break;
   2003  1.1.1.14  mrg 	}
   2004   1.1.1.3  mrg       ent = htab_find (task->depend_hash, &elem);
   2005   1.1.1.3  mrg       for (; ent; ent = ent->next)
   2006  1.1.1.14  mrg 	if (elem.is_in && elem.is_in == ent->is_in)
   2007   1.1.1.3  mrg 	  continue;
   2008   1.1.1.3  mrg 	else
   2009   1.1.1.3  mrg 	  {
   2010   1.1.1.3  mrg 	    struct gomp_task *tsk = ent->task;
   2011   1.1.1.3  mrg 	    if (!tsk->parent_depends_on)
   2012   1.1.1.3  mrg 	      {
   2013   1.1.1.3  mrg 		tsk->parent_depends_on = true;
   2014   1.1.1.3  mrg 		++num_awaited;
   2015  1.1.1.10  mrg 		/* If dependency TSK itself has no dependencies and is
   2016   1.1.1.4  mrg 		   ready to run, move it up front so that we run it as
   2017   1.1.1.4  mrg 		   soon as possible.  */
   2018   1.1.1.3  mrg 		if (tsk->num_dependees == 0 && tsk->kind == GOMP_TASK_WAITING)
   2019   1.1.1.4  mrg 		  priority_queue_upgrade_task (tsk, task);
   2020   1.1.1.3  mrg 	      }
   2021   1.1.1.3  mrg 	  }
   2022   1.1.1.3  mrg     }
   2023   1.1.1.3  mrg   if (num_awaited == 0)
   2024   1.1.1.3  mrg     {
   2025   1.1.1.3  mrg       gomp_mutex_unlock (&team->task_lock);
   2026   1.1.1.3  mrg       return;
   2027   1.1.1.3  mrg     }
   2028   1.1.1.3  mrg 
   2029   1.1.1.3  mrg   memset (&taskwait, 0, sizeof (taskwait));
   2030   1.1.1.3  mrg   taskwait.n_depend = num_awaited;
   2031   1.1.1.3  mrg   gomp_sem_init (&taskwait.taskwait_sem, 0);
   2032   1.1.1.3  mrg   task->taskwait = &taskwait;
   2033   1.1.1.3  mrg 
   2034   1.1.1.3  mrg   while (1)
   2035   1.1.1.3  mrg     {
   2036   1.1.1.3  mrg       bool cancelled = false;
   2037   1.1.1.3  mrg       if (taskwait.n_depend == 0)
   2038   1.1.1.3  mrg 	{
   2039   1.1.1.3  mrg 	  task->taskwait = NULL;
   2040   1.1.1.3  mrg 	  gomp_mutex_unlock (&team->task_lock);
   2041   1.1.1.3  mrg 	  if (to_free)
   2042   1.1.1.3  mrg 	    {
   2043   1.1.1.3  mrg 	      gomp_finish_task (to_free);
   2044   1.1.1.3  mrg 	      free (to_free);
   2045   1.1.1.3  mrg 	    }
   2046   1.1.1.3  mrg 	  gomp_sem_destroy (&taskwait.taskwait_sem);
   2047       1.1  mrg 	  return;
   2048       1.1  mrg 	}
   2049   1.1.1.4  mrg 
   2050   1.1.1.4  mrg       /* Theoretically when we have multiple priorities, we should
   2051   1.1.1.4  mrg 	 chose between the highest priority item in
   2052   1.1.1.4  mrg 	 task->children_queue and team->task_queue here, so we should
   2053   1.1.1.4  mrg 	 use priority_queue_next_task().  However, since we are
   2054   1.1.1.4  mrg 	 running an undeferred task, perhaps that makes all tasks it
   2055   1.1.1.4  mrg 	 depends on undeferred, thus a priority of INF?  This would
   2056   1.1.1.4  mrg 	 make it unnecessary to take anything into account here,
   2057   1.1.1.4  mrg 	 but the dependencies.
   2058   1.1.1.4  mrg 
   2059   1.1.1.4  mrg 	 On the other hand, if we want to use priority_queue_next_task(),
   2060   1.1.1.4  mrg 	 care should be taken to only use priority_queue_remove()
   2061   1.1.1.4  mrg 	 below if the task was actually removed from the children
   2062   1.1.1.4  mrg 	 queue.  */
   2063   1.1.1.4  mrg       bool ignored;
   2064   1.1.1.4  mrg       struct gomp_task *next_task
   2065   1.1.1.4  mrg 	= priority_queue_next_task (PQ_CHILDREN, &task->children_queue,
   2066   1.1.1.4  mrg 				    PQ_IGNORED, NULL, &ignored);
   2067   1.1.1.4  mrg 
   2068   1.1.1.4  mrg       if (next_task->kind == GOMP_TASK_WAITING)
   2069   1.1.1.3  mrg 	{
   2070   1.1.1.4  mrg 	  child_task = next_task;
   2071   1.1.1.3  mrg 	  cancelled
   2072   1.1.1.4  mrg 	    = gomp_task_run_pre (child_task, task, team);
   2073   1.1.1.3  mrg 	  if (__builtin_expect (cancelled, 0))
   2074   1.1.1.3  mrg 	    {
   2075   1.1.1.3  mrg 	      if (to_free)
   2076   1.1.1.3  mrg 		{
   2077   1.1.1.3  mrg 		  gomp_finish_task (to_free);
   2078   1.1.1.3  mrg 		  free (to_free);
   2079   1.1.1.3  mrg 		  to_free = NULL;
   2080   1.1.1.3  mrg 		}
   2081   1.1.1.3  mrg 	      goto finish_cancelled;
   2082   1.1.1.3  mrg 	    }
   2083   1.1.1.3  mrg 	}
   2084   1.1.1.3  mrg       else
   2085   1.1.1.4  mrg 	/* All tasks we are waiting for are either running in other
   2086   1.1.1.4  mrg 	   threads, or they are tasks that have not had their
   2087   1.1.1.4  mrg 	   dependencies met (so they're not even in the queue).  Wait
   2088   1.1.1.4  mrg 	   for them.  */
   2089   1.1.1.3  mrg 	taskwait.in_depend_wait = true;
   2090   1.1.1.3  mrg       gomp_mutex_unlock (&team->task_lock);
   2091   1.1.1.3  mrg       if (do_wake)
   2092   1.1.1.3  mrg 	{
   2093   1.1.1.3  mrg 	  gomp_team_barrier_wake (&team->barrier, do_wake);
   2094   1.1.1.3  mrg 	  do_wake = 0;
   2095   1.1.1.3  mrg 	}
   2096   1.1.1.3  mrg       if (to_free)
   2097   1.1.1.3  mrg 	{
   2098   1.1.1.3  mrg 	  gomp_finish_task (to_free);
   2099   1.1.1.3  mrg 	  free (to_free);
   2100   1.1.1.3  mrg 	  to_free = NULL;
   2101   1.1.1.3  mrg 	}
   2102   1.1.1.3  mrg       if (child_task)
   2103   1.1.1.3  mrg 	{
   2104   1.1.1.3  mrg 	  thr->task = child_task;
   2105   1.1.1.4  mrg 	  if (__builtin_expect (child_task->fn == NULL, 0))
   2106   1.1.1.4  mrg 	    {
   2107   1.1.1.4  mrg 	      if (gomp_target_task_fn (child_task->fn_data))
   2108   1.1.1.4  mrg 		{
   2109   1.1.1.4  mrg 		  thr->task = task;
   2110   1.1.1.4  mrg 		  gomp_mutex_lock (&team->task_lock);
   2111   1.1.1.4  mrg 		  child_task->kind = GOMP_TASK_ASYNC_RUNNING;
   2112   1.1.1.4  mrg 		  struct gomp_target_task *ttask
   2113   1.1.1.4  mrg 		    = (struct gomp_target_task *) child_task->fn_data;
   2114   1.1.1.4  mrg 		  /* If GOMP_PLUGIN_target_task_completion has run already
   2115   1.1.1.4  mrg 		     in between gomp_target_task_fn and the mutex lock,
   2116   1.1.1.4  mrg 		     perform the requeuing here.  */
   2117   1.1.1.4  mrg 		  if (ttask->state == GOMP_TARGET_TASK_FINISHED)
   2118   1.1.1.4  mrg 		    gomp_target_task_completion (team, child_task);
   2119   1.1.1.4  mrg 		  else
   2120   1.1.1.4  mrg 		    ttask->state = GOMP_TARGET_TASK_RUNNING;
   2121   1.1.1.4  mrg 		  child_task = NULL;
   2122   1.1.1.4  mrg 		  continue;
   2123   1.1.1.4  mrg 		}
   2124   1.1.1.4  mrg 	    }
   2125   1.1.1.4  mrg 	  else
   2126   1.1.1.4  mrg 	    child_task->fn (child_task->fn_data);
   2127   1.1.1.3  mrg 	  thr->task = task;
   2128   1.1.1.3  mrg 	}
   2129   1.1.1.3  mrg       else
   2130   1.1.1.3  mrg 	gomp_sem_wait (&taskwait.taskwait_sem);
   2131       1.1  mrg       gomp_mutex_lock (&team->task_lock);
   2132       1.1  mrg       if (child_task)
   2133       1.1  mrg 	{
   2134   1.1.1.3  mrg 	 finish_cancelled:;
   2135   1.1.1.3  mrg 	  size_t new_tasks
   2136   1.1.1.3  mrg 	    = gomp_task_run_post_handle_depend (child_task, team);
   2137   1.1.1.3  mrg 	  if (child_task->parent_depends_on)
   2138   1.1.1.3  mrg 	    --taskwait.n_depend;
   2139   1.1.1.4  mrg 
   2140   1.1.1.4  mrg 	  priority_queue_remove (PQ_CHILDREN, &task->children_queue,
   2141   1.1.1.4  mrg 				 child_task, MEMMODEL_RELAXED);
   2142   1.1.1.4  mrg 	  child_task->pnode[PQ_CHILDREN].next = NULL;
   2143   1.1.1.4  mrg 	  child_task->pnode[PQ_CHILDREN].prev = NULL;
   2144   1.1.1.4  mrg 
   2145   1.1.1.4  mrg 	  gomp_clear_parent (&child_task->children_queue);
   2146   1.1.1.3  mrg 	  gomp_task_run_post_remove_taskgroup (child_task);
   2147       1.1  mrg 	  to_free = child_task;
   2148       1.1  mrg 	  child_task = NULL;
   2149       1.1  mrg 	  team->task_count--;
   2150   1.1.1.3  mrg 	  if (new_tasks > 1)
   2151   1.1.1.3  mrg 	    {
   2152   1.1.1.3  mrg 	      do_wake = team->nthreads - team->task_running_count
   2153   1.1.1.3  mrg 			- !task->in_tied_task;
   2154   1.1.1.3  mrg 	      if (do_wake > new_tasks)
   2155   1.1.1.3  mrg 		do_wake = new_tasks;
   2156   1.1.1.3  mrg 	    }
   2157       1.1  mrg 	}
   2158       1.1  mrg     }
   2159       1.1  mrg }
   2160   1.1.1.2  mrg 
   2161   1.1.1.2  mrg /* Called when encountering a taskyield directive.  */
   2162   1.1.1.2  mrg 
   2163   1.1.1.2  mrg void
   2164   1.1.1.2  mrg GOMP_taskyield (void)
   2165   1.1.1.2  mrg {
   2166   1.1.1.2  mrg   /* Nothing at the moment.  */
   2167   1.1.1.2  mrg }
   2168   1.1.1.2  mrg 
   2169   1.1.1.9  mrg static inline struct gomp_taskgroup *
   2170   1.1.1.9  mrg gomp_taskgroup_init (struct gomp_taskgroup *prev)
   2171   1.1.1.9  mrg {
   2172   1.1.1.9  mrg   struct gomp_taskgroup *taskgroup
   2173   1.1.1.9  mrg     = gomp_malloc (sizeof (struct gomp_taskgroup));
   2174   1.1.1.9  mrg   taskgroup->prev = prev;
   2175   1.1.1.9  mrg   priority_queue_init (&taskgroup->taskgroup_queue);
   2176   1.1.1.9  mrg   taskgroup->reductions = prev ? prev->reductions : NULL;
   2177   1.1.1.9  mrg   taskgroup->in_taskgroup_wait = false;
   2178   1.1.1.9  mrg   taskgroup->cancelled = false;
   2179   1.1.1.9  mrg   taskgroup->workshare = false;
   2180   1.1.1.9  mrg   taskgroup->num_children = 0;
   2181   1.1.1.9  mrg   gomp_sem_init (&taskgroup->taskgroup_sem, 0);
   2182   1.1.1.9  mrg   return taskgroup;
   2183   1.1.1.9  mrg }
   2184   1.1.1.9  mrg 
   2185   1.1.1.3  mrg void
   2186   1.1.1.3  mrg GOMP_taskgroup_start (void)
   2187   1.1.1.3  mrg {
   2188   1.1.1.3  mrg   struct gomp_thread *thr = gomp_thread ();
   2189   1.1.1.3  mrg   struct gomp_team *team = thr->ts.team;
   2190   1.1.1.3  mrg   struct gomp_task *task = thr->task;
   2191   1.1.1.3  mrg 
   2192   1.1.1.3  mrg   /* If team is NULL, all tasks are executed as
   2193   1.1.1.4  mrg      GOMP_TASK_UNDEFERRED tasks and thus all children tasks of
   2194   1.1.1.3  mrg      taskgroup and their descendant tasks will be finished
   2195   1.1.1.3  mrg      by the time GOMP_taskgroup_end is called.  */
   2196   1.1.1.3  mrg   if (team == NULL)
   2197   1.1.1.3  mrg     return;
   2198   1.1.1.9  mrg   task->taskgroup = gomp_taskgroup_init (task->taskgroup);
   2199   1.1.1.3  mrg }
   2200   1.1.1.3  mrg 
   2201   1.1.1.3  mrg void
   2202   1.1.1.3  mrg GOMP_taskgroup_end (void)
   2203   1.1.1.3  mrg {
   2204   1.1.1.3  mrg   struct gomp_thread *thr = gomp_thread ();
   2205   1.1.1.3  mrg   struct gomp_team *team = thr->ts.team;
   2206   1.1.1.3  mrg   struct gomp_task *task = thr->task;
   2207   1.1.1.3  mrg   struct gomp_taskgroup *taskgroup;
   2208   1.1.1.3  mrg   struct gomp_task *child_task = NULL;
   2209   1.1.1.3  mrg   struct gomp_task *to_free = NULL;
   2210   1.1.1.3  mrg   int do_wake = 0;
   2211   1.1.1.3  mrg 
   2212   1.1.1.3  mrg   if (team == NULL)
   2213   1.1.1.3  mrg     return;
   2214   1.1.1.3  mrg   taskgroup = task->taskgroup;
   2215   1.1.1.4  mrg   if (__builtin_expect (taskgroup == NULL, 0)
   2216   1.1.1.4  mrg       && thr->ts.level == 0)
   2217   1.1.1.4  mrg     {
   2218   1.1.1.4  mrg       /* This can happen if GOMP_taskgroup_start is called when
   2219   1.1.1.4  mrg 	 thr->ts.team == NULL, but inside of the taskgroup there
   2220   1.1.1.4  mrg 	 is #pragma omp target nowait that creates an implicit
   2221   1.1.1.4  mrg 	 team with a single thread.  In this case, we want to wait
   2222   1.1.1.4  mrg 	 for all outstanding tasks in this team.  */
   2223   1.1.1.4  mrg       gomp_team_barrier_wait (&team->barrier);
   2224   1.1.1.4  mrg       return;
   2225   1.1.1.4  mrg     }
   2226   1.1.1.3  mrg 
   2227   1.1.1.3  mrg   /* The acquire barrier on load of taskgroup->num_children here
   2228   1.1.1.3  mrg      synchronizes with the write of 0 in gomp_task_run_post_remove_taskgroup.
   2229   1.1.1.3  mrg      It is not necessary that we synchronize with other non-0 writes at
   2230   1.1.1.3  mrg      this point, but we must ensure that all writes to memory by a
   2231   1.1.1.3  mrg      child thread task work function are seen before we exit from
   2232   1.1.1.3  mrg      GOMP_taskgroup_end.  */
   2233   1.1.1.3  mrg   if (__atomic_load_n (&taskgroup->num_children, MEMMODEL_ACQUIRE) == 0)
   2234   1.1.1.3  mrg     goto finish;
   2235   1.1.1.3  mrg 
   2236   1.1.1.4  mrg   bool unused;
   2237   1.1.1.3  mrg   gomp_mutex_lock (&team->task_lock);
   2238   1.1.1.3  mrg   while (1)
   2239   1.1.1.3  mrg     {
   2240   1.1.1.3  mrg       bool cancelled = false;
   2241   1.1.1.4  mrg       if (priority_queue_empty_p (&taskgroup->taskgroup_queue,
   2242   1.1.1.4  mrg 				  MEMMODEL_RELAXED))
   2243   1.1.1.3  mrg 	{
   2244   1.1.1.3  mrg 	  if (taskgroup->num_children)
   2245   1.1.1.3  mrg 	    {
   2246   1.1.1.4  mrg 	      if (priority_queue_empty_p (&task->children_queue,
   2247   1.1.1.4  mrg 					  MEMMODEL_RELAXED))
   2248   1.1.1.3  mrg 		goto do_wait;
   2249   1.1.1.4  mrg 	      child_task
   2250   1.1.1.4  mrg 		= priority_queue_next_task (PQ_CHILDREN, &task->children_queue,
   2251   1.1.1.4  mrg 					    PQ_TEAM, &team->task_queue,
   2252   1.1.1.4  mrg 					    &unused);
   2253   1.1.1.4  mrg 	    }
   2254   1.1.1.4  mrg 	  else
   2255   1.1.1.3  mrg 	    {
   2256   1.1.1.3  mrg 	      gomp_mutex_unlock (&team->task_lock);
   2257   1.1.1.3  mrg 	      if (to_free)
   2258   1.1.1.3  mrg 		{
   2259   1.1.1.3  mrg 		  gomp_finish_task (to_free);
   2260   1.1.1.3  mrg 		  free (to_free);
   2261   1.1.1.3  mrg 		}
   2262   1.1.1.3  mrg 	      goto finish;
   2263   1.1.1.3  mrg 	    }
   2264   1.1.1.3  mrg 	}
   2265   1.1.1.3  mrg       else
   2266   1.1.1.4  mrg 	child_task
   2267   1.1.1.4  mrg 	  = priority_queue_next_task (PQ_TASKGROUP, &taskgroup->taskgroup_queue,
   2268   1.1.1.4  mrg 				      PQ_TEAM, &team->task_queue, &unused);
   2269   1.1.1.3  mrg       if (child_task->kind == GOMP_TASK_WAITING)
   2270   1.1.1.3  mrg 	{
   2271   1.1.1.3  mrg 	  cancelled
   2272   1.1.1.4  mrg 	    = gomp_task_run_pre (child_task, child_task->parent, team);
   2273   1.1.1.3  mrg 	  if (__builtin_expect (cancelled, 0))
   2274   1.1.1.3  mrg 	    {
   2275   1.1.1.3  mrg 	      if (to_free)
   2276   1.1.1.3  mrg 		{
   2277   1.1.1.3  mrg 		  gomp_finish_task (to_free);
   2278   1.1.1.3  mrg 		  free (to_free);
   2279   1.1.1.3  mrg 		  to_free = NULL;
   2280   1.1.1.3  mrg 		}
   2281   1.1.1.3  mrg 	      goto finish_cancelled;
   2282   1.1.1.3  mrg 	    }
   2283   1.1.1.3  mrg 	}
   2284   1.1.1.3  mrg       else
   2285   1.1.1.3  mrg 	{
   2286   1.1.1.3  mrg 	  child_task = NULL;
   2287   1.1.1.3  mrg 	 do_wait:
   2288   1.1.1.4  mrg 	/* All tasks we are waiting for are either running in other
   2289   1.1.1.4  mrg 	   threads, or they are tasks that have not had their
   2290   1.1.1.4  mrg 	   dependencies met (so they're not even in the queue).  Wait
   2291   1.1.1.4  mrg 	   for them.  */
   2292   1.1.1.3  mrg 	  taskgroup->in_taskgroup_wait = true;
   2293   1.1.1.3  mrg 	}
   2294   1.1.1.3  mrg       gomp_mutex_unlock (&team->task_lock);
   2295   1.1.1.3  mrg       if (do_wake)
   2296   1.1.1.3  mrg 	{
   2297   1.1.1.3  mrg 	  gomp_team_barrier_wake (&team->barrier, do_wake);
   2298   1.1.1.3  mrg 	  do_wake = 0;
   2299   1.1.1.3  mrg 	}
   2300   1.1.1.3  mrg       if (to_free)
   2301   1.1.1.3  mrg 	{
   2302   1.1.1.3  mrg 	  gomp_finish_task (to_free);
   2303   1.1.1.3  mrg 	  free (to_free);
   2304   1.1.1.3  mrg 	  to_free = NULL;
   2305   1.1.1.3  mrg 	}
   2306   1.1.1.3  mrg       if (child_task)
   2307   1.1.1.3  mrg 	{
   2308   1.1.1.3  mrg 	  thr->task = child_task;
   2309   1.1.1.4  mrg 	  if (__builtin_expect (child_task->fn == NULL, 0))
   2310   1.1.1.4  mrg 	    {
   2311   1.1.1.4  mrg 	      if (gomp_target_task_fn (child_task->fn_data))
   2312   1.1.1.4  mrg 		{
   2313   1.1.1.4  mrg 		  thr->task = task;
   2314   1.1.1.4  mrg 		  gomp_mutex_lock (&team->task_lock);
   2315   1.1.1.4  mrg 		  child_task->kind = GOMP_TASK_ASYNC_RUNNING;
   2316   1.1.1.4  mrg 		  struct gomp_target_task *ttask
   2317   1.1.1.4  mrg 		    = (struct gomp_target_task *) child_task->fn_data;
   2318   1.1.1.4  mrg 		  /* If GOMP_PLUGIN_target_task_completion has run already
   2319   1.1.1.4  mrg 		     in between gomp_target_task_fn and the mutex lock,
   2320   1.1.1.4  mrg 		     perform the requeuing here.  */
   2321   1.1.1.4  mrg 		  if (ttask->state == GOMP_TARGET_TASK_FINISHED)
   2322   1.1.1.4  mrg 		    gomp_target_task_completion (team, child_task);
   2323   1.1.1.4  mrg 		  else
   2324   1.1.1.4  mrg 		    ttask->state = GOMP_TARGET_TASK_RUNNING;
   2325   1.1.1.4  mrg 		  child_task = NULL;
   2326   1.1.1.4  mrg 		  continue;
   2327   1.1.1.4  mrg 		}
   2328   1.1.1.4  mrg 	    }
   2329   1.1.1.4  mrg 	  else
   2330   1.1.1.4  mrg 	    child_task->fn (child_task->fn_data);
   2331   1.1.1.3  mrg 	  thr->task = task;
   2332   1.1.1.3  mrg 	}
   2333   1.1.1.3  mrg       else
   2334   1.1.1.3  mrg 	gomp_sem_wait (&taskgroup->taskgroup_sem);
   2335   1.1.1.3  mrg       gomp_mutex_lock (&team->task_lock);
   2336   1.1.1.3  mrg       if (child_task)
   2337   1.1.1.3  mrg 	{
   2338  1.1.1.13  mrg 	  if (child_task->detach_team)
   2339  1.1.1.13  mrg 	    {
   2340  1.1.1.13  mrg 	      assert (child_task->detach_team == team);
   2341  1.1.1.13  mrg 	      child_task->kind = GOMP_TASK_DETACHED;
   2342  1.1.1.13  mrg 	      ++team->task_detach_count;
   2343  1.1.1.13  mrg 	      gomp_debug (0,
   2344  1.1.1.13  mrg 			  "thread %d: task with event %p finished without "
   2345  1.1.1.13  mrg 			  "completion event fulfilled in taskgroup\n",
   2346  1.1.1.13  mrg 			  thr->ts.team_id, child_task);
   2347  1.1.1.13  mrg 	      child_task = NULL;
   2348  1.1.1.13  mrg 	      continue;
   2349  1.1.1.13  mrg 	    }
   2350  1.1.1.13  mrg 
   2351   1.1.1.3  mrg 	 finish_cancelled:;
   2352   1.1.1.3  mrg 	  size_t new_tasks
   2353   1.1.1.3  mrg 	    = gomp_task_run_post_handle_depend (child_task, team);
   2354   1.1.1.3  mrg 	  gomp_task_run_post_remove_parent (child_task);
   2355   1.1.1.4  mrg 	  gomp_clear_parent (&child_task->children_queue);
   2356   1.1.1.3  mrg 	  gomp_task_run_post_remove_taskgroup (child_task);
   2357   1.1.1.3  mrg 	  to_free = child_task;
   2358   1.1.1.3  mrg 	  child_task = NULL;
   2359   1.1.1.3  mrg 	  team->task_count--;
   2360   1.1.1.3  mrg 	  if (new_tasks > 1)
   2361   1.1.1.3  mrg 	    {
   2362   1.1.1.3  mrg 	      do_wake = team->nthreads - team->task_running_count
   2363   1.1.1.3  mrg 			- !task->in_tied_task;
   2364   1.1.1.3  mrg 	      if (do_wake > new_tasks)
   2365   1.1.1.3  mrg 		do_wake = new_tasks;
   2366   1.1.1.3  mrg 	    }
   2367   1.1.1.3  mrg 	}
   2368   1.1.1.3  mrg     }
   2369   1.1.1.3  mrg 
   2370   1.1.1.3  mrg  finish:
   2371   1.1.1.3  mrg   task->taskgroup = taskgroup->prev;
   2372   1.1.1.3  mrg   gomp_sem_destroy (&taskgroup->taskgroup_sem);
   2373   1.1.1.3  mrg   free (taskgroup);
   2374   1.1.1.3  mrg }
   2375   1.1.1.3  mrg 
   2376   1.1.1.9  mrg static inline __attribute__((always_inline)) void
   2377   1.1.1.9  mrg gomp_reduction_register (uintptr_t *data, uintptr_t *old, uintptr_t *orig,
   2378   1.1.1.9  mrg 			 unsigned nthreads)
   2379   1.1.1.9  mrg {
   2380   1.1.1.9  mrg   size_t total_cnt = 0;
   2381   1.1.1.9  mrg   uintptr_t *d = data;
   2382   1.1.1.9  mrg   struct htab *old_htab = NULL, *new_htab;
   2383   1.1.1.9  mrg   do
   2384   1.1.1.9  mrg     {
   2385   1.1.1.9  mrg       if (__builtin_expect (orig != NULL, 0))
   2386   1.1.1.9  mrg 	{
   2387   1.1.1.9  mrg 	  /* For worksharing task reductions, memory has been allocated
   2388   1.1.1.9  mrg 	     already by some other thread that encountered the construct
   2389   1.1.1.9  mrg 	     earlier.  */
   2390   1.1.1.9  mrg 	  d[2] = orig[2];
   2391   1.1.1.9  mrg 	  d[6] = orig[6];
   2392   1.1.1.9  mrg 	  orig = (uintptr_t *) orig[4];
   2393   1.1.1.9  mrg 	}
   2394   1.1.1.9  mrg       else
   2395   1.1.1.9  mrg 	{
   2396   1.1.1.9  mrg 	  size_t sz = d[1] * nthreads;
   2397   1.1.1.9  mrg 	  /* Should use omp_alloc if d[3] is not -1.  */
   2398   1.1.1.9  mrg 	  void *ptr = gomp_aligned_alloc (d[2], sz);
   2399   1.1.1.9  mrg 	  memset (ptr, '\0', sz);
   2400   1.1.1.9  mrg 	  d[2] = (uintptr_t) ptr;
   2401   1.1.1.9  mrg 	  d[6] = d[2] + sz;
   2402   1.1.1.9  mrg 	}
   2403   1.1.1.9  mrg       d[5] = 0;
   2404   1.1.1.9  mrg       total_cnt += d[0];
   2405   1.1.1.9  mrg       if (d[4] == 0)
   2406   1.1.1.9  mrg 	{
   2407   1.1.1.9  mrg 	  d[4] = (uintptr_t) old;
   2408   1.1.1.9  mrg 	  break;
   2409   1.1.1.9  mrg 	}
   2410   1.1.1.9  mrg       else
   2411   1.1.1.9  mrg 	d = (uintptr_t *) d[4];
   2412   1.1.1.9  mrg     }
   2413   1.1.1.9  mrg   while (1);
   2414   1.1.1.9  mrg   if (old && old[5])
   2415   1.1.1.9  mrg     {
   2416   1.1.1.9  mrg       old_htab = (struct htab *) old[5];
   2417   1.1.1.9  mrg       total_cnt += htab_elements (old_htab);
   2418   1.1.1.9  mrg     }
   2419   1.1.1.9  mrg   new_htab = htab_create (total_cnt);
   2420   1.1.1.9  mrg   if (old_htab)
   2421   1.1.1.9  mrg     {
   2422   1.1.1.9  mrg       /* Copy old hash table, like in htab_expand.  */
   2423   1.1.1.9  mrg       hash_entry_type *p, *olimit;
   2424   1.1.1.9  mrg       new_htab->n_elements = htab_elements (old_htab);
   2425   1.1.1.9  mrg       olimit = old_htab->entries + old_htab->size;
   2426   1.1.1.9  mrg       p = old_htab->entries;
   2427   1.1.1.9  mrg       do
   2428   1.1.1.9  mrg 	{
   2429   1.1.1.9  mrg 	  hash_entry_type x = *p;
   2430   1.1.1.9  mrg 	  if (x != HTAB_EMPTY_ENTRY && x != HTAB_DELETED_ENTRY)
   2431   1.1.1.9  mrg 	    *find_empty_slot_for_expand (new_htab, htab_hash (x)) = x;
   2432   1.1.1.9  mrg 	  p++;
   2433   1.1.1.9  mrg 	}
   2434   1.1.1.9  mrg       while (p < olimit);
   2435   1.1.1.9  mrg     }
   2436   1.1.1.9  mrg   d = data;
   2437   1.1.1.9  mrg   do
   2438   1.1.1.9  mrg     {
   2439   1.1.1.9  mrg       size_t j;
   2440   1.1.1.9  mrg       for (j = 0; j < d[0]; ++j)
   2441   1.1.1.9  mrg 	{
   2442   1.1.1.9  mrg 	  uintptr_t *p = d + 7 + j * 3;
   2443   1.1.1.9  mrg 	  p[2] = (uintptr_t) d;
   2444   1.1.1.9  mrg 	  /* Ugly hack, hash_entry_type is defined for the task dependencies,
   2445   1.1.1.9  mrg 	     which hash on the first element which is a pointer.  We need
   2446   1.1.1.9  mrg 	     to hash also on the first sizeof (uintptr_t) bytes which contain
   2447   1.1.1.9  mrg 	     a pointer.  Hide the cast from the compiler.  */
   2448   1.1.1.9  mrg 	  hash_entry_type n;
   2449   1.1.1.9  mrg 	  __asm ("" : "=g" (n) : "0" (p));
   2450   1.1.1.9  mrg 	  *htab_find_slot (&new_htab, n, INSERT) = n;
   2451   1.1.1.9  mrg 	}
   2452   1.1.1.9  mrg       if (d[4] == (uintptr_t) old)
   2453   1.1.1.9  mrg 	break;
   2454   1.1.1.9  mrg       else
   2455   1.1.1.9  mrg 	d = (uintptr_t *) d[4];
   2456   1.1.1.9  mrg     }
   2457   1.1.1.9  mrg   while (1);
   2458   1.1.1.9  mrg   d[5] = (uintptr_t) new_htab;
   2459   1.1.1.9  mrg }
   2460   1.1.1.9  mrg 
   2461   1.1.1.9  mrg static void
   2462   1.1.1.9  mrg gomp_create_artificial_team (void)
   2463   1.1.1.9  mrg {
   2464   1.1.1.9  mrg   struct gomp_thread *thr = gomp_thread ();
   2465   1.1.1.9  mrg   struct gomp_task_icv *icv;
   2466   1.1.1.9  mrg   struct gomp_team *team = gomp_new_team (1);
   2467   1.1.1.9  mrg   struct gomp_task *task = thr->task;
   2468  1.1.1.12  mrg   struct gomp_task **implicit_task = &task;
   2469   1.1.1.9  mrg   icv = task ? &task->icv : &gomp_global_icv;
   2470   1.1.1.9  mrg   team->prev_ts = thr->ts;
   2471   1.1.1.9  mrg   thr->ts.team = team;
   2472   1.1.1.9  mrg   thr->ts.team_id = 0;
   2473   1.1.1.9  mrg   thr->ts.work_share = &team->work_shares[0];
   2474   1.1.1.9  mrg   thr->ts.last_work_share = NULL;
   2475   1.1.1.9  mrg #ifdef HAVE_SYNC_BUILTINS
   2476   1.1.1.9  mrg   thr->ts.single_count = 0;
   2477   1.1.1.9  mrg #endif
   2478   1.1.1.9  mrg   thr->ts.static_trip = 0;
   2479   1.1.1.9  mrg   thr->task = &team->implicit_task[0];
   2480   1.1.1.9  mrg   gomp_init_task (thr->task, NULL, icv);
   2481  1.1.1.12  mrg   while (*implicit_task
   2482  1.1.1.12  mrg 	 && (*implicit_task)->kind != GOMP_TASK_IMPLICIT)
   2483  1.1.1.12  mrg     implicit_task = &(*implicit_task)->parent;
   2484  1.1.1.12  mrg   if (*implicit_task)
   2485   1.1.1.9  mrg     {
   2486  1.1.1.12  mrg       thr->task = *implicit_task;
   2487   1.1.1.9  mrg       gomp_end_task ();
   2488  1.1.1.12  mrg       free (*implicit_task);
   2489   1.1.1.9  mrg       thr->task = &team->implicit_task[0];
   2490   1.1.1.9  mrg     }
   2491   1.1.1.9  mrg #ifdef LIBGOMP_USE_PTHREADS
   2492   1.1.1.9  mrg   else
   2493   1.1.1.9  mrg     pthread_setspecific (gomp_thread_destructor, thr);
   2494   1.1.1.9  mrg #endif
   2495  1.1.1.12  mrg   if (implicit_task != &task)
   2496  1.1.1.12  mrg     {
   2497  1.1.1.12  mrg       *implicit_task = thr->task;
   2498  1.1.1.12  mrg       thr->task = task;
   2499  1.1.1.12  mrg     }
   2500   1.1.1.9  mrg }
   2501   1.1.1.9  mrg 
   2502   1.1.1.9  mrg /* The format of data is:
   2503   1.1.1.9  mrg    data[0]	cnt
   2504   1.1.1.9  mrg    data[1]	size
   2505   1.1.1.9  mrg    data[2]	alignment (on output array pointer)
   2506   1.1.1.9  mrg    data[3]	allocator (-1 if malloc allocator)
   2507   1.1.1.9  mrg    data[4]	next pointer
   2508   1.1.1.9  mrg    data[5]	used internally (htab pointer)
   2509   1.1.1.9  mrg    data[6]	used internally (end of array)
   2510   1.1.1.9  mrg    cnt times
   2511   1.1.1.9  mrg    ent[0]	address
   2512   1.1.1.9  mrg    ent[1]	offset
   2513   1.1.1.9  mrg    ent[2]	used internally (pointer to data[0])
   2514   1.1.1.9  mrg    The entries are sorted by increasing offset, so that a binary
   2515   1.1.1.9  mrg    search can be performed.  Normally, data[8] is 0, exception is
   2516   1.1.1.9  mrg    for worksharing construct task reductions in cancellable parallel,
   2517   1.1.1.9  mrg    where at offset 0 there should be space for a pointer and an integer
   2518   1.1.1.9  mrg    which are used internally.  */
   2519   1.1.1.9  mrg 
   2520   1.1.1.9  mrg void
   2521   1.1.1.9  mrg GOMP_taskgroup_reduction_register (uintptr_t *data)
   2522   1.1.1.9  mrg {
   2523   1.1.1.9  mrg   struct gomp_thread *thr = gomp_thread ();
   2524   1.1.1.9  mrg   struct gomp_team *team = thr->ts.team;
   2525   1.1.1.9  mrg   struct gomp_task *task;
   2526   1.1.1.9  mrg   unsigned nthreads;
   2527   1.1.1.9  mrg   if (__builtin_expect (team == NULL, 0))
   2528   1.1.1.9  mrg     {
   2529   1.1.1.9  mrg       /* The task reduction code needs a team and task, so for
   2530   1.1.1.9  mrg 	 orphaned taskgroups just create the implicit team.  */
   2531   1.1.1.9  mrg       gomp_create_artificial_team ();
   2532   1.1.1.9  mrg       ialias_call (GOMP_taskgroup_start) ();
   2533   1.1.1.9  mrg       team = thr->ts.team;
   2534   1.1.1.9  mrg     }
   2535   1.1.1.9  mrg   nthreads = team->nthreads;
   2536   1.1.1.9  mrg   task = thr->task;
   2537   1.1.1.9  mrg   gomp_reduction_register (data, task->taskgroup->reductions, NULL, nthreads);
   2538   1.1.1.9  mrg   task->taskgroup->reductions = data;
   2539   1.1.1.9  mrg }
   2540   1.1.1.9  mrg 
   2541   1.1.1.9  mrg void
   2542   1.1.1.9  mrg GOMP_taskgroup_reduction_unregister (uintptr_t *data)
   2543   1.1.1.9  mrg {
   2544   1.1.1.9  mrg   uintptr_t *d = data;
   2545   1.1.1.9  mrg   htab_free ((struct htab *) data[5]);
   2546   1.1.1.9  mrg   do
   2547   1.1.1.9  mrg     {
   2548   1.1.1.9  mrg       gomp_aligned_free ((void *) d[2]);
   2549   1.1.1.9  mrg       d = (uintptr_t *) d[4];
   2550   1.1.1.9  mrg     }
   2551   1.1.1.9  mrg   while (d && !d[5]);
   2552   1.1.1.9  mrg }
   2553   1.1.1.9  mrg ialias (GOMP_taskgroup_reduction_unregister)
   2554   1.1.1.9  mrg 
   2555   1.1.1.9  mrg /* For i = 0 to cnt-1, remap ptrs[i] which is either address of the
   2556   1.1.1.9  mrg    original list item or address of previously remapped original list
   2557   1.1.1.9  mrg    item to address of the private copy, store that to ptrs[i].
   2558   1.1.1.9  mrg    For i < cntorig, additionally set ptrs[cnt+i] to the address of
   2559   1.1.1.9  mrg    the original list item.  */
   2560   1.1.1.9  mrg 
   2561   1.1.1.9  mrg void
   2562   1.1.1.9  mrg GOMP_task_reduction_remap (size_t cnt, size_t cntorig, void **ptrs)
   2563   1.1.1.9  mrg {
   2564   1.1.1.9  mrg   struct gomp_thread *thr = gomp_thread ();
   2565   1.1.1.9  mrg   struct gomp_task *task = thr->task;
   2566   1.1.1.9  mrg   unsigned id = thr->ts.team_id;
   2567   1.1.1.9  mrg   uintptr_t *data = task->taskgroup->reductions;
   2568   1.1.1.9  mrg   uintptr_t *d;
   2569   1.1.1.9  mrg   struct htab *reduction_htab = (struct htab *) data[5];
   2570   1.1.1.9  mrg   size_t i;
   2571   1.1.1.9  mrg   for (i = 0; i < cnt; ++i)
   2572   1.1.1.9  mrg     {
   2573   1.1.1.9  mrg       hash_entry_type ent, n;
   2574   1.1.1.9  mrg       __asm ("" : "=g" (ent) : "0" (ptrs + i));
   2575   1.1.1.9  mrg       n = htab_find (reduction_htab, ent);
   2576   1.1.1.9  mrg       if (n)
   2577   1.1.1.9  mrg 	{
   2578   1.1.1.9  mrg 	  uintptr_t *p;
   2579   1.1.1.9  mrg 	  __asm ("" : "=g" (p) : "0" (n));
   2580   1.1.1.9  mrg 	  /* At this point, p[0] should be equal to (uintptr_t) ptrs[i],
   2581   1.1.1.9  mrg 	     p[1] is the offset within the allocated chunk for each
   2582   1.1.1.9  mrg 	     thread, p[2] is the array registered with
   2583   1.1.1.9  mrg 	     GOMP_taskgroup_reduction_register, d[2] is the base of the
   2584   1.1.1.9  mrg 	     allocated memory and d[1] is the size of the allocated chunk
   2585   1.1.1.9  mrg 	     for one thread.  */
   2586   1.1.1.9  mrg 	  d = (uintptr_t *) p[2];
   2587   1.1.1.9  mrg 	  ptrs[i] = (void *) (d[2] + id * d[1] + p[1]);
   2588   1.1.1.9  mrg 	  if (__builtin_expect (i < cntorig, 0))
   2589   1.1.1.9  mrg 	    ptrs[cnt + i] = (void *) p[0];
   2590   1.1.1.9  mrg 	  continue;
   2591   1.1.1.9  mrg 	}
   2592   1.1.1.9  mrg       d = data;
   2593   1.1.1.9  mrg       while (d != NULL)
   2594   1.1.1.9  mrg 	{
   2595   1.1.1.9  mrg 	  if ((uintptr_t) ptrs[i] >= d[2] && (uintptr_t) ptrs[i] < d[6])
   2596   1.1.1.9  mrg 	    break;
   2597   1.1.1.9  mrg 	  d = (uintptr_t *) d[4];
   2598   1.1.1.9  mrg 	}
   2599   1.1.1.9  mrg       if (d == NULL)
   2600   1.1.1.9  mrg 	gomp_fatal ("couldn't find matching task_reduction or reduction with "
   2601   1.1.1.9  mrg 		    "task modifier for %p", ptrs[i]);
   2602   1.1.1.9  mrg       uintptr_t off = ((uintptr_t) ptrs[i] - d[2]) % d[1];
   2603   1.1.1.9  mrg       ptrs[i] = (void *) (d[2] + id * d[1] + off);
   2604   1.1.1.9  mrg       if (__builtin_expect (i < cntorig, 0))
   2605   1.1.1.9  mrg 	{
   2606   1.1.1.9  mrg 	  size_t lo = 0, hi = d[0] - 1;
   2607   1.1.1.9  mrg 	  while (lo <= hi)
   2608   1.1.1.9  mrg 	    {
   2609   1.1.1.9  mrg 	      size_t m = (lo + hi) / 2;
   2610   1.1.1.9  mrg 	      if (d[7 + 3 * m + 1] < off)
   2611   1.1.1.9  mrg 		lo = m + 1;
   2612   1.1.1.9  mrg 	      else if (d[7 + 3 * m + 1] == off)
   2613   1.1.1.9  mrg 		{
   2614   1.1.1.9  mrg 		  ptrs[cnt + i] = (void *) d[7 + 3 * m];
   2615   1.1.1.9  mrg 		  break;
   2616   1.1.1.9  mrg 		}
   2617   1.1.1.9  mrg 	      else
   2618   1.1.1.9  mrg 		hi = m - 1;
   2619   1.1.1.9  mrg 	    }
   2620   1.1.1.9  mrg 	  if (lo > hi)
   2621   1.1.1.9  mrg 	    gomp_fatal ("couldn't find matching task_reduction or reduction "
   2622   1.1.1.9  mrg 			"with task modifier for %p", ptrs[i]);
   2623   1.1.1.9  mrg 	}
   2624   1.1.1.9  mrg     }
   2625   1.1.1.9  mrg }
   2626   1.1.1.9  mrg 
   2627   1.1.1.9  mrg struct gomp_taskgroup *
   2628   1.1.1.9  mrg gomp_parallel_reduction_register (uintptr_t *data, unsigned nthreads)
   2629   1.1.1.9  mrg {
   2630   1.1.1.9  mrg   struct gomp_taskgroup *taskgroup = gomp_taskgroup_init (NULL);
   2631   1.1.1.9  mrg   gomp_reduction_register (data, NULL, NULL, nthreads);
   2632   1.1.1.9  mrg   taskgroup->reductions = data;
   2633   1.1.1.9  mrg   return taskgroup;
   2634   1.1.1.9  mrg }
   2635   1.1.1.9  mrg 
   2636   1.1.1.9  mrg void
   2637   1.1.1.9  mrg gomp_workshare_task_reduction_register (uintptr_t *data, uintptr_t *orig)
   2638   1.1.1.9  mrg {
   2639   1.1.1.9  mrg   struct gomp_thread *thr = gomp_thread ();
   2640   1.1.1.9  mrg   struct gomp_team *team = thr->ts.team;
   2641   1.1.1.9  mrg   struct gomp_task *task = thr->task;
   2642   1.1.1.9  mrg   unsigned nthreads = team->nthreads;
   2643   1.1.1.9  mrg   gomp_reduction_register (data, task->taskgroup->reductions, orig, nthreads);
   2644   1.1.1.9  mrg   task->taskgroup->reductions = data;
   2645   1.1.1.9  mrg }
   2646   1.1.1.9  mrg 
   2647   1.1.1.9  mrg void
   2648   1.1.1.9  mrg gomp_workshare_taskgroup_start (void)
   2649   1.1.1.9  mrg {
   2650   1.1.1.9  mrg   struct gomp_thread *thr = gomp_thread ();
   2651   1.1.1.9  mrg   struct gomp_team *team = thr->ts.team;
   2652   1.1.1.9  mrg   struct gomp_task *task;
   2653   1.1.1.9  mrg 
   2654   1.1.1.9  mrg   if (team == NULL)
   2655   1.1.1.9  mrg     {
   2656   1.1.1.9  mrg       gomp_create_artificial_team ();
   2657   1.1.1.9  mrg       team = thr->ts.team;
   2658   1.1.1.9  mrg     }
   2659   1.1.1.9  mrg   task = thr->task;
   2660   1.1.1.9  mrg   task->taskgroup = gomp_taskgroup_init (task->taskgroup);
   2661   1.1.1.9  mrg   task->taskgroup->workshare = true;
   2662   1.1.1.9  mrg }
   2663   1.1.1.9  mrg 
   2664   1.1.1.9  mrg void
   2665   1.1.1.9  mrg GOMP_workshare_task_reduction_unregister (bool cancelled)
   2666   1.1.1.9  mrg {
   2667   1.1.1.9  mrg   struct gomp_thread *thr = gomp_thread ();
   2668   1.1.1.9  mrg   struct gomp_task *task = thr->task;
   2669   1.1.1.9  mrg   struct gomp_team *team = thr->ts.team;
   2670   1.1.1.9  mrg   uintptr_t *data = task->taskgroup->reductions;
   2671   1.1.1.9  mrg   ialias_call (GOMP_taskgroup_end) ();
   2672   1.1.1.9  mrg   if (thr->ts.team_id == 0)
   2673   1.1.1.9  mrg     ialias_call (GOMP_taskgroup_reduction_unregister) (data);
   2674   1.1.1.9  mrg   else
   2675   1.1.1.9  mrg     htab_free ((struct htab *) data[5]);
   2676   1.1.1.9  mrg 
   2677   1.1.1.9  mrg   if (!cancelled)
   2678   1.1.1.9  mrg     gomp_team_barrier_wait (&team->barrier);
   2679   1.1.1.9  mrg }
   2680   1.1.1.9  mrg 
   2681   1.1.1.2  mrg int
   2682   1.1.1.2  mrg omp_in_final (void)
   2683   1.1.1.2  mrg {
   2684   1.1.1.2  mrg   struct gomp_thread *thr = gomp_thread ();
   2685   1.1.1.2  mrg   return thr->task && thr->task->final_task;
   2686   1.1.1.2  mrg }
   2687   1.1.1.2  mrg 
   2688   1.1.1.2  mrg ialias (omp_in_final)
   2689  1.1.1.13  mrg 
   2690  1.1.1.14  mrg int
   2691  1.1.1.14  mrg omp_in_explicit_task (void)
   2692  1.1.1.14  mrg {
   2693  1.1.1.14  mrg   struct gomp_thread *thr = gomp_thread ();
   2694  1.1.1.14  mrg   struct gomp_task *task = thr->task;
   2695  1.1.1.14  mrg   return task && task->kind != GOMP_TASK_IMPLICIT;
   2696  1.1.1.14  mrg }
   2697  1.1.1.14  mrg 
   2698  1.1.1.14  mrg ialias (omp_in_explicit_task)
   2699  1.1.1.14  mrg 
   2700  1.1.1.13  mrg void
   2701  1.1.1.13  mrg omp_fulfill_event (omp_event_handle_t event)
   2702  1.1.1.13  mrg {
   2703  1.1.1.13  mrg   struct gomp_task *task = (struct gomp_task *) event;
   2704  1.1.1.13  mrg   if (!task->deferred_p)
   2705  1.1.1.13  mrg     {
   2706  1.1.1.13  mrg       if (gomp_sem_getcount (task->completion_sem) > 0)
   2707  1.1.1.13  mrg 	gomp_fatal ("omp_fulfill_event: %p event already fulfilled!\n", task);
   2708  1.1.1.13  mrg 
   2709  1.1.1.13  mrg       gomp_debug (0, "omp_fulfill_event: %p event for undeferred task\n",
   2710  1.1.1.13  mrg 		  task);
   2711  1.1.1.13  mrg       gomp_sem_post (task->completion_sem);
   2712  1.1.1.13  mrg       return;
   2713  1.1.1.13  mrg     }
   2714  1.1.1.13  mrg 
   2715  1.1.1.13  mrg   struct gomp_team *team = __atomic_load_n (&task->detach_team,
   2716  1.1.1.13  mrg 					    MEMMODEL_RELAXED);
   2717  1.1.1.13  mrg   if (!team)
   2718  1.1.1.13  mrg     gomp_fatal ("omp_fulfill_event: %p event is invalid or has already "
   2719  1.1.1.13  mrg 		"been fulfilled!\n", task);
   2720  1.1.1.13  mrg 
   2721  1.1.1.13  mrg   gomp_mutex_lock (&team->task_lock);
   2722  1.1.1.13  mrg   if (task->kind != GOMP_TASK_DETACHED)
   2723  1.1.1.13  mrg     {
   2724  1.1.1.13  mrg       /* The task has not finished running yet.  */
   2725  1.1.1.13  mrg       gomp_debug (0,
   2726  1.1.1.13  mrg 		  "omp_fulfill_event: %p event fulfilled for unfinished "
   2727  1.1.1.13  mrg 		  "task\n", task);
   2728  1.1.1.13  mrg       __atomic_store_n (&task->detach_team, NULL, MEMMODEL_RELAXED);
   2729  1.1.1.13  mrg       gomp_mutex_unlock (&team->task_lock);
   2730  1.1.1.13  mrg       return;
   2731  1.1.1.13  mrg     }
   2732  1.1.1.13  mrg 
   2733  1.1.1.13  mrg   gomp_debug (0, "omp_fulfill_event: %p event fulfilled for finished task\n",
   2734  1.1.1.13  mrg 	      task);
   2735  1.1.1.13  mrg   size_t new_tasks = gomp_task_run_post_handle_depend (task, team);
   2736  1.1.1.13  mrg   gomp_task_run_post_remove_parent (task);
   2737  1.1.1.13  mrg   gomp_clear_parent (&task->children_queue);
   2738  1.1.1.13  mrg   gomp_task_run_post_remove_taskgroup (task);
   2739  1.1.1.13  mrg   team->task_count--;
   2740  1.1.1.13  mrg   team->task_detach_count--;
   2741  1.1.1.13  mrg 
   2742  1.1.1.13  mrg   int do_wake = 0;
   2743  1.1.1.13  mrg   bool shackled_thread_p = team == gomp_thread ()->ts.team;
   2744  1.1.1.13  mrg   if (new_tasks > 0)
   2745  1.1.1.13  mrg     {
   2746  1.1.1.13  mrg       /* Wake up threads to run new tasks.  */
   2747  1.1.1.13  mrg       gomp_team_barrier_set_task_pending (&team->barrier);
   2748  1.1.1.13  mrg       do_wake = team->nthreads - team->task_running_count;
   2749  1.1.1.13  mrg       if (do_wake > new_tasks)
   2750  1.1.1.13  mrg 	do_wake = new_tasks;
   2751  1.1.1.13  mrg     }
   2752  1.1.1.13  mrg 
   2753  1.1.1.13  mrg   if (!shackled_thread_p
   2754  1.1.1.13  mrg       && !do_wake
   2755  1.1.1.13  mrg       && team->task_detach_count == 0
   2756  1.1.1.13  mrg       && gomp_team_barrier_waiting_for_tasks (&team->barrier))
   2757  1.1.1.13  mrg     /* Ensure that at least one thread is woken up to signal that the
   2758  1.1.1.13  mrg        barrier can finish.  */
   2759  1.1.1.13  mrg     do_wake = 1;
   2760  1.1.1.13  mrg 
   2761  1.1.1.13  mrg   /* If we are running in an unshackled thread, the team might vanish before
   2762  1.1.1.13  mrg      gomp_team_barrier_wake is run if we release the lock first, so keep the
   2763  1.1.1.13  mrg      lock for the call in that case.  */
   2764  1.1.1.13  mrg   if (shackled_thread_p)
   2765  1.1.1.13  mrg     gomp_mutex_unlock (&team->task_lock);
   2766  1.1.1.13  mrg   if (do_wake)
   2767  1.1.1.13  mrg     gomp_team_barrier_wake (&team->barrier, do_wake);
   2768  1.1.1.13  mrg   if (!shackled_thread_p)
   2769  1.1.1.13  mrg     gomp_mutex_unlock (&team->task_lock);
   2770  1.1.1.13  mrg 
   2771  1.1.1.13  mrg   gomp_finish_task (task);
   2772  1.1.1.13  mrg   free (task);
   2773  1.1.1.13  mrg }
   2774  1.1.1.13  mrg 
   2775  1.1.1.13  mrg ialias (omp_fulfill_event)
   2776