--- rtlinux-3.2-pre1/doc/Configure.help 2003-03-01 12:46:36.000000000 +0100 +++ rtlinux-3.2-pre1-edf/doc/Configure.help 2003-04-01 17:24:38.000000000 +0200 @@ -89,3 +89,29 @@ to dramatically reduce scheduling jitter. You need a 2.4.X kernel with CONFIG_SMP enabled for this option to work. +EDF Scheduler +CONFIG_RTL_EDF + Say Y if you want to use the Earliest Deadline First scheduling + (EDF) policy. Tasks with closer deadline are scheduled first. + The EDF policy is only applied among tasks of the same + priority. Therefore, it is possible to jointly use fixed and + dynamic priorities. + + This is an extension to the POSIX API. Therefore, you have to + disable "RTLinux V1 API Suport". + + If you say Y here you may also need "SRP Mutex Priority Inversion" + It is safe to say yes. + +SRP Mutex Control +CONFIG_RTL_SRP + Say Y if you want to use the Stack Resource Protocol (SRP) to + control the priority inversion of the mutex. The SRP is an + improvement over the "POSIX priority ceiling protocol" to allow + dynamic priorities. + + This is an extension to the POSIX API. Therefore, you have to + disable "RTLinux V1 API Suport". + + If you use EDF scheduling and mutex, then you have to say Y here. + It is safe to say yes. diff -NruBb rtlinux-3.2-pre1/include/rtl_mutex.h rtlinux-3.2-pre1-edf/include/rtl_mutex.h --- rtlinux-3.2-pre1/include/rtl_mutex.h 2003-03-01 12:46:37.000000000 +0100 +++ rtlinux-3.2-pre1-edf/include/rtl_mutex.h 2003-04-01 17:24:38.000000000 +0200 @@ -5,6 +5,8 @@ * Copyright (C) Finite State Machine Labs Inc., 1999 * Released under the terms of the GPL Version 2 * + * Ismael Ripoll & Patricia Balbastre: + * Stack Resource Policy implementation (2001-07-20) */ #ifndef __RTL_MUTEX__ @@ -24,6 +26,9 @@ int pshared; int protocol; int prioceiling; +#ifdef CONFIG_RTL_SRP + struct rtl_sched_param preemptceiling; +#endif } pthread_mutexattr_t; #define PTHREAD_PROCESS_PRIVATE 0 @@ -61,13 +66,15 @@ int protocol; int prioceiling; int oldprio; +#ifdef CONFIG_RTL_SRP + struct rtl_sched_param preemptceiling; +#endif } pthread_mutex_t; #define PTHREAD_MUTEX_INITIALIZER { 0,0,1, SPIN_LOCK_UNLOCKED, PTHREAD_MUTEX_DEFAULT, RTL_WAIT_INITIALIZER, PTHREAD_PRIO_NONE } -enum {PTHREAD_PRIO_NONE, PTHREAD_PRIO_PROTECT}; - +enum {PTHREAD_PRIO_NONE, PTHREAD_PRIO_PROTECT, PTHREAD_PRIO_SRP}; static inline int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) { @@ -132,10 +139,11 @@ static inline int pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr, int protocol) { -#ifndef _RTL_POSIX_THREAD_PRIO_PROTECT +#if ! (defined(_RTL_POSIX_THREAD_PRIO_PROTECT) || defined(CONFIG_RTL_SRP)) return ENOTSUP; #endif - if (protocol != PTHREAD_PRIO_PROTECT && protocol != PTHREAD_PRIO_NONE) { + if (protocol != PTHREAD_PRIO_PROTECT && protocol != PTHREAD_PRIO_NONE && + protocol != PTHREAD_PRIO_SRP) { return ENOTSUP; } attr->protocol = protocol; @@ -225,6 +233,65 @@ extern int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime); -#endif + +/* + * Stack Resource Protocol constants and functions + */ + +#ifdef CONFIG_RTL_SRP + + +typedef struct { + struct rtl_sched_param preempt_level; + pthread_t owner; +} srp_stack_t; + +static inline int cmp_preempt_level(struct rtl_sched_param *A, struct rtl_sched_param *B) +{ + register int tmp; + hrtime_t diff; + if (!B) + return 1; + if ( (tmp = (A->sched_priority - B->sched_priority)) ) + return tmp; + diff = B->sched_deadline - A->sched_deadline; + return (diff>0 ? 1: (diff==0? 0: -1)); +} + +extern pthread_t srp_ceiling_owner(void); + +extern struct rtl_sched_param *srp_current_sysceil(void); + + +/* External API functions */ + +static inline int pthread_mutexattr_setpreemptceiling_np(pthread_mutexattr_t *attr, struct rtl_sched_param *preemptceiling) +{ + attr->preemptceiling = *preemptceiling; + return 0; +} + + +static inline int pthread_mutexattr_getpreemptceiling_np(const pthread_mutexattr_t *attr, struct rtl_sched_param *preemptceiling) +{ + *preemptceiling = attr->preemptceiling; + return 0; +} + +static inline int pthread_mutex_getpreemptceiling_np(const pthread_mutex_t *mutex, struct rtl_sched_param *old_ceiling) +{ + *old_ceiling = mutex->preemptceiling; + return 0; +} + +extern int pthread_mutex_setpreemptceiling_np(pthread_mutex_t *mutex, + struct rtl_sched_param *preemptceiling, + struct rtl_sched_param *oldpreemptceiling ); + +extern int pthread_mutex_register_np(pthread_t thread, pthread_mutex_t *mutex); + +#endif /* CONFIG_RTL_SRP */ + +#endif /* __KERNEL __*/ #endif diff -NruBb rtlinux-3.2-pre1/include/rtl_sched.h rtlinux-3.2-pre1-edf/include/rtl_sched.h --- rtlinux-3.2-pre1/include/rtl_sched.h 2003-03-01 12:46:37.000000000 +0100 +++ rtlinux-3.2-pre1-edf/include/rtl_sched.h 2003-04-01 17:24:38.000000000 +0200 @@ -5,6 +5,8 @@ * Copyright (C) Finite State Machine Labs Inc., 1998-1999 * Released under the terms of the GPL Version 2 * + * Ismael Ripoll & Patricia Balbastre: + * Small modificacions to include EDF scheduling and SRP mutex control. */ #ifndef __RTL__SCHED__ @@ -28,6 +30,29 @@ #include #include +/* #define CONFIG_RTL_EDF_DEBUG y */ + + +#ifdef CONFIG_RTL_EDF_DEBUG +#include + +#define EXEC 11 +#define ACTIV 22 +#define LOCKM 33 +#define UNLKM 44 +struct events_stuct{ + int type; + int id; + hrtime_t in,out; +}; +#endif + + + +#ifdef CONFIG_RTL_EDF +#define SCHED_EDF_NP 3 +#endif + #ifdef __cplusplus struct sched_param { int sched_priority; @@ -39,8 +64,23 @@ #include #endif + + +#ifdef CONFIG_RTL_EDF + +struct rtl_sched_param { + int sched_priority; + hrtime_t sched_deadline; +}; +#define RTL_DEADLINE(th) ((th)->sched_param.sched_deadline) + +#else + #define rtl_sched_param sched_param +#endif + + #define TIMER_ABSTIME 1 #define RTL_MAX_TIMERS 32 @@ -85,6 +125,10 @@ void *user[4]; int errno_val; struct rtl_cleanup_struct *cleanup; +#ifdef CONFIG_RTL_EDF + hrtime_t current_deadline; + int policy; +#endif int magic; struct rtl_posix_thread_struct posix_data; void *tsd [RTL_PTHREAD_KEYS_MAX]; @@ -238,6 +282,9 @@ int use_fp; rtl_sigset_t initial_state; int detachstate; +#ifdef CONFIG_RTL_EDF + int policy; +#endif } pthread_attr_t; extern inline int pthread_attr_init(pthread_attr_t *attr) @@ -245,6 +292,10 @@ attr->stack_addr = 0; attr->stack_size = 20480; attr->sched_param.sched_priority = sched_get_priority_min(0); +#ifdef CONFIG_RTL_EDF + attr->sched_param.sched_deadline = HRTIME_INFINITY; + attr->policy = SCHED_FIFO; +#endif attr->cpu = rtl_getcpuid(); rtl_sigemptyset(&attr->initial_state); rtl_sigaddset(&attr->initial_state, RTL_SIGNAL_READY); @@ -295,6 +346,37 @@ #define pthread_attr_getcpu(attr,cpu) pthread_attr_getcpu_np(attr,cpu) #define pthread_attr_setcpu(attr,cpu) pthread_attr_setcpu_np(attr,cpu) + +#ifdef CONFIG_RTL_EDF +extern inline int pthread_attr_setdeadline_np(pthread_attr_t *attr, hrtime_t deadline) +{ + attr->sched_param.sched_deadline = deadline; + return 0; +} + +extern inline int pthread_attr_getdeadline_np(const pthread_attr_t *attr, hrtime_t *deadline) +{ + *deadline = attr->sched_param.sched_deadline; + return 0; +} + + +extern inline int pthread_setdeadline_np(pthread_t thread, + hrtime_t deadline) { + thread->sched_param.sched_deadline = deadline; + return 0; +} + + +extern inline int pthread_getdeadline_np(pthread_t thread, + hrtime_t *deadline) { + *deadline = thread->sched_param.sched_deadline; + return 0; +} + +#endif /* CONFIG_RTL_EDF */ + + extern int pthread_wait_np(void); extern int pthread_make_periodic_np (pthread_t p, hrtime_t start_time, hrtime_t period); @@ -316,29 +398,46 @@ extern inline int pthread_setschedparam(pthread_t thread, int policy, - const struct rtl_sched_param *param) { - thread->sched_param = *param; + const struct sched_param *param) { + thread->sched_param.sched_priority = param->sched_priority; return 0; } extern inline int pthread_getschedparam(pthread_t thread, int *policy, - struct rtl_sched_param *param) { - *param = thread->sched_param; + struct sched_param *param) { + param->sched_priority = thread->sched_param.sched_priority; +#ifdef CONFIG_RTL_EDF + *policy = thread->policy; +#endif return 0; } extern inline int pthread_attr_setschedparam(pthread_attr_t *attr, - const struct rtl_sched_param *param) { - attr->sched_param = *param; + const struct sched_param *param) { + attr->sched_param.sched_priority = param->sched_priority; return 0; } extern inline int pthread_attr_getschedparam(const pthread_attr_t *attr, - struct rtl_sched_param *param) { - *param = attr->sched_param; + struct sched_param *param) { + param->sched_priority = attr->sched_param.sched_priority; return 0; } +#ifdef CONFIG_RTL_EDF +extern inline int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) +{ + attr->policy = policy; + return 0; +} + +extern inline int pthread_attr_getschedpolicy(pthread_attr_t *attr, int *policy) +{ + *policy = attr->policy; + return 0; +} +#endif + extern int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr); extern int pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr); diff -NruBb rtlinux-3.2-pre1/schedulers/rtl_mutex.c rtlinux-3.2-pre1-edf/schedulers/rtl_mutex.c --- rtlinux-3.2-pre1/schedulers/rtl_mutex.c 2003-03-01 12:46:38.000000000 +0100 +++ rtlinux-3.2-pre1-edf/schedulers/rtl_mutex.c 2003-04-01 17:24:38.000000000 +0200 @@ -6,6 +6,8 @@ * Copyright (C) Finite State Machine Labs Inc., 1999,2000 * Released under the terms of the GPL Version 2 * + * Ismael Ripoll & Patrcia Balbastre: + * SRP (Stack Resource Policy implementation, 2001-07-20) */ #include @@ -15,6 +17,84 @@ #include + +#ifdef CONFIG_RTL_SRP + + +/* + * ------- Stack Resource Protocol utility functions -------- + */ + +static srp_stack_t srp_ceil_stack[RTL_SEM_NSEMS_MAX]; +static int srp_ceil_stack_count=-1; + +inline struct rtl_sched_param *srp_current_sysceil () +{ + if (srp_ceil_stack_count>=0) + return &srp_ceil_stack[srp_ceil_stack_count].preempt_level; + else + return (struct rtl_sched_param *)0; +} + +/* A new mutex is being locked and the system ceil may raise */ +static inline int srp_add_sysceil(struct rtl_sched_param *ceil) +{ + if (srp_ceil_stack_count >= RTL_SEM_NSEMS_MAX) { + //rtl_printf("pthread_mutex_lock: Too many mutex locked (SRP protocol).\n"); + //rtl_printf("Edit RTL_SEM_NSEMS_MAX constant. Current value is: %d", RTL_SEM_NSEMS_MAX); + return EBUSY; + } + if ( cmp_preempt_level(ceil, srp_current_sysceil()) >= 0 ){ + srp_ceil_stack[++srp_ceil_stack_count].preempt_level = *ceil; + srp_ceil_stack[srp_ceil_stack_count].owner = pthread_self(); + } + return 0; +} + + +/* When calling mutex_unlock, the top of system ceil stack will be removed if apropiate */ +static inline void srp_del_sysceil(struct rtl_sched_param *ceil, struct rtl_sched_param *prev_level) +{ + if (cmp_preempt_level(&srp_ceil_stack[srp_ceil_stack_count].preempt_level, ceil) == 0){ + (*prev_level)=srp_ceil_stack[srp_ceil_stack_count--].preempt_level; + } + (*prev_level).sched_priority=-1; +} + +pthread_t srp_ceiling_owner() +{ + if (srp_ceil_stack_count>=0) + return srp_ceil_stack[srp_ceil_stack_count].owner; + else + return (pthread_t) 0; +} + + + +int pthread_mutex_register_np(pthread_t thread, pthread_mutex_t *mutex) +{ + if (!mutex->valid){ + return EINVAL; + } + switch (mutex->protocol) { + case PTHREAD_PRIO_PROTECT: + if ( (mutex->prioceiling == sched_get_priority_max(SCHED_FIFO)+1) || + (mutex->prioceiling < thread->sched_param.sched_priority)){ + mutex->prioceiling = thread->sched_param.sched_priority; + } + break; + case PTHREAD_PRIO_SRP: + if ( (mutex->preemptceiling.sched_deadline == 0) || + (cmp_preempt_level(&(thread->sched_param), &(mutex->preemptceiling)) > 0 ) ) { + mutex->preemptceiling = thread->sched_param; + } + } + return 0; +} + +#endif /* CONFIG_RTL_SRP */ + + static void rtl_wait_abort(void *data) { pthread_t self = pthread_self(); @@ -91,7 +171,11 @@ attr->type = PTHREAD_MUTEX_DEFAULT; attr->pshared = PTHREAD_PROCESS_SHARED; attr->protocol = PTHREAD_PRIO_NONE; - attr->prioceiling = sched_get_priority_max(SCHED_FIFO); + attr->prioceiling = sched_get_priority_max(SCHED_FIFO)+1; +#ifdef CONFIG_RTL_SRP + attr->preemptceiling.sched_priority = attr->prioceiling+1; /* PTHREAD_PRIO_SRP */ + attr->preemptceiling.sched_deadline = 0LL; /* PTHREAD_PRIO_SRP */ +#endif return 0; } @@ -117,12 +201,20 @@ mutex->type = attr->type; mutex->protocol = attr->protocol; mutex->prioceiling = attr->prioceiling; +#ifdef CONFIG_RTL_SRP + mutex->preemptceiling = attr->preemptceiling; /* PTHREAD_PRIO_SRP */ +#endif return 0; } static inline int __pthread_mutex_trylock(pthread_mutex_t *mutex) { + +#ifdef CONFIG_RTL_EDF_DEBUG + struct events_stuct events; +#endif + #ifdef _RTL_POSIX_THREAD_PRIO_PROTECT /* if _RTL_POSIX_THREAD_PRIO_PROTECT, this code is protected by a spinlock */ if (mutex->protocol == PTHREAD_PRIO_PROTECT) { @@ -134,6 +226,18 @@ RTL_PRIO (RTL_CURRENT) = mutex->prioceiling; } #endif +#ifdef CONFIG_RTL_SRP + if (mutex->protocol == PTHREAD_PRIO_SRP) { + srp_add_sysceil(&(mutex->preemptceiling)); + //rtl_printf("Current Ceil: %d", (int)srp_current_sysceil()->sched_deadline); +#ifdef CONFIG_RTL_EDF_DEBUG + events.type = LOCKM; + events.id = ((int)pthread_self()->user[0]+1); + events.in = gethrtime(); + rtf_put(0, (char *) &events, sizeof(events)); +#endif + } +#endif if (test_and_set_bit(0, &mutex->busy)) { return EBUSY; } @@ -157,11 +261,11 @@ break; case PTHREAD_MUTEX_NORMAL: default: -#ifdef _RTL_POSIX_THREAD_PRIO_PROTECT +#if defined(_RTL_POSIX_THREAD_PRIO_PROTECT) | defined(CONFIG_RTL_SRP) rtl_spin_lock_irqsave (&mutex->lock, flags); #endif ret = __pthread_mutex_trylock(mutex); -#ifdef _RTL_POSIX_THREAD_PRIO_PROTECT +#if defined(_RTL_POSIX_THREAD_PRIO_PROTECT) | defined(CONFIG_RTL_SRP) rtl_spin_unlock_irqrestore(&mutex->lock, flags); #endif return ret; @@ -205,7 +309,15 @@ int pthread_mutex_unlock(pthread_mutex_t *mutex) { + +#ifdef CONFIG_RTL_EDF_DEBUG + struct events_stuct events; +#endif + rtl_irqstate_t flags; +#ifdef CONFIG_RTL_SRP + struct rtl_sched_param srp_prev_sysceil; // avoid bogus "uninit" warning !?! +#endif switch (mutex->type) { case PTHREAD_MUTEX_SPINLOCK_NP: @@ -225,11 +337,32 @@ RTL_PRIO(RTL_CURRENT) = mutex->oldprio; } #endif +#ifdef CONFIG_RTL_SRP + if (mutex->protocol == PTHREAD_PRIO_SRP) { + srp_del_sysceil(&mutex->preemptceiling, &srp_prev_sysceil); + } +#endif clear_bit (0, &mutex->busy); rtl_wait_wakeup(&mutex->wait); rtl_spin_unlock_irqrestore (&mutex->lock, flags); /* XXX we do not call the scheduler here by design; * for fast wakeups, use semaphores & pthread_wakeup_np */ + +#ifdef CONFIG_RTL_SRP + /* Ismael Ripoll: If a higher priority task is waiting at this + mutex, then it must be waked-up ASAP. + Why fsml do not call rtl_scheduler for PRIO_PROTECT ? + */ +#ifdef CONFIG_RTL_EDF_DEBUG + events.type = UNLKM; + events.id = ((int)pthread_self()->user[0]+1); + events.in = gethrtime(); + rtf_put(0, (char *) &events, sizeof(events)); +#endif + if (mutex->protocol == PTHREAD_PRIO_SRP) + rtl_schedule(); + +#endif return 0; } } @@ -301,6 +434,21 @@ } #endif +#ifdef CONFIG_RTL_SRP +int pthread_mutex_setpreemptceiling_np(pthread_mutex_t *mutex, struct rtl_sched_param *preemptceiling, struct rtl_sched_param *old_ceiling) +{ + int ret; + ret = pthread_mutex_lock (mutex); + if (ret) { + return ret; + } + *old_ceiling = mutex->preemptceiling; + mutex->preemptceiling = (*preemptceiling); + pthread_mutex_unlock (mutex); + return 0; +} +#endif + /* For condvar wait and signal operations the mutex should * be locked; otherwise the behaviour is undefined */ diff -NruBb rtlinux-3.2-pre1/schedulers/rtl_sched.c rtlinux-3.2-pre1-edf/schedulers/rtl_sched.c --- rtlinux-3.2-pre1/schedulers/rtl_sched.c 2003-03-01 12:46:38.000000000 +0100 +++ rtlinux-3.2-pre1-edf/schedulers/rtl_sched.c 2003-04-01 17:24:38.000000000 +0200 @@ -13,17 +13,13 @@ * Copyright (C) Finite State Machine Labs Inc., 1998,1999 * Released under the terms of the GNU General Public License Version 2 * + * Patricia Balbastre & Ismael Ripoll: + * Added POSIX-like EDF and SRP support (7-2001) */ #include #include #include -#include -#include -#include -#include - -#include #include @@ -33,9 +29,25 @@ #include #include #include +#include #include #include +#include +#include +#include +#include + +#include + + +#ifdef CONFIG_RTL_EDF_DEBUG +static struct events_stuct events; +hrtime_t ini_time; +static int first_time = 0; +#endif + + static spinlock_t rtl_tqueue_lock; static int rtl_sched_irq; @@ -49,6 +61,63 @@ /* # define rtl_printf(fac, args...) do ; while (0) */ + +static inline int cmp_prio(pthread_t A, pthread_t B) +{ +#ifdef CONFIG_RTL_EDF + register int tmp; + if ( (tmp= (A->sched_param).sched_priority - (B->sched_param).sched_priority) ) + return tmp; + else + return ( (B->current_deadline) > (A->current_deadline) ); +#else + return (A->sched_param).sched_priority - (B->sched_param).sched_priority; +#endif + +} + +#ifdef CONFIG_RTL_EDF_DEBUG +inline static void rt_print_request(struct rtl_thread_struct *task, int is_linux_task) +{ + events.type = ACTIV; + if (is_linux_task){ + events.id = 0; + } else { + events.id = ((int)task->user[0]+1); + } + events.in = task->resume_time; + if (task->policy == SCHED_EDF_NP) { /* So, the DEBUG also runs with SCHED_PRIO (Guillot Jean-Marie) */ + events.out = task->current_deadline + task->period; + } else { + events.out = task->resume_time; + } + events.out = task->current_deadline + task->period; + rtf_put(0, (char *) &events, sizeof(events)); +} + + + +inline static void rt_print_exec(schedule_t *sched, hrtime_t now){ + if ((sched->rtl_current != NULL)) { + events.type = EXEC; + events.in = ini_time; + events.out = now; + if (sched->rtl_current != &sched->rtl_linux_task) { + events.id = (int)sched->rtl_current->user[0]+1; + rtf_put(0, (void *) &events, sizeof(events)); + first_time=1; + } else { + events.id = 0; + if (first_time!=0) + rtf_put(0, (void *) &events, sizeof(events)); + } + + } +} + +#endif + + int rtl_startup(void *(*fn)(void *), void *data) { void *retval; @@ -299,8 +368,16 @@ rtl_no_interrupts(interrupt_state); p->period = period; +#ifdef CONFIG_RTL_EDF + if (p->policy == SCHED_EDF_NP) + p->current_deadline = start_time + p->sched_param.sched_deadline - p->period; +#endif __rtl_setup_timeout(p, start_time); +#ifdef CONFIG_RTL_EDF_DEBUG + rt_print_request(p, 0); +#endif + rtl_reschedule_thread(p); rtl_restore_interrupts(interrupt_state); return 0; @@ -345,17 +422,34 @@ inline static struct rtl_thread_struct * find_preemptor(schedule_t *s, struct rtl_thread_struct *chosen){ struct rtl_thread_struct *t; struct rtl_thread_struct *preemptor=0; +#ifdef CONFIG_RTL_SRP + struct rtl_sched_param *current_sysceil = srp_current_sysceil(); +#endif + for (t = s->rtl_tasks; t; t = t->next) { if (test_bit(RTL_THREAD_TIMERARMED, &t->threadflags)) { - if (t->sched_param.sched_priority > chosen->sched_param.sched_priority) + /*if (t->sched_param.sched_priority > chosen->sched_param.sched_priority) { if(!preemptor ||(t->resume_time < preemptor->resume_time)) { preemptor = t; } } + */ + + if ( (cmp_prio(t , chosen) > 0) && + (!preemptor || (t->resume_time < preemptor->resume_time)) ){ +#ifdef CONFIG_RTL_SRP + if ( !current_sysceil || + (cmp_preempt_level(&t->sched_param, srp_current_sysceil())>0) ) +#endif // CONFIG_RTL_SRP + preemptor = t; } + + } + } + return preemptor; } @@ -407,6 +501,9 @@ struct rtl_thread_struct *t; struct rtl_thread_struct *new_task; struct rtl_thread_struct *preemptor = 0; +#ifdef CONFIG_RTL_SRP + struct rtl_sched_param *current_sysceil; +#endif unsigned long interrupt_state; int cpu_id = rtl_getcpuid(); hrtime_t now; @@ -416,11 +513,27 @@ rtl_trace2 (RTL_TRACE_SCHED_IN, (long) pthread_self()); /* new_task = &sched->rtl_linux_task;*/ - new_task = 0; + sched = &rtl_sched[cpu_id]; +#ifdef CONFIG_RTL_SRP + new_task=srp_ceiling_owner(); + if (new_task && !(new_task->pending & ~new_task->blocked)){ + new_task = &sched->rtl_linux_task; + } + current_sysceil=srp_current_sysceil(); +#else + new_task = &sched->rtl_linux_task; +#endif /* CONFIG_RTL_SRP */ + now = sched->clock->gethrtime(sched->clock); +#ifdef CONFIG_RTL_EDF_DEBUG + rt_print_exec(sched, now); + ini_time=now; +#endif + + if (sched->clock->mode == RTL_CLOCK_MODE_ONESHOT) { sched->clock->value = now; } @@ -434,6 +547,10 @@ rtl_sigaddset (&t->pending, RTL_SIGNAL_TIMER); if (t->period != 0) { /* periodic */ t->resume_time += t->period; +#ifdef CONFIG_RTL_EDF_DEBUG + rt_print_request(t, (t == &sched->rtl_linux_task) ); +#endif + /* timer overrun */ #ifndef CONFIG_RTL_OLD_TIMER_BEHAVIOUR while (now >= t->resume_time) { @@ -448,10 +565,18 @@ } /* and find highest priority runnable task */ - if ((t->pending & ~t->blocked) && (!new_task || - (t->sched_param.sched_priority > new_task->sched_param.sched_priority))) { + + if ( (t->pending & ~t->blocked) && + (!new_task || (cmp_prio(t, new_task)>0) ) ) { +#ifdef CONFIG_RTL_SRP + if (!current_sysceil || + (cmp_preempt_level(&t->sched_param, current_sysceil)>0)) +#endif // CONFIG_RTL_SRP new_task = t; + } + + } if (sched->clock->mode == RTL_CLOCK_MODE_ONESHOT && !test_bit (RTL_SCHED_TIMER_OK, &sched->sched_flags)) { @@ -583,6 +708,10 @@ struct rtl_thread_struct *task; pthread_attr_t default_attr; int stack_size; +#ifdef CONFIG_RTL_EDF_DEBUG + static int nr_tasks=0; +#endif + if (!attr) { pthread_attr_init(&default_attr); attr = &default_attr; @@ -621,9 +750,12 @@ task->abort = 0; task->cpu = attr->cpu; - task->cleanup = 0; task->resume_time = HRTIME_INFINITY; +#ifdef CONFIG_RTL_EDF + task->policy = attr->policy; + task->current_deadline = 0LL; +#endif task->period = 0; task->sched_param = attr->sched_param; task->stack = stack_addr + stack_size / sizeof(int); @@ -633,6 +765,11 @@ task->fpu_initialized = 0; task->uses_fp = attr->use_fp; +#ifdef CONFIG_RTL_EDF_DEBUG + task->user[0]=(int *)nr_tasks; + nr_tasks++; +#endif + { schedule_t *s = sched_data(task->cpu); #ifdef CONFIG_SMP @@ -794,6 +931,10 @@ long interrupt_state; pthread_t self = pthread_self(); rtl_no_interrupts(interrupt_state); +#ifdef CONFIG_RTL_EDF + if (self->policy == SCHED_EDF_NP) + self->current_deadline += self->period; +#endif RTL_MARK_SUSPENDED (self); __rtl_setup_timeout (self, self->resume_time); rtl_schedule(); @@ -884,6 +1025,14 @@ s -> rtl_linux_task . blocked = 0; s -> rtl_linux_task . threadflags = 0; s -> rtl_linux_task . sched_param . sched_priority = -1; +#ifdef CONFIG_RTL_EDF + s -> rtl_linux_task . sched_param . sched_deadline = HRTIME_INFINITY; + s -> rtl_linux_task . current_deadline = HRTIME_INFINITY; +#endif +#ifdef CONFIG_RTL_EDF_DEBUG + s -> rtl_linux_task . user [0] = (void *)-1; +#endif + rtl_posix_init (&s->rtl_linux_task); s -> rtl_linux_task . next = 0; s -> rtl_linux_task . uses_fp = 1; s -> rtl_linux_task . fpu_initialized = 1; @@ -892,7 +1041,6 @@ s -> rtl_task_fpu_owner = &s->rtl_linux_task; s -> sched_flags = 0; - rtl_posix_init (&s->rtl_linux_task); s-> clock = rtl_getbestclock (cpu_id); if (s->clock && rtl_setclockhandler (s->clock, rtl_sched_timer_interrupt) == 0) { @@ -920,6 +1068,13 @@ save_errno_location = __errno_location; __errno_location = thread_errno_location; +#ifdef CONFIG_RTL_EDF_DEBUG + rtf_destroy (0); + rtf_create(0, 20000); + rtl_printf("EDF Sched ready\n"); +#endif + + /* rtl_setdebug (RTLDBG_ALL); */ return 0; } @@ -940,6 +1095,10 @@ #ifdef CONFIG_SMP rtl_free_ipi(cpu); #endif +#ifdef CONFIG_RTL_EDF_DEBUG + rtf_destroy (0); +#endif + } } diff -NruBb rtlinux-3.2-pre1/scripts/config.in rtlinux-3.2-pre1-edf/scripts/config.in --- rtlinux-3.2-pre1/scripts/config.in 2003-03-01 12:46:38.000000000 +0100 +++ rtlinux-3.2-pre1-edf/scripts/config.in 2003-04-01 17:24:38.000000000 +0200 @@ -39,6 +39,10 @@ bool 'Nolinux support (experimental)' CONFIG_RTL_RESERVE_CPU bool 'RTLinux tracer support (experimental)' CONFIG_RTL_TRACER source main/arch/config.in +if [ "$CONFIG_RTL_USE_V1_API" != "y" ]; then + bool 'Enable EDF scheduling (experimental)' CONFIG_RTL_EDF + bool 'SRP Mutex Priority Inversion (experimental)' CONFIG_RTL_SRP +fi endmenu mainmenu_option next_comment