Moved tests for dos.library functions into the 'dos' subdir.
[AROS.git] / rom / exec / wait.c
blobedc004cdd69de2bfd293ea70de4ed2adb0747862
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"
17 #if defined(__AROSEXEC_SMP__)
18 #include "etask.h"
19 #endif
21 /*****************************************************************************
23 NAME */
25 AROS_LH1(ULONG, Wait,
27 /* SYNOPSIS */
28 AROS_LHA(ULONG, signalSet, D0),
30 /* LOCATION */
31 struct ExecBase *, SysBase, 53, Exec)
33 /* FUNCTION
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
38 powerful mechanism.
40 INPUTS
41 signalSet - The set of signals to wait for.
43 RESULT
44 The set of active signals.
46 NOTES
47 Naturally it's not allowed to wait in supervisor mode.
49 Calling Wait() breaks an active Disable() or Forbid().
51 EXAMPLE
53 BUGS
55 SEE ALSO
56 Signal(), SetSignal(), AllocSignal(), FreeSignal()
58 INTERNALS
60 HISTORY
62 ******************************************************************************/
64 AROS_LIBFUNC_INIT
66 struct Task *ThisTask = GET_THIS_TASK;
67 #if defined(__AROSEXEC_SMP__)
68 spinlock_t *task_listlock = NULL;
69 #endif
70 ULONG rcvd;
72 D(bug("[Exec] Wait(%08lX)\n", signalSet));
73 #if !defined(__AROSEXEC_SMP__)
74 Disable();
75 #endif
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)
85 #endif
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)
93 case TS_RUN:
94 task_listlock = &PrivExecBase(SysBase)->TaskRunningSpinLock;
95 break;
96 default:
97 task_listlock = &PrivExecBase(SysBase)->TaskReadySpinLock;
98 break;
100 EXEC_SPINLOCK_LOCK(task_listlock, SPINLOCK_MODE_WRITE);
101 Forbid();
102 Remove(&ThisTask->tc_Node);
103 EXEC_SPINLOCK_UNLOCK(task_listlock);
104 Permit();
105 EXEC_SPINLOCK_LOCK(&PrivExecBase(SysBase)->TaskWaitSpinLock, SPINLOCK_MODE_WRITE);
106 Forbid();
107 #endif
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;
113 TDNESTCOUNT_SET(-1);
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);
121 else
123 Forbid();
124 ThisTask->tc_TDNestCnt = TDNESTCOUNT_GET;
125 TDNESTCOUNT_SET(-1);
127 #endif
128 /* And switch to the next ready task. */
129 KrnSwitch();
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__)
141 Permit();
142 #endif
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);
150 Disable();
151 #endif
152 ThisTask->tc_SigRecvd &= ~signalSet;
153 #if defined(__AROSEXEC_SMP__)
154 EXEC_SPINLOCK_UNLOCK(&IntETask(ThisTask->tc_UnionETask.tc_ETask)->iet_TaskLock);
155 #endif
156 Enable();
158 /* All done. */
159 return rcvd;
161 AROS_LIBFUNC_EXIT