1  /* PR target/78694.  */
       2  
       3  enum
       4  {
       5    MEMMODEL_RELAXED,
       6    MEMMODEL_ACQUIRE,
       7    PRIORITY_INSERT_END
       8  };
       9  enum
      10  {
      11    PQ_CHILDREN,
      12    PQ_TASKGROUP
      13  };
      14  struct gomp_team_state
      15  {
      16    struct gomp_team *team;
      17  };
      18  enum gomp_task_kind
      19  {
      20    GOMP_TASK_UNDEFERRED,
      21    GOMP_TASK_WAITING
      22  };
      23  struct gomp_taskwait
      24  {
      25    _Bool in_taskwait;
      26  };
      27  struct gomp_task
      28  {
      29    struct gomp_task *parent;
      30    int children_queue;
      31    struct gomp_taskgroup *taskgroup;
      32    int dependers;
      33    struct gomp_taskwait taskwait;
      34    enum gomp_task_kind kind;
      35    _Bool in_tied_task;
      36  } j, q, *n;
      37  struct gomp_taskgroup
      38  {
      39    _Bool in_taskgroup_wait;
      40    int num_children;
      41  } l;
      42  struct gomp_team
      43  {
      44    int task_queue;
      45    int task_running_count;
      46  };
      47  struct gomp_thread
      48  {
      49    struct gomp_team_state ts;
      50    struct gomp_task task;
      51  } extern __thread a;
      52  
      53  int b, c, d, e, f, g, h, i, k, m, o, p, r;
      54  
      55  void priority_queue_next_task (struct gomp_task *, int, int);
      56  int gomp_task_run_pre (struct gomp_task *, struct gomp_task, struct gomp_team);
      57  void priority_queue_insert (int, struct gomp_task);
      58  void priority_queue_insert2 (int, struct gomp_task, int, int, int);
      59  void priority_queue_insert3 (int, struct gomp_task, int, int, int);
      60  void gomp_sem_post (int);
      61  void free (void *);
      62  
      63  _Bool s;
      64  int
      65  GOMP_taskgroup_end ()
      66  {
      67    struct gomp_thread *t = &a;
      68    struct gomp_team u = *t->ts.team;
      69    struct gomp_task *v = &t->task, *w;
      70    if (__atomic_load_n (&l.num_children, MEMMODEL_ACQUIRE))
      71      while (1)
      72        {
      73  	if (l.num_children)
      74  	  priority_queue_next_task (v, u.task_queue, r);
      75  	else if (w)
      76  	  free (w);
      77  	if (n->kind == GOMP_TASK_WAITING)
      78  	  {
      79  	    s = gomp_task_run_pre (n, q, u);
      80  	    if (__builtin_expect (s, 0))
      81  	      {
      82  		if (w)
      83  		  free (w);
      84  		goto finish_cancelled;
      85  	      }
      86  	    n = 0;
      87  	    l.in_taskgroup_wait = 1;
      88  	  }
      89  	if (w)
      90  	  {
      91  	    t->task = *n;
      92  	    if (__builtin_expect (p, 0))
      93  	      if (o)
      94  		t->task = *v;
      95  	  }
      96  	if (n)
      97  	  {
      98  	    struct gomp_task x = x;
      99  	    for (; i; b++)
     100  	      {
     101  		struct gomp_task y = j;
     102  		if (g)
     103  		  continue;
     104  		priority_queue_insert (PQ_CHILDREN, x);
     105  		if (x.taskwait.in_taskwait)
     106  		  priority_queue_insert2 (PQ_TASKGROUP, y, e, 0, d);
     107  		if (h)
     108  		  gomp_sem_post (f);
     109  		priority_queue_insert3 (k, y, PRIORITY_INSERT_END, 0, d);
     110  		++c;
     111  	      }
     112  	  }
     113        finish_cancelled:
     114  	w = (struct gomp_task *) (n - u.task_running_count - v);
     115        }
     116    v->taskgroup = (struct gomp_taskgroup *) m;
     117    return 1;
     118  }