revert between 56095 -> 55830 in arch
[AROS.git] / rom / exec / childwait.c
blobd07effedae61826eef733e97c5a1e0851d53a8e1
1 /*
2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
3 $Id$
5 ChildWait() - Wait for a task to finish it processing.
6 */
7 #include "exec_intern.h"
8 #include <proto/exec.h>
10 /*****************************************************************************
12 NAME */
14 AROS_LH1(IPTR, ChildWait,
16 /* SYNOPSIS */
17 AROS_LHA(ULONG, tid, D0),
19 /* LOCATION */
20 struct ExecBase *, SysBase, 126, Exec)
22 /* FUNCTION
23 Wait for either a specific child task, or any child task to finish.
24 If you specify tid = 0, then the call will return when any child
25 task exits, otherwise it will not return until the requested task
26 finishes.
28 Note that the tid is NOT the task control block (ie struct Task *),
29 rather it is the value of the ETask et_UniqueID field. Passing in a
30 Task pointer will cause your Task to deadlock.
32 You must call ChildFree() on the returned task before calling
33 ChildWait() again. Ie.
35 struct ETask *et;
37 et = ChildWait(0);
38 ChildFree(et->et_UniqueID);
40 INPUTS
41 tid - The UniqueID of a task.
43 RESULT
44 Returns either the ETask structure of the child, or one of the
45 CHILD_* values on error.
47 This allows you to work out which of the children has exited.
49 NOTES
50 This function will work correctly only for child tasks that are
51 processes created with NP_NotifyOnDeath set to TRUE.
53 Calling ChildWait() on a task that isn't your child will result in
54 a deadlock.
56 EXAMPLE
58 BUGS
59 Be careful with the return result of this function.
61 SEE ALSO
63 INTERNALS
65 *****************************************************************************/
67 AROS_LIBFUNC_INIT
69 struct Task *ThisTask = GET_THIS_TASK;
70 struct ETask *et;
71 struct ETask *child;
74 ChildWait() will wait for either a specific or any child task to
75 finish. We we get it we return the task unique id to the caller.
77 Firstly, are we a new-style Task?
79 if (!ThisTask || (ThisTask->tc_Flags & TF_ETASK) == 0)
80 return CHILD_NOTNEW;
82 et = ThisTask->tc_UnionETask.tc_ETask;
85 Scanning the msgport list is unsafe, we need to Forbid().
86 Note that the Wait() below will break the Forbid() condition.
87 This is how we need it to be.
89 Forbid();
90 /* We do not return until the condition is met */
91 for (;;)
93 #if defined(__AROSEXEC_SMP__)
94 EXEC_SPINLOCK_LOCK(&et->et_TaskMsgPort.mp_SpinLock, NULL, SPINLOCK_MODE_READ);
95 #endif
96 /* Check if it has returned already. This will also take the first. */
97 ForeachNode(&et->et_TaskMsgPort.mp_MsgList, child)
99 if (tid == 0 || child->et_UniqueID == tid)
101 #if defined(__AROSEXEC_SMP__)
102 EXEC_SPINLOCK_UNLOCK(&et->et_TaskMsgPort.mp_SpinLock);
103 #endif
104 goto child_exited;
108 #if defined(__AROSEXEC_SMP__)
109 EXEC_SPINLOCK_UNLOCK(&et->et_TaskMsgPort.mp_SpinLock);
110 #endif
111 /* No matching children, we have to wait */
112 SetSignal(0, SIGF_CHILD);
113 Wait(SIGF_CHILD);
116 child_exited:
117 Permit();
118 return (IPTR)child;
120 AROS_LIBFUNC_EXIT
121 } /* ChildWait */