If se Enable() unconditionaly at the end of function, we should Disable() uncondition...
[AROS.git] / rom / exec / wait.c
blob6c1796fdfc9ec1a64dad763cea80beaa8e2e5e02
1 /*
2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Wait for some signal.
6 Lang: english
7 */
8 #define DEBUG 0
10 #include <aros/debug.h>
11 #include <exec/execbase.h>
12 #include <aros/libcall.h>
13 #include <proto/exec.h>
15 #include "exec_intern.h"
16 #if defined(__AROSEXEC_SMP__)
17 #include "etask.h"
18 #endif
20 /*****************************************************************************
22 NAME */
24 AROS_LH1(ULONG, Wait,
26 /* SYNOPSIS */
27 AROS_LHA(ULONG, signalSet, D0),
29 /* LOCATION */
30 struct ExecBase *, SysBase, 53, Exec)
32 /* FUNCTION
33 Wait until some signals are sent to the current task. If any signal
34 of the specified set is already set when entering this function it
35 returns immediately. Since almost any event in the OS can send a
36 signal to your task if you specify it to do so signals are a very
37 powerful mechanism.
39 INPUTS
40 signalSet - The set of signals to wait for.
42 RESULT
43 The set of active signals.
45 NOTES
46 Naturally it's not allowed to wait in supervisor mode.
48 Calling Wait() breaks an active Disable() or Forbid().
50 EXAMPLE
52 BUGS
54 SEE ALSO
55 Signal(), SetSignal(), AllocSignal(), FreeSignal()
57 INTERNALS
59 HISTORY
61 ******************************************************************************/
63 AROS_LIBFUNC_INIT
65 struct Task *thisTask = GET_THIS_TASK;
66 ULONG rcvd;
68 D(bug("[Exec] Wait(%08lX)\n", signalSet);)
69 Disable();
71 /* If at least one of the signals is already set do not wait. */
72 while (!(thisTask->tc_SigRecvd & signalSet))
74 /* Set the wait signal mask */
75 thisTask->tc_SigWait = signalSet;
77 D(bug("[Exec] Moving '%s' @ 0x%p to Task Wait queue\n", thisTask->tc_Node.ln_Name, thisTask);)
78 D(bug("[Exec] Task state = %08x\n", thisTask->tc_State);)
81 Clear TDNestCnt (because Switch() will not care about it),
82 but memorize it first. IDNestCnt is handled by Switch().
84 thisTask->tc_TDNestCnt = TDNESTCOUNT_GET;
85 TDNESTCOUNT_SET(-1);
87 thisTask->tc_State = TS_WAIT;
88 // nb: on smp builds switch will move us.
89 #if !defined(__AROSEXEC_SMP__)
90 /* Move current task to the waiting list. */
91 Enqueue(&SysBase->TaskWait, &thisTask->tc_Node);
92 #endif
94 /* And switch to the next ready task. */
95 KrnSwitch();
98 OK. Somebody awakened us. This means that either the
99 signals are there or it's just a finished task exception.
100 Test again to be sure (see above).
103 /* Restore TDNestCnt. */
104 TDNESTCOUNT_SET(thisTask->tc_TDNestCnt);
106 /* Get active signals. */
107 rcvd = (thisTask->tc_SigRecvd & signalSet);
109 /* And clear them. */
110 #if defined(__AROSEXEC_SMP__)
111 __AROS_ATOMIC_AND_L(thisTask->tc_SigRecvd, ~signalSet);
112 #else
113 thisTask->tc_SigRecvd &= ~signalSet;
114 #endif
115 Enable();
117 /* All done. */
118 return rcvd;
120 AROS_LIBFUNC_EXIT