2 Copyright © 1995-2015, The AROS Development Team. All rights reserved.
5 Desc: Wait for some signal.
10 #include <aros/debug.h>
11 #include <exec/execbase.h>
12 #include <aros/libcall.h>
13 #include <proto/exec.h>
14 #include <proto/kernel.h>
16 #include "exec_intern.h"
17 #if defined(__AROSEXEC_SMP__)
21 /*****************************************************************************
28 AROS_LHA(ULONG
, signalSet
, D0
),
31 struct ExecBase
*, SysBase
, 53, Exec
)
34 Wait until some signals are sent to the current task. If any signal
35 of the specified set is already set when entering this function it
36 returns immediately. Since almost any event in the OS can send a
37 signal to your task if you specify it to do so signals are a very
41 signalSet - The set of signals to wait for.
44 The set of active signals.
47 Naturally it's not allowed to wait in supervisor mode.
49 Calling Wait() breaks an active Disable() or Forbid().
56 Signal(), SetSignal(), AllocSignal(), FreeSignal()
62 ******************************************************************************/
66 struct Task
*ThisTask
= GET_THIS_TASK
;
67 #if defined(__AROSEXEC_SMP__)
68 spinlock_t
*task_listlock
= NULL
;
72 D(bug("[Exec] Wait(%08lX)\n", signalSet
);)
73 #if !defined(__AROSEXEC_SMP__)
77 /* If at least one of the signals is already set do not wait. */
78 while (!(ThisTask
->tc_SigRecvd
& signalSet
))
80 /* Set the wait signal mask */
81 ThisTask
->tc_SigWait
= signalSet
;
82 #if defined(__AROSEXEC_SMP__)
83 if (ThisTask
->tc_State
!= TS_WAIT
)
86 D(bug("[Exec] Moving '%s' @ 0x%p to Task Wait queue\n", ThisTask
->tc_Node
.ln_Name
, ThisTask
);)
87 D(bug("[Exec] Task state = %08x\n", ThisTask
->tc_State
);)
89 /* Protect the task lists against access by other tasks. */
90 #if defined(__AROSEXEC_SMP__)
91 switch (ThisTask
->tc_State
)
94 task_listlock
= &PrivExecBase(SysBase
)->TaskRunningSpinLock
;
97 task_listlock
= &PrivExecBase(SysBase
)->TaskReadySpinLock
;
100 EXEC_SPINLOCK_LOCK(task_listlock
, SPINLOCK_MODE_WRITE
);
102 Remove(&ThisTask
->tc_Node
);
103 EXEC_SPINLOCK_UNLOCK(task_listlock
);
105 EXEC_SPINLOCK_LOCK(&PrivExecBase(SysBase
)->TaskWaitSpinLock
, SPINLOCK_MODE_WRITE
);
109 Clear TDNestCnt (because Switch() will not care about it),
110 but memorize it first. IDNestCnt is handled by Switch().
112 ThisTask
->tc_TDNestCnt
= TDNESTCOUNT_GET
;
115 /* Move current task to the waiting list. */
116 ThisTask
->tc_State
= TS_WAIT
;
117 Enqueue(&SysBase
->TaskWait
, &ThisTask
->tc_Node
);
118 #if defined(__AROSEXEC_SMP__)
119 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase
)->TaskWaitSpinLock
);
124 ThisTask
->tc_TDNestCnt
= TDNESTCOUNT_GET
;
128 /* And switch to the next ready task. */
132 OK. Somebody awakened us. This means that either the
133 signals are there or it's just a finished task exception.
134 Test again to be sure (see above).
137 /* Restore TDNestCnt. */
138 TDNESTCOUNT_SET(ThisTask
->tc_TDNestCnt
);
140 #if defined(__AROSEXEC_SMP__)
144 /* Get active signals. */
145 rcvd
= (ThisTask
->tc_SigRecvd
& signalSet
);
147 /* And clear them. */
148 #if defined(__AROSEXEC_SMP__)
149 EXEC_SPINLOCK_LOCK(&IntETask(ThisTask
->tc_UnionETask
.tc_ETask
)->iet_TaskLock
, SPINLOCK_MODE_WRITE
);
152 ThisTask
->tc_SigRecvd
&= ~signalSet
;
153 #if defined(__AROSEXEC_SMP__)
154 EXEC_SPINLOCK_UNLOCK(&IntETask(ThisTask
->tc_UnionETask
.tc_ETask
)->iet_TaskLock
);