pass -static-libstdc++ via LDFLAGS
[AROS.git] / rom / exec / signal.c
blob088e7f39acfefd03f4fd7a82bc1093b1b4d0db14
1 /*
2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Send some signal to a given task
6 Lang: english
7 */
9 #define DEBUG 0
10 #include <aros/debug.h>
12 #include <exec/execbase.h>
13 #include <aros/libcall.h>
14 #include <proto/exec.h>
16 #define __AROS_KERNEL__
17 #include "exec_intern.h"
19 #if defined(__AROSEXEC_SMP__)
20 #include <utility/hooks.h>
22 void core_DoCallIPI(struct Hook *hook, void *cpu_mask, int async, APTR *_KernelBase);
24 struct signal_message {
25 struct ExecBase * SysBase;
26 struct Task * target;
27 ULONG sigset;
30 AROS_UFH3(IPTR, signal_hook,
31 AROS_UFHA(struct Hook *, hook, A0),
32 AROS_UFHA(APTR, object, A2),
33 AROS_UFHA(APTR, message, A1)
36 AROS_USERFUNC_INIT
38 struct signal_message *msg = hook->h_Data;
39 struct ExecBase *SysBase = msg->SysBase;
42 struct KernelBase *KernelBase = __kernelBase;
43 int cpunum = KrnGetCPUNumber();
44 bug("[Exec] CPU%03d: Using IPI to do Signal(%p, %08x), SysBase=%p\n", cpunum, msg->target, msg->sigset, SysBase);
47 Signal(msg->target, msg->sigset);
49 return 0;
51 AROS_USERFUNC_EXIT
53 #endif
55 /*****************************************************************************
57 NAME */
59 AROS_LH2(void, Signal,
61 /* SYNOPSIS */
62 AROS_LHA(struct Task *, task, A1),
63 AROS_LHA(ULONG, signalSet, D0),
65 /* LOCATION */
66 struct ExecBase *, SysBase, 54, Exec)
68 /* FUNCTION
69 Send some signals to a given task. If the task is currently waiting
70 on these signals, has a higher priority as the current one and if
71 taskswitches are allowed the new task begins to run immediately.
73 INPUTS
74 task - Pointer to task structure.
75 signalSet - The set of signals to send to the task.
77 RESULT
79 NOTES
80 This function may be used from interrupts.
82 EXAMPLE
84 BUGS
86 SEE ALSO
87 AllocSignal(), FreeSignal(), Wait(), SetSignal(), SetExcept()
89 INTERNALS
91 HISTORY
93 ******************************************************************************/
95 AROS_LIBFUNC_INIT
97 struct Task *thisTask = GET_THIS_TASK;
99 #if defined(__AROSEXEC_SMP__)
100 struct KernelBase *KernelBase = __kernelBase;
101 int cpunum = KrnGetCPUNumber();
103 //EXEC_SPINLOCK_LOCK(IntETask(task->tc_UnionETask.tc_ETask)->iet_SpinLock, NULL, SPINLOCK_MODE_READ);
105 * # If current CPU number is not the task's CPU and the task is running now, send signal to that task
106 * from CPU which the task is running on.
107 * # If task is not running and the current CPU is not in the Affinitymask, send signal to CPU form Affinity mask
108 * # If task is not running and the current CPU is in the Affinity mask, just proceed with regular signal
110 if ((PrivExecBase(SysBase)->IntFlags & EXECF_CPUAffinity) &&
111 ((IntETask(task->tc_UnionETask.tc_ETask)->iet_CpuNumber != cpunum && task->tc_State == TS_RUN) ||
112 !KrnCPUInMask(cpunum, IntETask(task->tc_UnionETask.tc_ETask)->iet_CpuAffinity)))
114 struct Hook h;
115 struct signal_message msg;
116 void *cpu_mask = KrnAllocCPUMask();
118 /* Task is running *now* on another CPU, send signal there */
119 if (task->tc_State == TS_RUN)
121 KrnGetCPUMask(IntETask(task->tc_UnionETask.tc_ETask)->iet_CpuNumber, cpu_mask);
123 else
125 int i;
126 int cpumax = KrnGetCPUCount();
128 /* Task is not running now, find first cpu suitable to run this task. Use CPU balancing some day... */
129 for (i=0; i < cpumax; i++)
131 if (KrnCPUInMask(i, IntETask(task->tc_UnionETask.tc_ETask)->iet_CpuAffinity))
133 KrnGetCPUMask(i, cpu_mask);
134 break;
139 msg.SysBase = SysBase;
140 msg.target = task;
141 msg.sigset = signalSet;
143 D(bug("[Exec] Signal: Signaling from CPU%03d -> CPU%03d using IPI...\n", cpunum, IntETask(task->tc_UnionETask.tc_ETask)->iet_CpuNumber));
145 h.h_Entry = signal_hook;
146 h.h_Data = &msg;
148 D(bug("[Exec] Sending IPI...\n"));
149 core_DoCallIPI(&h, cpu_mask, 0, (void *)KernelBase);
150 D(bug("[Exec] IPI Sent\n"));
152 KrnFreeCPUMask(cpu_mask);
154 //EXEC_SPINLOCK_UNLOCK(IntETask(task->tc_UnionETask.tc_ETask)->iet_SpinLock);
156 if (cpunum != 0)
158 D(bug("[Exec] Signal(0x%p, %08lX) on CPU%03d\n", task, signalSet, cpunum));
160 #else
161 D(bug("[Exec] Signal(0x%p, %08lX)\n", task, signalSet);)
162 #endif
165 bug("[Exec] Signal: Signaling '%s', state = %08x\n", task->tc_Node.ln_Name, task->tc_State);
166 if (((struct KernelBase *)KernelBase)->kb_ICFlags & KERNBASEF_IRQPROCESSING)
167 bug("[Exec] Signal: (Called from Interrupt)\n");
168 else
169 bug("[Exec] Signal: (Called from '%s')\n", thisTask->tc_Node.ln_Name);
172 Disable();
173 D(bug("[Exec] Signal: Target signal flags : %08x ->", task->tc_SigRecvd);)
174 /* Set the signals in the task structure. */
175 #if defined(__AROSEXEC_SMP__)
176 __AROS_ATOMIC_OR_L(task->tc_SigRecvd, signalSet);
177 #else
178 task->tc_SigRecvd |= signalSet;
179 #endif
180 D(bug(" %08x\n", task->tc_SigRecvd);)
182 /* Do those bits raise exceptions? */
183 if (task->tc_SigRecvd & task->tc_SigExcept)
185 /* Yes. Set the exception flag. */
186 #if defined(__AROSEXEC_SMP__)
187 __AROS_ATOMIC_OR_B(task->tc_Flags, TF_EXCEPT);
188 #else
189 task->tc_Flags |= TF_EXCEPT;
190 #endif
191 D(bug("[Exec] Signal: TF_EXCEPT set\n");)
194 if the target task is running (called from within interrupt handler, or from another processor),
195 raise the exception or defer it for later.
197 if (task->tc_State == TS_RUN)
199 #if defined(__AROSEXEC_SMP__)
200 if (!(PrivExecBase(SysBase)->IntFlags & EXECF_CPUAffinity) ||
201 (IntETask(task->tc_UnionETask.tc_ETask)->iet_CpuNumber == cpunum))
203 #endif
204 D(bug("[Exec] Signal: Raising Exception for 'running' Task\n");)
205 /* Order a reschedule */
206 Reschedule();
207 #if defined(__AROSEXEC_SMP__)
209 else
211 D(bug("[Exec] Signal: Raising Exception for 'running' Task on CPU %03u\n", IntETask(task->tc_UnionETask.tc_ETask)->iet_CpuNumber));
212 KrnScheduleCPU(IntETask(task->tc_UnionETask.tc_ETask)->iet_CpuAffinity);
214 #endif
215 Enable();
217 /* All done. */
218 return;
222 Is the task receiving the signals waiting on them
223 (or on a exception) ?
225 if ((task->tc_State == TS_WAIT) &&
226 (task->tc_SigRecvd & (task->tc_SigWait | task->tc_SigExcept)))
228 D(bug("[Exec] Signal: Signaling 'waiting' Task\n");)
230 /* Yes. Move it to the ready list. */
231 #if defined(__AROSEXEC_SMP__)
232 krnSysCallReschedTask(task, TS_READY);
233 #else
234 Remove(&task->tc_Node);
235 task->tc_State = TS_READY;
236 Enqueue(&SysBase->TaskReady, &task->tc_Node);
237 #endif
238 /* Has it a higher priority as the current one? */
239 if (
240 #if defined(__AROSEXEC_SMP__)
241 (!(PrivExecBase(SysBase)->IntFlags & EXECF_CPUAffinity) ||
242 (KrnCPUInMask(cpunum, IntETask(task->tc_UnionETask.tc_ETask)->iet_CpuAffinity))) &&
243 #endif
244 (task->tc_Node.ln_Pri >= thisTask->tc_Node.ln_Pri))
247 Yes. A taskswitch is necessary. Prepare one if possible.
248 (If the current task is not running it is already moved)
250 if (thisTask->tc_State == TS_RUN)
252 D(bug("[Exec] Signal: Rescheduling 'running' Task to let it process the signal...\n"));
253 Reschedule();
256 #if defined(__AROSEXEC_SMP__)
257 else if ((PrivExecBase(SysBase)->IntFlags & EXECF_CPUAffinity) &&
258 !(KrnCPUInMask(cpunum, IntETask(task->tc_UnionETask.tc_ETask)->iet_CpuAffinity)))
260 D(bug("[Exec] Signal: Signaling task on another CPU\n"));
261 krnSysCallReschedTask(task, TS_READY);
262 KrnScheduleCPU(IntETask(task->tc_UnionETask.tc_ETask)->iet_CpuAffinity);
264 #endif
265 else
267 D(bug("[Exec] Signal: Letting Task process signal when next scheduled to run...\n"););
271 Enable();
273 D(bug("[Exec] Signal: 0x%p finished signal processing\n", task);)
275 AROS_LIBFUNC_EXIT