Updated PCI IDs to latest snapshot.
[tangerine.git] / rom / exec / allocsignal.c
blob58650a917b42ba030bcca8c50c5225459c098605
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Allocate a signal
6 Lang: english
7 */
8 #include <exec/execbase.h>
9 #include <exec/tasks.h>
10 #include <aros/libcall.h>
11 #include <proto/exec.h>
13 /*****************************************************************************
15 NAME */
17 AROS_LH1(BYTE, AllocSignal,
19 /* SYNOPSIS */
20 AROS_LHA(LONG, signalNum, D0),
22 /* LOCATION */
23 struct ExecBase *, SysBase, 55, Exec)
25 /* FUNCTION
26 Allocate a given signal out of the current task's pool of signals.
27 Every task has a set of signals to communicate with other tasks.
28 Half of them are reserved for the system and half of them are
29 free for general use. Some of the reserved signals (e.g.
30 SIGBREAKF_CTRL_C) have a defined behaviour and may be used by user
31 code, however.
33 You must not allocate or free signals from exception handlers.
35 INPUTS
36 signalNum - Number of the signal to allocate or -1 if any signal
37 will do.
39 RESULT
40 Number of the signal or -1 if the signal couldn't be allocated.
42 NOTES
44 EXAMPLE
46 BUGS
48 SEE ALSO
49 FreeSignal(), Signal(), Wait()
51 INTERNALS
53 ******************************************************************************/
55 AROS_LIBFUNC_INIT
57 struct Task *ThisTask;
58 ULONG mask;
59 ULONG mask1;
61 signalNum = (BYTE)signalNum; /* AOS/68k compatibility. Apps may set up only D0.b */
63 ThisTask = FindTask(NULL);
64 mask = ThisTask->tc_SigAlloc;
66 /* Will any signal do? */
67 if(signalNum < 0)
70 * To get the last nonzero bit in a number I use a&~a+1:
71 * Given a number that ends with a row of zeros xxxx1000
72 * I first toggle all bits in that number XXXX0111
73 * then add 1 to toggle all but the last 0 again XXXX1000
74 * and AND this with the original number 00001000
76 * And since ~a+1=-a I can use a&-a instead.
78 * And to get the last zero bit I finally use ~a&-~a.
80 mask1 = ~mask & - ~mask;
82 /* Is the bit already allocated? */
83 if(mask1 == 0)
84 return -1;
86 /* And get the bit number */
87 signalNum=(mask1&0xffff0000?16:0)+(mask1&0xff00ff00?8:0)+
88 (mask1&0xf0f0f0f0? 4:0)+(mask1&0xcccccccc?2:0)+
89 (mask1&0xaaaaaaaa? 1:0);
91 else
93 mask1 = 1L << signalNum;
95 /* If signal bit is already allocated, return. */
96 if(ThisTask->tc_SigAlloc & mask1)
97 return -1;
101 * I shouldn't need to disable around changing the signal masks
102 * because the only thing allowed to change the mask of allocated,
103 * excepting and waiting signals is the task itself. On the other
104 * hand, I need to use Disable around the received signals because it
105 * can be modified by interrupts, and I cannot rely upon the below
106 * being atomic.
109 ThisTask->tc_SigAlloc |= mask1;
110 ThisTask->tc_SigExcept &= ~mask1;
111 ThisTask->tc_SigWait &= ~mask1;
113 Disable();
114 ThisTask->tc_SigRecvd &= ~mask1;
115 Enable();
117 return signalNum;
118 AROS_LIBFUNC_EXIT
119 } /* AllocSignal() */