diff options
| author | Bjoern B. Brandenburg <bbb@cs.unc.edu> | 2007-09-18 12:23:43 -0400 |
|---|---|---|
| committer | Bjoern B. Brandenburg <bbb@cs.unc.edu> | 2007-09-18 12:23:43 -0400 |
| commit | 957ad72229186c5d21e44366f61d58a4dfa89bfe (patch) | |
| tree | 2284b3f2f4c1ed7c81ba0ccda720997fab4dab85 /src | |
| parent | 5760b6ad37c794a0dd5312206184d0b8ae8e8eda (diff) | |
Change liblitmus to have a more sane repository layout.
Diffstat (limited to 'src')
| -rw-r--r-- | src/edf-hsb.c | 48 | ||||
| -rw-r--r-- | src/hrt.c | 78 | ||||
| -rw-r--r-- | src/iotest.c | 74 | ||||
| -rw-r--r-- | src/litmus.c | 295 | ||||
| -rw-r--r-- | src/np_test.c | 56 | ||||
| -rw-r--r-- | src/rt_launch.c | 83 | ||||
| -rw-r--r-- | src/run.c | 8 | ||||
| -rw-r--r-- | src/set_rt_mode.c | 22 | ||||
| -rw-r--r-- | src/show_scheduler.c | 10 | ||||
| -rw-r--r-- | src/timeout.c | 36 | ||||
| -rw-r--r-- | src/wait_test.c | 103 |
11 files changed, 813 insertions, 0 deletions
diff --git a/src/edf-hsb.c b/src/edf-hsb.c new file mode 100644 index 0000000..9ace2ca --- /dev/null +++ b/src/edf-hsb.c | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | #include "litmus.h" | ||
| 2 | #include "edf-hsb.h" | ||
| 3 | |||
| 4 | |||
| 5 | typedef enum { | ||
| 6 | EDF_HSB_SET_HRT, | ||
| 7 | EDF_HSB_GET_HRT, | ||
| 8 | EDF_HSB_CREATE_BE | ||
| 9 | } edf_hsb_setup_cmds_t; | ||
| 10 | |||
| 11 | typedef struct { | ||
| 12 | int cpu; | ||
| 13 | unsigned int wcet; | ||
| 14 | unsigned int period; | ||
| 15 | } setup_hrt_param_t; | ||
| 16 | |||
| 17 | typedef struct { | ||
| 18 | unsigned int wcet; | ||
| 19 | unsigned int period; | ||
| 20 | } create_be_param_t; | ||
| 21 | |||
| 22 | int set_hrt(int cpu, unsigned int wcet, unsigned int period) | ||
| 23 | { | ||
| 24 | setup_hrt_param_t param; | ||
| 25 | param.cpu = cpu; | ||
| 26 | param.wcet = wcet; | ||
| 27 | param.period = period; | ||
| 28 | return scheduler_setup(EDF_HSB_SET_HRT, ¶m); | ||
| 29 | } | ||
| 30 | |||
| 31 | int get_hrt(int cpu, unsigned int *wcet, unsigned int *period) | ||
| 32 | { | ||
| 33 | setup_hrt_param_t param; | ||
| 34 | int ret; | ||
| 35 | param.cpu = cpu; | ||
| 36 | ret = scheduler_setup(EDF_HSB_GET_HRT, ¶m); | ||
| 37 | *wcet = param.wcet; | ||
| 38 | *period = param.period; | ||
| 39 | return ret; | ||
| 40 | } | ||
| 41 | |||
| 42 | int create_be(unsigned int wcet, unsigned int period) | ||
| 43 | { | ||
| 44 | create_be_param_t param; | ||
| 45 | param.wcet = wcet; | ||
| 46 | param.period = period; | ||
| 47 | return scheduler_setup(EDF_HSB_CREATE_BE, ¶m); | ||
| 48 | } | ||
diff --git a/src/hrt.c b/src/hrt.c new file mode 100644 index 0000000..224293c --- /dev/null +++ b/src/hrt.c | |||
| @@ -0,0 +1,78 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include <stdlib.h> | ||
| 3 | #include <string.h> | ||
| 4 | |||
| 5 | #include "edf-hsb.h" | ||
| 6 | |||
| 7 | |||
| 8 | void usage(char *name) | ||
| 9 | { | ||
| 10 | fprintf(stderr, | ||
| 11 | "EDF-HSB server setup utility\n" | ||
| 12 | "Usage: %s hrt show <#cpu>\n" | ||
| 13 | " %s hrt set <#cpu> <wcet> <period>\n" | ||
| 14 | " %s be create <wcet> <period>\n", | ||
| 15 | name, name, name); | ||
| 16 | exit(1); | ||
| 17 | } | ||
| 18 | |||
| 19 | |||
| 20 | int hrt(int argc, char** argv) | ||
| 21 | { | ||
| 22 | int wcet, period, cpu; | ||
| 23 | |||
| 24 | if (argc == 2 && !strcmp(argv[0], "show")) { | ||
| 25 | cpu = atoi(argv[1]); | ||
| 26 | if (!get_hrt(cpu, &wcet, &period)) | ||
| 27 | printf("HRT/%d = (%d, %d)\n", cpu, wcet, period); | ||
| 28 | else | ||
| 29 | perror("cannot read HRT settings"); | ||
| 30 | } else if (argc == 4 && !strcmp(argv[0], "set")) { | ||
| 31 | cpu = atoi(argv[1]); | ||
| 32 | wcet = atoi(argv[2]); | ||
| 33 | period = atoi(argv[3]); | ||
| 34 | printf("Setting HRT/%d to (%d, %d)", cpu, wcet, period); | ||
| 35 | if (!set_hrt(cpu, wcet, period)) | ||
| 36 | printf(" OK.\n"); | ||
| 37 | else { | ||
| 38 | printf("\n"); | ||
| 39 | perror("cannot write HRT settings"); | ||
| 40 | } | ||
| 41 | } else | ||
| 42 | return 1; | ||
| 43 | |||
| 44 | return 0; | ||
| 45 | } | ||
| 46 | |||
| 47 | int be(int argc, char** argv) | ||
| 48 | { | ||
| 49 | int wcet, period; | ||
| 50 | if (argc == 3 && !strcmp(argv[0], "create")) { | ||
| 51 | wcet = atoi(argv[1]); | ||
| 52 | period = atoi(argv[2]); | ||
| 53 | printf("Creating BE with (%d, %d)", wcet, period); | ||
| 54 | if (!create_be(wcet, period)) | ||
| 55 | printf(" OK.\n"); | ||
| 56 | else { | ||
| 57 | printf("\n"); | ||
| 58 | perror("cannot create BE server"); | ||
| 59 | } | ||
| 60 | return 0; | ||
| 61 | } | ||
| 62 | else | ||
| 63 | return 1; | ||
| 64 | } | ||
| 65 | |||
| 66 | int main(int argc, char** argv) | ||
| 67 | { | ||
| 68 | int ret = 1; | ||
| 69 | if (argc > 1) { | ||
| 70 | if (!strcmp(argv[1], "hrt")) | ||
| 71 | ret = hrt(argc - 2, argv + 2); | ||
| 72 | else if (!strcmp(argv[1], "be")) | ||
| 73 | ret = be(argc - 2, argv + 2); | ||
| 74 | } | ||
| 75 | if (ret) | ||
| 76 | usage(argv[0]); | ||
| 77 | return ret; | ||
| 78 | } | ||
diff --git a/src/iotest.c b/src/iotest.c new file mode 100644 index 0000000..ac07e74 --- /dev/null +++ b/src/iotest.c | |||
| @@ -0,0 +1,74 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include <stdlib.h> | ||
| 3 | #include <signal.h> | ||
| 4 | #include <unistd.h> | ||
| 5 | #include <sys/time.h> | ||
| 6 | #include <sys/wait.h> | ||
| 7 | |||
| 8 | #include "litmus.h" | ||
| 9 | |||
| 10 | #define US_PER_MS 1000 | ||
| 11 | |||
| 12 | int iotest(void *nil) { | ||
| 13 | int id = getpid(); | ||
| 14 | FILE* file; | ||
| 15 | char str[255]; | ||
| 16 | unsigned long last = 0; | ||
| 17 | struct timeval time; | ||
| 18 | |||
| 19 | printf("I'am real time task %d doing IO!\n", id); | ||
| 20 | snprintf(str, sizeof(str), "rt-io-%d.txt", id); | ||
| 21 | file = fopen(str, "w"); | ||
| 22 | if (!file) { | ||
| 23 | perror("could not open file for output"); | ||
| 24 | exit(1); | ||
| 25 | } | ||
| 26 | while (1) { | ||
| 27 | gettimeofday(&time, NULL); | ||
| 28 | if (time.tv_usec - last > US_PER_MS) { | ||
| 29 | fprintf(file, "ran at %lus %lums\n", time.tv_sec, time.tv_usec / US_PER_MS); | ||
| 30 | last = time.tv_usec; | ||
| 31 | } | ||
| 32 | fflush(file); | ||
| 33 | } | ||
| 34 | return id; | ||
| 35 | } | ||
| 36 | |||
| 37 | #define NUMTASKS 4 | ||
| 38 | |||
| 39 | int main(int argc, char** argv) | ||
| 40 | { | ||
| 41 | int rt_task[NUMTASKS]; | ||
| 42 | int i; | ||
| 43 | int ret, pid; | ||
| 44 | |||
| 45 | for (i = 0; i < NUMTASKS; i++) { | ||
| 46 | /* func arg cpu wcet period */ | ||
| 47 | rt_task[i] = create_rt_task(iotest, NULL, 0, 25, 100); | ||
| 48 | if (rt_task[i] < 0) { | ||
| 49 | perror("Could not create rt child process"); | ||
| 50 | } | ||
| 51 | } | ||
| 52 | |||
| 53 | sync(); | ||
| 54 | sync(); | ||
| 55 | |||
| 56 | printf(":: Starting real-time mode.\n"); | ||
| 57 | set_rt_mode(MODE_RT_RUN); | ||
| 58 | |||
| 59 | printf(":: Sleeping...\n"); | ||
| 60 | sleep(120); | ||
| 61 | |||
| 62 | printf("Killing real-time tasks.\n"); | ||
| 63 | for (i = 0; i < NUMTASKS; i++) { | ||
| 64 | printf(":: sending SIGKILL to %d\n", rt_task[i]); | ||
| 65 | kill(rt_task[i], SIGKILL); | ||
| 66 | } | ||
| 67 | for (i = 0; i < NUMTASKS; i++) { | ||
| 68 | pid = wait(&ret); | ||
| 69 | printf(":: %d exited with status %d\n", pid, ret); | ||
| 70 | } | ||
| 71 | printf(":: Leaving real-time mode.\n"); | ||
| 72 | set_rt_mode(MODE_NON_RT); | ||
| 73 | return 0; | ||
| 74 | } | ||
diff --git a/src/litmus.c b/src/litmus.c new file mode 100644 index 0000000..65ad294 --- /dev/null +++ b/src/litmus.c | |||
| @@ -0,0 +1,295 @@ | |||
| 1 | #include <stdlib.h> | ||
| 2 | #include <stdio.h> | ||
| 3 | #include <string.h> | ||
| 4 | #include <sys/types.h> | ||
| 5 | #include <unistd.h> | ||
| 6 | #include <errno.h> | ||
| 7 | #include <signal.h> | ||
| 8 | #include <sys/mman.h> | ||
| 9 | |||
| 10 | |||
| 11 | #include "litmus.h" | ||
| 12 | |||
| 13 | |||
| 14 | /* this is missing in newer linux/unistd.h versions */ | ||
| 15 | |||
| 16 | #define _syscall0(type,name) \ | ||
| 17 | type name(void) \ | ||
| 18 | {\ | ||
| 19 | return syscall(__NR_##name);\ | ||
| 20 | } | ||
| 21 | |||
| 22 | #define _syscall1(type,name,type1,arg1) \ | ||
| 23 | type name(type1 arg1) \ | ||
| 24 | {\ | ||
| 25 | return syscall(__NR_##name, arg1);\ | ||
| 26 | } | ||
| 27 | |||
| 28 | |||
| 29 | #define _syscall2(type,name,type1,arg1,type2,arg2) \ | ||
| 30 | type name(type1 arg1,type2 arg2) \ | ||
| 31 | {\ | ||
| 32 | return syscall(__NR_##name, arg1, arg2);\ | ||
| 33 | } | ||
| 34 | |||
| 35 | |||
| 36 | /* clear the TID in the child */ | ||
| 37 | #define CLONE_CHILD_CLEARTID 0x00200000 | ||
| 38 | /* set the TID in the child */ | ||
| 39 | #define CLONE_CHILD_SETTID 0x01000000 | ||
| 40 | /* don't let the child run before we have completed setup */ | ||
| 41 | #define CLONE_STOPPED 0x02000000 | ||
| 42 | /* litmus clone flag */ | ||
| 43 | #define CLONE_REALTIME 0x10000000 | ||
| 44 | |||
| 45 | /* CLONE_REALTIME is necessary because CLONE_STOPPED will put a SIGSTOP in | ||
| 46 | * the pending signal queue. Thus the first thing a newly created task will | ||
| 47 | * do after it is released is to stop, which is not what we want | ||
| 48 | * | ||
| 49 | * CLONE_REALTIME just sets the status to TASK_STOPPED without queueing a | ||
| 50 | * signal. | ||
| 51 | */ | ||
| 52 | |||
| 53 | |||
| 54 | /* this is essentially a fork with CLONE_STOPPED */ | ||
| 55 | /* #define CLONE_LITMUS CLONE_STOPPED | CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID */ | ||
| 56 | #define CLONE_LITMUS CLONE_REALTIME | CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | ||
| 57 | |||
| 58 | /* we need to override libc because it wants to be clever | ||
| 59 | * and rejects our call without presenting it even to the kernel | ||
| 60 | */ | ||
| 61 | #define __NR_raw_clone 120 | ||
| 62 | |||
| 63 | |||
| 64 | _syscall2(int, raw_clone, unsigned long, flags, unsigned long, child_stack) | ||
| 65 | |||
| 66 | |||
| 67 | const char* get_scheduler_name(spolicy scheduler) | ||
| 68 | { | ||
| 69 | const char* name; | ||
| 70 | |||
| 71 | switch (scheduler){ | ||
| 72 | case SCHED_LINUX : | ||
| 73 | name = "Linux"; | ||
| 74 | break; | ||
| 75 | case SCHED_PFAIR: | ||
| 76 | name = "Pfair"; | ||
| 77 | break; | ||
| 78 | case SCHED_PFAIR_STAGGER: | ||
| 79 | name = "Pfair (staggered)"; | ||
| 80 | break; | ||
| 81 | case SCHED_PART_EDF: | ||
| 82 | name = "Partioned EDF"; | ||
| 83 | break; | ||
| 84 | case SCHED_PART_EEVDF: | ||
| 85 | name = "Partioned EEVDF"; | ||
| 86 | break; | ||
| 87 | case SCHED_GLOBAL_EDF: | ||
| 88 | name = "Global EDF"; | ||
| 89 | break; | ||
| 90 | case SCHED_EDF_HSB: | ||
| 91 | name = "EDF-HSB"; | ||
| 92 | break; | ||
| 93 | case SCHED_GSN_EDF: | ||
| 94 | name = "GSN-EDF"; | ||
| 95 | break; | ||
| 96 | case SCHED_PSN_EDF: | ||
| 97 | name = "PSN-EDF"; | ||
| 98 | break; | ||
| 99 | default: | ||
| 100 | name = "Unkown"; | ||
| 101 | break; | ||
| 102 | } | ||
| 103 | return name; | ||
| 104 | } | ||
| 105 | |||
| 106 | int create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period) { | ||
| 107 | return __create_rt_task(rt_prog, arg, cpu, wcet, period, RT_CLASS_HARD); | ||
| 108 | } | ||
| 109 | |||
| 110 | int __create_rt_task(rt_fn_t rt_prog, void *arg, int cpu, int wcet, int period, | ||
| 111 | task_class_t class) | ||
| 112 | { | ||
| 113 | int ret; | ||
| 114 | rt_param_t params; | ||
| 115 | int rt_task = raw_clone(CLONE_LITMUS, 0); | ||
| 116 | |||
| 117 | if (rt_task < 0) | ||
| 118 | return rt_task; | ||
| 119 | |||
| 120 | if (rt_task > 0) { | ||
| 121 | /* we are the controller task */ | ||
| 122 | params.period = period; | ||
| 123 | params.exec_cost = wcet; | ||
| 124 | params.cpu = cpu; | ||
| 125 | params.cls = class; | ||
| 126 | ret = set_rt_task_param(rt_task, ¶ms); | ||
| 127 | if (ret < 0) { | ||
| 128 | /* we have a problem: we created the task but | ||
| 129 | * for some stupid reason we cannot set the real-time | ||
| 130 | * parameters. We must clean up the stopped task. | ||
| 131 | */ | ||
| 132 | kill(rt_task, SIGKILL); | ||
| 133 | /* syscall will have set errno, we don't have to do | ||
| 134 | * anything | ||
| 135 | */ | ||
| 136 | return -1; | ||
| 137 | } | ||
| 138 | ret = prepare_rt_task(rt_task); | ||
| 139 | if (ret < 0) { | ||
| 140 | /* same problem as above*/ | ||
| 141 | //kill(rt_task, SIGKILL); | ||
| 142 | rt_task = -1; | ||
| 143 | } | ||
| 144 | return rt_task; | ||
| 145 | } | ||
| 146 | else { | ||
| 147 | /* we are the real-time task | ||
| 148 | * launch task and die when it is done | ||
| 149 | */ | ||
| 150 | |||
| 151 | exit(rt_prog(arg)); | ||
| 152 | } | ||
| 153 | } | ||
| 154 | |||
| 155 | |||
| 156 | void show_rt_param(rt_param_t* tp) | ||
| 157 | { | ||
| 158 | printf("rt params:\n\t" | ||
| 159 | "exec_cost:\t%ld\n\tperiod:\t\t%ld\n\tcpu:\t%d\n", | ||
| 160 | tp->exec_cost, tp->period, tp->cpu); | ||
| 161 | } | ||
| 162 | |||
| 163 | task_class_t str2class(const char* str) | ||
| 164 | { | ||
| 165 | if (!strcmp(str, "hrt")) | ||
| 166 | return RT_CLASS_HARD; | ||
| 167 | else if (!strcmp(str, "srt")) | ||
| 168 | return RT_CLASS_SOFT; | ||
| 169 | else if (!strcmp(str, "be")) | ||
| 170 | return RT_CLASS_BEST_EFFORT; | ||
| 171 | else | ||
| 172 | return -1; | ||
| 173 | } | ||
| 174 | |||
| 175 | |||
| 176 | |||
| 177 | struct np_flag { | ||
| 178 | #define RT_PREEMPTIVE 0x2050 /* = NP */ | ||
| 179 | #define RT_NON_PREEMPTIVE 0x4e50 /* = P */ | ||
| 180 | unsigned short preemptivity; | ||
| 181 | |||
| 182 | #define RT_EXIT_NP_REQUESTED 0x5251 /* = RQ */ | ||
| 183 | unsigned short request; | ||
| 184 | |||
| 185 | unsigned int ctr; | ||
| 186 | }; | ||
| 187 | |||
| 188 | static struct np_flag np_flag; | ||
| 189 | |||
| 190 | int register_np_flag(struct np_flag* flag); | ||
| 191 | int signal_exit_np(void); | ||
| 192 | |||
| 193 | |||
| 194 | static inline void barrier(void) | ||
| 195 | { | ||
| 196 | __asm__ __volatile__("sfence": : :"memory"); | ||
| 197 | } | ||
| 198 | |||
| 199 | void enter_np(void) | ||
| 200 | { | ||
| 201 | if (++np_flag.ctr == 1) | ||
| 202 | { | ||
| 203 | np_flag.request = 0; | ||
| 204 | barrier(); | ||
| 205 | np_flag.preemptivity = RT_NON_PREEMPTIVE; | ||
| 206 | } | ||
| 207 | } | ||
| 208 | |||
| 209 | |||
| 210 | void exit_np(void) | ||
| 211 | { | ||
| 212 | if (--np_flag.ctr == 0) | ||
| 213 | { | ||
| 214 | np_flag.preemptivity = RT_PREEMPTIVE; | ||
| 215 | barrier(); | ||
| 216 | if (np_flag.request == RT_EXIT_NP_REQUESTED) | ||
| 217 | signal_exit_np(); | ||
| 218 | } | ||
| 219 | } | ||
| 220 | |||
| 221 | |||
| 222 | #define check(str) if (ret == -1) {perror(str); fprintf(stderr, \ | ||
| 223 | "Could not initialize LITMUS^RT, aborting...\n"); exit(1);} | ||
| 224 | |||
| 225 | void init_litmus(void) | ||
| 226 | { | ||
| 227 | int ret; | ||
| 228 | np_flag.preemptivity = RT_PREEMPTIVE; | ||
| 229 | np_flag.ctr = 0; | ||
| 230 | |||
| 231 | ret = mlockall(MCL_CURRENT | MCL_FUTURE); | ||
| 232 | check("mlockall"); | ||
| 233 | ret = register_np_flag(&np_flag); | ||
| 234 | check("register_np_flag"); | ||
| 235 | } | ||
| 236 | |||
| 237 | |||
| 238 | |||
| 239 | /* Litmus syscalls definitions */ | ||
| 240 | #define __NR_sched_setpolicy 320 | ||
| 241 | #define __NR_sched_getpolicy 321 | ||
| 242 | #define __NR_set_rt_mode 322 | ||
| 243 | #define __NR_set_rt_task_param 323 | ||
| 244 | #define __NR_get_rt_task_param 324 | ||
| 245 | #define __NR_prepare_rt_task 325 | ||
| 246 | #define __NR_reset_stat 326 | ||
| 247 | #define __NR_sleep_next_period 327 | ||
| 248 | #define __NR_scheduler_setup 328 | ||
| 249 | #define __NR_register_np_flag 329 | ||
| 250 | #define __NR_signal_exit_np 330 | ||
| 251 | #define __NR_pi_sema_init 331 | ||
| 252 | #define __NR_pi_down 332 | ||
| 253 | #define __NR_pi_up 333 | ||
| 254 | #define __NR_pi_sema_free 334 | ||
| 255 | #define __NR_sema_init 335 | ||
| 256 | #define __NR_down 336 | ||
| 257 | #define __NR_up 337 | ||
| 258 | #define __NR_sema_free 338 | ||
| 259 | #define __NR_srp_sema_init 339 | ||
| 260 | #define __NR_srp_down 340 | ||
| 261 | #define __NR_srp_up 341 | ||
| 262 | #define __NR_reg_task_srp_sem 342 | ||
| 263 | #define __NR_srp_sema_free 343 | ||
| 264 | #define __NR_get_job_no 344 | ||
| 265 | #define __NR_wait_for_job_release 345 | ||
| 266 | |||
| 267 | |||
| 268 | /* Syscall stub for setting RT mode and scheduling options */ | ||
| 269 | _syscall1(spolicy, sched_setpolicy, spolicy, arg1); | ||
| 270 | _syscall0(spolicy, sched_getpolicy); | ||
| 271 | _syscall1(int, set_rt_mode, int, arg1); | ||
| 272 | _syscall2(int, set_rt_task_param, pid_t, pid, rt_param_t*, arg1); | ||
| 273 | _syscall2(int, get_rt_task_param, pid_t, pid, rt_param_t*, arg1); | ||
| 274 | _syscall1(int, prepare_rt_task, pid_t, pid); | ||
| 275 | _syscall0(int, reset_stat); | ||
| 276 | _syscall0(int, sleep_next_period); | ||
| 277 | _syscall2(int, scheduler_setup, int, cmd, void*, param); | ||
| 278 | _syscall1(int, register_np_flag, struct np_flag*, flag); | ||
| 279 | _syscall0(int, signal_exit_np); | ||
| 280 | _syscall0(int, pi_sema_init); | ||
| 281 | _syscall1(int, pi_down, pi_sema_id, sem_id); | ||
| 282 | _syscall1(int, pi_up, pi_sema_id, sem_id); | ||
| 283 | _syscall1(int, pi_sema_free, pi_sema_id, sem_id); | ||
| 284 | _syscall0(int, sema_init); | ||
| 285 | _syscall1(int, down, sema_id, sem_id); | ||
| 286 | _syscall1(int, up, sema_id, sem_id); | ||
| 287 | _syscall1(int, sema_free, sema_id, sem_id); | ||
| 288 | _syscall0(int, srp_sema_init); | ||
| 289 | _syscall1(int, srp_down, srp_sema_id, sem_id); | ||
| 290 | _syscall1(int, srp_up, srp_sema_id, sem_id); | ||
| 291 | _syscall2(int, reg_task_srp_sem, srp_sema_id, sem_id, pid_t, t_pid); | ||
| 292 | _syscall1(int, srp_sema_free, srp_sema_id, sem_id); | ||
| 293 | _syscall1(int, get_job_no, unsigned int*, job_no); | ||
| 294 | _syscall1(int, wait_for_job_release, unsigned int, job_no); | ||
| 295 | |||
diff --git a/src/np_test.c b/src/np_test.c new file mode 100644 index 0000000..dad68aa --- /dev/null +++ b/src/np_test.c | |||
| @@ -0,0 +1,56 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include <stdlib.h> | ||
| 3 | #include <signal.h> | ||
| 4 | #include <unistd.h> | ||
| 5 | #include <sys/time.h> | ||
| 6 | #include <sys/wait.h> | ||
| 7 | #include <sys/types.h> | ||
| 8 | #include <sys/stat.h> | ||
| 9 | #include <fcntl.h> | ||
| 10 | |||
| 11 | #include "litmus.h" | ||
| 12 | |||
| 13 | #define US_PER_MS 1000 | ||
| 14 | |||
| 15 | #define NUMTASKS 4 | ||
| 16 | |||
| 17 | int prefix(void) | ||
| 18 | { | ||
| 19 | char field[1024]; | ||
| 20 | int prefix[1024]; | ||
| 21 | int i, sum = 0; | ||
| 22 | |||
| 23 | for (i = 0; i < 1024; i++) { | ||
| 24 | sum += field[i]; | ||
| 25 | prefix[i] = sum; | ||
| 26 | } | ||
| 27 | return sum; | ||
| 28 | } | ||
| 29 | |||
| 30 | |||
| 31 | void do_stuff(void) | ||
| 32 | { | ||
| 33 | int i =0, j =0; | ||
| 34 | |||
| 35 | for (; i < 50000; i++) | ||
| 36 | j += prefix(); | ||
| 37 | } | ||
| 38 | |||
| 39 | #define CALL(sc) do { ret = sc; if (ret == -1) {perror(" (!!) " #sc " failed: "); /*exit(1)*/;}} while (0); | ||
| 40 | |||
| 41 | |||
| 42 | int main(int argc, char** argv) | ||
| 43 | { | ||
| 44 | int ret; | ||
| 45 | |||
| 46 | init_litmus(); | ||
| 47 | |||
| 48 | enter_np(); | ||
| 49 | |||
| 50 | do_stuff(); | ||
| 51 | |||
| 52 | exit_np(); | ||
| 53 | |||
| 54 | |||
| 55 | return 0; | ||
| 56 | } | ||
diff --git a/src/rt_launch.c b/src/rt_launch.c new file mode 100644 index 0000000..31e6447 --- /dev/null +++ b/src/rt_launch.c | |||
| @@ -0,0 +1,83 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include <stdlib.h> | ||
| 3 | #include <unistd.h> | ||
| 4 | |||
| 5 | #include "litmus.h" | ||
| 6 | |||
| 7 | typedef struct { | ||
| 8 | char * exec_path; | ||
| 9 | char ** argv; | ||
| 10 | } startup_info_t; | ||
| 11 | |||
| 12 | |||
| 13 | int launch(void *task_info_p) { | ||
| 14 | startup_info_t *info = (startup_info_t*) task_info_p; | ||
| 15 | int ret; | ||
| 16 | ret = execv(info->exec_path, info->argv); | ||
| 17 | perror("execv failed"); | ||
| 18 | return ret; | ||
| 19 | } | ||
| 20 | |||
| 21 | void usage(char *error) { | ||
| 22 | fprintf(stderr, "%s\nUsage: launch_rt [-c {hrt|srt|be}] [-p <cpu>]" | ||
| 23 | "<wcet> <period> program arg1 arg2 ...\n", | ||
| 24 | error); | ||
| 25 | exit(1); | ||
| 26 | } | ||
| 27 | |||
| 28 | #define OPTSTR "p:c:" | ||
| 29 | |||
| 30 | int main(int argc, char** argv) | ||
| 31 | { | ||
| 32 | int ret; | ||
| 33 | int wcet; | ||
| 34 | int period; | ||
| 35 | int cpu = 0; | ||
| 36 | int opt; | ||
| 37 | startup_info_t info; | ||
| 38 | task_class_t class = RT_CLASS_HARD; | ||
| 39 | |||
| 40 | while ((opt = getopt(argc, argv, OPTSTR)) != -1) { | ||
| 41 | switch (opt) { | ||
| 42 | case 'p': | ||
| 43 | cpu = atoi(optarg); | ||
| 44 | break; | ||
| 45 | case 'c': | ||
| 46 | class = str2class(optarg); | ||
| 47 | if (class == -1) | ||
| 48 | usage("Unknown task class."); | ||
| 49 | break; | ||
| 50 | |||
| 51 | case ':': | ||
| 52 | usage("Argument missing."); | ||
| 53 | break; | ||
| 54 | case '?': | ||
| 55 | default: | ||
| 56 | usage("Unknown flag."); | ||
| 57 | break; | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 61 | if (argc - optind < 3) | ||
| 62 | { | ||
| 63 | printf("argc: %d optind: %d\n", argc, optind); | ||
| 64 | usage("Arguments missing."); | ||
| 65 | } | ||
| 66 | wcet = atoi(argv[optind + 0]); | ||
| 67 | period = atoi(argv[optind + 1]); | ||
| 68 | if (wcet <= 0) | ||
| 69 | usage("The worst-case execution time must be a positive number."); | ||
| 70 | if (period <= 0) | ||
| 71 | usage("The period must be a positive number."); | ||
| 72 | if (wcet > period) { | ||
| 73 | usage("The worst-case execution time must not exceed the period."); | ||
| 74 | } | ||
| 75 | info.exec_path = argv[optind + 2]; | ||
| 76 | info.argv = argv + optind + 2; | ||
| 77 | ret = __create_rt_task(launch, &info, cpu, wcet, period, class); | ||
| 78 | if (ret < 0) { | ||
| 79 | perror("Could not create rt child process"); | ||
| 80 | } | ||
| 81 | |||
| 82 | return 0; | ||
| 83 | } | ||
diff --git a/src/run.c b/src/run.c new file mode 100644 index 0000000..3719d6f --- /dev/null +++ b/src/run.c | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | |||
| 2 | |||
| 3 | int main(int argc, char** argv) | ||
| 4 | { | ||
| 5 | int i; | ||
| 6 | for (i = 0; i < 500000000; i++); | ||
| 7 | return 0; | ||
| 8 | } | ||
diff --git a/src/set_rt_mode.c b/src/set_rt_mode.c new file mode 100644 index 0000000..5936d7d --- /dev/null +++ b/src/set_rt_mode.c | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include <strings.h> | ||
| 3 | #include <stdlib.h> | ||
| 4 | #include "litmus.h" | ||
| 5 | |||
| 6 | |||
| 7 | int main(int argc, char** argv) | ||
| 8 | { | ||
| 9 | if (argc == 2) { | ||
| 10 | if (!strcmp(argv[1], "on")) { | ||
| 11 | printf("Enabling real-time mode.\n"); | ||
| 12 | set_rt_mode(MODE_RT_RUN); | ||
| 13 | exit(0); | ||
| 14 | } else if (!strcmp(argv[1], "off")) { | ||
| 15 | printf("Disabling real-time mode.\n"); | ||
| 16 | set_rt_mode(MODE_NON_RT); | ||
| 17 | exit(0); | ||
| 18 | } | ||
| 19 | } | ||
| 20 | printf("Usage: %s {on|off}\n", argv[0]); | ||
| 21 | return 1; | ||
| 22 | } | ||
diff --git a/src/show_scheduler.c b/src/show_scheduler.c new file mode 100644 index 0000000..7026e2a --- /dev/null +++ b/src/show_scheduler.c | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | #include <sys/types.h> | ||
| 2 | #include <stdio.h> | ||
| 3 | |||
| 4 | #include "litmus.h" | ||
| 5 | |||
| 6 | int main(int argc, char** argv) { | ||
| 7 | spolicy scheduler = sched_getpolicy(); | ||
| 8 | printf("%s\n", get_scheduler_name(scheduler)); | ||
| 9 | return 0; | ||
| 10 | } | ||
diff --git a/src/timeout.c b/src/timeout.c new file mode 100644 index 0000000..ba513f9 --- /dev/null +++ b/src/timeout.c | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include <stdlib.h> | ||
| 3 | #include <unistd.h> | ||
| 4 | |||
| 5 | #include "litmus.h" | ||
| 6 | |||
| 7 | int main(int argc, char** argv) | ||
| 8 | { | ||
| 9 | int timeout; | ||
| 10 | rt_param_t my_param; | ||
| 11 | |||
| 12 | if (argc != 2) | ||
| 13 | { | ||
| 14 | printf("Usage: %s <timeout in seconds>\n", argv[0]); | ||
| 15 | exit(1); | ||
| 16 | } | ||
| 17 | timeout = atoi(argv[1]); | ||
| 18 | if (timeout <= 0) { | ||
| 19 | printf("Timeout must be a positive number.\n"); | ||
| 20 | exit(1); | ||
| 21 | } | ||
| 22 | |||
| 23 | /* printf("This is the kill real-time mode task.\n" | ||
| 24 | "Expected end of real %u seconds.\n", timeout); | ||
| 25 | */ | ||
| 26 | /* get_rt_task_param(getpid(), &my_param); | ||
| 27 | show_rt_param(&my_param); | ||
| 28 | */ | ||
| 29 | |||
| 30 | sleep(timeout); | ||
| 31 | |||
| 32 | |||
| 33 | set_rt_mode(MODE_NON_RT); | ||
| 34 | printf("End of real-time mode.\n"); | ||
| 35 | return 0; | ||
| 36 | } | ||
diff --git a/src/wait_test.c b/src/wait_test.c new file mode 100644 index 0000000..efd4d90 --- /dev/null +++ b/src/wait_test.c | |||
| @@ -0,0 +1,103 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include <stdlib.h> | ||
| 3 | #include <signal.h> | ||
| 4 | #include <unistd.h> | ||
| 5 | #include <sys/time.h> | ||
| 6 | #include <sys/wait.h> | ||
| 7 | #include <sys/types.h> | ||
| 8 | #include <sys/stat.h> | ||
| 9 | #include <fcntl.h> | ||
| 10 | |||
| 11 | #include "litmus.h" | ||
| 12 | |||
| 13 | #define US_PER_MS 1000 | ||
| 14 | |||
| 15 | #define NUMTASKS 4 | ||
| 16 | |||
| 17 | int prefix(void) | ||
| 18 | { | ||
| 19 | char field[1024]; | ||
| 20 | int prefix[1024]; | ||
| 21 | int i, sum = 0; | ||
| 22 | |||
| 23 | for (i = 0; i < 1024; i++) { | ||
| 24 | sum += field[i]; | ||
| 25 | prefix[i] = sum; | ||
| 26 | } | ||
| 27 | return sum; | ||
| 28 | } | ||
| 29 | |||
| 30 | |||
| 31 | void do_stuff(void) | ||
| 32 | { | ||
| 33 | int i =0, j =0; | ||
| 34 | |||
| 35 | for (; i < 50000; i++) | ||
| 36 | j += prefix(); | ||
| 37 | } | ||
| 38 | |||
| 39 | #define CALL(sc) do { ret = sc; if (ret == -1) {perror(" (!!) " #sc " failed: "); /*exit(1)*/;}} while (0); | ||
| 40 | |||
| 41 | unsigned int job_no; | ||
| 42 | |||
| 43 | |||
| 44 | void next(void) | ||
| 45 | { | ||
| 46 | int ret; | ||
| 47 | unsigned int actual; | ||
| 48 | CALL(get_job_no(&actual)); | ||
| 49 | CALL(wait_for_job_release(++job_no)); | ||
| 50 | printf("Now executing job %u, waited for %u\n", actual, job_no); | ||
| 51 | } | ||
| 52 | |||
| 53 | void sync_jobs(void) | ||
| 54 | { | ||
| 55 | int ret; | ||
| 56 | unsigned int actual; | ||
| 57 | CALL(get_job_no(&actual)); | ||
| 58 | job_no = actual; | ||
| 59 | } | ||
| 60 | |||
| 61 | |||
| 62 | int main(int argc, char** argv) | ||
| 63 | { | ||
| 64 | int ret; | ||
| 65 | |||
| 66 | init_litmus(); | ||
| 67 | |||
| 68 | CALL(getpid()); | ||
| 69 | printf("my pid is %d\n", ret); | ||
| 70 | |||
| 71 | |||
| 72 | CALL(get_job_no(&job_no)); | ||
| 73 | printf("my job_no is %u", job_no); | ||
| 74 | |||
| 75 | next(); | ||
| 76 | next(); | ||
| 77 | next(); | ||
| 78 | |||
| 79 | /* now overrun a job for good */ | ||
| 80 | do_stuff(); | ||
| 81 | do_stuff(); | ||
| 82 | do_stuff(); | ||
| 83 | do_stuff(); | ||
| 84 | do_stuff(); | ||
| 85 | do_stuff(); | ||
| 86 | do_stuff(); | ||
| 87 | do_stuff(); | ||
| 88 | do_stuff(); | ||
| 89 | do_stuff(); | ||
| 90 | |||
| 91 | |||
| 92 | next(); | ||
| 93 | next(); | ||
| 94 | next(); | ||
| 95 | next(); | ||
| 96 | sync_jobs(); | ||
| 97 | next(); | ||
| 98 | next(); | ||
| 99 | next(); | ||
| 100 | |||
| 101 | |||
| 102 | return 0; | ||
| 103 | } | ||
