2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Desc: Allocate a signal
9 #include <exec/execbase.h>
10 #include <exec/tasks.h>
11 #include <aros/libcall.h>
12 #include <proto/exec.h>
14 #include "exec_util.h"
16 /*****************************************************************************
20 AROS_LH1(BYTE
, AllocSignal
,
23 AROS_LHA(LONG
, signalNum
, D0
),
26 struct ExecBase
*, SysBase
, 55, Exec
)
29 Allocate a given signal out of the current task's pool of signals.
30 Every task has a set of signals to communicate with other tasks.
31 Half of them are reserved for the system and half of them are
32 free for general use. Some of the reserved signals (e.g.
33 SIGBREAKF_CTRL_C) have a defined behaviour and may be used by user
36 You must not allocate or free signals from exception handlers.
39 signalNum - Number of the signal to allocate or -1 if any signal
43 Number of the signal or -1 if the signal couldn't be allocated.
52 FreeSignal(), Signal(), Wait()
56 ******************************************************************************/
60 /* Cast signalNum to BYTE for AOS/68k compatibility. Apps may set up only D0.b */
61 return AllocTaskSignal(FindTask(NULL
), (BYTE
)signalNum
, SysBase
);
66 LONG
AllocTaskSignal(struct Task
*ThisTask
, LONG signalNum
, struct ExecBase
*SysBase
)
71 mask
= ThisTask
->tc_SigAlloc
;
73 /* Will any signal do? */
77 * To get the last nonzero bit in a number I use a&~a+1:
78 * Given a number that ends with a row of zeros xxxx1000
79 * I first toggle all bits in that number XXXX0111
80 * then add 1 to toggle all but the last 0 again XXXX1000
81 * and AND this with the original number 00001000
83 * And since ~a+1=-a I can use a&-a instead.
85 * And to get the last zero bit I finally use ~a&-~a.
87 mask1
= ~mask
& - ~mask
;
89 /* Is the bit already allocated? */
93 /* And get the bit number */
94 signalNum
=(mask1
&0xffff0000?16:0)+(mask1
&0xff00ff00?8:0)+
95 (mask1
&0xf0f0f0f0? 4:0)+(mask1
&0xcccccccc?2:0)+
96 (mask1
&0xaaaaaaaa? 1:0);
100 mask1
= 1L << signalNum
;
102 /* If signal bit is already allocated, return. */
103 if(ThisTask
->tc_SigAlloc
& mask1
)
108 * I shouldn't need to disable around changing the signal masks
109 * because the only thing allowed to change the mask of allocated,
110 * excepting and waiting signals is the task itself. On the other
111 * hand, I need to use Disable around the received signals because it
112 * can be modified by interrupts, and I cannot rely upon the below
116 ThisTask
->tc_SigAlloc
|= mask1
;
117 ThisTask
->tc_SigExcept
&= ~mask1
;
118 ThisTask
->tc_SigWait
&= ~mask1
;
121 ThisTask
->tc_SigRecvd
&= ~mask1
;