diff -NruBb rtlinux-3.2-pre1/doc/Configure.help rtlinux-3.2-pre1-cbs/doc/Configure.help --- rtlinux-3.2-pre1/doc/Configure.help 2003-04-01 18:28:34.000000000 +0200 +++ rtlinux-3.2-pre1-cbs/doc/Configure.help 2003-04-01 18:33:43.000000000 +0200 @@ -103,6 +103,17 @@ If you say Y here you may also need "SRP Mutex Priority Inversion" It is safe to say yes. +CBS Scheduler +CONFIG_OC_RTLCBS + Say Y if you want to use the Constant Bandwidth Server scheduling + policy (CBS). + + This is an extension to the POSIX API. Therefore, you have to + disable "RTLinux V1 API Support". + + If you say Y you also need "EDF Scheduler". + 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 diff -NruBb rtlinux-3.2-pre1/include/rtl_sched.h rtlinux-3.2-pre1-cbs/include/rtl_sched.h --- rtlinux-3.2-pre1/include/rtl_sched.h 2003-04-01 18:30:36.000000000 +0200 +++ rtlinux-3.2-pre1-cbs/include/rtl_sched.h 2003-04-01 20:26:41.000000000 +0200 @@ -7,8 +7,12 @@ * * Ismael Ripoll & Patricia Balbastre: * Small modificacions to include EDF scheduling and SRP mutex control. + * + * Pau Mendoza and Patricia Balbastre + * Small modifications to include CBS scheduling */ + #ifndef __RTL__SCHED__ #define __RTL__SCHED__ @@ -30,7 +34,7 @@ #include #include -/* #define CONFIG_RTL_EDF_DEBUG y */ +#define CONFIG_RTL_EDF_DEBUG y #ifdef CONFIG_RTL_EDF_DEBUG @@ -53,6 +57,10 @@ #define SCHED_EDF_NP 3 #endif +#ifdef CONFIG_OC_RTLCBS +#define SCHED_CBS_NP 4 +#endif + #ifdef __cplusplus struct sched_param { int sched_priority; @@ -71,16 +79,16 @@ struct rtl_sched_param { int sched_priority; hrtime_t sched_deadline; +#ifdef CONFIG_OC_RTLCBS + hrtime_t sched_cbs_init_budget; +#define RTL_INIT_BUDGET(th) ((th)->sched_param.sched_cbs_init_budget) +#endif }; #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 @@ -128,6 +136,9 @@ #ifdef CONFIG_RTL_EDF hrtime_t current_deadline; int policy; +#ifdef CONFIG_OC_RTLCBS + hrtime_t sched_cbs_current_budget; +#endif #endif int magic; struct rtl_posix_thread_struct posix_data; @@ -285,6 +296,11 @@ #ifdef CONFIG_RTL_EDF int policy; #endif + +#ifdef CONFIG_OC_RTLCBS + hrtime_t sched_cbs_current_budget; +#endif + } pthread_attr_t; extern inline int pthread_attr_init(pthread_attr_t *attr) @@ -296,6 +312,10 @@ attr->sched_param.sched_deadline = HRTIME_INFINITY; attr->policy = SCHED_FIFO; #endif +#ifdef CONFIG_OC_RTLCBS + attr->sched_cbs_current_budget = 0; + attr->sched_param.sched_cbs_init_budget = 0; +#endif attr->cpu = rtl_getcpuid(); rtl_sigemptyset(&attr->initial_state); rtl_sigaddset(&attr->initial_state, RTL_SIGNAL_READY); @@ -376,6 +396,46 @@ #endif /* CONFIG_RTL_EDF */ +#ifdef CONFIG_OC_RTLCBS +extern inline int pthread_attr_setinitbudget_np(pthread_attr_t *attr, hrtime_t initbudget) +{ + attr->sched_param.sched_cbs_init_budget = initbudget; + return 0; +} + +extern inline int pthread_attr_getinitbudget_np(const pthread_attr_t *attr, hrtime_t *initbudget) +{ + *initbudget = attr->sched_param.sched_cbs_init_budget; + return 0; +} + + +extern inline int pthread_setinitbudget_np(pthread_t thread, hrtime_t initbudget) +{ + thread->sched_param.sched_cbs_init_budget = initbudget; + return 0; +} + + +extern inline int pthread_getinitbudget_np(pthread_t thread, + hrtime_t *initbudget) { + *initbudget = thread->sched_param.sched_cbs_init_budget; + return 0; +} + +extern inline int pthread_initcbs_np(pthread_t thread, hrtime_t period) { + + thread->current_deadline = 0; /* By definition of CBS, first activation deadline is 0 */ + thread->sched_cbs_current_budget = thread->sched_param.sched_cbs_init_budget; + thread->period = period; + + return 0; +} + +extern void make_linux_task_cbs_server(hrtime_t start,hrtime_t initbudget, hrtime_t deadline, hrtime_t period, int priority); + +#endif /* CONFIG_OC_RTLCBS */ + extern int pthread_wait_np(void); diff -NruBb rtlinux-3.2-pre1/schedulers/rtl_sched.c rtlinux-3.2-pre1-cbs/schedulers/rtl_sched.c --- rtlinux-3.2-pre1/schedulers/rtl_sched.c 2003-04-01 18:28:34.000000000 +0200 +++ rtlinux-3.2-pre1-cbs/schedulers/rtl_sched.c 2003-04-01 20:38:38.000000000 +0200 @@ -15,6 +15,9 @@ * * Patricia Balbastre & Ismael Ripoll: * Added POSIX-like EDF and SRP support (7-2001) + * + * Pau Mendoza and Patricia Balbastre: + * Added CBS support (9-2002) */ #include @@ -47,6 +50,9 @@ static int first_time = 0; #endif +#ifdef CONFIG_OC_RTLCBS +static hrtime_t rtl_prev_sched_time; +#endif static spinlock_t rtl_tqueue_lock; @@ -59,6 +65,10 @@ struct rtl_sched_cpu_struct rtl_sched [1]; #endif +#ifdef CONFIG_RTL_EDF_DEBUG +static int nr_tasks=0; +#endif + /* # define rtl_printf(fac, args...) do ; while (0) */ @@ -86,16 +96,19 @@ events.id = ((int)task->user[0]+1); } events.in = task->resume_time; +#ifdef CONFIG_OC_RTLCBS 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; + } else +#endif + events.out = task->resume_time + task->period; rtf_put(0, (char *) &events, sizeof(events)); } +#ifdef CONFIG_OC_RTLCBS +static int last_task_in_cpu = 0; +#endif inline static void rt_print_exec(schedule_t *sched, hrtime_t now){ if ((sched->rtl_current != NULL)) { @@ -106,8 +119,25 @@ events.id = (int)sched->rtl_current->user[0]+1; rtf_put(0, (void *) &events, sizeof(events)); first_time=1; +#ifdef CONFIG_OC_RTLCBS + last_task_in_cpu = events.id; +#endif } else { +#ifdef CONFIG_OC_RTLCBS + if(sched->rtl_linux_task.policy == SCHED_CBS_NP ){ + if (last_task_in_cpu == 0){ events.id = 0; + } else { + events.id = nr_tasks + 1; + } + last_task_in_cpu = nr_tasks + 1; + } else { +#endif + events.id = 0; +#ifdef CONFIG_OC_RTLCBS + last_task_in_cpu = events.id; + } +#endif if (first_time!=0) rtf_put(0, (void *) &events, sizeof(events)); } @@ -209,6 +239,70 @@ #define CHECK_VALID(thread) do { if ((thread)->magic != RTL_THREAD_MAGIC) return ESRCH; } while (0) + +#ifdef CONFIG_OC_RTLCBS +static inline void rtl_cbs_reset_deadline(pthread_t t) +{ + hrtime_t now; + rtl_irqstate_t flags; + int cpu_id = rtl_getcpuid(); + schedule_t *sched; + + rtl_no_interrupts(flags); + sched = &rtl_sched[cpu_id]; + if ((t->policy == SCHED_CBS_NP) && (!rtl_sigismember(&(t)->pending,RTL_SIGNAL_READY))) { + if(RTL_INIT_BUDGET(t)){ + now = sched->clock->gethrtime(sched->clock); + if (now + ((t->sched_cbs_current_budget * t->period )/ RTL_INIT_BUDGET(t)) >= t->current_deadline) { + t->current_deadline = now + t->period; + t->sched_cbs_current_budget = RTL_INIT_BUDGET(t); + } + t->resume_time = now; + } else { + rtl_printf("Error in cbs_task atributes; init_budget is 0"); + } + } + rtl_restore_interrupts(flags); +} + + +void make_linux_task_cbs_server(hrtime_t start,hrtime_t initbudget, hrtime_t deadline, hrtime_t period, int priority){ + + hrtime_t now; + int cpu_id = rtl_getcpuid(); + pthread_t linux_task = rtl_get_linux_thread(cpu_id); + schedule_t *sched; + + if (linux_task->policy != SCHED_CBS_NP) { + sched = &rtl_sched[cpu_id]; + now = sched->clock->gethrtime(sched->clock); + +#ifdef CONFIG_RTL_EDF_DEBUG +#ifdef CONFIG_OC_RTLCBS + last_task_in_cpu = 0; +#endif +#endif + RTL_INIT_BUDGET(linux_task) = initbudget; + linux_task->sched_param.sched_deadline = deadline; + linux_task->period = period; + linux_task->sched_param.sched_priority = priority; + linux_task->policy = SCHED_CBS_NP; + + linux_task->sched_cbs_current_budget = 0; + if (linux_task->current_deadline < now) + linux_task->current_deadline = now; + cbs_linux_idle = 1; + + rtl_cbs_reset_deadline(linux_task); + rtl_reschedule_thread(linux_task); + // Call the scheduler to program other deadline if need. + }; + return; +} + +#endif + + int pthread_kill(pthread_t thread, int signal) { if ((unsigned) signal <= RTL_MAX_SIGNAL) { @@ -217,6 +311,10 @@ return 0; } set_bit(signal, &thread->pending); +#ifdef CONFIG_OC_RTLCBS + if ((unsigned) signal == RTL_SIGNAL_WAKEUP) + rtl_cbs_reset_deadline(thread); +#endif return 0; } else if(thread != rtl_get_linux_thread(rtl_getcpuid())) { return EINVAL; @@ -369,9 +467,12 @@ p->period = period; #ifdef CONFIG_RTL_EDF - if (p->policy == SCHED_EDF_NP) + 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 @@ -509,6 +610,9 @@ hrtime_t now; rtl_sigset_t mask; +#ifdef CONFIG_OC_RTLCBS + hrtime_t elapsed_time; +#endif rtl_no_interrupts(interrupt_state); rtl_trace2 (RTL_TRACE_SCHED_IN, (long) pthread_self()); /* new_task = &sched->rtl_linux_task;*/ @@ -533,6 +637,36 @@ ini_time=now; #endif +#ifdef CONFIG_OC_RTLCBS + elapsed_time = now - rtl_prev_sched_time; + rtl_prev_sched_time = now; + + + if (sched->rtl_current->policy == SCHED_CBS_NP) { + if (sched->rtl_current->sched_cbs_current_budget >= elapsed_time){ + sched->rtl_current->sched_cbs_current_budget -= elapsed_time; + } else { + sched->rtl_current->sched_cbs_current_budget = RTL_INIT_BUDGET(sched->rtl_current); + sched->rtl_current->current_deadline += sched->rtl_current->period; + sched->rtl_current->resume_time = now; + } + if (sched->rtl_current == &sched->rtl_linux_task) { + // Checking if Linux has been in idle state + if (cbs_linux_idle == 0) { + // Become back Linux to initial priority + sched->rtl_linux_task.sched_param.sched_priority = -1; +#ifdef CONFIG_RTL_EDF + sched->rtl_linux_task.sched_param.sched_deadline = 0; + sched->rtl_linux_task.current_deadline = 0; +#endif + sched->rtl_linux_task.sched_cbs_current_budget = 0; + RTL_INIT_BUDGET(&sched->rtl_linux_task) = 0; + sched->rtl_linux_task.period = HRTIME_INFINITY; + sched->rtl_linux_task.policy = SCHED_OTHER; + } + } + } +#endif if (sched->clock->mode == RTL_CLOCK_MODE_ONESHOT) { sched->clock->value = now; @@ -578,11 +712,40 @@ } - +/* if (sched->clock->mode == RTL_CLOCK_MODE_ONESHOT && !test_bit (RTL_SCHED_TIMER_OK, &sched->sched_flags)) { if ( (preemptor = find_preemptor(sched,new_task))) { (sched->clock)->settimer(sched->clock, preemptor->resume_time - now); + } else {*/ +#ifdef CONFIG_OC_RTLCBS + if ((sched->clock->mode == RTL_CLOCK_MODE_ONESHOT && !test_bit (RTL_SCHED_TIMER_OK, &sched->sched_flags)) || (new_task->policy == SCHED_CBS_NP)) { +#else + if ((sched->clock->mode == RTL_CLOCK_MODE_ONESHOT && !test_bit (RTL_SCHED_TIMER_OK, &sched->sched_flags))) { +#endif + if ( (preemptor = find_preemptor(sched,new_task))) { +#ifdef CONFIG_OC_RTLCBS + if (new_task->policy == SCHED_CBS_NP) { + if (( preemptor->resume_time - now) > (new_task->sched_cbs_current_budget)){ + (sched->clock)->settimer(sched->clock, new_task->sched_cbs_current_budget); + if (new_task == &sched->rtl_linux_task) { + } + } else { + if (new_task == &sched->rtl_linux_task) { + } +#endif + (sched->clock)->settimer(sched->clock, preemptor->resume_time - now); +#ifdef CONFIG_OC_RTLCBS + } } else { + (sched->clock)->settimer(sched->clock, preemptor->resume_time - now); + } +#endif + } else { +#ifdef CONFIG_OC_RTLCBS + if (new_task->policy == SCHED_CBS_NP) { + (sched->clock)->settimer(sched->clock, new_task->sched_cbs_current_budget); + } else +#endif (sched->clock)->settimer(sched->clock, (HRTICKS_PER_SEC / HZ) / 2); } set_bit (RTL_SCHED_TIMER_OK, &sched->sched_flags); @@ -708,9 +871,6 @@ 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); @@ -755,6 +915,9 @@ #ifdef CONFIG_RTL_EDF task->policy = attr->policy; task->current_deadline = 0LL; +#ifdef CONFIG_OC_RTLCBS + task->sched_cbs_current_budget = 0LL; +#endif #endif task->period = 0; task->sched_param = attr->sched_param; @@ -1028,6 +1191,10 @@ #ifdef CONFIG_RTL_EDF s -> rtl_linux_task . sched_param . sched_deadline = HRTIME_INFINITY; s -> rtl_linux_task . current_deadline = HRTIME_INFINITY; +#ifdef CONFIG_OC_RTLCBS + s -> rtl_linux_task . sched_cbs_current_budget = 0; + s -> rtl_linux_task . current_deadline = 0; +#endif #endif #ifdef CONFIG_RTL_EDF_DEBUG s -> rtl_linux_task . user [0] = (void *)-1; @@ -1050,6 +1217,7 @@ rtl_restore_interrupts (interrupt_state); return -EINVAL; } + cbs_linux_idle = 0; } cpu_id = my_cpu_id; @@ -1073,6 +1241,9 @@ rtf_create(0, 20000); rtl_printf("EDF Sched ready\n"); #endif +#ifdef CONFIG_OC_RTLCBS + rtl_prev_sched_time = s->clock->gethrtime(s->clock); +#endif /* rtl_setdebug (RTLDBG_ALL); */ diff -NruBb rtlinux-3.2-pre1/scripts/config.in rtlinux-3.2-pre1-cbs/scripts/config.in --- rtlinux-3.2-pre1/scripts/config.in 2003-04-01 18:28:34.000000000 +0200 +++ rtlinux-3.2-pre1-cbs/scripts/config.in 2003-04-01 18:34:54.000000000 +0200 @@ -42,6 +42,9 @@ 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 + if [ "$CONFIG_RTL_EDF" = "y" ]; then + bool 'Enable CBS schedulig (experimental)' CONFIG_OC_RTLCBS + fi fi endmenu