use new platform macros to access scheduling/per-cpu flags. fix execsmp wait()
[AROS.git] / rom / exec / wait.c
blobe70ae90035d8fbef0bb8f625f1266fdec48aa54f
1 /*
2 Copyright © 1995-2015, 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>
14 #include <proto/kernel.h>
16 #include "exec_intern.h"
18 /*****************************************************************************
20 NAME */
22 AROS_LH1(ULONG, Wait,
24 /* SYNOPSIS */
25 AROS_LHA(ULONG, signalSet, D0),
27 /* LOCATION */
28 struct ExecBase *, SysBase, 53, Exec)
30 /* FUNCTION
31 Wait until some signals are sent to the current task. If any signal
32 of the specified set is already set when entering this function it
33 returns immediately. Since almost any event in the OS can send a
34 signal to your task if you specify it to do so signals are a very
35 powerful mechanism.
37 INPUTS
38 signalSet - The set of signals to wait for.
40 RESULT
41 The set of active signals.
43 NOTES
44 Naturally it's not allowed to wait in supervisor mode.
46 Calling Wait() breaks an active Disable() or Forbid().
48 EXAMPLE
50 BUGS
52 SEE ALSO
53 Signal(), SetSignal(), AllocSignal(), FreeSignal()
55 INTERNALS
57 HISTORY
59 ******************************************************************************/
61 AROS_LIBFUNC_INIT
63 ULONG rcvd;
64 struct Task *me;
66 /* Get pointer to current task - I'll need it very often */
67 me = FindTask(NULL);
69 D(bug("[Exec] Wait(0x%08lX)\n", signalSet));
71 /* If at least one of the signals is already set do not wait. */
72 while (!(me->tc_SigRecvd & signalSet))
74 #if defined(__AROSEXEC_SMP__)
75 if (me->tc_State != TS_WAIT)
77 #endif
78 D(bug("[Exec] Moving '%s' @ 0x%p to Task Wait queue\n", me->tc_Node.ln_Name, me));
79 D(bug("[Exec] Task state = %08x\n", me->tc_State));
80 /* Set the wait signal mask */
81 me->tc_SigWait = signalSet;
84 Clear TDNestCnt (because Switch() will not care about it),
85 but memorize it first. IDNestCnt is handled by Switch().
87 me->tc_TDNestCnt = TDNESTCOUNT_GET;
88 TDNESTCOUNT_SET(-1);
90 /* Protect the task lists against access by other tasks. */
91 #if defined(__AROSEXEC_SMP__)
92 EXEC_SPINLOCK_LOCK(&PrivExecBase(SysBase)->TaskRunningSpinLock, SPINLOCK_MODE_WRITE);
93 #endif
94 Disable();
96 #if defined(__AROSEXEC_SMP__)
97 Remove(&me->tc_Node);
98 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase)->TaskRunningSpinLock);
99 Enable();
100 EXEC_SPINLOCK_LOCK(&PrivExecBase(SysBase)->TaskWaitSpinLock, SPINLOCK_MODE_WRITE);
101 Disable();
102 #endif
103 /* Move current task to the waiting list. */
104 me->tc_State = TS_WAIT;
105 Enqueue(&SysBase->TaskWait, &me->tc_Node);
106 #if defined(__AROSEXEC_SMP__)
107 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase)->TaskWaitSpinLock);
108 #endif
109 /* And switch to the next ready task. */
110 KrnSwitch();
113 OK. Somebody awakened me. This means that either the
114 signals are there or it's just a finished task exception.
115 Test again to be sure (see above).
118 /* Restore TDNestCnt. */
119 TDNESTCOUNT_SET(me->tc_TDNestCnt);
121 Enable();
122 #if defined(__AROSEXEC_SMP__)
124 #endif
126 /* Get active signals. */
127 rcvd = (me->tc_SigRecvd & signalSet);
129 /* And clear them. */
130 me->tc_SigRecvd &= ~signalSet;
132 /* All done. */
133 return rcvd;
135 AROS_LIBFUNC_EXIT