forked from carlware/microkernel
/
kernel_signal.c
86 lines (75 loc) · 2.19 KB
/
kernel_signal.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include "kernel.h"
#include "kernel_port.h"
#include "kernel_log.h"
void task_signal(Task *task, Signal signal)
{
/* Set destionation signal. Unblock the task if the target
signal is in mask. */
interrupts_disable();
task_line("");
log_hex(signal);
log_string(" --> ");
log_string(task->name);
log_string(" {mask=");
log_hex(task->sig_mask);
log_string(", rec=");
log_hex(task->sig_rec);
log_string("} ==> rec=");
task->sig_rec |= signal;
log_hex(task->sig_rec);
if (task->sig_mask & signal) {
log_string(", unblock, prio:");
list_remove_node((Node *) task);
list_enqueue(&ready_tasks, (Node *) task);
if (running_task->node.ln_pri < task->node.ln_pri) {
log_string("hi");
port_reschedule();
} else {
/* An unneeded context switch is optimized away. */
log_string("lo");
interrupts_enable();
}
} else {
log_string(", no unblock.");
interrupts_enable();
}
}
/* Why are satisfied signal bits cleared? Because there is no
need to clear it manually afterwards then. */
Signal task_wait(Signal mask)
{
Signal ret;
interrupts_disable();
task_line("{mask=");
log_hex(mask);
log_string(", rec=");
log_hex(running_task->sig_rec);
log_string("} ==> ");
if (!(mask & running_task->sig_rec)) {
running_task->sig_mask = mask;
list_remove_node((Node *) running_task);
list_enqueue(&waiting_tasks, (Node *) running_task);
log_string("blocked...");
port_reschedule();
/* Interrupts may occur here. */
interrupts_disable();
task_line("...unblocked ");
log_string("{mask=");
log_hex(mask);
log_string("(");
log_hex(running_task->sig_mask);
log_string(")");
log_string(", rec=");
log_hex(running_task->sig_rec);
log_string("} ==> ");
}
ret = running_task->sig_rec & mask;
running_task->sig_rec &= ~mask;
running_task->sig_mask = 0;
log_string("{rec=");
log_hex(running_task->sig_rec);
log_string("}, return ");
log_hex(ret);
interrupts_enable();
return ret;
}