-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhandler.c
More file actions
218 lines (165 loc) · 3.97 KB
/
handler.c
File metadata and controls
218 lines (165 loc) · 3.97 KB
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/time.h>
#define LEVEL 6 /* priority level array length */
#define SIG_COUNT 5 /* total number of signals, also array length */
/*
* NOTE:
* This is random work simulation,
* doesn't do anything actually.
*/
#define WORKERS 5 /* number of work to do */
#define WAIT_TIME 1 /* worker's job time (in seconds) */
int CURR_PRIOR = 0; /* 0 prior is main function, signal interrupts are 1..LEVEL priors */
int PRIORITY[LEVEL] = {0}; /* keeps track of interrupted job (job with lower priority) */
int WAIT[LEVEL] = {0}; /* keeps track of total interrupt signals */
/* arbitrarily signals */
int SIGNALS[SIG_COUNT] = {SIGUSR1, SIGUSR2, SIGPROF, SIGCHLD, SIGINT};
int MAIN_COUNTER = 1; /* see in main function */
/* <print functions> */
void print_main(int n)
{
printf("%3d", n);
for (int i = 0; i < SIG_COUNT; i++) {
if (i == 0) {
printf("\t");
}
printf(" - ");
}
printf("\n");
}
void print_status(int sig_index, char c)
{
for (int i = 1; i < SIG_COUNT+1; i++) {
if (i == 1) {
printf("\t");
}
if (i == sig_index) {
printf(" %c ", c);
}
else {
printf(" - ");
}
}
printf("\n");
}
void print_signal_interrupt(int sig_index)
{
print_status(sig_index, 'X');
}
void print_job_start(int sig_index)
{
print_status(sig_index, 'P');
}
void print_job_progress(int sig_index, char c)
{
print_status(sig_index, c);
}
void print_job_end(int sig_index)
{
print_status(sig_index, 'K');
}
/* </print functions> */
/* <workers> */
/*
* NOTE:
* This is random work simulation,
* doesn't do anything actually.
*/
void do_work(int sig_index)
{
print_job_start(sig_index);
for (int i = 0; i < WORKERS; i++) {
print_job_progress(sig_index, '1'+i);
sleep(WAIT_TIME);
}
print_job_end(sig_index);
}
/* </workers> */
/* <interrupt handlers> */
void allow_interrupts(void)
{
for (int i = 0; i < SIG_COUNT; i++) {
sigrelse(SIGNALS[i]);
}
}
void deny_interrupts(void)
{
for (int i = 0; i < SIG_COUNT; i++) {
sighold(SIGNALS[i]);
}
}
void handle_interrupts(int sig)
{
int sig_index = -1;
int new_prior;
/* deny new signal interrupts while processing the current one */
deny_interrupts();
/* identify new signal interrupt index */
switch (sig) {
case SIGUSR1:
sig_index = 1;
print_signal_interrupt(sig_index);
break;
case SIGUSR2:
sig_index = 2;
print_signal_interrupt(sig_index);
break;
case SIGPROF:
sig_index = 3;
print_signal_interrupt(sig_index);
break;
case SIGCHLD:
sig_index = 4;
print_signal_interrupt(sig_index);
break;
case SIGINT:
sig_index = 5;
print_signal_interrupt(sig_index);
break;
default:
break;
}
/* save new signal interrupt index to wait list */
WAIT[sig_index]++;
/* find signal with the highest priority */
do {
new_prior = 0; /* reset to main function priority */
for (int i = LEVEL-1; i > CURR_PRIOR; i--) {
if (WAIT[i]) {
new_prior = i;
break;
}
}
if (new_prior > CURR_PRIOR) {
WAIT[new_prior]--; /* remove from wait list */
PRIORITY[new_prior] = CURR_PRIOR; /* save lower priority job, continue that later */
CURR_PRIOR = new_prior; /* change current priority to higher signal priority */
allow_interrupts(); /* allow interrupts while job is running */
do_work(CURR_PRIOR);
deny_interrupts();
CURR_PRIOR = PRIORITY[new_prior]; /* continue job with lower priority */
}
} while (new_prior > 0);
/* allow new signal interrupts, processing has finished */
allow_interrupts();
}
/* </interrupt handlers> */
int main(void)
{
/* assign signal handler function to each signal */
for (int i = 0; i < SIG_COUNT; i++) {
signal(SIGNALS[i], handle_interrupts);
}
printf("Main started with PID=%d\n", getpid());
while (1) {
if (!CURR_PRIOR) {
print_main(MAIN_COUNTER++);
sleep(WAIT_TIME);
}
}
printf("Main stopped\n");
return 0;
}