📄 rt_monotonic_sched.c
字号:
/* A simple rate-monotonic scheduler */#ifndef MODULE# define MODULE#endif#include <linux/module.h>#include <linux/kernel.h>#include <linux/version.h>#include <linux/errno.h>#include <linux/malloc.h>#include <linux/kernel.h>#include <linux/cons.h>#ifdef MODVERSIONS# include <linux/modversions.h>#endif#include <asm/system.h>#include <asm/rt_time.h>#include <asm/rt_irq.h>#include <asm/segment.h>#include "rt_sched.h"#include <linux/rtf.h>#ifdef DEBUG/* Process's state ( for debug purposes only ) */ #include "control.h"RTIME init_time = 0;#endif#define __STR(x) #x#define STR(x) __STR(x)#define PRINTAX \ "pushl %%eax\n\t" \ "pushl %%ebp\n\t" \ "pushl %%edi\n\t" \ "pushl %%esi\n\t" \ "pushl %%edx\n\t" \ "pushl %%ecx\n\t" \ "pushl %%ebx\n\t" \ "pushl %%eax\n\t" \ "call "SYMBOL_NAME_STR(conprn)"\n\t" \ "add $4, %%esp\n\t" \ "popl %%ebx\n\t \ popl %%ecx\n\t \ popl %%edx\n\t \ popl %%esi\n\t \ popl %%edi\n\t \ popl %%ebp\n\t \ popl %%eax\n\t"#define rt_switch_to(tsk) \ __asm__ __volatile__( \ "pushl %%eax\n\t" \ "pushl %%ebp\n\t" \ "pushl %%edi\n\t" \ "pushl %%esi\n\t" \ "pushl %%edx\n\t" \ "pushl %%ecx\n\t" \ "pushl %%ebx\n\t" \ "movl "SYMBOL_NAME_STR(rt_current)", %%edx\n\t" \ "cmpl $0, 4(%%edx)\n\t" \ "jz 25f\n\t" \ "sub $108,%%esp\n\t" \ "fsave (%%esp)\n\t" \"25: pushl $1f\n\t" \ "movl %%esp, (%%edx)\n\t" \ "movl (%%ecx), %%esp\n\t" \ "movl %%ecx, "SYMBOL_NAME_STR(rt_current)"\n\t" \ "ret\n\t" \"1: cmpl $0, 4(%%ecx)\n\t" \ "jz 26f\n\t" \ "frstor (%%esp)\n\t" \ "add $108,%%esp \n\t" \"26: popl %%ebx\n\t" \ "popl %%ecx\n\t" \ "popl %%edx\n\t" \ "popl %%esi\n\t" \ "popl %%edi\n\t" \ "popl %%ebp\n\t" \ "popl %%eax\n\t" \ : /* no output */ \ : "c" (tsk) \ :"cx");/* RT_TASK *run_queue; */RT_TASK *rt_tasks;RT_TASK *rt_current;RT_TASK rt_linux_task;static int linux_irq_state;extern int rt_startup(void);__asm__(".align 4; .globl "SYMBOL_NAME_STR(rt_startup)"\n\t" SYMBOL_NAME_STR(rt_startup)": iret");int rt_task_init(RT_TASK *task, void (*fn)(int), int data, int stack_size, int id) /* Monotonic */ { int *st; long flags; if (task->magic == RT_TASK_MAGIC) { return -EINVAL; } st = (int *) kmalloc(stack_size, GFP_KERNEL); if (!st) { return -ENOMEM; } /* task->priority = priority; Don't use in monotonic scheduler */ task->magic = RT_TASK_MAGIC; task->state = RT_TASK_DORMANT; task->stack_bottom = st; task->stack = st + stack_size / sizeof(int); task->uses_fp = 0; task->identifier = id; /* Monotonic */ *--(task->stack) = data; *--(task->stack) = data; *--(task->stack) = 0x200; /* execute with interrupts enabled */ *--(task->stack) = KERNEL_CS; *--(task->stack) = (int) fn; *--(task->stack) = (int) rt_startup; r_save_flags(flags); r_cli(); task->next = rt_tasks; rt_tasks = task; r_restore_flags(flags); return 0;}void rt_schedule(void){ RTIME now; RTIME preemption_time; RT_TASK *task; RT_TASK *new_task; RT_TASK *preemptor; RTIME shortest_period; int flags; r_save_flags(flags); r_cli();#ifdef DEBUG now = rt_get_time(); if (rt_current->identifier != -1) { debug.state = EXEC; debug.id = rt_current->identifier; debug.in = init_time; debug.out = now; rtf_put(DEBUG_FIFO, (char *) &debug, sizeof(debug)); }#endif for (task = rt_tasks; task; task = task->next) { if ( task->state == RT_TASK_DELAYED && task->resume_time < (now+10) ) { task->state = RT_TASK_READY; } } new_task = &rt_linux_task; /* begin rate-monotonic scheduling */ shortest_period = rt_linux_task.period; for (task = rt_tasks; task; task = task->next) { if (task->state == RT_TASK_READY && task->period < shortest_period) { new_task = task; shortest_period = task->period; } } preemptor = 0; preemption_time = RT_TIME_END; for (task = rt_tasks; task; task = task->next) { if (task->state == RT_TASK_DELAYED && task->resume_time < preemption_time) { preemption_time = task->resume_time; preemptor = task; } }/* End of rate-monotonic scheduler */ if (preemptor) { rt_set_timer(preemption_time); } else { rt_no_timer(); } if (new_task == rt_current) { r_restore_flags(flags); return; } if (new_task == &rt_linux_task) { SFIF = linux_irq_state; } else if (rt_current == &rt_linux_task) { linux_irq_state = SFIF; SFIF = 0; }#ifdef DEBUG if (new_task->identifier != -1) { /* Monotonic scheduler */ init_time = now; }#endif new_task->state = RT_TASK_READY; rt_switch_to(new_task); r_restore_flags(flags);}#ifdef DEBUGstatic void rt_print_request(RT_TASK *task){ debug.state = SUSP; debug.id = task->identifier; debug.in = task->resume_time; debug.out = task->resume_time+task->period; rtf_put(DEBUG_FIFO, (char *) &debug, sizeof(debug)); } #endifint rt_task_delete(RT_TASK *task) { RT_TASK *t; int found = 0; long flags; r_save_flags(flags); r_cli(); if (task->magic != RT_TASK_MAGIC) { r_restore_flags(flags); return -EINVAL; } if (task != rt_tasks) { for (t = rt_tasks; t; t = t->next) { if (t->next == task) { t->next = task->next; found = 1; break; } } if (!found) { r_restore_flags(flags); return -EINVAL; } } else rt_tasks = task->next; task->magic = 0; r_restore_flags(flags); kfree(task->stack_bottom); rt_schedule(); return 0;}int rt_task_suspend(RT_TASK *task){ task->state = RT_TASK_DORMANT; rt_schedule(); return 0;}int rt_task_wakeup(RT_TASK *task){ task->state = RT_TASK_READY; rt_schedule(); return 0;}int rt_task_wait(void){ long flags; r_save_flags(flags); r_cli(); rt_current->state = RT_TASK_DELAYED; rt_current->resume_time += rt_current->period;#ifdef DEBUG rt_print_request(rt_current);#endif rt_schedule(); r_restore_flags(flags); return 0;}/* Rate-monotonic scheduler ( set priority ) */int rt_task_make_periodic(RT_TASK *task, RTIME start_time, RTIME period){ long flags; if (task->magic != RT_TASK_MAGIC) return -EINVAL; r_save_flags(flags); r_cli(); task->resume_time = start_time; task->period = period; task->state = RT_TASK_DELAYED;#ifdef DEBUG rt_print_request(task);#endif r_restore_flags(flags); rt_schedule(); return 0;}int init_module(void){#ifdef DEBUG rtf_create(DEBUG_FIFO, 4000);#endif rt_tasks = &rt_linux_task; rt_current = &rt_linux_task; rt_linux_task.priority = RT_LOWEST_PRIORITY; rt_linux_task.period = RT_BIGGEST_PERIOD; rt_linux_task.next = 0; rt_linux_task.identifier = -1; /* Monotonic */ rt_linux_task.state = RT_TASK_READY; rt_request_timer(&rt_schedule); return 0;}void cleanup_module(void){ RT_TASK *t; RT_TASK *next_t;#ifdef DEBUG rtf_destroy(DEBUG_FIFO);#endif rt_free_timer(); for (t = rt_tasks; t; t = next_t) { next_t = t->next; if (t != &rt_linux_task) { rt_task_delete(t); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -