diff options
| author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-09-10 16:38:25 -0400 |
|---|---|---|
| committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-09-10 16:38:25 -0400 |
| commit | 9bc72959cf8d4750de7f968fc35ea3b7463cad11 (patch) | |
| tree | 5b75736d9f574bcc47394475bdf8d8060c8497ff | |
| parent | 12d8c50580f06ba48fd1563508e49fcaabd936d0 (diff) | |
| parent | 4829f4175482e0a4ad8f282dd0441904c33e2f97 (diff) | |
Merge remote-tracking branch 'github/prop/litmus-signals' into wip-gpu-rtas12
Conflicts:
Makefile
| -rw-r--r-- | Makefile | 5 | ||||
| -rw-r--r-- | bin/rt_launch.c | 8 | ||||
| -rw-r--r-- | bin/rtspin.c | 48 | ||||
| -rw-r--r-- | dgl.c | 2 | ||||
| -rw-r--r-- | ikglptest.c | 50 | ||||
| -rw-r--r-- | include/litmus.h | 134 | ||||
| -rw-r--r-- | nested.c | 2 | ||||
| -rw-r--r-- | src/litmus.c | 13 | ||||
| -rw-r--r-- | src/signal.c | 107 | ||||
| -rw-r--r-- | src/task.c | 4 | ||||
| -rw-r--r-- | tests/fdso.c | 4 |
11 files changed, 324 insertions, 53 deletions
| @@ -19,7 +19,7 @@ LITMUS_KERNEL ?= ../litmus-rt | |||
| 19 | # Internal configuration. | 19 | # Internal configuration. |
| 20 | 20 | ||
| 21 | # compiler flags | 21 | # compiler flags |
| 22 | flags-debug = -g -std=c99 | 22 | flags-debug = -Wall -Werror -Wdeclaration-after-statement -g |
| 23 | flags-api = -D_XOPEN_SOURCE=600 -D_GNU_SOURCE | 23 | flags-api = -D_XOPEN_SOURCE=600 -D_GNU_SOURCE |
| 24 | 24 | ||
| 25 | # architecture-specific flags | 25 | # architecture-specific flags |
| @@ -157,6 +157,7 @@ litmus-headers = \ | |||
| 157 | include/litmus/rt_param.h \ | 157 | include/litmus/rt_param.h \ |
| 158 | include/litmus/fpmath.h \ | 158 | include/litmus/fpmath.h \ |
| 159 | include/litmus/binheap.h \ | 159 | include/litmus/binheap.h \ |
| 160 | include/litmus/signal.h \ | ||
| 160 | include/litmus/unistd_32.h \ | 161 | include/litmus/unistd_32.h \ |
| 161 | include/litmus/unistd_64.h | 162 | include/litmus/unistd_64.h |
| 162 | 163 | ||
| @@ -237,7 +238,7 @@ lib-measure_syscall = -lm | |||
| 237 | 238 | ||
| 238 | .SECONDEXPANSION: | 239 | .SECONDEXPANSION: |
| 239 | ${rt-apps}: $${obj-$$@} liblitmus.a | 240 | ${rt-apps}: $${obj-$$@} liblitmus.a |
| 240 | $(CC) -o $@ $(LDFLAGS) ${ldf-$@} $(filter-out liblitmus.a,$+) $(LOADLIBS) $(LDLIBS) ${lib-$@} ${liblitmus-flags} ${lib-$@} | 241 | $(CC) -o $@ $(LDFLAGS) ${ldf-$@} $(filter-out liblitmus.a,$+) $(LOADLIBS) $(LDLIBS) ${liblitmus-flags} ${lib-$@} |
| 241 | 242 | ||
| 242 | # ############################################################################## | 243 | # ############################################################################## |
| 243 | # Dependency resolution. | 244 | # Dependency resolution. |
diff --git a/bin/rt_launch.c b/bin/rt_launch.c index 3863031..84a5e6c 100644 --- a/bin/rt_launch.c +++ b/bin/rt_launch.c | |||
| @@ -54,7 +54,7 @@ int main(int argc, char** argv) | |||
| 54 | int verbose = 0; | 54 | int verbose = 0; |
| 55 | int wait = 0; | 55 | int wait = 0; |
| 56 | startup_info_t info; | 56 | startup_info_t info; |
| 57 | task_class_t class = RT_CLASS_HARD; | 57 | task_class_t rt_class = RT_CLASS_HARD; |
| 58 | 58 | ||
| 59 | while ((opt = getopt(argc, argv, OPTSTR)) != -1) { | 59 | while ((opt = getopt(argc, argv, OPTSTR)) != -1) { |
| 60 | switch (opt) { | 60 | switch (opt) { |
| @@ -69,8 +69,8 @@ int main(int argc, char** argv) | |||
| 69 | migrate = 1; | 69 | migrate = 1; |
| 70 | break; | 70 | break; |
| 71 | case 'c': | 71 | case 'c': |
| 72 | class = str2class(optarg); | 72 | rt_class = str2class(optarg); |
| 73 | if (class == -1) | 73 | if (rt_class == -1) |
| 74 | usage("Unknown task class."); | 74 | usage("Unknown task class."); |
| 75 | break; | 75 | break; |
| 76 | 76 | ||
| @@ -107,7 +107,7 @@ int main(int argc, char** argv) | |||
| 107 | if (ret < 0) | 107 | if (ret < 0) |
| 108 | bail_out("could not migrate to target partition"); | 108 | bail_out("could not migrate to target partition"); |
| 109 | } | 109 | } |
| 110 | ret = __create_rt_task(launch, &info, cpu, wcet, period, class); | 110 | ret = __create_rt_task(launch, &info, cpu, wcet, period, rt_class); |
| 111 | 111 | ||
| 112 | 112 | ||
| 113 | if (ret < 0) | 113 | if (ret < 0) |
diff --git a/bin/rtspin.c b/bin/rtspin.c index ae76941..8ee26d5 100644 --- a/bin/rtspin.c +++ b/bin/rtspin.c | |||
| @@ -67,7 +67,7 @@ static void get_exec_times(const char *file, const int column, | |||
| 67 | bail_out("rewinding file failed"); | 67 | bail_out("rewinding file failed"); |
| 68 | 68 | ||
| 69 | /* allocate space for exec times */ | 69 | /* allocate space for exec times */ |
| 70 | *exec_times = calloc(*num_jobs, sizeof(*exec_times)); | 70 | *exec_times = (double*)calloc(*num_jobs, sizeof(*exec_times)); |
| 71 | if (!*exec_times) | 71 | if (!*exec_times) |
| 72 | bail_out("couldn't allocate memory"); | 72 | bail_out("couldn't allocate memory"); |
| 73 | 73 | ||
| @@ -152,16 +152,28 @@ static void debug_delay_loop(void) | |||
| 152 | 152 | ||
| 153 | static int job(double exec_time, double program_end) | 153 | static int job(double exec_time, double program_end) |
| 154 | { | 154 | { |
| 155 | if (wctime() > program_end) | 155 | int exit = 0; |
| 156 | return 0; | 156 | if (wctime() > program_end) { |
| 157 | exit = 1; | ||
| 158 | } | ||
| 157 | else { | 159 | else { |
| 158 | loop_for(exec_time, program_end + 1); | 160 | LITMUS_TRY { |
| 161 | loop_for(exec_time, program_end + 1); | ||
| 162 | } | ||
| 163 | LITMUS_CATCH(SIG_BUDGET) { | ||
| 164 | fprintf(stdout, "Exhausted budget! Finishing job NOW!\n"); | ||
| 165 | } | ||
| 166 | END_LITMUS_TRY; | ||
| 167 | } | ||
| 168 | |||
| 169 | if (!exit) { | ||
| 159 | sleep_next_period(); | 170 | sleep_next_period(); |
| 160 | return 1; | ||
| 161 | } | 171 | } |
| 172 | |||
| 173 | return !exit; | ||
| 162 | } | 174 | } |
| 163 | 175 | ||
| 164 | #define OPTSTR "p:c:wlveo:f:s:" | 176 | #define OPTSTR "p:c:wlveio:f:s:" |
| 165 | 177 | ||
| 166 | int main(int argc, char** argv) | 178 | int main(int argc, char** argv) |
| 167 | { | 179 | { |
| @@ -177,10 +189,11 @@ int main(int argc, char** argv) | |||
| 177 | int column = 1; | 189 | int column = 1; |
| 178 | const char *file = NULL; | 190 | const char *file = NULL; |
| 179 | int want_enforcement = 0; | 191 | int want_enforcement = 0; |
| 192 | int want_signals = 0; | ||
| 180 | double duration = 0, start; | 193 | double duration = 0, start; |
| 181 | double *exec_times = NULL; | 194 | double *exec_times = NULL; |
| 182 | double scale = 1.0; | 195 | double scale = 1.0; |
| 183 | task_class_t class = RT_CLASS_HARD; | 196 | task_class_t rt_class = RT_CLASS_HARD; |
| 184 | int cur_job, num_jobs; | 197 | int cur_job, num_jobs; |
| 185 | 198 | ||
| 186 | progname = argv[0]; | 199 | progname = argv[0]; |
| @@ -195,13 +208,16 @@ int main(int argc, char** argv) | |||
| 195 | migrate = 1; | 208 | migrate = 1; |
| 196 | break; | 209 | break; |
| 197 | case 'c': | 210 | case 'c': |
| 198 | class = str2class(optarg); | 211 | rt_class = str2class(optarg); |
| 199 | if (class == -1) | 212 | if (rt_class == -1) |
| 200 | usage("Unknown task class."); | 213 | usage("Unknown task class."); |
| 201 | break; | 214 | break; |
| 202 | case 'e': | 215 | case 'e': |
| 203 | want_enforcement = 1; | 216 | want_enforcement = 1; |
| 204 | break; | 217 | break; |
| 218 | case 'i': | ||
| 219 | want_signals = 1; | ||
| 220 | break; | ||
| 205 | case 'l': | 221 | case 'l': |
| 206 | test_loop = 1; | 222 | test_loop = 1; |
| 207 | break; | 223 | break; |
| @@ -274,15 +290,22 @@ int main(int argc, char** argv) | |||
| 274 | bail_out("could not migrate to target partition"); | 290 | bail_out("could not migrate to target partition"); |
| 275 | } | 291 | } |
| 276 | 292 | ||
| 277 | ret = sporadic_task_ns(wcet, period, 0, cpu, class, | 293 | ret = sporadic_task_ns(wcet, period, 0, cpu, rt_class, |
| 278 | want_enforcement ? PRECISE_ENFORCEMENT | 294 | want_enforcement ? PRECISE_ENFORCEMENT |
| 279 | : NO_ENFORCEMENT, | 295 | : NO_ENFORCEMENT, |
| 296 | want_signals ? PRECISE_SIGNALS | ||
| 297 | : NO_SIGNALS, | ||
| 280 | migrate); | 298 | migrate); |
| 281 | if (ret < 0) | 299 | if (ret < 0) |
| 282 | bail_out("could not setup rt task params"); | 300 | bail_out("could not setup rt task params"); |
| 283 | 301 | ||
| 284 | init_litmus(); | 302 | init_litmus(); |
| 285 | 303 | ||
| 304 | if (want_signals) { | ||
| 305 | /* bind default longjmp signal handler to SIG_BUDGET. */ | ||
| 306 | activate_litmus_signals(SIG_BUDGET_MASK, longjmp_on_litmus_signal); | ||
| 307 | } | ||
| 308 | |||
| 286 | ret = task_mode(LITMUS_RT_TASK); | 309 | ret = task_mode(LITMUS_RT_TASK); |
| 287 | if (ret != 0) | 310 | if (ret != 0) |
| 288 | bail_out("could not become RT task"); | 311 | bail_out("could not become RT task"); |
| @@ -304,7 +327,10 @@ int main(int argc, char** argv) | |||
| 304 | } | 327 | } |
| 305 | } else { | 328 | } else { |
| 306 | /* conver to seconds and scale */ | 329 | /* conver to seconds and scale */ |
| 307 | while (job(wcet_ms * 0.001 * scale, start + duration)); | 330 | int run = 1; |
| 331 | while (run) { | ||
| 332 | run = job(wcet_ms * 0.001 * scale, start + duration); | ||
| 333 | } | ||
| 308 | } | 334 | } |
| 309 | 335 | ||
| 310 | ret = task_mode(BACKGROUND_TASK); | 336 | ret = task_mode(BACKGROUND_TASK); |
| @@ -149,7 +149,7 @@ void* rt_thread(void* _ctx) | |||
| 149 | TH_CALL( init_rt_thread() ); | 149 | TH_CALL( init_rt_thread() ); |
| 150 | 150 | ||
| 151 | /* Vary period a little bit. */ | 151 | /* Vary period a little bit. */ |
| 152 | TH_CALL( sporadic_task_ns(EXEC_COST, PERIOD + 10*ctx->id, 0, 0, RT_CLASS_SOFT, NO_ENFORCEMENT, 0) ); | 152 | TH_CALL( sporadic_task_ns(EXEC_COST, PERIOD + 10*ctx->id, 0, 0, RT_CLASS_SOFT, NO_ENFORCEMENT, NO_SIGNALS, 0) ); |
| 153 | 153 | ||
| 154 | ctx->ikglp = open_ikglp_sem(ctx->fd, 0, (void*)&NUM_REPLICAS); | 154 | ctx->ikglp = open_ikglp_sem(ctx->fd, 0, (void*)&NUM_REPLICAS); |
| 155 | if(ctx->ikglp < 0) | 155 | if(ctx->ikglp < 0) |
diff --git a/ikglptest.c b/ikglptest.c index 8c1ac0b..8e088c1 100644 --- a/ikglptest.c +++ b/ikglptest.c | |||
| @@ -109,7 +109,7 @@ struct avg_info feedback(int _a, int _b) | |||
| 109 | fp_t _est, _err; | 109 | fp_t _est, _err; |
| 110 | 110 | ||
| 111 | int base = 1000000; | 111 | int base = 1000000; |
| 112 | int range = 40; | 112 | //int range = 40; |
| 113 | 113 | ||
| 114 | fp_t est = _integer_to_fp(base); | 114 | fp_t est = _integer_to_fp(base); |
| 115 | fp_t err = _fp(base/2); | 115 | fp_t err = _fp(base/2); |
| @@ -117,50 +117,56 @@ struct avg_info feedback(int _a, int _b) | |||
| 117 | #define NUM_SAMPLES 10000 | 117 | #define NUM_SAMPLES 10000 |
| 118 | 118 | ||
| 119 | float samples[NUM_SAMPLES] = {0.0}; | 119 | float samples[NUM_SAMPLES] = {0.0}; |
| 120 | 120 | float accu_abs, accu; | |
| 121 | float avg; | ||
| 122 | float devsum; | ||
| 123 | float stdev; | ||
| 124 | struct avg_info ret; | ||
| 121 | 125 | ||
| 122 | for(i = 0; i < NUM_SAMPLES; ++i) { | 126 | for(i = 0; i < NUM_SAMPLES; ++i) { |
| 123 | int num = ((rand()%40)*(rand()%2 ? -1 : 1)/100.0)*base + base; | 127 | int num = ((rand()%40)*(rand()%2 ? -1 : 1)/100.0)*base + base; |
| 124 | actual_fp = _integer_to_fp(num); | 128 | float rel_err; |
| 129 | |||
| 130 | actual_fp = _integer_to_fp(num); | ||
| 125 | 131 | ||
| 126 | // printf("Before: est = %d\terr = %d\n", (int)_fp_to_integer(est), (int)_fp_to_integer(err)); | 132 | // printf("Before: est = %d\terr = %d\n", (int)_fp_to_integer(est), (int)_fp_to_integer(err)); |
| 127 | 133 | ||
| 128 | _err = _sub(actual_fp, est); | 134 | _err = _sub(actual_fp, est); |
| 129 | _est = _add(_mul(a, _err), _mul(b, err)); | 135 | _est = _add(_mul(a, _err), _mul(b, err)); |
| 130 | 136 | ||
| 131 | float rel_err = _fp_to_integer(_mul(_div(_err, est), _integer_to_fp(10000)))/10000.0; | 137 | rel_err = _fp_to_integer(_mul(_div(_err, est), _integer_to_fp(10000)))/10000.0; |
| 132 | rel_err *= 100.0; | 138 | rel_err *= 100.0; |
| 133 | //printf("%6.2f\n", rel_err); | 139 | //printf("%6.2f\n", rel_err); |
| 134 | samples[i] = rel_err; | 140 | samples[i] = rel_err; |
| 135 | 141 | ||
| 136 | est = _est; | 142 | est = _est; |
| 137 | err = _add(err, _err); | 143 | err = _add(err, _err); |
| 138 | 144 | ||
| 139 | if((int)_fp_to_integer(est) <= 0) { | 145 | if((int)_fp_to_integer(est) <= 0) { |
| 140 | est = actual_fp; | 146 | est = actual_fp; |
| 141 | err = _div(actual_fp, _integer_to_fp(2)); | 147 | err = _div(actual_fp, _integer_to_fp(2)); |
| 142 | } | 148 | } |
| 143 | 149 | ||
| 144 | //printf("After: est = %d\terr = %d\n", (int)_fp_to_integer(est), (int)_fp_to_integer(err)); | 150 | //printf("After: est = %d\terr = %d\n", (int)_fp_to_integer(est), (int)_fp_to_integer(err)); |
| 145 | } | 151 | } |
| 146 | 152 | ||
| 147 | float accu_abs = 0.0, accu = 0.0; | 153 | accu_abs = 0.0; |
| 154 | accu = 0.0; | ||
| 148 | for(i = 0; i < NUM_SAMPLES; ++i) { | 155 | for(i = 0; i < NUM_SAMPLES; ++i) { |
| 149 | accu += samples[i]; | 156 | accu += samples[i]; |
| 150 | accu_abs += abs(samples[i]); | 157 | accu_abs += abs(samples[i]); |
| 151 | } | 158 | } |
| 152 | 159 | ||
| 153 | float avg = accu_abs/NUM_SAMPLES; | 160 | avg = accu_abs/NUM_SAMPLES; |
| 154 | float devsum = 0; | 161 | devsum = 0; |
| 155 | for(i = 0; i < NUM_SAMPLES; ++i) { | 162 | for(i = 0; i < NUM_SAMPLES; ++i) { |
| 156 | float dev = samples[i] - avg; | 163 | float dev = samples[i] - avg; |
| 157 | dev *= dev; | 164 | dev *= dev; |
| 158 | devsum += dev; | 165 | devsum += dev; |
| 159 | } | 166 | } |
| 160 | 167 | ||
| 161 | float stdev = sqrtf(devsum/(NUM_SAMPLES-1)); | 168 | stdev = sqrtf(devsum/(NUM_SAMPLES-1)); |
| 162 | 169 | ||
| 163 | struct avg_info ret; | ||
| 164 | ret.avg = avg; | 170 | ret.avg = avg; |
| 165 | ret.stdev = stdev; | 171 | ret.stdev = stdev; |
| 166 | 172 | ||
| @@ -381,7 +387,7 @@ void* rt_thread(void* _ctx) | |||
| 381 | TH_CALL( init_rt_thread() ); | 387 | TH_CALL( init_rt_thread() ); |
| 382 | 388 | ||
| 383 | /* Vary period a little bit. */ | 389 | /* Vary period a little bit. */ |
| 384 | TH_CALL( sporadic_task_ns(EXEC_COST, PERIOD + 10*ctx->id, 0, 0, RT_CLASS_SOFT, NO_ENFORCEMENT, 1) ); | 390 | TH_CALL( sporadic_task_ns(EXEC_COST, PERIOD + 10*ctx->id, 0, 0, RT_CLASS_SOFT, NO_ENFORCEMENT, NO_SIGNALS, 1) ); |
| 385 | 391 | ||
| 386 | if(USE_KFMLP) { | 392 | if(USE_KFMLP) { |
| 387 | ctx->kexclu = open_kfmlp_gpu_sem(ctx->fd, | 393 | ctx->kexclu = open_kfmlp_gpu_sem(ctx->fd, |
diff --git a/include/litmus.h b/include/litmus.h index 2e26868..c3ef941 100644 --- a/include/litmus.h +++ b/include/litmus.h | |||
| @@ -7,12 +7,14 @@ extern "C" { | |||
| 7 | 7 | ||
| 8 | #include <sys/types.h> | 8 | #include <sys/types.h> |
| 9 | #include <stdint.h> | 9 | #include <stdint.h> |
| 10 | #include <setjmp.h> | ||
| 10 | 11 | ||
| 11 | /* Include kernel header. | 12 | /* Include kernel header. |
| 12 | * This is required for the rt_param | 13 | * This is required for the rt_param |
| 13 | * and control_page structures. | 14 | * and control_page structures. |
| 14 | */ | 15 | */ |
| 15 | #include "litmus/rt_param.h" | 16 | #include "litmus/rt_param.h" |
| 17 | #include "litmus/signal.h" | ||
| 16 | 18 | ||
| 17 | #include "asm/cycles.h" /* for null_call() */ | 19 | #include "asm/cycles.h" /* for null_call() */ |
| 18 | 20 | ||
| @@ -33,19 +35,23 @@ int get_rt_task_param(pid_t pid, struct rt_task* param); | |||
| 33 | int sporadic_task( | 35 | int sporadic_task( |
| 34 | lt_t e, lt_t p, lt_t phase, | 36 | lt_t e, lt_t p, lt_t phase, |
| 35 | int partition, task_class_t cls, | 37 | int partition, task_class_t cls, |
| 36 | budget_policy_t budget_policy, int set_cpu_set); | 38 | budget_policy_t budget_policy, |
| 39 | budget_signal_policy_t budget_signal_policy, | ||
| 40 | int set_cpu_set); | ||
| 37 | 41 | ||
| 38 | /* times are given in ns */ | 42 | /* times are given in ns */ |
| 39 | int sporadic_task_ns( | 43 | int sporadic_task_ns( |
| 40 | lt_t e, lt_t p, lt_t phase, | 44 | lt_t e, lt_t p, lt_t phase, |
| 41 | int cpu, task_class_t cls, | 45 | int cpu, task_class_t cls, |
| 42 | budget_policy_t budget_policy, int set_cpu_set); | 46 | budget_policy_t budget_policy, |
| 47 | budget_signal_policy_t budget_signal_policy, | ||
| 48 | int set_cpu_set); | ||
| 43 | 49 | ||
| 44 | /* budget enforcement off by default in these macros */ | 50 | /* budget enforcement off by default in these macros */ |
| 45 | #define sporadic_global(e, p) \ | 51 | #define sporadic_global(e, p) \ |
| 46 | sporadic_task(e, p, 0, 0, RT_CLASS_SOFT, NO_ENFORCEMENT, 0) | 52 | sporadic_task(e, p, 0, 0, RT_CLASS_SOFT, NO_ENFORCEMENT, NO_SIGNALS, 0) |
| 47 | #define sporadic_partitioned(e, p, cpu) \ | 53 | #define sporadic_partitioned(e, p, cpu) \ |
| 48 | sporadic_task(e, p, 0, cpu, RT_CLASS_SOFT, NO_ENFORCEMENT, 1) | 54 | sporadic_task(e, p, 0, cpu, RT_CLASS_SOFT, NO_ENFORCEMENT, NO_SIGNALS, 1) |
| 49 | 55 | ||
| 50 | /* file descriptor attached shared objects support */ | 56 | /* file descriptor attached shared objects support */ |
| 51 | typedef enum { | 57 | typedef enum { |
| @@ -199,7 +205,127 @@ int null_call(cycles_t *timestamp); | |||
| 199 | */ | 205 | */ |
| 200 | struct control_page* get_ctrl_page(void); | 206 | struct control_page* get_ctrl_page(void); |
| 201 | 207 | ||
| 208 | |||
| 209 | /* Litmus signal handling */ | ||
| 210 | |||
| 211 | typedef struct litmus_sigjmp | ||
| 212 | { | ||
| 213 | sigjmp_buf env; | ||
| 214 | struct litmus_sigjmp *prev; | ||
| 215 | } litmus_sigjmp_t; | ||
| 216 | |||
| 217 | void push_sigjmp(litmus_sigjmp_t* buf); | ||
| 218 | litmus_sigjmp_t* pop_sigjmp(void); | ||
| 219 | |||
| 220 | typedef void (*litmus_sig_handler_t)(int); | ||
| 221 | typedef void (*litmus_sig_actions_t)(int, siginfo_t *, void *); | ||
| 222 | |||
| 223 | /* ignore specified signals. all signals raised while ignored are dropped */ | ||
| 224 | void ignore_litmus_signals(unsigned long litmus_sig_mask); | ||
| 225 | |||
| 226 | /* register a handler for the given set of litmus signals */ | ||
| 227 | void activate_litmus_signals(unsigned long litmus_sig_mask, | ||
| 228 | litmus_sig_handler_t handler); | ||
| 229 | |||
| 230 | /* register an action signal handler for a given set of signals */ | ||
| 231 | void activate_litmus_signal_actions(unsigned long litmus_sig_mask, | ||
| 232 | litmus_sig_actions_t handler); | ||
| 233 | |||
| 234 | /* Block a given set of litmus signals. Any signals raised while blocked | ||
| 235 | * are queued and delivered after unblocking. Call ignore_litmus_signals() | ||
| 236 | * before unblocking if you wish to discard these. Blocking may be | ||
| 237 | * useful to protect COTS code in Litmus that may not be able to deal | ||
| 238 | * with exception-raising signals. | ||
| 239 | */ | ||
| 240 | void block_litmus_signals(unsigned long litmus_sig_mask); | ||
| 241 | |||
| 242 | /* Unblock a given set of litmus signals. */ | ||
| 243 | void unblock_litmus_signals(unsigned long litmus_sig_mask); | ||
| 244 | |||
| 245 | #define SIG_BUDGET_MASK 0x00000001 | ||
| 246 | /* more ... */ | ||
| 247 | |||
| 248 | #define ALL_LITMUS_SIG_MASKS (SIG_BUDGET_MASK) | ||
| 249 | |||
| 250 | /* Try/Catch structures useful for implementing abortable jobs. | ||
| 251 | * Should only be used in legitimate cases. ;) | ||
| 252 | */ | ||
| 253 | #define LITMUS_TRY \ | ||
| 254 | do { \ | ||
| 255 | int sigsetjmp_ret_##__FUNCTION__##__LINE__; \ | ||
| 256 | litmus_sigjmp_t lit_env_##__FUNCTION__##__LINE__; \ | ||
| 257 | push_sigjmp(&lit_env_##__FUNCTION__##__LINE__); \ | ||
| 258 | sigsetjmp_ret_##__FUNCTION__##__LINE__ = \ | ||
| 259 | sigsetjmp(lit_env_##__FUNCTION__##__LINE__.env, 1); \ | ||
| 260 | if (sigsetjmp_ret_##__FUNCTION__##__LINE__ == 0) { | ||
| 261 | |||
| 262 | #define LITMUS_CATCH(x) \ | ||
| 263 | } else if (sigsetjmp_ret_##__FUNCTION__##__LINE__ == (x)) { | ||
| 264 | |||
| 265 | #define END_LITMUS_TRY \ | ||
| 266 | } /* end if-else-if chain */ \ | ||
| 267 | } while(0); /* end do from 'LITMUS_TRY' */ | ||
| 268 | |||
| 269 | /* Calls siglongjmp(signum). Use with TRY/CATCH. | ||
| 270 | * Example: | ||
| 271 | * activate_litmus_signals(SIG_BUDGET_MASK, longjmp_on_litmus_signal); | ||
| 272 | */ | ||
| 273 | void longjmp_on_litmus_signal(int signum); | ||
| 274 | |||
| 202 | #ifdef __cplusplus | 275 | #ifdef __cplusplus |
| 203 | } | 276 | } |
| 204 | #endif | 277 | #endif |
| 278 | |||
| 279 | |||
| 280 | |||
| 281 | |||
| 282 | #ifdef __cplusplus | ||
| 283 | /* Expose litmus exceptions if C++. | ||
| 284 | * | ||
| 285 | * KLUDGE: We define everything in the header since liblitmus is a C-only | ||
| 286 | * library, but this header could be included in C++ code. | ||
| 287 | */ | ||
| 288 | |||
| 289 | #include <exception> | ||
| 290 | |||
| 291 | namespace litmus | ||
| 292 | { | ||
| 293 | class litmus_exception: public std::exception | ||
| 294 | { | ||
| 295 | public: | ||
| 296 | litmus_exception() throw() {} | ||
| 297 | virtual ~litmus_exception() throw() {} | ||
| 298 | virtual const char* what() const throw() { return "litmus_exception";} | ||
| 299 | }; | ||
| 300 | |||
| 301 | class sigbudget: public litmus_exception | ||
| 302 | { | ||
| 303 | public: | ||
| 304 | sigbudget() throw() {} | ||
| 305 | virtual ~sigbudget() throw() {} | ||
| 306 | virtual const char* what() const throw() { return "sigbudget"; } | ||
| 307 | }; | ||
| 308 | |||
| 309 | /* Must compile your program with "non-call-exception". */ | ||
| 310 | static __attribute__((used)) | ||
| 311 | void throw_on_litmus_signal(int signum) | ||
| 312 | { | ||
| 313 | /* We have to unblock the received signal to get more in the future | ||
| 314 | * because we are not calling siglongjmp(), which normally restores | ||
| 315 | * the mask for us. | ||
| 316 | */ | ||
| 317 | if (SIG_BUDGET == signum) { | ||
| 318 | unblock_litmus_signals(SIG_BUDGET_MASK); | ||
| 319 | throw sigbudget(); | ||
| 320 | } | ||
| 321 | /* else if (...) */ | ||
| 322 | else { | ||
| 323 | /* silently ignore */ | ||
| 324 | } | ||
| 325 | } | ||
| 326 | |||
| 327 | }; /* end namespace 'litmus' */ | ||
| 328 | |||
| 329 | #endif /* end __cplusplus */ | ||
| 330 | |||
| 205 | #endif | 331 | #endif |
| @@ -147,7 +147,7 @@ void* rt_thread(void* _ctx) | |||
| 147 | //printf("RT Thread %d active.\n", ctx->id); | 147 | //printf("RT Thread %d active.\n", ctx->id); |
| 148 | 148 | ||
| 149 | TH_CALL( init_rt_thread() ); | 149 | TH_CALL( init_rt_thread() ); |
| 150 | TH_CALL( sporadic_task_ns(EXEC_COST, PERIOD + 10*ctx->id, 0, 0, RT_CLASS_SOFT, NO_ENFORCEMENT, 0) ); | 150 | TH_CALL( sporadic_task_ns(EXEC_COST, PERIOD + 10*ctx->id, 0, 0, RT_CLASS_SOFT, NO_ENFORCEMENT, NO_SIGNALS, 0) ); |
| 151 | 151 | ||
| 152 | for (i = 0; i < NUM_SEMS; i++) { | 152 | for (i = 0; i < NUM_SEMS; i++) { |
| 153 | ctx->od[i] = open_rsm_sem(ctx->fd, i); | 153 | ctx->od[i] = open_rsm_sem(ctx->fd, i); |
diff --git a/src/litmus.c b/src/litmus.c index 4f404e2..3bab483 100644 --- a/src/litmus.c +++ b/src/litmus.c | |||
| @@ -26,7 +26,7 @@ task_class_t str2class(const char* str) | |||
| 26 | else if (!strcmp(str, "be")) | 26 | else if (!strcmp(str, "be")) |
| 27 | return RT_CLASS_BEST_EFFORT; | 27 | return RT_CLASS_BEST_EFFORT; |
| 28 | else | 28 | else |
| 29 | return -1; | 29 | return (task_class_t)(-1); |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | #define NS_PER_MS 1000000 | 32 | #define NS_PER_MS 1000000 |
| @@ -43,15 +43,19 @@ int be_migrate_to(int target_cpu) | |||
| 43 | 43 | ||
| 44 | int sporadic_task(lt_t e, lt_t p, lt_t phase, | 44 | int sporadic_task(lt_t e, lt_t p, lt_t phase, |
| 45 | int cpu, task_class_t cls, | 45 | int cpu, task_class_t cls, |
| 46 | budget_policy_t budget_policy, int set_cpu_set) | 46 | budget_policy_t budget_policy, |
| 47 | budget_signal_policy_t budget_signal_policy, | ||
| 48 | int set_cpu_set) | ||
| 47 | { | 49 | { |
| 48 | return sporadic_task_ns(e * NS_PER_MS, p * NS_PER_MS, phase * NS_PER_MS, | 50 | return sporadic_task_ns(e * NS_PER_MS, p * NS_PER_MS, phase * NS_PER_MS, |
| 49 | cpu, cls, budget_policy, set_cpu_set); | 51 | cpu, cls, budget_policy, budget_signal_policy, set_cpu_set); |
| 50 | } | 52 | } |
| 51 | 53 | ||
| 52 | int sporadic_task_ns(lt_t e, lt_t p, lt_t phase, | 54 | int sporadic_task_ns(lt_t e, lt_t p, lt_t phase, |
| 53 | int cpu, task_class_t cls, | 55 | int cpu, task_class_t cls, |
| 54 | budget_policy_t budget_policy, int set_cpu_set) | 56 | budget_policy_t budget_policy, |
| 57 | budget_signal_policy_t budget_signal_policy, | ||
| 58 | int set_cpu_set) | ||
| 55 | { | 59 | { |
| 56 | struct rt_task param; | 60 | struct rt_task param; |
| 57 | int ret; | 61 | int ret; |
| @@ -67,6 +71,7 @@ int sporadic_task_ns(lt_t e, lt_t p, lt_t phase, | |||
| 67 | param.cls = cls; | 71 | param.cls = cls; |
| 68 | param.phase = phase; | 72 | param.phase = phase; |
| 69 | param.budget_policy = budget_policy; | 73 | param.budget_policy = budget_policy; |
| 74 | param.budget_signal_policy = budget_signal_policy; | ||
| 70 | 75 | ||
| 71 | if (set_cpu_set) { | 76 | if (set_cpu_set) { |
| 72 | ret = be_migrate_to(cpu); | 77 | ret = be_migrate_to(cpu); |
diff --git a/src/signal.c b/src/signal.c new file mode 100644 index 0000000..bfe18b9 --- /dev/null +++ b/src/signal.c | |||
| @@ -0,0 +1,107 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include <string.h> | ||
| 3 | |||
| 4 | #include "litmus.h" | ||
| 5 | #include "internal.h" | ||
| 6 | |||
| 7 | /* setjmp calls are stored on a singlely link list, | ||
| 8 | * one stack per thread. | ||
| 9 | */ | ||
| 10 | static __thread litmus_sigjmp_t *g_sigjmp_tail = 0; | ||
| 11 | |||
| 12 | void push_sigjmp(litmus_sigjmp_t *buf) | ||
| 13 | { | ||
| 14 | buf->prev = g_sigjmp_tail; | ||
| 15 | g_sigjmp_tail = buf; | ||
| 16 | } | ||
| 17 | |||
| 18 | litmus_sigjmp_t* pop_sigjmp(void) | ||
| 19 | { | ||
| 20 | litmus_sigjmp_t* ret; | ||
| 21 | ret = g_sigjmp_tail; | ||
| 22 | g_sigjmp_tail = (ret) ? ret->prev : NULL; | ||
| 23 | return ret; | ||
| 24 | } | ||
| 25 | |||
| 26 | static void reg_litmus_signals(unsigned long litmus_sig_mask, | ||
| 27 | struct sigaction *pAction) | ||
| 28 | { | ||
| 29 | int ret; | ||
| 30 | |||
| 31 | if (litmus_sig_mask | SIG_BUDGET_MASK) { | ||
| 32 | ret = sigaction(SIG_BUDGET, pAction, NULL); | ||
| 33 | check("SIG_BUDGET"); | ||
| 34 | } | ||
| 35 | /* more signals ... */ | ||
| 36 | } | ||
| 37 | |||
| 38 | void ignore_litmus_signals(unsigned long litmus_sig_mask) | ||
| 39 | { | ||
| 40 | activate_litmus_signals(litmus_sig_mask, SIG_IGN); | ||
| 41 | } | ||
| 42 | |||
| 43 | void activate_litmus_signals(unsigned long litmus_sig_mask, | ||
| 44 | litmus_sig_handler_t handle) | ||
| 45 | { | ||
| 46 | struct sigaction action; | ||
| 47 | memset(&action, 0, sizeof(action)); | ||
| 48 | action.sa_handler = handle; | ||
| 49 | |||
| 50 | reg_litmus_signals(litmus_sig_mask, &action); | ||
| 51 | } | ||
| 52 | |||
| 53 | void activate_litmus_signal_actions(unsigned long litmus_sig_mask, | ||
| 54 | litmus_sig_actions_t handle) | ||
| 55 | { | ||
| 56 | struct sigaction action; | ||
| 57 | memset(&action, 0, sizeof(action)); | ||
| 58 | action.sa_sigaction = handle; | ||
| 59 | action.sa_flags = SA_SIGINFO; | ||
| 60 | |||
| 61 | reg_litmus_signals(litmus_sig_mask, &action); | ||
| 62 | } | ||
| 63 | |||
| 64 | void block_litmus_signals(unsigned long litmus_sig_mask) | ||
| 65 | { | ||
| 66 | int ret; | ||
| 67 | sigset_t sigs; | ||
| 68 | sigemptyset(&sigs); | ||
| 69 | |||
| 70 | if (litmus_sig_mask | SIG_BUDGET_MASK) { | ||
| 71 | sigaddset(&sigs, SIG_BUDGET); | ||
| 72 | } | ||
| 73 | /* more signals ... */ | ||
| 74 | |||
| 75 | ret = sigprocmask(SIG_BLOCK, &sigs, NULL); | ||
| 76 | check("SIG_BLOCK litmus signals"); | ||
| 77 | } | ||
| 78 | |||
| 79 | void unblock_litmus_signals(unsigned long litmus_sig_mask) | ||
| 80 | { | ||
| 81 | int ret; | ||
| 82 | sigset_t sigs; | ||
| 83 | sigemptyset(&sigs); | ||
| 84 | |||
| 85 | if (litmus_sig_mask | SIG_BUDGET_MASK) { | ||
| 86 | sigaddset(&sigs, SIG_BUDGET); | ||
| 87 | } | ||
| 88 | /* more ... */ | ||
| 89 | |||
| 90 | ret = sigprocmask(SIG_UNBLOCK, &sigs, NULL); | ||
| 91 | check("SIG_UNBLOCK litmus signals"); | ||
| 92 | } | ||
| 93 | |||
| 94 | |||
| 95 | void longjmp_on_litmus_signal(int signum) | ||
| 96 | { | ||
| 97 | /* We get signal! Main screen turn on! */ | ||
| 98 | litmus_sigjmp_t *lit_env; | ||
| 99 | lit_env = pop_sigjmp(); | ||
| 100 | if (lit_env) { | ||
| 101 | /* What you say?! */ | ||
| 102 | siglongjmp(lit_env->env, signum); /* restores signal mask */ | ||
| 103 | } | ||
| 104 | else { | ||
| 105 | /* silently ignore the signal */ | ||
| 106 | } | ||
| 107 | } | ||
| @@ -41,13 +41,13 @@ int __launch_rt_task(rt_fn_t rt_prog, void *rt_arg, rt_setup_fn_t setup, | |||
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period, | 43 | int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period, |
| 44 | task_class_t class) | 44 | task_class_t rt_class) |
| 45 | { | 45 | { |
| 46 | struct rt_task params; | 46 | struct rt_task params; |
| 47 | params.cpu = cpu; | 47 | params.cpu = cpu; |
| 48 | params.period = period; | 48 | params.period = period; |
| 49 | params.exec_cost = wcet; | 49 | params.exec_cost = wcet; |
| 50 | params.cls = class; | 50 | params.cls = rt_class; |
| 51 | params.phase = 0; | 51 | params.phase = 0; |
| 52 | /* enforce budget for tasks that might not use sleep_next_period() */ | 52 | /* enforce budget for tasks that might not use sleep_next_period() */ |
| 53 | params.budget_policy = QUANTUM_ENFORCEMENT; | 53 | params.budget_policy = QUANTUM_ENFORCEMENT; |
diff --git a/tests/fdso.c b/tests/fdso.c index 8a2a0d0..8e320cf 100644 --- a/tests/fdso.c +++ b/tests/fdso.c | |||
| @@ -48,8 +48,8 @@ TESTCASE(invalid_od, ALL, | |||
| 48 | TESTCASE(invalid_obj_type, ALL, | 48 | TESTCASE(invalid_obj_type, ALL, |
| 49 | "reject invalid object types") | 49 | "reject invalid object types") |
| 50 | { | 50 | { |
| 51 | SYSCALL_FAILS( EINVAL, od_open(0, -1, 0) ); | 51 | SYSCALL_FAILS( EINVAL, od_open(0, (obj_type_t)-1, 0) ); |
| 52 | SYSCALL_FAILS( EINVAL, od_open(0, 10, 0) ); | 52 | SYSCALL_FAILS( EINVAL, od_open(0, (obj_type_t)10, 0) ); |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | TESTCASE(not_inherit_od, GSN_EDF | PSN_EDF, | 55 | TESTCASE(not_inherit_od, GSN_EDF | PSN_EDF, |
