fix non-smp builds
[AROS.git] / rom / exec / allocsignal.c
blob17630d42a65833281777daa46aa5af1685d50375
1 /*
2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Allocate a signal
6 Lang: english
7 */
9 #define DEBUG 0
11 #include <exec/execbase.h>
12 #include <exec/tasks.h>
13 #include <aros/libcall.h>
14 #include <proto/exec.h>
16 #include "exec_util.h"
17 #if defined(__AROSEXEC_SMP__)
18 #include "etask.h"
19 #include "exec_locks.h"
20 #endif
22 /*****************************************************************************
24 NAME */
26 AROS_LH1(BYTE, AllocSignal,
28 /* SYNOPSIS */
29 AROS_LHA(LONG, signalNum, D0),
31 /* LOCATION */
32 struct ExecBase *, SysBase, 55, Exec)
34 /* FUNCTION
35 Allocate a given signal out of the current task's pool of signals.
36 Every task has a set of signals to communicate with other tasks.
37 Half of them are reserved for the system and half of them are
38 free for general use. Some of the reserved signals (e.g.
39 SIGBREAKF_CTRL_C) have a defined behaviour and may be used by user
40 code, however.
42 You must not allocate or free signals from exception handlers.
44 INPUTS
45 signalNum - Number of the signal to allocate or -1 if any signal
46 will do.
48 RESULT
49 Number of the signal or -1 if the signal couldn't be allocated.
51 NOTES
53 EXAMPLE
55 BUGS
57 SEE ALSO
58 FreeSignal(), Signal(), Wait()
60 INTERNALS
62 ******************************************************************************/
64 AROS_LIBFUNC_INIT
66 /* Cast signalNum to BYTE for AOS/68k compatibility. Apps may set up only D0.b */
67 return AllocTaskSignal(GET_THIS_TASK, (BYTE)signalNum, SysBase);
69 AROS_LIBFUNC_EXIT
70 } /* AllocSignal() */
72 LONG AllocTaskSignal(struct Task *thisTask, LONG signalNum, struct ExecBase *SysBase)
74 ULONG mask;
75 ULONG mask1;
77 D(bug("[Exec] %s()\n", __func__));
79 mask = thisTask->tc_SigAlloc;
81 /* Will any signal do? */
82 if(signalNum < 0)
85 * To get the last nonzero bit in a number I use a&~a+1:
86 * Given a number that ends with a row of zeros xxxx1000
87 * I first toggle all bits in that number XXXX0111
88 * then add 1 to toggle all but the last 0 again XXXX1000
89 * and AND this with the original number 00001000
91 * And since ~a+1=-a I can use a&-a instead.
93 * And to get the last zero bit I finally use ~a&-~a.
95 mask1 = ~mask & - ~mask;
97 /* Is the bit already allocated? */
98 if(mask1 == 0)
99 return -1;
101 /* And get the bit number */
102 signalNum=(mask1&0xffff0000?16:0)+(mask1&0xff00ff00?8:0)+
103 (mask1&0xf0f0f0f0? 4:0)+(mask1&0xcccccccc?2:0)+
104 (mask1&0xaaaaaaaa? 1:0);
106 else
108 mask1 = 1L << signalNum;
110 /* If signal bit is already allocated, return. */
111 if(thisTask->tc_SigAlloc & mask1)
112 return -1;
116 * Exec shouldn't need to protect the changing of the task signal masks
117 * because the only thing allowed to change the mask of allocated,
118 * excepting and waiting signals is the task itself.
119 * Received signals do need protected because they can be modified
120 * by interrupts, so atomicity cannot be relied upon.
123 thisTask->tc_SigAlloc |= mask1;
124 thisTask->tc_SigExcept &= ~mask1;
125 thisTask->tc_SigWait &= ~mask1;
127 Disable();
128 #if defined(__AROSEXEC_SMP__)
129 if (thisTask->tc_UnionETask.tc_ETask)
131 EXEC_LOCK_WRITE(&IntETask(thisTask->tc_UnionETask.tc_ETask)->iet_TaskLock);
133 #endif
135 thisTask->tc_SigRecvd &= ~mask1;
137 #if defined(__AROSEXEC_SMP__)
138 if (thisTask->tc_UnionETask.tc_ETask)
140 EXEC_UNLOCK(&IntETask(thisTask->tc_UnionETask.tc_ETask)->iet_TaskLock);
142 #endif
143 Enable();
145 return signalNum;