[Date Prev][Date Next]
[Chronological]
[Thread]
[Top]
Re: [rtl] Release 9F Problems...
On Thu, Oct 01, 1998 at 05:13:02PM -0400, Donald Gaffney wrote:
>
> Hello RTLers,
>
> I've been playing around with release 2.0.35-9F a little bit and my
> feeling is that it is not quite as stable as 2.0.33-0.6 that I did
Could you try your tests with the two attached files replacing
rtl/include/rtl_sched.h and rtl/schedulrs/rtl_sched.c?
Appreciate it.
/* a primitive real-time scheduler
copyright Victor Yodaiken, Michael Barabanov
History: Barabanov
modified Oleg Subbotin, Ramesh Nalluri, April 1998
modified Victor Yodaiken, August 1998
Added compatability macros
changed search loop
replaced old style r_cli with rtl_no_interrupt
removed x86 code
*/
/* This is the interrupt latency + scheduler latency,
The user needs to determine this and hardcode it accordingly */
#define ADJUSTUP 23 /*if time to run is no more than this time ahead, run*/
#define ADJUSTDOWN 10 /*set timer to interrupt this time less than requested*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/errno.h>
#include <linux/malloc.h>
#include <linux/cons.h>
#include <asm/system.h>
#include <linux/timex.h>
#include <asm/rt_time.h>
#include <asm/rt_irq.h>
#include <rtl_sync.h>
static int linux_irq_state;
static int rtl_active = 0;
#define rtl_make_unrtactive() { SFIF = linux_irq_state; rtl_active=0;}
#define rtl_make_rtactive() {linux_irq_state = SFIF; SFIF = 0; rtl_active=1;}
#define rtl_is_rtactive() (rtl_active)
#include <linux/kernel.h>
#include <rtl_sched.h>
#ifndef RTL_FPU
#define rtl_fpu_switch(a,b) ;
#define rtl_fpu_task_init(a,b) { printk("RTL error: tried to get the \
non fp scheduling module to \
create a fp real time task!\n");\
kfree(st); return -ENOMEM;}
#define rtl_fpu_init() ;
#define rtl_fpu_task_delete(x) ;
#else
static void rtl_fpu_task_init(RT_TASK *, RT_TASK *);
static void rtl_fpu_switch(RT_TASK *, RT_TASK *);
static void rtl_fpu_init(void);
static void rtl_fpu_task_delete(RT_TASK *);
#endif
#ifdef RTL_DEBUG
void debug_resched(RT_TASK * ,RTIME );
#endif
#include <asm/segment.h>
#include "x86/switch.h"
RT_TASK *rt_tasks;
RT_TASK *rtl_current;
RT_TASK rtl_linux_task;
#define rtl_is_linux_task(a) (a == &rtl_linux_task)
int rt_startup(void (*fn)(int), int data)
{
r_sti();
(*fn)(data);
rt_task_delete(rtl_current);
/* should never reach this line */
return 0;
}
int rtl_task_init(RT_TASK *task, void (*fn)(int), int data, int stack_size,
int priority,int fp)
{
int *st;
long interrupt_state;
if (task->magic == RT_TASK_MAGIC) {
return -EINVAL;
}
st = (int *) kmalloc(stack_size, GFP_KERNEL);
if (!st) {
return -ENOMEM;
}
task->priority = priority;
task->magic = RT_TASK_MAGIC;
task->state = RT_TASK_DORMANT;
task->stack_bottom = st;
task->stack = st + stack_size / sizeof(int);
if(fp){
rtl_fpu_task_init(task,rtl_current);
}
else task->uses_fp = 0;
x86_init_stack(task,data,rt_startup);
rtl_no_interrupts(interrupt_state);
task->next = rt_tasks;
rt_tasks = task;
rtl_restore_interrupts(interrupt_state);
return 0;
}
void rt_schedule(void)
{
RTIME now;
RT_TASK *t;
RT_TASK *newt = 0; /* new task to run, if any */
RT_TASK *nextt = 0; /* task that will preempt, if any */
unsigned long interrupt_state;
rtl_no_interrupts(interrupt_state);
now = rt_get_time();
/* find a task that can be run */
for (t = rt_tasks; t; t = t->next) {
if( (t->state == RT_TASK_DELAYED)&&
( t->resume_time < now + ADJUSTUP)){
t->state = RT_TASK_READY;
}
if(t->state == RT_TASK_READY)
if (!newt || (t->priority < newt->priority)) {
newt = t;
}
}
/* find the pre-empting task */
for (t = rt_tasks; t; t = t->next) {
if( (t->state == RT_TASK_DELAYED) &&
(!newt || (t->priority < newt->priority)) &&
(!nextt ||(t->resume_time < nextt->resume_time))
)
nextt = t;
}
/* DEBUG */
{
static int nolinux = 0;
if(newt) nolinux++;
else nolinux = 0;
if(nolinux > 100000){
conpr("HELP NO LINUX EVER!!!");
nolinux = 0;
newt->resume_time = now+100000;
}
}
/* END DEUBG */
/* if nextt there is a preemptor so set timer to preempt
if !nextt
if there is a rt task, turn off the timer
if there is no rt task, linux needs a clock interrupt
*/
if (nextt) {
rt_set_timer(nextt->resume_time - ADJUSTDOWN );
} else{
if(newt) { rt_no_timer(); }
else { rt_set_timer(now+LATCH);}
}
/* if there is no rt task to run, then run linux */
if(!newt){
newt = &rtl_linux_task;
rtl_make_unrtactive();
}
else {
rtl_make_rtactive();
}
/* if the new task is the current task nothing to do */
if ( newt == rtl_current) {
rtl_restore_interrupts(interrupt_state);
return;
}
else{ /* switch out old, switch in new */
if (newt->uses_fp)rtl_fpu_switch(newt,rtl_current);
rt_switch_to(newt);
rtl_restore_interrupts(interrupt_state);
}
}
int rt_task_delete(RT_TASK *task)
{
RT_TASK *t;
int found = 0, count = 0;
long interrupt_state;
rtl_no_interrupts(interrupt_state);
if (task->magic != RT_TASK_MAGIC) {
rtl_restore_interrupts(interrupt_state);
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) {
rtl_restore_interrupts(interrupt_state);
return -EINVAL;
}
} else {
conpr("RTL Delete first task\n");
rt_tasks = task->next;
}
task->state = RTL_TASK_ZOMBIE;
/*
*If the current task is the task that is being freed, dont free it
* but wait for the scheduler to run and switch it for you
*/
if ( rtl_current == task ){
rt_set_timer(rt_get_time());
rtl_restore_interrupts(interrupt_state);
/*
* wait for the scheduler to switch the current task and then free
*/
while (rtl_current == task){
if (count++ >= 1000000) {
conpr("RT_SCHED:PANIC: The task with priority ");
conprn(task->priority);
conpr(" has not been switched yet\n");
return -EINVAL;
}
}
}
/*
* Now happily free it
*/
rtl_fpu_task_delete(task);
if(!rtl_is_rtactive())
kfree(task->stack_bottom);
else conpr("RTL Delete while active!");
rtl_restore_interrupts(interrupt_state);
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 interrupt_state;
rtl_no_interrupts(interrupt_state);
rtl_current->state = RT_TASK_DELAYED;
rtl_current->resume_time += rtl_current->period;
rt_schedule();
rtl_no_interrupts(interrupt_state);
return 0;
}
int rt_task_make_periodic(RT_TASK *task, RTIME start_time, RTIME period)
{
long interrupt_state;
if (task->magic != RT_TASK_MAGIC) {
return -EINVAL;
}
rtl_no_interrupts(interrupt_state);
task->resume_time = start_time;
task->period = period;
task->state = RT_TASK_DELAYED;
rt_set_timer(rt_get_time());
rtl_restore_interrupts(interrupt_state);
return 0;
}
int init_module(void)
{
long interrupt_state;
rtl_no_interrupts(interrupt_state);
rt_no_timer();
rt_tasks = 0;
rtl_current = &rtl_linux_task;
rtl_linux_task.priority = RT_LOWEST_PRIORITY;
rtl_linux_task.next = 0;
rtl_linux_task.state = RT_TASK_READY;
rtl_fpu_init();
rt_request_timer(&rt_schedule);
rtl_restore_interrupts(interrupt_state);
return 0;
}
void cleanup_module(void)
{
RT_TASK *t;
RT_TASK *next_t;
rt_free_timer();
for (t = rt_tasks; t; t = next_t) {
next_t = t->next;
if (t != &rtl_linux_task) {
rt_task_delete(t);
}
}
}
#ifndef __RT__SCHED__
#define __RT__SCHED__
#include <asm/rt_time.h>
#define RT_TASK_MAGIC 0x754d2774
#define RT_LOWEST_PRIORITY 1000000
#ifndef RTL_FPU
#define RTL_FPU_STRUCT
#endif
enum {RT_TASK_READY, RT_TASK_DELAYED, RT_TASK_DORMANT,RT_TASK_ACTIVE,RTL_TASK_ZOMBIE};
struct rt_task_struct {
int *stack; /* hardcoded */
int uses_fp; /* this one is too */
int magic;
int state;
int *stack_bottom;
int priority;
RTIME period;
RTIME resume_time;
struct rt_task_struct *next;
RTL_FPU_STRUCT /*if RTL_FPU is not defined this is null */
};
typedef struct rt_task_struct RT_TASK;
extern RT_TASK *rt_current;
#define rt_task_init(a,b,c,d,e) rtl_task_init(a,b,c,d,e,0)
#define rt_fptask_init(a,b,c,d,e) rtl_task_init(a,b,c,d,e,1)
extern int rtl_task_init(RT_TASK *task, void (*fn)(int data), int data, int stack_size, int priority, int use_fpu);
extern int rt_task_delete(RT_TASK *task);
extern int rt_task_wait(void);
extern int rt_task_suspend(RT_TASK *task);
extern int rt_task_wakeup(RT_TASK *task);
extern int rt_task_make_periodic(RT_TASK *task, RTIME start_time, RTIME period);
extern inline void rt_use_fp(int flag)
{
rt_current->uses_fp = flag;
}
#endif