xref: /dflybsd-src/contrib/gcc-4.7/libgomp/task.c (revision 629ff9f7b980ce64c3aea92486ca4bb1a64f1bf3)
1*629ff9f7SJohn Marino /* Copyright (C) 2007, 2008, 2009, 2011 Free Software Foundation, Inc.
2*629ff9f7SJohn Marino    Contributed by Richard Henderson <rth@redhat.com>.
3*629ff9f7SJohn Marino 
4*629ff9f7SJohn Marino    This file is part of the GNU OpenMP Library (libgomp).
5*629ff9f7SJohn Marino 
6*629ff9f7SJohn Marino    Libgomp is free software; you can redistribute it and/or modify it
7*629ff9f7SJohn Marino    under the terms of the GNU General Public License as published by
8*629ff9f7SJohn Marino    the Free Software Foundation; either version 3, or (at your option)
9*629ff9f7SJohn Marino    any later version.
10*629ff9f7SJohn Marino 
11*629ff9f7SJohn Marino    Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
12*629ff9f7SJohn Marino    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13*629ff9f7SJohn Marino    FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14*629ff9f7SJohn Marino    more details.
15*629ff9f7SJohn Marino 
16*629ff9f7SJohn Marino    Under Section 7 of GPL version 3, you are granted additional
17*629ff9f7SJohn Marino    permissions described in the GCC Runtime Library Exception, version
18*629ff9f7SJohn Marino    3.1, as published by the Free Software Foundation.
19*629ff9f7SJohn Marino 
20*629ff9f7SJohn Marino    You should have received a copy of the GNU General Public License and
21*629ff9f7SJohn Marino    a copy of the GCC Runtime Library Exception along with this program;
22*629ff9f7SJohn Marino    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23*629ff9f7SJohn Marino    <http://www.gnu.org/licenses/>.  */
24*629ff9f7SJohn Marino 
25*629ff9f7SJohn Marino /* This file handles the maintainence of tasks in response to task
26*629ff9f7SJohn Marino    creation and termination.  */
27*629ff9f7SJohn Marino 
28*629ff9f7SJohn Marino #include "libgomp.h"
29*629ff9f7SJohn Marino #include <stdlib.h>
30*629ff9f7SJohn Marino #include <string.h>
31*629ff9f7SJohn Marino 
32*629ff9f7SJohn Marino 
33*629ff9f7SJohn Marino /* Create a new task data structure.  */
34*629ff9f7SJohn Marino 
35*629ff9f7SJohn Marino void
36*629ff9f7SJohn Marino gomp_init_task (struct gomp_task *task, struct gomp_task *parent_task,
37*629ff9f7SJohn Marino 		struct gomp_task_icv *prev_icv)
38*629ff9f7SJohn Marino {
39*629ff9f7SJohn Marino   task->parent = parent_task;
40*629ff9f7SJohn Marino   task->icv = *prev_icv;
41*629ff9f7SJohn Marino   task->kind = GOMP_TASK_IMPLICIT;
42*629ff9f7SJohn Marino   task->in_taskwait = false;
43*629ff9f7SJohn Marino   task->in_tied_task = false;
44*629ff9f7SJohn Marino   task->final_task = false;
45*629ff9f7SJohn Marino   task->children = NULL;
46*629ff9f7SJohn Marino   gomp_sem_init (&task->taskwait_sem, 0);
47*629ff9f7SJohn Marino }
48*629ff9f7SJohn Marino 
49*629ff9f7SJohn Marino /* Clean up a task, after completing it.  */
50*629ff9f7SJohn Marino 
51*629ff9f7SJohn Marino void
52*629ff9f7SJohn Marino gomp_end_task (void)
53*629ff9f7SJohn Marino {
54*629ff9f7SJohn Marino   struct gomp_thread *thr = gomp_thread ();
55*629ff9f7SJohn Marino   struct gomp_task *task = thr->task;
56*629ff9f7SJohn Marino 
57*629ff9f7SJohn Marino   gomp_finish_task (task);
58*629ff9f7SJohn Marino   thr->task = task->parent;
59*629ff9f7SJohn Marino }
60*629ff9f7SJohn Marino 
61*629ff9f7SJohn Marino static inline void
62*629ff9f7SJohn Marino gomp_clear_parent (struct gomp_task *children)
63*629ff9f7SJohn Marino {
64*629ff9f7SJohn Marino   struct gomp_task *task = children;
65*629ff9f7SJohn Marino 
66*629ff9f7SJohn Marino   if (task)
67*629ff9f7SJohn Marino     do
68*629ff9f7SJohn Marino       {
69*629ff9f7SJohn Marino 	task->parent = NULL;
70*629ff9f7SJohn Marino 	task = task->next_child;
71*629ff9f7SJohn Marino       }
72*629ff9f7SJohn Marino     while (task != children);
73*629ff9f7SJohn Marino }
74*629ff9f7SJohn Marino 
75*629ff9f7SJohn Marino /* Called when encountering an explicit task directive.  If IF_CLAUSE is
76*629ff9f7SJohn Marino    false, then we must not delay in executing the task.  If UNTIED is true,
77*629ff9f7SJohn Marino    then the task may be executed by any member of the team.  */
78*629ff9f7SJohn Marino 
79*629ff9f7SJohn Marino void
80*629ff9f7SJohn Marino GOMP_task (void (*fn) (void *), void *data, void (*cpyfn) (void *, void *),
81*629ff9f7SJohn Marino 	   long arg_size, long arg_align, bool if_clause, unsigned flags)
82*629ff9f7SJohn Marino {
83*629ff9f7SJohn Marino   struct gomp_thread *thr = gomp_thread ();
84*629ff9f7SJohn Marino   struct gomp_team *team = thr->ts.team;
85*629ff9f7SJohn Marino 
86*629ff9f7SJohn Marino #ifdef HAVE_BROKEN_POSIX_SEMAPHORES
87*629ff9f7SJohn Marino   /* If pthread_mutex_* is used for omp_*lock*, then each task must be
88*629ff9f7SJohn Marino      tied to one thread all the time.  This means UNTIED tasks must be
89*629ff9f7SJohn Marino      tied and if CPYFN is non-NULL IF(0) must be forced, as CPYFN
90*629ff9f7SJohn Marino      might be running on different thread than FN.  */
91*629ff9f7SJohn Marino   if (cpyfn)
92*629ff9f7SJohn Marino     if_clause = false;
93*629ff9f7SJohn Marino   if (flags & 1)
94*629ff9f7SJohn Marino     flags &= ~1;
95*629ff9f7SJohn Marino #endif
96*629ff9f7SJohn Marino 
97*629ff9f7SJohn Marino   if (!if_clause || team == NULL
98*629ff9f7SJohn Marino       || (thr->task && thr->task->final_task)
99*629ff9f7SJohn Marino       || team->task_count > 64 * team->nthreads)
100*629ff9f7SJohn Marino     {
101*629ff9f7SJohn Marino       struct gomp_task task;
102*629ff9f7SJohn Marino 
103*629ff9f7SJohn Marino       gomp_init_task (&task, thr->task, gomp_icv (false));
104*629ff9f7SJohn Marino       task.kind = GOMP_TASK_IFFALSE;
105*629ff9f7SJohn Marino       task.final_task = (thr->task && thr->task->final_task) || (flags & 2);
106*629ff9f7SJohn Marino       if (thr->task)
107*629ff9f7SJohn Marino 	task.in_tied_task = thr->task->in_tied_task;
108*629ff9f7SJohn Marino       thr->task = &task;
109*629ff9f7SJohn Marino       if (__builtin_expect (cpyfn != NULL, 0))
110*629ff9f7SJohn Marino 	{
111*629ff9f7SJohn Marino 	  char buf[arg_size + arg_align - 1];
112*629ff9f7SJohn Marino 	  char *arg = (char *) (((uintptr_t) buf + arg_align - 1)
113*629ff9f7SJohn Marino 				& ~(uintptr_t) (arg_align - 1));
114*629ff9f7SJohn Marino 	  cpyfn (arg, data);
115*629ff9f7SJohn Marino 	  fn (arg);
116*629ff9f7SJohn Marino 	}
117*629ff9f7SJohn Marino       else
118*629ff9f7SJohn Marino 	fn (data);
119*629ff9f7SJohn Marino       if (team != NULL)
120*629ff9f7SJohn Marino 	{
121*629ff9f7SJohn Marino 	  gomp_mutex_lock (&team->task_lock);
122*629ff9f7SJohn Marino 	  if (task.children != NULL)
123*629ff9f7SJohn Marino 	    gomp_clear_parent (task.children);
124*629ff9f7SJohn Marino 	  gomp_mutex_unlock (&team->task_lock);
125*629ff9f7SJohn Marino 	}
126*629ff9f7SJohn Marino       gomp_end_task ();
127*629ff9f7SJohn Marino     }
128*629ff9f7SJohn Marino   else
129*629ff9f7SJohn Marino     {
130*629ff9f7SJohn Marino       struct gomp_task *task;
131*629ff9f7SJohn Marino       struct gomp_task *parent = thr->task;
132*629ff9f7SJohn Marino       char *arg;
133*629ff9f7SJohn Marino       bool do_wake;
134*629ff9f7SJohn Marino 
135*629ff9f7SJohn Marino       task = gomp_malloc (sizeof (*task) + arg_size + arg_align - 1);
136*629ff9f7SJohn Marino       arg = (char *) (((uintptr_t) (task + 1) + arg_align - 1)
137*629ff9f7SJohn Marino 		      & ~(uintptr_t) (arg_align - 1));
138*629ff9f7SJohn Marino       gomp_init_task (task, parent, gomp_icv (false));
139*629ff9f7SJohn Marino       task->kind = GOMP_TASK_IFFALSE;
140*629ff9f7SJohn Marino       task->in_tied_task = parent->in_tied_task;
141*629ff9f7SJohn Marino       thr->task = task;
142*629ff9f7SJohn Marino       if (cpyfn)
143*629ff9f7SJohn Marino 	cpyfn (arg, data);
144*629ff9f7SJohn Marino       else
145*629ff9f7SJohn Marino 	memcpy (arg, data, arg_size);
146*629ff9f7SJohn Marino       thr->task = parent;
147*629ff9f7SJohn Marino       task->kind = GOMP_TASK_WAITING;
148*629ff9f7SJohn Marino       task->fn = fn;
149*629ff9f7SJohn Marino       task->fn_data = arg;
150*629ff9f7SJohn Marino       task->in_tied_task = true;
151*629ff9f7SJohn Marino       task->final_task = (flags & 2) >> 1;
152*629ff9f7SJohn Marino       gomp_mutex_lock (&team->task_lock);
153*629ff9f7SJohn Marino       if (parent->children)
154*629ff9f7SJohn Marino 	{
155*629ff9f7SJohn Marino 	  task->next_child = parent->children;
156*629ff9f7SJohn Marino 	  task->prev_child = parent->children->prev_child;
157*629ff9f7SJohn Marino 	  task->next_child->prev_child = task;
158*629ff9f7SJohn Marino 	  task->prev_child->next_child = task;
159*629ff9f7SJohn Marino 	}
160*629ff9f7SJohn Marino       else
161*629ff9f7SJohn Marino 	{
162*629ff9f7SJohn Marino 	  task->next_child = task;
163*629ff9f7SJohn Marino 	  task->prev_child = task;
164*629ff9f7SJohn Marino 	}
165*629ff9f7SJohn Marino       parent->children = task;
166*629ff9f7SJohn Marino       if (team->task_queue)
167*629ff9f7SJohn Marino 	{
168*629ff9f7SJohn Marino 	  task->next_queue = team->task_queue;
169*629ff9f7SJohn Marino 	  task->prev_queue = team->task_queue->prev_queue;
170*629ff9f7SJohn Marino 	  task->next_queue->prev_queue = task;
171*629ff9f7SJohn Marino 	  task->prev_queue->next_queue = task;
172*629ff9f7SJohn Marino 	}
173*629ff9f7SJohn Marino       else
174*629ff9f7SJohn Marino 	{
175*629ff9f7SJohn Marino 	  task->next_queue = task;
176*629ff9f7SJohn Marino 	  task->prev_queue = task;
177*629ff9f7SJohn Marino 	  team->task_queue = task;
178*629ff9f7SJohn Marino 	}
179*629ff9f7SJohn Marino       ++team->task_count;
180*629ff9f7SJohn Marino       gomp_team_barrier_set_task_pending (&team->barrier);
181*629ff9f7SJohn Marino       do_wake = team->task_running_count + !parent->in_tied_task
182*629ff9f7SJohn Marino 		< team->nthreads;
183*629ff9f7SJohn Marino       gomp_mutex_unlock (&team->task_lock);
184*629ff9f7SJohn Marino       if (do_wake)
185*629ff9f7SJohn Marino 	gomp_team_barrier_wake (&team->barrier, 1);
186*629ff9f7SJohn Marino     }
187*629ff9f7SJohn Marino }
188*629ff9f7SJohn Marino 
189*629ff9f7SJohn Marino void
190*629ff9f7SJohn Marino gomp_barrier_handle_tasks (gomp_barrier_state_t state)
191*629ff9f7SJohn Marino {
192*629ff9f7SJohn Marino   struct gomp_thread *thr = gomp_thread ();
193*629ff9f7SJohn Marino   struct gomp_team *team = thr->ts.team;
194*629ff9f7SJohn Marino   struct gomp_task *task = thr->task;
195*629ff9f7SJohn Marino   struct gomp_task *child_task = NULL;
196*629ff9f7SJohn Marino   struct gomp_task *to_free = NULL;
197*629ff9f7SJohn Marino 
198*629ff9f7SJohn Marino   gomp_mutex_lock (&team->task_lock);
199*629ff9f7SJohn Marino   if (gomp_barrier_last_thread (state))
200*629ff9f7SJohn Marino     {
201*629ff9f7SJohn Marino       if (team->task_count == 0)
202*629ff9f7SJohn Marino 	{
203*629ff9f7SJohn Marino 	  gomp_team_barrier_done (&team->barrier, state);
204*629ff9f7SJohn Marino 	  gomp_mutex_unlock (&team->task_lock);
205*629ff9f7SJohn Marino 	  gomp_team_barrier_wake (&team->barrier, 0);
206*629ff9f7SJohn Marino 	  return;
207*629ff9f7SJohn Marino 	}
208*629ff9f7SJohn Marino       gomp_team_barrier_set_waiting_for_tasks (&team->barrier);
209*629ff9f7SJohn Marino     }
210*629ff9f7SJohn Marino 
211*629ff9f7SJohn Marino   while (1)
212*629ff9f7SJohn Marino     {
213*629ff9f7SJohn Marino       if (team->task_queue != NULL)
214*629ff9f7SJohn Marino 	{
215*629ff9f7SJohn Marino 	  struct gomp_task *parent;
216*629ff9f7SJohn Marino 
217*629ff9f7SJohn Marino 	  child_task = team->task_queue;
218*629ff9f7SJohn Marino 	  parent = child_task->parent;
219*629ff9f7SJohn Marino 	  if (parent && parent->children == child_task)
220*629ff9f7SJohn Marino 	    parent->children = child_task->next_child;
221*629ff9f7SJohn Marino 	  child_task->prev_queue->next_queue = child_task->next_queue;
222*629ff9f7SJohn Marino 	  child_task->next_queue->prev_queue = child_task->prev_queue;
223*629ff9f7SJohn Marino 	  if (child_task->next_queue != child_task)
224*629ff9f7SJohn Marino 	    team->task_queue = child_task->next_queue;
225*629ff9f7SJohn Marino 	  else
226*629ff9f7SJohn Marino 	    team->task_queue = NULL;
227*629ff9f7SJohn Marino 	  child_task->kind = GOMP_TASK_TIED;
228*629ff9f7SJohn Marino 	  team->task_running_count++;
229*629ff9f7SJohn Marino 	  if (team->task_count == team->task_running_count)
230*629ff9f7SJohn Marino 	    gomp_team_barrier_clear_task_pending (&team->barrier);
231*629ff9f7SJohn Marino 	}
232*629ff9f7SJohn Marino       gomp_mutex_unlock (&team->task_lock);
233*629ff9f7SJohn Marino       if (to_free)
234*629ff9f7SJohn Marino 	{
235*629ff9f7SJohn Marino 	  gomp_finish_task (to_free);
236*629ff9f7SJohn Marino 	  free (to_free);
237*629ff9f7SJohn Marino 	  to_free = NULL;
238*629ff9f7SJohn Marino 	}
239*629ff9f7SJohn Marino       if (child_task)
240*629ff9f7SJohn Marino 	{
241*629ff9f7SJohn Marino 	  thr->task = child_task;
242*629ff9f7SJohn Marino 	  child_task->fn (child_task->fn_data);
243*629ff9f7SJohn Marino 	  thr->task = task;
244*629ff9f7SJohn Marino 	}
245*629ff9f7SJohn Marino       else
246*629ff9f7SJohn Marino 	return;
247*629ff9f7SJohn Marino       gomp_mutex_lock (&team->task_lock);
248*629ff9f7SJohn Marino       if (child_task)
249*629ff9f7SJohn Marino 	{
250*629ff9f7SJohn Marino 	  struct gomp_task *parent = child_task->parent;
251*629ff9f7SJohn Marino 	  if (parent)
252*629ff9f7SJohn Marino 	    {
253*629ff9f7SJohn Marino 	      child_task->prev_child->next_child = child_task->next_child;
254*629ff9f7SJohn Marino 	      child_task->next_child->prev_child = child_task->prev_child;
255*629ff9f7SJohn Marino 	      if (parent->children == child_task)
256*629ff9f7SJohn Marino 		{
257*629ff9f7SJohn Marino 		  if (child_task->next_child != child_task)
258*629ff9f7SJohn Marino 		    parent->children = child_task->next_child;
259*629ff9f7SJohn Marino 		  else
260*629ff9f7SJohn Marino 		    {
261*629ff9f7SJohn Marino 		      parent->children = NULL;
262*629ff9f7SJohn Marino 		      if (parent->in_taskwait)
263*629ff9f7SJohn Marino 			gomp_sem_post (&parent->taskwait_sem);
264*629ff9f7SJohn Marino 		    }
265*629ff9f7SJohn Marino 		}
266*629ff9f7SJohn Marino 	    }
267*629ff9f7SJohn Marino 	  gomp_clear_parent (child_task->children);
268*629ff9f7SJohn Marino 	  to_free = child_task;
269*629ff9f7SJohn Marino 	  child_task = NULL;
270*629ff9f7SJohn Marino 	  team->task_running_count--;
271*629ff9f7SJohn Marino 	  if (--team->task_count == 0
272*629ff9f7SJohn Marino 	      && gomp_team_barrier_waiting_for_tasks (&team->barrier))
273*629ff9f7SJohn Marino 	    {
274*629ff9f7SJohn Marino 	      gomp_team_barrier_done (&team->barrier, state);
275*629ff9f7SJohn Marino 	      gomp_mutex_unlock (&team->task_lock);
276*629ff9f7SJohn Marino 	      gomp_team_barrier_wake (&team->barrier, 0);
277*629ff9f7SJohn Marino 	      gomp_mutex_lock (&team->task_lock);
278*629ff9f7SJohn Marino 	    }
279*629ff9f7SJohn Marino 	}
280*629ff9f7SJohn Marino     }
281*629ff9f7SJohn Marino }
282*629ff9f7SJohn Marino 
283*629ff9f7SJohn Marino /* Called when encountering a taskwait directive.  */
284*629ff9f7SJohn Marino 
285*629ff9f7SJohn Marino void
286*629ff9f7SJohn Marino GOMP_taskwait (void)
287*629ff9f7SJohn Marino {
288*629ff9f7SJohn Marino   struct gomp_thread *thr = gomp_thread ();
289*629ff9f7SJohn Marino   struct gomp_team *team = thr->ts.team;
290*629ff9f7SJohn Marino   struct gomp_task *task = thr->task;
291*629ff9f7SJohn Marino   struct gomp_task *child_task = NULL;
292*629ff9f7SJohn Marino   struct gomp_task *to_free = NULL;
293*629ff9f7SJohn Marino 
294*629ff9f7SJohn Marino   if (task == NULL || team == NULL)
295*629ff9f7SJohn Marino     return;
296*629ff9f7SJohn Marino 
297*629ff9f7SJohn Marino   gomp_mutex_lock (&team->task_lock);
298*629ff9f7SJohn Marino   while (1)
299*629ff9f7SJohn Marino     {
300*629ff9f7SJohn Marino       if (task->children == NULL)
301*629ff9f7SJohn Marino 	{
302*629ff9f7SJohn Marino 	  gomp_mutex_unlock (&team->task_lock);
303*629ff9f7SJohn Marino 	  if (to_free)
304*629ff9f7SJohn Marino 	    {
305*629ff9f7SJohn Marino 	      gomp_finish_task (to_free);
306*629ff9f7SJohn Marino 	      free (to_free);
307*629ff9f7SJohn Marino 	    }
308*629ff9f7SJohn Marino 	  return;
309*629ff9f7SJohn Marino 	}
310*629ff9f7SJohn Marino       if (task->children->kind == GOMP_TASK_WAITING)
311*629ff9f7SJohn Marino 	{
312*629ff9f7SJohn Marino 	  child_task = task->children;
313*629ff9f7SJohn Marino 	  task->children = child_task->next_child;
314*629ff9f7SJohn Marino 	  child_task->prev_queue->next_queue = child_task->next_queue;
315*629ff9f7SJohn Marino 	  child_task->next_queue->prev_queue = child_task->prev_queue;
316*629ff9f7SJohn Marino 	  if (team->task_queue == child_task)
317*629ff9f7SJohn Marino 	    {
318*629ff9f7SJohn Marino 	      if (child_task->next_queue != child_task)
319*629ff9f7SJohn Marino 		team->task_queue = child_task->next_queue;
320*629ff9f7SJohn Marino 	      else
321*629ff9f7SJohn Marino 		team->task_queue = NULL;
322*629ff9f7SJohn Marino 	    }
323*629ff9f7SJohn Marino 	  child_task->kind = GOMP_TASK_TIED;
324*629ff9f7SJohn Marino 	  team->task_running_count++;
325*629ff9f7SJohn Marino 	  if (team->task_count == team->task_running_count)
326*629ff9f7SJohn Marino 	    gomp_team_barrier_clear_task_pending (&team->barrier);
327*629ff9f7SJohn Marino 	}
328*629ff9f7SJohn Marino       else
329*629ff9f7SJohn Marino 	/* All tasks we are waiting for are already running
330*629ff9f7SJohn Marino 	   in other threads.  Wait for them.  */
331*629ff9f7SJohn Marino 	task->in_taskwait = true;
332*629ff9f7SJohn Marino       gomp_mutex_unlock (&team->task_lock);
333*629ff9f7SJohn Marino       if (to_free)
334*629ff9f7SJohn Marino 	{
335*629ff9f7SJohn Marino 	  gomp_finish_task (to_free);
336*629ff9f7SJohn Marino 	  free (to_free);
337*629ff9f7SJohn Marino 	  to_free = NULL;
338*629ff9f7SJohn Marino 	}
339*629ff9f7SJohn Marino       if (child_task)
340*629ff9f7SJohn Marino 	{
341*629ff9f7SJohn Marino 	  thr->task = child_task;
342*629ff9f7SJohn Marino 	  child_task->fn (child_task->fn_data);
343*629ff9f7SJohn Marino 	  thr->task = task;
344*629ff9f7SJohn Marino 	}
345*629ff9f7SJohn Marino       else
346*629ff9f7SJohn Marino 	{
347*629ff9f7SJohn Marino 	  gomp_sem_wait (&task->taskwait_sem);
348*629ff9f7SJohn Marino 	  task->in_taskwait = false;
349*629ff9f7SJohn Marino 	  return;
350*629ff9f7SJohn Marino 	}
351*629ff9f7SJohn Marino       gomp_mutex_lock (&team->task_lock);
352*629ff9f7SJohn Marino       if (child_task)
353*629ff9f7SJohn Marino 	{
354*629ff9f7SJohn Marino 	  child_task->prev_child->next_child = child_task->next_child;
355*629ff9f7SJohn Marino 	  child_task->next_child->prev_child = child_task->prev_child;
356*629ff9f7SJohn Marino 	  if (task->children == child_task)
357*629ff9f7SJohn Marino 	    {
358*629ff9f7SJohn Marino 	      if (child_task->next_child != child_task)
359*629ff9f7SJohn Marino 		task->children = child_task->next_child;
360*629ff9f7SJohn Marino 	      else
361*629ff9f7SJohn Marino 		task->children = NULL;
362*629ff9f7SJohn Marino 	    }
363*629ff9f7SJohn Marino 	  gomp_clear_parent (child_task->children);
364*629ff9f7SJohn Marino 	  to_free = child_task;
365*629ff9f7SJohn Marino 	  child_task = NULL;
366*629ff9f7SJohn Marino 	  team->task_count--;
367*629ff9f7SJohn Marino 	  team->task_running_count--;
368*629ff9f7SJohn Marino 	}
369*629ff9f7SJohn Marino     }
370*629ff9f7SJohn Marino }
371*629ff9f7SJohn Marino 
372*629ff9f7SJohn Marino /* Called when encountering a taskyield directive.  */
373*629ff9f7SJohn Marino 
374*629ff9f7SJohn Marino void
375*629ff9f7SJohn Marino GOMP_taskyield (void)
376*629ff9f7SJohn Marino {
377*629ff9f7SJohn Marino   /* Nothing at the moment.  */
378*629ff9f7SJohn Marino }
379*629ff9f7SJohn Marino 
380*629ff9f7SJohn Marino int
381*629ff9f7SJohn Marino omp_in_final (void)
382*629ff9f7SJohn Marino {
383*629ff9f7SJohn Marino   struct gomp_thread *thr = gomp_thread ();
384*629ff9f7SJohn Marino   return thr->task && thr->task->final_task;
385*629ff9f7SJohn Marino }
386*629ff9f7SJohn Marino 
387*629ff9f7SJohn Marino ialias (omp_in_final)
388