adapted to new ResetSpin parameter
[aros:aros.git] / AROS / rom / exec / wait.c
1 /*
2     Copyright © 1995-2010, The AROS Development Team. All rights reserved.
3     $Id$
4
5     Desc: Wait for some signal.
6     Lang: english
7 */
8 #define DEBUG 1
9
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>
15
16 #include "exec_intern.h"
17
18 /*****************************************************************************
19
20     NAME */
21
22         AROS_LH1(ULONG, Wait,
23
24 /*  SYNOPSIS */
25         AROS_LHA(ULONG, signalSet, D0),
26
27 /*  LOCATION */
28         struct ExecBase *, SysBase, 53, Exec)
29
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.
36
37     INPUTS
38         signalSet - The set of signals to wait for.
39
40     RESULT
41         The set of active signals.
42
43     NOTES
44         Naturally it's not allowed to wait in supervisor mode.
45
46         Calling Wait() breaks an active Disable() or Forbid().
47
48     EXAMPLE
49
50     BUGS
51
52     SEE ALSO
53         Signal(), SetSignal(), AllocSignal(), FreeSignal()
54
55     INTERNALS
56
57     HISTORY
58
59 ******************************************************************************/
60 {
61     AROS_LIBFUNC_INIT
62
63     ULONG rcvd;
64     struct Task *me;
65     ULONG spincount=0;
66
67     /* Get pointer to current task - I'll need it very often */
68     me = FindTask (NULL);
69
70     //D(bug("[Exec] Wait(0x%08lX) called by %s\n", signalSet, me->tc_Node.ln_Name));
71     /* Protect the task lists against access by other tasks. */
72     Disable();
73
74     /* If at least one of the signals is already set do not wait. */
75     while(!(me->tc_SigRecvd&signalSet))
76     {
77         //D(bug("[Exec] Signals are not set, putting the task to sleep\n"));
78         /* Set the wait signal mask */
79         me->tc_SigWait=signalSet;
80
81         /* Move current task to the waiting list. */
82         me->tc_State=TS_WAIT;
83         Enqueue(&SysBase->TaskWait,&me->tc_Node);
84
85         /* temporarly release all our spinlocks */
86         spincount=ResetSpin(&(PrivExecBase(SysBase)->LibList_spinlock), 0);
87         if(spincount)
88             D(bug("[Exec] Wait() task %p released %d %p spinlocks\n", FindTask(NULL), spincount, &(PrivExecBase(SysBase)->LibList_spinlock)));
89
90         /* And switch to the next ready task. */
91         KrnSwitch();
92
93         /*
94             OK. Somebody awakened me. This means that either the
95             signals are there or it's just a finished task exception.
96             Test again to be sure (see above).
97         */
98     }
99     /* Get active signals. */
100     rcvd=me->tc_SigRecvd&signalSet;
101
102     /* And clear them. */
103     me->tc_SigRecvd&=~signalSet;
104
105     if(spincount)
106         D(bug("[Exec] Wait() needs back spinlock %p %d times for task %p.\n", &(PrivExecBase(SysBase)->LibList_spinlock), spincount), FindTask(NULL));
107     /* All done. */
108     Enable();
109
110
111     /* get our locks back ! */
112     while(spincount)
113     {
114         LockSpin(&(PrivExecBase(SysBase)->LibList_spinlock));
115         D(bug("[Exec] Wait() aquired back spinlock %p number %d\n", &(PrivExecBase(SysBase)->LibList_spinlock), spincount, FindTask(NULL)));
116         spincount--;
117     }
118
119     return rcvd;
120
121     AROS_LIBFUNC_EXIT
122 }
123