diff -BNru rtlinux-3.1/doc/Configure.help appsched_rt/doc/Configure.help --- rtlinux-3.1/doc/Configure.help Tue Feb 18 08:48:24 2003 +++ appsched_rt/doc/Configure.help Tue Feb 18 08:55:02 2003 @@ -114,50 +114,11 @@ POSIX timers deppends on POSIX signals. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +POSIX-Compatible Application-Defined Scheduling +_RTL_POSIX_APP_SCHEDULING + POSIX-Compatible Application-defined scheduling is an application + program interface (API) that enables applications to use + application-defined scheduling algorithms in a way compatible + with the scheduling model defined in POSIX. Several + application-defined schedulers, implemented as special + user threads, can coexist in the system in a predictable way. diff -BNru rtlinux-3.1/examples/README appsched_rt/examples/README --- rtlinux-3.1/examples/README Tue Feb 18 08:48:24 2003 +++ appsched_rt/examples/README Tue Feb 18 08:55:02 2003 @@ -1,90 +1,19 @@ +This version of Open RTLinux is considered stable. It supports both Linux 2.2.x +and Linux 2.4.x kernel series. Please see the RELEASENOTE file to find out +what's new in this version. -Scheduler BUG 6-11-02: +RTLinux is a hard real-time extension to Linux. +More information can be found at http://www.rtlinux.org/ +and http://www.fsmlabs.com/ - The RTLinux scheduler for version 3.1 is re-entrant when it wants to -suspend a thread. The procedure is the following. When it wants to -suspend a thread different from pthread_self() (with pthread_suspend_np()) -it sends a signal to that thread ( RTL_SIGNAL_SUSPEND). Then the scheduler -decides to give the CPU for that thread so it has a pending signal. But -the handler for that signal marks the thread as suspended and calls the -scheduler again. -If the process is repeated, as in the following example (sched_bug.c), -what we are doing is to push calls to the scheduler in the threads stack. -If we are suspended and nobody wakes up us (in a mutex, calling -pthread_suspend_np,etc ..) the stack becomes exhausted in a finite time. -In version 3.0 the scheduler wasn't reentrant and this error doesn't occur. -A good test is to change the stack size and observe that the iterates -proportionaly to the stack increment.We have the same problem with user -signals handlers. +The installation instructions are in doc/html/Installation/Installation.html +file. The doc/html/GettingStarted document contains a brief intoduction to +RTLinux as well as sources of help and a quick API reference. -Proposed solution: -The solution was to return to the scheduler policy of version 3.0, being -non re-entrant. +If you are upgrading from previous versions of RTL, please read the +file UPGRADING. -Mutex BUG 4-12-02: +Please send bug reports in to support@fsmlabs.com - Well, the fact is that do_signal when receives the signal RTL_SIGNAL_SUSPENDS sets -t->abort to zero. So, when it calls do_abort(t) it has no effect. - In our example, blocked thread was blocked on a mutex. Meantime mutex owner thread -is sending signal to it (pthread_suspend_np, pthread_wakeup_np,pthread_wakeup_np). - What happens is the following: - 1.- The blocked gets blocked on the mutex (calling rtl_wait_sleep on the -pthread_mutex_lock loop), and it is queued in the mutex wait queue. - 2.- At this point, mutex owner sends the following signals: - 2.1.- RTL_SIGNAL_WAKEUP: blocked thread takes the CPU to manage it. Then it calls to -do_abort and rtl_wait_abort takes it out of the mutex wait queue. Then it loops again and -calls rtl_wait_sleep and it is queued on mutex wait queue. - 2.2.- Next blocked thread receives the signal RTL_SIGNAL_SUSPEND which sets -t->abort to zero, marks blocked thread suspended and calls the scheduler. - 2.3.- Finally, blocked thread receives the RTL_SIGNAL_WAKEUP again. But this time -when do_abort is called, it has no effect (so RTL_SIGNAL_SUSPEND set its to zero). So blocked -thread isn't removed from mutex wait queue. But the code follows (rtl_wait_sleep returns) -looping at pthread_mutex_lock loop, calling rtl_wait_sleep again. This function queues -blocked thread in mutex wait queue which was queued allready (well, not exactly since -the struct queued was local to rtl_wait_sleep.). At this time mutex wait queue contains the -following: head -> thread1 -> head. - And here is the bug we got a double linked wait queue where the head and the tail are storing the same waiter (blocked thread ). - 4.- When thread 0 calls pthread_mutex_unlock and runs the mutex wait queue to wake up blocked threads it runs an infinite loop and the user lost the machine control (so linux never enters). - - -Proposed solution: - Possibly, setting do_abort to zero when managing RTL_SIGNAL_SUSPEND is for future compatibility or a simple mistake. Now abort field of thread's structure is only used for mutexes and semaphores. One solution is to not set to zero and execute do_abort when managing the RTL_SIGNAL_SUPEND signal. - -timespec_add_ns BUG 22-11-02 -The macro timespec_add-ns available in include/rtl_time.h is implemented as: -#define old_timespec_add_ns(t,n) do { \ - (t)->tv_nsec += n; \ - timespec_normalize(t); \ -} while (0) -and timespec_normalize is implemented as: - #define timespec_normalize(t) {\ - if ((t)->tv_nsec >= NSECS_PER_SEC) { \ - (t)->tv_nsec -= NSECS_PER_SEC; \ - (t)->tv_sec++; \ - } else if ((t)->tv_nsec < 0) { \ - (t)->tv_nsec += NSECS_PER_SEC; \ - (t)->tv_sec--; \ - } \ - } - -What should happen if the result of (t)->tv_nsec += n; is bigger than two seconds. Clearly, -this will lead to an invalid time specification having tv_nsec field a value bigger of -NSECS_PER_SEC (1000*1000*1000). Also overflow could happen if the result is bigger than -2^31 ( 2147483648 ). - -The alternative solution is to implement timespec_normalize as: - -#define TWOSECONDS (NSECS_PER_SEC*2) -#define timespec_add_ns(t,n) do { \ - long long aux=(t)->tv_nsec+(n);\ - \ - if ((aux > TWOSECONDS) || (aux < -TWOSECONDS)) /*check overflow*/ {\ - (t)->tv_nsec +=((n) % NSECS_PER_SEC) ; \ - (t)->tv_sec += ((n) / NSECS_PER_SEC); \ - } else { (t)->tv_nsec=aux; }\ - \ - timespec_normalize(t); \ -} while (0) - -The file timespec_add_ns placed in the dirtory examples/bug tests the -both implementations. +Finite State Machine Labs Inc. (FSMLabs) created and maintains +RTLinux. diff -BNru rtlinux-3.1/include/cpu_tracer.h appsched_rt/include/cpu_tracer.h --- rtlinux-3.1/include/cpu_tracer.h Tue Feb 18 08:48:23 2003 +++ appsched_rt/include/cpu_tracer.h Tue Feb 18 08:55:02 2003 @@ -25,23 +25,24 @@ #endif #define FIFO 0 +#define UFIFO (FIFO+1) + #define MAXTASKS 100 #ifdef __CPU_USAGE #define window_size 10 -#define UNIT 100000 +#define UNIT (hrtime_t) NSECS_PER_SEC // 1G. #endif #ifdef __SCHEDULER__ #ifdef __CPU_USAGE unsigned int ntasks=0; -pthread_t threads[MAXTASKS]; +//pthread_t threads[MAXTASKS]; hrtime_t t_usage[MAXTASKS]; hrtime_t t_u_counter[MAXTASKS]; hrtime_t last_t_u_counter[MAXTASKS]; -hrtime_t PERIOD=1*1000*1000*1000LL; -//#include +hrtime_t PERIOD=NSECS_PER_SEC; // 1 second. hrtime_t usage_window[window_size]; unsigned long sample; #endif @@ -46,10 +47,9 @@ unsigned long sample; #endif #else - #ifdef __CPU_USAGE extern unsigned int ntasks; -extern pthread_t threads[MAXTASKS]; +//extern pthread_t threads[MAXTASKS]; extern hrtime_t t_usage[MAXTASKS]; extern hrtime_t PERIOD; extern unsigned long sample; @@ -101,74 +101,37 @@ rtf_put(fifo, (char *) &events, sizeof(events)); \ } while (0) -#define rt_print_now_request(events,now,task,fifo) do { \ - events.type = ACTIV; \ - events.id = ((int)task->user[0]);\ - events.in = now; \ - events.out = events.in; \ - rtf_put(fifo, (char *) &events, sizeof(events)); \ -} while (0) - -#define rt_print_activ_request(events,now,task,fifo) do { \ - events.type = ACTIV; \ - events.id = ((int)task->user[0])+3;\ - events.in = now; \ - events.out = events.in; \ - rtf_put(fifo, (char *) &events, sizeof(events)); \ -} while (0) - -#define rt_print_suspend_request(events,now,task,fifo) do { \ - events.type = ACTIV; \ - events.id = ((int)task->user[0])+4;\ - events.in = now; \ - events.out = events.in; \ - rtf_put(fifo, (char *) &events, sizeof(events)); \ -} while (0) - -#define rt_print_app_activ_request(events,now,task,fifo) do { \ - events.type = ACTIV; \ - events.id = ((int)task->user[0])+1;\ - events.in = now; \ - events.out = events.in; \ - rtf_put(fifo, (char *) &events, sizeof(events)); \ -} while (0) - -#define rt_print_app_suspend_request(events,now,task,fifo) do { \ - events.type = ACTIV; \ - events.id = ((int)task->user[0])+2;\ - events.in = now; \ - events.out = events.in; \ - rtf_put(fifo, (char *) &events, sizeof(events)); \ -} while (0) -#define rt_print_resume_time_request(events,t,fifo) do { \ +#define rt_print_fixed_request(events,t,fifo) do { \ events.type = ACTIV; \ events.id = ((int)t->thread->user[0]); \ - events.in = t->thread->resume_time; \ - events.out = events.in; \ + events.in = t->resume_time; \ + events.out = events.in + t->period; \ rtf_put(fifo, (char *) &events, sizeof(events)); \ } while (0) - -#define rt_print_fixed_request(events,t,fifo) do { \ +#define rt_print_edf_request(events,t,fifo) do { \ events.type = ACTIV; \ - events.id = ((int)t->thread->user[0]); \ - events.in = t->resume_time; \ - events.out = events.in + t->period; \ + events.id = ((int)t->thread_id->user[0]); \ + events.in = timespec_to_ns(&t->next_deadline); \ + events.out = events.in + timespec_to_ns(&t->period); \ rtf_put(fifo, (char *) &events, sizeof(events)); \ } while (0) #endif - - - - - - - - - +#ifdef __CPU_USAGE +extern inline void rt_print_usage_request(void) +{ + int i=0; + + for (i=0; i<=ntasks;i++){ + rtf_put(UFIFO,&sample, sizeof(sample)); + rtf_put(UFIFO,&i, sizeof(i)); + rtf_put(UFIFO,&t_usage[i], sizeof(t_usage[i])); + } +} +#endif diff -BNru rtlinux-3.1/include/rtl_mutex.h appsched_rt/include/rtl_mutex.h --- rtlinux-3.1/include/rtl_mutex.h Thu Jul 26 21:32:42 2001 +++ appsched_rt/include/rtl_mutex.h Tue Feb 18 08:55:02 2003 @@ -17,13 +17,34 @@ #include enum { PTHREAD_MUTEX_NORMAL, PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_ERRORCHECK, - PTHREAD_MUTEX_SPINLOCK_NP, PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL }; + PTHREAD_MUTEX_SPINLOCK_NP, PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL}; + +#ifdef _RTL_POSIX_APP_SCHEDULING +// POSIX APPLICATION SCHEDULING MUTEX PARAMETERS STRUCT. +struct pthread_mutex_schedparam { + void *sched_param; + size_t param_size; +}; +// POSIX APPLICATION SCHEDULING MUTEX DATA STRUCT. +struct posix_appsched_mutex_data_struct { + struct pthread_mutex_schedparam appsched_param; + struct rtl_thread_struct *posix_appscheduler; + struct rtl_thread_struct *owner; + void *tsd; +}; +#define mutex_appscheduler(m) (m->appsched_data.posix_appscheduler) +#define mutex_owner(m) (m->appsched_data.owner) +#endif typedef struct { int type; int pshared; int protocol; int prioceiling; +#ifdef _RTL_POSIX_APP_SCHEDULING + struct pthread_mutex_schedparam appsched_param; + struct rtl_thread_struct *posix_appscheduler; +#endif } pthread_mutexattr_t; #define PTHREAD_PROCESS_PRIVATE 0 @@ -61,13 +82,19 @@ int protocol; int prioceiling; int oldprio; +#ifdef _RTL_POSIX_APP_SCHEDULING + struct posix_appsched_mutex_data_struct appsched_data; +#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 +#ifdef _RTL_POSIX_APP_SCHEDULING +, PTHREAD_APPSCHED_PROTOCOL +#endif +}; static inline int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) { @@ -132,10 +159,16 @@ static inline int pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr, int protocol) { -#ifndef _RTL_POSIX_THREAD_PRIO_PROTECT +#ifndef _RTL_POSIX_THREAD_PRIO_PROTECT +#ifndef _RTL_POSIX_APP_SCHEDULING return ENOTSUP; #endif - if (protocol != PTHREAD_PRIO_PROTECT && protocol != PTHREAD_PRIO_NONE) { +#endif + if (protocol != PTHREAD_PRIO_PROTECT && protocol != PTHREAD_PRIO_NONE +#ifdef _RTL_POSIX_APP_SCHEDULING + && protocol != PTHREAD_APPSCHED_PROTOCOL +#endif +) { return ENOTSUP; } attr->protocol = protocol; @@ -224,6 +257,63 @@ extern int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime); + +#ifdef _RTL_POSIX_APP_SCHEDULING +/* Application-defined Mutex Protocol */ +extern inline int pthread_mutexattr_setappscheduler (pthread_mutexattr_t *attr, struct rtl_thread_struct * appscheduler){ + if (appscheduler && attr){ + attr->posix_appscheduler=appscheduler; + return 0; + } + errno=EFAULT; + return -1; +} +extern inline int pthread_mutexattr_getappscheduler (const pthread_mutexattr_t *attr, struct rtl_thread_struct * *appscheduler){ + if (appscheduler && attr){ + *appscheduler=attr->posix_appscheduler; + return 0; + } + errno=EFAULT; + return -1; +} +extern inline int pthread_mutexattr_setappschedparam (pthread_mutexattr_t *attr, const struct pthread_mutex_schedparam *sched_param){ + if (sched_param && attr){ + attr->appsched_param=*sched_param; + return 0; + } + errno=EFAULT; + return -1; +} +extern inline int pthread_mutexattr_getappschedparam (const pthread_mutexattr_t *attr, struct pthread_mutex_schedparam *sched_param){ + if (sched_param && attr){ + *sched_param=attr->appsched_param; + return 0; + } + errno=EFAULT; + return -1; +} +extern inline int pthread_mutex_setappschedparam (pthread_mutex_t *mutex, const struct pthread_mutex_schedparam *sched_param); + +extern inline int pthread_mutex_getappschedparam (const pthread_mutex_t *mutex, struct pthread_mutex_schedparam *sched_param){ + if (sched_param && mutex){ + *sched_param=mutex->appsched_data.appsched_param; + return 0; + } + errno=EFAULT; + return -1; +} + +// Set mutex-specific data +extern inline int posix_appsched_mutex_setspecific (pthread_mutex_t *mutex,void *value ){ + mutex->appsched_data.tsd=value; + return 0; +} +// Get mutex-specific data +extern inline int posix_appsched_mutex_getspecific (const pthread_mutex_t *mutex, void **data){ + *data=mutex->appsched_data.tsd; + return 0; +} +#endif #endif diff -BNru rtlinux-3.1/include/rtl_sched.h appsched_rt/include/rtl_sched.h --- rtlinux-3.1/include/rtl_sched.h Tue Feb 18 08:48:24 2003 +++ appsched_rt/include/rtl_sched.h Tue Feb 18 08:55:02 2003 @@ -5,6 +5,8 @@ * Copyright (C) Finite State Machine Labs Inc., 1998-1999 * Released under the terms of the GPL Version 2 * + * Added POSIX-Compatible application scheduling support + * Dec, 2002 J. Vidal (OCERA) */ #ifndef __RTL__SCHED__ @@ -24,7 +26,12 @@ #include #include #include +#ifndef _RTL_POSIX_APP_SCHEDULING #include +#else +#include +#include +#endif #include #include @@ -39,6 +46,9 @@ #include #endif +#ifdef _RTL_POSIX_APP_SCHEDULING +#define SCHED_APP 3 +#endif #define rtl_sched_param sched_param #define TIMER_ABSTIME 1 @@ -60,12 +70,97 @@ #include +#ifdef _RTL_POSIX_APP_SCHEDULING + +// POSIX APPLICATION SCHEDULING PARAMETERS STRUCT. +struct posix_appsched_param_struct { + pthread_t posix_appscheduler; + void *posix_appsched_param; + unsigned int posix_appsched_paramsize; +}; + +#define MAX_SCHEDULEDTHREADS_X_APPSCHEDULER 50 +/* This is a very pesimystic quote for the event queue size. + TODO: try to make a better, more realystic quote. + */ +#define APPSCHED_EVENT_QUEUE_SIZE (MAX_SCHEDULEDTHREADS_X_APPSCHEDULER + 1) + +/* Scheduling Events */ +union posix_appsched_eventinfo { + int sched_priority; + siginfo_t siginfo; + pthread_mutex_t *mutex; + void *info; +}; + +struct posix_appsched_event { + int event_code; + pthread_t thread; + union posix_appsched_eventinfo event_info; + size_t info_size; +}; + + +typedef struct events_queue_struct { + struct posix_appsched_event c_array[APPSCHED_EVENT_QUEUE_SIZE]; + unsigned int rear; + unsigned int front; + unsigned int size; +} event_queue_t; + +#define PTHREAD_APPSCHEDULER 1 +#define PTHREAD_REGULAR 2 +#define appscheduler(t) (t->appsched.appsched_param.posix_appscheduler) +#define regular_thread(t) (t->appsched.type==PTHREAD_REGULAR) +#define appscheduler_thread(t) (t->appsched.type==PTHREAD_APPSCHEDULER) +#define system_scheduled_thread(t) (t->appsched.type==0) + +/* The event codes are defined in the following here. */ +enum rtl_appsched_events_enum { + POSIX_APPSCHED_NEW , + POSIX_APPSCHED_TERMINATE , + POSIX_APPSCHED_READY , + POSIX_APPSCHED_BLOCK , + POSIX_APPSCHED_YIELD , + POSIX_APPSCHED_SIGNAL , + POSIX_APPSCHED_CHANGE_SCHED_PARAM , + POSIX_APPSCHED_EXPLICIT_CALL , + POSIX_APPSCHED_TIMEOUT , + POSIX_APPSCHED_PRIORITY_INHERIT , + POSIX_APPSCHED_PRIORITY_UNINHERIT , + POSIX_APPSCHED_INIT_MUTEX , + POSIX_APPSCHED_DESTROY_MUTEX , + POSIX_APPSCHED_LOCK_MUTEX , + POSIX_APPSCHED_TRY_LOCK_MUTEX , + POSIX_APPSCHED_UNLOCK_MUTEX , + POSIX_APPSCHED_BLOCK_AT_MUTEX , + POSIX_APPSCHED_CHANGE_SCHED_PARAM_MUTEX +}; + +enum rtl_appsched_thread_status_t { UNINITIALITZED, READY, APPSCHED_SUSPENDED, WAITING_TO_LOCK_APPSCHED_MUTEX, TRYING_TO_LOCK_APPSCHED_MUTEX }; + +struct rtl_appsched_data_struct { + struct posix_appsched_param_struct appsched_param; + struct events_queue_struct *events; // events repository. + pthread_mutex_t *appsched_mutex_where_waiting; + rtl_sigset_t events_mask; + int status; + clockid_t clockid; + int type; + int flags; +}; + +#endif + struct rtl_thread_struct { int *stack; /* hardcoded */ int fpu_initialized; RTL_FPU_CONTEXT fpu_regs; int uses_fp; int *kmalloc_stack_bottom; +#ifdef _RTL_POSIX_APP_SCHEDULING + struct rtl_appsched_data_struct appsched; +#endif struct rtl_sched_param sched_param; struct rtl_thread_struct *next; int cpu; @@ -240,9 +335,17 @@ extern int pthread_cancel (pthread_t thread); extern void pthread_testcancel(void); +#ifdef _RTL_POSIX_APP_SCHEDULING +/* Scheduling events sets */ +#define posix_appsched_eventset_t rtl_sigset_t +#endif + typedef struct STRUCT_PTHREAD_ATTR { size_t stack_size; void *stack_addr; +#ifdef _RTL_POSIX_APP_SCHEDULING + struct rtl_appsched_data_struct appsched; +#endif struct rtl_sched_param sched_param; int cpu; int use_fp; @@ -255,6 +358,14 @@ attr->stack_addr = 0; attr->stack_size = 20480; attr->sched_param.sched_priority = sched_get_priority_min(0); +#ifdef _RTL_POSIX_APP_SCHEDULING + attr->appsched.type=0; + attr->appsched.status=0; + attr->appsched.flags=0; + attr->appsched.appsched_param.posix_appscheduler=NULL; + attr->appsched.appsched_param.posix_appsched_param=NULL; + attr->appsched.appsched_param.posix_appsched_paramsize=0; +#endif attr->cpu = rtl_getcpuid(); rtl_sigemptyset(&attr->initial_state); rtl_sigaddset(&attr->initial_state, RTL_SIGNAL_READY); @@ -324,27 +435,17 @@ extern int sched_yield(void); - -extern inline int pthread_setschedparam(pthread_t thread, int policy, - const struct rtl_sched_param *param) { - thread->sched_param = *param; - return 0; -} - -extern inline int pthread_getschedparam(pthread_t thread, int *policy, - struct rtl_sched_param *param) { - *param = thread->sched_param; - return 0; +extern inline int pthread_getschedparam(pthread_t thread, int *policy, struct rtl_sched_param *param) { + *param = thread->sched_param; + return 0; } -extern inline int pthread_attr_setschedparam(pthread_attr_t *attr, - const struct rtl_sched_param *param) { +extern inline int pthread_attr_setschedparam(pthread_attr_t *attr, const struct rtl_sched_param *param) { attr->sched_param = *param; return 0; } -extern inline int pthread_attr_getschedparam(const pthread_attr_t *attr, - struct rtl_sched_param *param) { +extern inline int pthread_attr_getschedparam(const pthread_attr_t *attr, struct rtl_sched_param *param) { *param = attr->sched_param; return 0; } @@ -417,67 +518,225 @@ } -#endif - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +/* POSIX APPLICATION DEFINED SCHEDULING */ +#ifdef _RTL_POSIX_APP_SCHEDULING +extern inline int pthread_remote_setspecific(pthread_key_t key,pthread_t th,void *value){ + th->tsd[key] = (void *) value; + return 0; +} +extern inline void *pthread_remote_getspecific(pthread_key_t key,pthread_t th) { + return th->tsd[key]; +} +#define pthread_setspecific_for(k,th,data) pthread_remote_setspecific(k,th,data) +#define pthread_getspecific_from(k,th,data) ({int err=0; if (data) *data=pthread_remote_getspecific(k,th); else err=-1; err;}) +/* + * Application-defined scheduling policy + */ +#define MAX_APPSCHED_EVENTS 18 +#define MAX_APPSCHED_ACTIONS_X_SCHEDULED_THREAD 3 +enum rtl_appsched_actions_enum { + POSIX_APPSCHED_ACTIVATE , + POSIX_APPSCHED_SUSPEND , + POSIX_APPSCHED_LOCK , + POSIX_APPSCHED_INVOKE_SCHEDULER , + + }; + +/* Scheduling actions */ + struct rtlinux_appsched_actions_struct { + int action; + pthread_t thread; + pthread_mutex_t *mutex; + void *msg; + int msg_size; +}; +typedef struct rtlinux_appsched_actions_struct posix_appsched_action; +/* + ************************************************************** + Queues managment for application schedulers actions threatment. + ************************************************************** +*/ +/* This is a very pesimystic quote for the action queue size. + TODO: try to make a better, more realystic quote. + */ +#define APPSCHED_ACTION_QUEUE_SIZE (MAX_SCHEDULEDTHREADS_X_APPSCHEDULER *MAX_APPSCHED_ACTIONS_X_SCHEDULED_THREAD + 1) +typedef struct actions_queue_struct { + unsigned int rear; + unsigned int front; + unsigned int size; + posix_appsched_action c_array[APPSCHED_ACTION_QUEUE_SIZE]; +} action_queue_t; + +#define posix_appsched_actions_t action_queue_t +#define rtl_init_queue(q,s) do {q->rear = 0; q->front = 0; q->size=s;} while (0) +#define rtl_init_actions_queue(q) rtl_init_queue(q, APPSCHED_ACTION_QUEUE_SIZE) + +#define APPSCHED_ACTIONS_LIST_SIZE MAX_SCHEDULEDTHREADS_X_APPSCHEDULER*MAX_APPSCHED_ACTIONS + +extern int posix_appsched_actions_init (posix_appsched_actions_t *sched_actions); +extern int posix_appsched_actions_destroy (posix_appsched_actions_t *sched_actions); + +extern int posix_appsched_actions_addactivate(posix_appsched_actions_t *sched_actions, pthread_t thread); +extern int posix_appsched_actions_addsuspend (posix_appsched_actions_t *sched_actions, + pthread_t thread); +extern int posix_appsched_actions_addlock (posix_appsched_actions_t *sched_actions, + pthread_t thread, + /*const*/ pthread_mutex_t *mutex); + +/* Explicit Scheduler Invocation */ +extern int posix_appsched_invoke_scheduler (void * msg, size_t msg_size); + +/* Execute Scheduling Actions */ +extern int posix_appsched_execute_actions (/*const*/ posix_appsched_actions_t *sched_actions, + const rtl_sigset_t *set, + const struct timespec *timeout, + struct timespec *current_time, + struct posix_appsched_event *event); +/* + * Scheduler attributes + */ +/* Scheduler clock */ +extern inline int posix_appschedattr_setclock (clockid_t clockid){ + //(clockid == CLOCK_REALTIME || clockid == CLOCK_MONOTONIC) + pthread_self()->appsched.clockid=clockid; + return 0; +} + +extern inline int posix_appschedattr_getclock (clockid_t *clockid){ + if (clockid) { + *clockid= pthread_self()->appsched.clockid; + } + return 0; +} + +/* extern inline int posix_getcpuclock_id(pthread_t th,clockid_t *clock_id){ */ +/* if (clockid) { */ +/* *clock_id= th->clockid; */ +/* } */ +/* return 0; */ +/* } */ + +/* Scheduler flags */ +#define POSIX_APPSCHED_PREEMPTION_TIMESTAMP 0 +#define POSIX_APPSCHED_ABSTIMEOUT 1 +extern inline int posix_appschedattr_setflags (int flags){ + pthread_self()->appsched.flags=flags; + return 0; +} +extern inline int posix_appschedattr_getflags (int *flags){ + if (flags){ + *flags=pthread_self()->appsched.flags; + } + return 0; +} + +/* Scheduler events mask */ + +/* Scheduling events sets manipulation */ +#define posix_appsched_eventset_t rtl_sigset_t +#define posix_appsched_emptyset(set) rtl_emptyset(set) +#define posix_appsched_fillset(set) rtl_sigfillset(set) +#define posix_appsched_addset(set,appsched_event) rtl_sigaddset(set,appsched_event) +#define posix_appsched_delset(set,appsched_event) rtl_sigdelset(set,appsched_event) +#define posix_appsched_ismember(set,appsched_event) rtl_sigismember(set,appsched_event) + +extern inline int posix_appschedattr_seteventmask (posix_appsched_eventset_t *set){ + if (set){ + pthread_self()->appsched.events_mask=*set; + return 0; + }else { + errno=EFAULT; + return -1; + } +} + +extern inline int posix_appschedattr_geteventmask (posix_appsched_eventset_t *set){ + if (set){ + *set= pthread_self()->appsched.events_mask; + } + return 0; +} + +/* + ************************************************************** + Queues managment for application schedulers events threatment. + ************************************************************** +*/ + +#define QUEUE_FULL -1 +#define QUEUE_EMPTY -2 +#define rtl_init_events_queue(q) rtl_init_queue(q,APPSCHED_EVENT_QUEUE_SIZE) +extern int generate_event(pthread_t th,pthread_t appscheduler,int code,union posix_appsched_eventinfo *info, size_t info_size); + +extern inline int pthread_attr_setappschedulerstate(pthread_attr_t *attr, int type){ +if (attr) { + attr->appsched.type=type; +} + return 0; +} + +extern inline int pthread_attr_setappscheduler(pthread_attr_t *attr, pthread_t sched){ +if (attr) { + attr->appsched.appsched_param.posix_appscheduler=sched; +} + return 0; +} + +extern inline int pthread_attr_setappschedparam(pthread_attr_t *attr, void *param, int size){ + if (attr) { + attr->appsched.appsched_param.posix_appsched_param= kmalloc (size, GFP_KERNEL); + memcpy(attr->appsched.appsched_param.posix_appsched_param,param,size); + attr->appsched.appsched_param.posix_appsched_paramsize=size; + } + return 0; +} + +extern inline int pthread_attr_getappscheduler(pthread_attr_t *attr, pthread_t *sched) { + if (sched) { + *sched= attr->appsched.appsched_param.posix_appscheduler; + } + return 0; +} + +extern inline int pthread_getappschedparam(pthread_t thread, void *param,int *size){ + if ((thread)->magic == RTL_THREAD_MAGIC){ + if (param){ + memcpy(param,thread->appsched.appsched_param.posix_appsched_param,thread->appsched.appsched_param.posix_appsched_paramsize); + } + if (size){ + *size= thread->appsched.appsched_param.posix_appsched_paramsize; + } + return 0; + } + else + return -1; +} +#endif +extern inline int pthread_setschedparam(pthread_t thread, int policy, + const struct rtl_sched_param *param) { +#ifdef _RTL_POSIX_APP_SCHEDULING + union posix_appsched_eventinfo event_info; + event_info.sched_priority=param->sched_priority; + generate_event(thread,appscheduler(thread),POSIX_APPSCHED_CHANGE_SCHED_PARAM,&event_info,sizeof(event_info)); +#endif + + thread->sched_param = *param; + return 0; +} +#endif diff -BNru rtlinux-3.1/monitor/Makefile appsched_rt/monitor/Makefile --- rtlinux-3.1/monitor/Makefile Mon Feb 17 17:58:54 2003 +++ appsched_rt/monitor/Makefile Tue Feb 18 08:55:01 2003 @@ -1,6 +1,6 @@ # (c) Victor Yodaiken 1998, Released under GPL -all: rtl_time.o rtl_sched.o rtl_timer.o reader +all: rtl_time.o rtl_timer.o rtl_appsched.o rtl_sched.o reader u_reader clean: rm -f *.o @@ -23,8 +23,8 @@ depend: rtl_sched.o $(CC) ${INCLUDE} ${CFLAGS} -M rtl_sched.c > .depends -rtl_sched.o: rtl_sched_tmp.o switch.o sw.o rtl_mutex.o unistd.o signal.o rtl_sema.o rtl_posix.o rtl_timer.o $(LIBGCC) - $(LD) $(LDFLAGS) -r -o rtl_sched.o rtl_sched_tmp.o switch.o sw.o rtl_mutex.o unistd.o signal.o rtl_sema.o rtl_posix.o rtl_timer.o -static ${LIBGCC} +rtl_sched.o: rtl_sched_tmp.o switch.o sw.o rtl_mutex.o unistd.o signal.o rtl_sema.o rtl_posix.o rtl_timer.o rtl_appsched.o $(LIBGCC) + $(LD) $(LDFLAGS) -r -o rtl_sched.o rtl_sched_tmp.o switch.o sw.o rtl_mutex.o unistd.o signal.o rtl_sema.o rtl_posix.o rtl_timer.o rtl_appsched.o -static ${LIBGCC} cp -f rtl_sched.o ../modules/ rtl_sched_tmp.o: rtl_sched.c ../include/rtl_sched.h $(CC) ${INCLUDE} ${CFLAGS} -o rtl_sched_tmp.o -c rtl_sched.c @@ -52,21 +52,16 @@ $(CC) ${INCLUDE} ${CFLAGS} -o rtl_timer_tmp.o -c rtl_timer.c $(LD) -r -o rtl_timer.o rtl_timer_tmp.o $(LIBGCC) +rtl_appsched.o: rtl_appsched.c ../include/rtl_sched.h + $(CC) ${INCLUDE} ${CFLAGS} -o rtl_appsched.o -c rtl_appsched.c + #read activations from rtlinux. reader: reader.c gcc -I${INCLUDE} -o reader reader.c #CPU USAGE from rtlinux. u_reader: u_reader.c - gcc -I${INCLUDE} -o u_reader u_reader.c - -# usage.o: usage.c -# $(CC) ${INCLUDE} ${CFLAGS} -c usage.c -# mv usage.o aux -# ld -i -o usage.o aux /usr/lib/gcc-lib/i386-linux/2.95.4/libgcc.a -# rm aux - - + gcc -O2 -fno-strict-aliasing -o u_reader u_reader.c install: rtl_sched.o install -c -m 644 rtl_sched.o ${RTL_DIR}/modules diff -BNru rtlinux-3.1/monitor/rtl_mutex.c appsched_rt/monitor/rtl_mutex.c --- rtlinux-3.1/monitor/rtl_mutex.c Thu Jul 26 21:32:41 2001 +++ appsched_rt/monitor/rtl_mutex.c Tue Feb 18 08:55:02 2003 @@ -92,18 +92,36 @@ attr->pshared = PTHREAD_PROCESS_SHARED; attr->protocol = PTHREAD_PRIO_NONE; attr->prioceiling = sched_get_priority_max(SCHED_FIFO); +#ifdef _RTL_POSIX_APP_SCHEDULING + attr->posix_appscheduler=NULL; + attr->appsched_param.sched_param=NULL; + attr->appsched_param.param_size=0; +#endif return 0; } int pthread_mutex_destroy(pthread_mutex_t *mutex) { + #ifdef _RTL_POSIX_APP_SCHEDULING + union posix_appsched_eventinfo event_info; +#endif + mutex->valid = 0; +#ifdef _RTL_POSIX_APP_SCHEDULING + //Inform to the scheduler the thread is destroying this mutex. + event_info.mutex=mutex; + generate_event(pthread_self(),mutex_appscheduler(mutex), POSIX_APPSCHED_DESTROY_MUTEX,&event_info,sizeof(event_info)); + rtl_schedule(); +#endif return 0; } int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) { +#ifdef _RTL_POSIX_APP_SCHEDULING + union posix_appsched_eventinfo event_info; +#endif pthread_mutexattr_t defattr; mutex->valid = 1; mutex->busy = 0; @@ -117,21 +135,68 @@ mutex->type = attr->type; mutex->protocol = attr->protocol; mutex->prioceiling = attr->prioceiling; +#ifdef _RTL_POSIX_APP_SCHEDULING + mutex->appsched_data.owner=NULL; + mutex->appsched_data.appsched_param=attr->appsched_param; + mutex->appsched_data.posix_appscheduler=attr->posix_appscheduler; + //Inform to the scheduler the thread is initializating this mutex. + event_info.mutex=mutex; + generate_event(pthread_self(),mutex_appscheduler(mutex), POSIX_APPSCHED_INIT_MUTEX,&event_info,sizeof(event_info)); + rtl_schedule(); +#endif return 0; } +#ifdef _RTL_POSIX_APP_SCHEDULING +inline int pthread_mutex_setappschedparam (pthread_mutex_t *mutex, const struct pthread_mutex_schedparam *sched_param){ + + union posix_appsched_eventinfo event_info; + pthread_t self=pthread_self(); + + if (mutex && sched_param){ + if (mutex->protocol == PTHREAD_APPSCHED_PROTOCOL && + self != &(rtl_sched[rtl_getcpuid()].rtl_linux_task) && + (mutex_appscheduler(mutex) != self && + mutex_appscheduler(mutex) != appscheduler(self))){ + /* + The parameters of an appmutex only can be changed from its + scheduler task or other task associated with its scheduler. + Linux thread is treated special. + */ + + return EPERM; + } + + mutex->appsched_data.appsched_param=*sched_param; + // Inform to the application-scheduler + event_info.mutex=mutex; + generate_event(self,mutex_appscheduler(mutex),POSIX_APPSCHED_CHANGE_SCHED_PARAM_MUTEX,&event_info,sizeof(event_info)); + rtl_schedule(); + return 0; + } + errno=EFAULT; + return -1; +} +#endif static inline int __pthread_mutex_trylock(pthread_mutex_t *mutex) { #ifdef _RTL_POSIX_THREAD_PRIO_PROTECT /* if _RTL_POSIX_THREAD_PRIO_PROTECT, this code is protected by a spinlock */ +#ifdef _RTL_POSIX_APP_SCHEDULING + union posix_appsched_eventinfo event_info; +#endif if (mutex->protocol == PTHREAD_PRIO_PROTECT) { if (RTL_PRIO(RTL_CURRENT) > mutex->prioceiling) { return EINVAL; } - mutex->oldprio = RTL_PRIO (RTL_CURRENT); RTL_PRIO (RTL_CURRENT) = mutex->prioceiling; +#ifdef _RTL_POSIX_APP_SCHEDULING + event_info.mutex=mutex; + event_info.sched_priority= mutex->prioceiling; + generate_event(RTL_CURRENT,appscheduler(RTL_CURRENT), POSIX_APPSCHED_PRIORITY_INHERIT,&event_info,sizeof(event_info)); +#endif } #endif if (test_and_set_bit(0, &mutex->busy)) { @@ -144,9 +209,13 @@ { rtl_irqstate_t flags; int ret; +#ifdef _RTL_POSIX_APP_SCHEDULING + pthread_t self=pthread_self(); + union posix_appsched_eventinfo event_info; +#endif switch (mutex->type) { - case PTHREAD_MUTEX_SPINLOCK_NP: - rtl_no_interrupts (flags); + case PTHREAD_MUTEX_SPINLOCK_NP: + rtl_no_interrupts (flags); if (rtl_spin_trylock(&mutex->lock)) { rtl_restore_interrupts (flags); return EBUSY; @@ -157,6 +226,39 @@ break; case PTHREAD_MUTEX_NORMAL: default: +#ifdef _RTL_POSIX_APP_SCHEDULING + if (mutex->protocol == PTHREAD_APPSCHED_PROTOCOL){ + // Error check. + /*if (!mutex->valid) { + return EINVAL; + }*/ + if (appscheduler(self)!=mutex_appscheduler(mutex) || + mutex_owner(mutex)!=self) { + return EPERM; + } + + rtl_spin_lock_irqsave (&mutex->lock, flags); + if (mutex_owner(mutex)) { + ret=EBUSY; + } else { + //Mutex free. Thread gets blocked. + self->appsched.appsched_mutex_where_waiting=mutex; + self->appsched.status=TRYING_TO_LOCK_APPSCHED_MUTEX; + RTL_MARK_SUSPENDED(self); + //Inform to the scheduler the task is trying to lock the mutex. + event_info.mutex=mutex; + generate_event(self,mutex_appscheduler(mutex),POSIX_APPSCHED_TRY_LOCK_MUTEX,&event_info,sizeof(event_info)); + //Leave the CPU and let the appscheduler to execute + rtl_schedule(); + self->appsched.appsched_mutex_where_waiting=NULL; + // Has the task successfully locked the mutex ? + ret=((self==mutex_owner(mutex))? 0 : EBUSY); + } + + rtl_spin_unlock_irqrestore(&mutex->lock, flags); + return ret; + } +#endif #ifdef _RTL_POSIX_THREAD_PRIO_PROTECT rtl_spin_lock_irqsave (&mutex->lock, flags); #endif @@ -173,6 +274,10 @@ { rtl_irqstate_t flags; int ret; +#ifdef _RTL_POSIX_APP_SCHEDULING + pthread_t self=pthread_self(); + union posix_appsched_eventinfo event_info; +#endif switch (mutex->type) { case PTHREAD_MUTEX_SPINLOCK_NP: @@ -182,11 +287,38 @@ return 0; case PTHREAD_MUTEX_NORMAL: default: - if (!mutex->valid) { + if (!mutex->valid) { return EINVAL; } - rtl_spin_lock_irqsave (&mutex->lock, flags); +#ifdef _RTL_POSIX_APP_SCHEDULING + if (mutex->protocol == PTHREAD_APPSCHED_PROTOCOL){ + // Error check. + if (appscheduler(self)!=mutex_appscheduler(mutex)) { + rtl_spin_unlock_irqrestore (&mutex->lock, flags); + return EPERM; + } + self->appsched.appsched_mutex_where_waiting=mutex; + self->appsched.status=WAITING_TO_LOCK_APPSCHED_MUTEX; + RTL_MARK_SUSPENDED(self); + event_info.mutex=mutex; + if (mutex_owner(mutex)){ + //Inform to the scheduler the task has blocked at the mutex. + generate_event(self,mutex_appscheduler(mutex),POSIX_APPSCHED_BLOCK_AT_MUTEX,&event_info,sizeof(event_info)); + } else { + // Inform to the scheduler the task wants to lock the mutex. + generate_event(self,mutex_appscheduler(mutex),POSIX_APPSCHED_LOCK_MUTEX,&event_info,sizeof(event_info)); + } + //Leave the CPU and let the appscheduler to execute + rtl_schedule(); + // When the locking task resume execution here is with the + // mutex taken (it has been given in posix_appsched_execute_actions) + self->appsched.appsched_mutex_where_waiting=NULL; + rtl_spin_unlock_irqrestore (&mutex->lock, flags); + return 0; + } +#endif + while ((ret = __pthread_mutex_trylock(mutex))) { if (ret == EINVAL) { rtl_spin_unlock_irqrestore(&mutex->lock, flags); @@ -206,6 +338,10 @@ int pthread_mutex_unlock(pthread_mutex_t *mutex) { rtl_irqstate_t flags; +#ifdef _RTL_POSIX_APP_SCHEDULING + pthread_t self=pthread_self(); + union posix_appsched_eventinfo event_info; +#endif switch (mutex->type) { case PTHREAD_MUTEX_SPINLOCK_NP: @@ -220,9 +356,31 @@ } rtl_spin_lock_irqsave (&mutex->lock, flags); +#ifdef _RTL_POSIX_APP_SCHEDULING + if (mutex->protocol == PTHREAD_APPSCHED_PROTOCOL) { + if (appscheduler(self)!=mutex_appscheduler(mutex) || + mutex_owner(mutex)!=self) { + rtl_spin_unlock_irqrestore (&mutex->lock, flags); + return EPERM; + } + // Free the mutex. The thread gives up ownership of mutex. + mutex_owner(mutex)=NULL; + // Inform to the scheduler the task has unlocked the mutex. + event_info.mutex=mutex; + generate_event(self,mutex_appscheduler(mutex),POSIX_APPSCHED_UNLOCK_MUTEX,&event_info,sizeof(event_info)); + rtl_schedule(); + rtl_spin_unlock_irqrestore (&mutex->lock, flags); + return 0; + } +#endif #ifdef _RTL_POSIX_THREAD_PRIO_PROTECT if (mutex->protocol == PTHREAD_PRIO_PROTECT) { RTL_PRIO(RTL_CURRENT) = mutex->oldprio; +#ifdef _RTL_POSIX_APP_SCHEDULING + event_info.mutex=mutex; + event_info.sched_priority= mutex->oldprio; + generate_event(RTL_CURRENT,appscheduler(RTL_CURRENT), POSIX_APPSCHED_PRIORITY_UNINHERIT,&event_info,sizeof(event_info)); +#endif } #endif clear_bit (0, &mutex->busy); @@ -367,7 +525,7 @@ const pthread_condattr_t *attr) { rtl_wait_init(&cond->wait); - spin_lock_init(&cond->lock); + spin_lock_init(&cond->lock); return 0; } diff -BNru rtlinux-3.1/monitor/rtl_sched.c appsched_rt/monitor/rtl_sched.c --- rtlinux-3.1/monitor/rtl_sched.c Mon Feb 17 17:58:54 2003 +++ appsched_rt/monitor/rtl_sched.c Tue Feb 18 08:55:01 2003 @@ -13,6 +13,15 @@ * Copyright (C) Finite State Machine Labs Inc., 1998,1999 * Released under the terms of the GNU General Public License Version 2 * + * Added user signals support - Dec, 2002 Josep Vidal (OCERA) + * Added POSIX timers support - Dec, 2002 Josep Vidal (OCERA) + * Added Application-defined scheduling support - Jan, 2003 Josep Vidal (OCERA) + * + * Fixed stack overflow when sending RTL_SIGNAL_SUSPEND signal. J. Vidal (OCERA) + * Fixed mutex bug when setting t->do_abort=0 on do_signal. J. Vidal (OCERA) + * Fixed long long casting in usleep P. Mendoza & J. Vidal (OCERA) + * thanks to I. Ripoll, P. Mendoza & P. Perez + * See example/bug directory for more info. */ /* for tracing tasks scheduling events */ /* J. Vidal */ @@ -21,7 +30,7 @@ #include #include #include -#include +#include #include #include #include @@ -160,7 +168,7 @@ set_bit(signal, &thread->pending); #ifdef _RTL_POSIX_SIGNALS if ((signal >= RTL_SIGUSR1) && HIGHER_PRIORITY_THREAD(thread,pthread_self())) rtl_schedule(); -#endif +#endif return 0; } else if(thread != rtl_get_linux_thread(rtl_getcpuid())) { return EINVAL; @@ -240,6 +248,16 @@ /* rtl_printf("freeing %#x %#x\n", task->kmalloc_stack_bottom); */ kfree (task->kmalloc_stack_bottom); } +#ifdef _RTL_POSIX_APP_SCHEDULING + if (appscheduler_thread(task) && task->appsched.events){ +/* rtl_printf("freeing appsched events %#x %#x\n", task->appsched.events); */ + kfree(task->appsched.events); + } + if (regular_thread(task) && task->appsched.appsched_param.posix_appsched_param){ +/* rtl_printf("freeing appsched params %#x %#x\n", task->appsched.appsched_param.posix_appsched_param); */ + kfree(task->appsched.appsched_param.posix_appsched_param); + } +#endif } @@ -288,7 +305,10 @@ rtl_sigfillset(&mask); pthread_sigmask(SIG_SETMASK,&mask,NULL); #endif - + +#ifdef _RTL_POSIX_APP_SCHEDULING + generate_event(pthread_self(),appscheduler(pthread_self()),POSIX_APPSCHED_TERMINATE,NULL,0); +#endif rtl_no_interrupts(flags); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); @@ -307,6 +327,12 @@ int sched_yield(void) { +#ifdef _RTL_POSIX_APP_SCHEDULING + int flags; + rtl_no_interrupts(flags); + generate_event(pthread_self(),appscheduler(pthread_self()),POSIX_APPSCHED_YIELD, NULL,0); + rtl_restore_interrupts(flags); +#endif rtl_schedule(); return 0; } @@ -445,12 +471,22 @@ int sig; unsigned long flags, initial_interrupt_state; void (*fun)(int)=NULL; - +#ifdef _RTL_POSIX_APP_SCHEDULING + union posix_appsched_eventinfo event_info; +#endif + rtl_no_interrupts(initial_interrupt_state); for (sig=RTL_MAX_SIGNAL;sig>=RTL_SIGUSR1;sig--){ if (test_bit(sig,&t->pending) && !test_bit(sig,&t->blocked)){ +#ifdef _RTL_POSIX_APP_SCHEDULING + event_info.siginfo.si_signo=sig; + if (appscheduler_thread(t)){ + generate_event(t,t,POSIX_APPSCHED_SIGNAL,&event_info,sizeof(event_info)); + } +#endif + if (rtl_sigact[sig].owner==t){ fun=rtl_sigact[sig].sa_handler; if (fun) { @@ -490,7 +526,10 @@ #ifdef _RTL_POSIX_TIMERS timer_t timer = 0; #endif - +#ifdef __CPU_USAGE + static hrtime_t last_sample=0; +#endif + idle: rtl_no_interrupts(interrupt_state); rtl_trace2 (RTL_TRACE_SCHED_IN, (long) pthread_self()); /* new_task = &sched->rtl_linux_task;*/ @@ -501,7 +540,34 @@ now = sched->clock->gethrtime(sched->clock); #ifdef __CPU_TRACER rt_print_exec(sched, now); - ini_time=now; +#ifdef __CPU_USAGE + t_u_counter[(int)sched->rtl_current->user[0]]+=now-ini_time; + { + unsigned int i=0; + hrtime_t time_diff=now-last_sample; + if (time_diff>=PERIOD){ +#ifdef __CPU_TRACER_DEBUG + rtl_printf("time_diff: %s PERIOD: %s now:%s last_sample:%s\n",lltostring(time_diff),lltostring(PERIOD),lltostring(now),lltostring(last_sample)); +#endif + + for (i=0; i<=ntasks; i++){ + t_usage[i]=(((t_u_counter[i]-last_t_u_counter[i])*UNIT)/time_diff); + last_t_u_counter[i]=t_u_counter[i]; +#ifdef __CPU_TRACER_DEBUG + rtl_printf("t_usage[%d]: %s t_u_counter[%d]: %s last_t_u_counter[%d]:%s\n",i,lltostring(t_usage[i]),i,lltostring(t_u_counter[i]),i,lltostring(last_t_u_counter[i])); + rtl_printf("s:%d t_usage[%d]=%d \n",sample,i,(int)t_usage[i]); +#endif + }// end for. + + rt_print_usage_request(); + + last_sample=now; + usage_window[sample%window_size]=t_usage[0]; + sample++; + } + }// end embedded code. +#endif + ini_time=now; #endif if (sched->clock->mode == RTL_CLOCK_MODE_ONESHOT) { sched->clock->value = now; @@ -540,9 +605,14 @@ } } - /* and find highest priority runnable task */ - if ((t->pending & ~t->blocked) && (!new_task || - (t->sched_param.sched_priority > new_task->sched_param.sched_priority))) { + /* and find highest priority runnable task */ + if ((t->pending & ~t->blocked) && (!new_task || + (t->sched_param.sched_priority > new_task->sched_param.sched_priority) +#ifdef _RTL_POSIX_APP_SCHEDULING + /* App scheduler always takes precedence over its scheduled threads*/ + || ((t->sched_param.sched_priority == new_task->sched_param.sched_priority) && (appscheduler(new_task) == t)) +#endif +)) { new_task = t; } } @@ -630,6 +700,18 @@ int pthread_suspend_np (pthread_t thread) { +#ifdef _RTL_POSIX_APP_SCHEDULING + int flags; + if (regular_thread(thread)){ + if (!test_bit (RTL_THREAD_FINISHED, &thread->threadflags)) { + rtl_no_interrupts(flags); + generate_event(thread,appscheduler(thread),POSIX_APPSCHED_SUSPEND,NULL,0); + rtl_restore_interrupts(flags); + } + return 0; + } +#endif + if (thread == pthread_self()) { RTL_MARK_SUSPENDED (pthread_self()); rtl_schedule(); @@ -642,6 +724,16 @@ int pthread_wakeup_np (pthread_t thread) { +#ifdef _RTL_POSIX_APP_SCHEDULING + int flags; + if (regular_thread(thread)){ + rtl_no_interrupts(flags); + generate_event(thread,appscheduler(thread),POSIX_APPSCHED_READY,NULL,0); + rtl_restore_interrupts(flags); + return 0; +} +#endif + #ifdef CONFIG_SMP if (thread->cpu != rtl_getcpuid()) { pthread_kill(thread,RTL_SIGNAL_WAKEUP); @@ -737,6 +829,26 @@ task->resume_time = HRTIME_INFINITY; task->period = 0; task->sched_param = attr->sched_param; + +#ifdef _RTL_POSIX_APP_SCHEDULING + task->appsched.appsched_param= attr->appsched.appsched_param; + task->appsched.type = attr->appsched.type; + + if (attr->appsched.type==PTHREAD_APPSCHEDULER) { + task->appsched.events_mask=0; + task->appsched.clockid=CLOCK_REALTIME; /* BE CAREFUL! must be changed */ + task->appsched.events=(event_queue_t *)kmalloc(sizeof(event_queue_t),GFP_KERNEL); + if (!task->appsched.events) return -1; + rtl_init_events_queue(task->appsched.events); + } else { + task->appsched.events=NULL; + + if (task->appsched.type) {//(type==PTHREAD_REGULAR) + generate_event(task,appscheduler(task),POSIX_APPSCHED_NEW, NULL,0); + } + } +#endif + task->stack = stack_addr + stack_size / sizeof(int); rtl_init_stack(task,start_routine, arg,rtl_startup); rtl_no_interrupts(interrupt_state); @@ -971,6 +1083,9 @@ #ifdef __CPU_TRACER int fifo; #endif +#ifdef __CPU_USAGE + int ufifo; +#endif #ifdef _RTL_POSIX_TIMERS rtl_spin_lock_init (&rtl_timer_list_lock); @@ -1010,6 +1125,12 @@ s -> rtl_linux_task . creator = 0; s -> rtl_linux_task . abort = 0; +#ifdef _RTL_POSIX_APP_SCHEDULING + s -> rtl_linux_task . appsched.appsched_param.posix_appscheduler = NULL; + s -> rtl_linux_task . appsched.type=0; + s -> rtl_linux_task . appsched.events=NULL; +#endif + s -> rtl_task_fpu_owner = &s->rtl_linux_task; s -> sched_flags = 0; rtl_posix_init (&s->rtl_linux_task); @@ -1044,6 +1165,10 @@ rtf_destroy (FIFO); fifo = rtf_create(FIFO, 32768); #endif +#ifdef __CPU_USAGE + rtf_destroy (UFIFO); + ufifo = rtf_create(UFIFO, 32768); +#endif /* rtl_setdebug (RTLDBG_ALL); */ return 0; } @@ -1068,6 +1193,9 @@ #ifdef __CPU_TRACER rtf_destroy (FIFO); #endif +#ifdef __CPU_USAGE + rtf_destroy (UFIFO); +#endif } int usleep (useconds_t interval) @@ -1080,7 +1208,7 @@ save_resume_time = th->resume_time; RTL_MARK_SUSPENDED(th); - __rtl_setup_timeout (th, gethrtime() + (long long) interval * 1000LL); + __rtl_setup_timeout (th, gethrtime() + (long long)interval * 1000LL); rtl_schedule(); pthread_testcancel(); diff -BNru rtlinux-3.1/monitor/rtl_timer.c appsched_rt/monitor/rtl_timer.c --- rtlinux-3.1/monitor/rtl_timer.c Tue Feb 18 08:48:23 2003 +++ appsched_rt/monitor/rtl_timer.c Tue Feb 18 08:55:02 2003 @@ -13,7 +13,7 @@ #include #ifdef _RTL_POSIX_TIMERS -#define _RTL_POSIX_TIMERS_DEBUG +//#define _RTL_POSIX_TIMERS_DEBUG /* Timer List Manipulation. */ struct rtl_timer_struct *timer_list_start=NULL; @@ -106,7 +106,7 @@ int timer_settime(timer_t timer_id, int flags, const struct itimerspec *new_setting, struct itimerspec *old_setting){ hrtime_t now=0; - + if (!timer_id){ errno=EINVAL; return -1; @@ -132,7 +132,7 @@ errno=EINVAL; return -1; } - + /* Check that it_value is different from 0, to program the timer. IF both are 0 timer is disarmed. @@ -172,9 +172,12 @@ } - /* For now, the schedule is called allways */ - clear_bit (RTL_SCHED_TIMER_OK, &sched_data((timer_id->owner)->cpu)->sched_flags); - rtl_schedule(); + + /* For now, the scheduler isn't called */ + clear_bit (RTL_SCHED_TIMER_OK, &sched_data((timer_id->owner)->cpu)->sched_flags); + /* + rtl_schedule(); + */ return 0; } diff -BNru rtlinux-3.1/schedulers/Makefile appsched_rt/schedulers/Makefile --- rtlinux-3.1/schedulers/Makefile Tue Feb 18 08:48:24 2003 +++ appsched_rt/schedulers/Makefile Tue Feb 18 08:55:02 2003 @@ -1,6 +1,6 @@ # (c) Victor Yodaiken 1998, Released under GPL -all: rtl_time.o rtl_timer.o rtl_sched.o +all: rtl_time.o rtl_timer.o rtl_appsched.o rtl_sched.o clean: rm -f *.o @@ -24,7 +24,7 @@ $(CC) ${INCLUDE} ${CFLAGS} -M rtl_sched.c > .depends rtl_sched.o: rtl_sched_tmp.o switch.o sw.o rtl_mutex.o unistd.o signal.o rtl_sema.o rtl_posix.o rtl_timer.o $(LIBGCC) - $(LD) $(LDFLAGS) -r -o rtl_sched.o rtl_sched_tmp.o switch.o sw.o rtl_mutex.o unistd.o signal.o rtl_sema.o rtl_posix.o rtl_timer.o -static ${LIBGCC} + $(LD) $(LDFLAGS) -r -o rtl_sched.o rtl_sched_tmp.o switch.o sw.o rtl_mutex.o unistd.o signal.o rtl_sema.o rtl_posix.o rtl_timer.o rtl_appsched.o -static ${LIBGCC} cp -f rtl_sched.o ../modules/ rtl_sched_tmp.o: rtl_sched.c ../include/rtl_sched.h @@ -51,6 +51,9 @@ rtl_timer.o: rtl_timer.c ../include/rtl_timer.h $(CC) ${INCLUDE} ${CFLAGS} -o rtl_timer.o -c rtl_timer.c + +rtl_appsched.o: rtl_appsched.c + $(CC) ${INCLUDE} ${CFLAGS} -o rtl_appsched.o -c rtl_appsched.c install: rtl_sched.o install -c -m 644 rtl_sched.o ${RTL_DIR}/modules diff -BNru rtlinux-3.1/schedulers/rtl_mutex.c appsched_rt/schedulers/rtl_mutex.c --- rtlinux-3.1/schedulers/rtl_mutex.c Thu Jul 26 21:32:41 2001 +++ appsched_rt/schedulers/rtl_mutex.c Tue Feb 18 08:55:02 2003 @@ -92,18 +92,36 @@ attr->pshared = PTHREAD_PROCESS_SHARED; attr->protocol = PTHREAD_PRIO_NONE; attr->prioceiling = sched_get_priority_max(SCHED_FIFO); +#ifdef _RTL_POSIX_APP_SCHEDULING + attr->posix_appscheduler=NULL; + attr->appsched_param.sched_param=NULL; + attr->appsched_param.param_size=0; +#endif return 0; } int pthread_mutex_destroy(pthread_mutex_t *mutex) { + #ifdef _RTL_POSIX_APP_SCHEDULING + union posix_appsched_eventinfo event_info; +#endif + mutex->valid = 0; +#ifdef _RTL_POSIX_APP_SCHEDULING + //Inform to the scheduler the thread is destroying this mutex. + event_info.mutex=mutex; + generate_event(pthread_self(),mutex_appscheduler(mutex), POSIX_APPSCHED_DESTROY_MUTEX,&event_info,sizeof(event_info)); + rtl_schedule(); +#endif return 0; } int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) { +#ifdef _RTL_POSIX_APP_SCHEDULING + union posix_appsched_eventinfo event_info; +#endif pthread_mutexattr_t defattr; mutex->valid = 1; mutex->busy = 0; @@ -117,21 +135,68 @@ mutex->type = attr->type; mutex->protocol = attr->protocol; mutex->prioceiling = attr->prioceiling; +#ifdef _RTL_POSIX_APP_SCHEDULING + mutex->appsched_data.owner=NULL; + mutex->appsched_data.appsched_param=attr->appsched_param; + mutex->appsched_data.posix_appscheduler=attr->posix_appscheduler; + //Inform to the scheduler the thread is initializating this mutex. + event_info.mutex=mutex; + generate_event(pthread_self(),mutex_appscheduler(mutex), POSIX_APPSCHED_INIT_MUTEX,&event_info,sizeof(event_info)); + rtl_schedule(); +#endif return 0; } +#ifdef _RTL_POSIX_APP_SCHEDULING +inline int pthread_mutex_setappschedparam (pthread_mutex_t *mutex, const struct pthread_mutex_schedparam *sched_param){ + + union posix_appsched_eventinfo event_info; + pthread_t self=pthread_self(); + + if (mutex && sched_param){ + if (mutex->protocol == PTHREAD_APPSCHED_PROTOCOL && + self != &(rtl_sched[rtl_getcpuid()].rtl_linux_task) && + (mutex_appscheduler(mutex) != self && + mutex_appscheduler(mutex) != appscheduler(self))){ + /* + The parameters of an appmutex only can be changed from its + scheduler task or other task associated with its scheduler. + Linux thread is treated special. + */ + + return EPERM; + } + + mutex->appsched_data.appsched_param=*sched_param; + // Inform to the application-scheduler + event_info.mutex=mutex; + generate_event(self,mutex_appscheduler(mutex),POSIX_APPSCHED_CHANGE_SCHED_PARAM_MUTEX,&event_info,sizeof(event_info)); + rtl_schedule(); + return 0; + } + errno=EFAULT; + return -1; +} +#endif static inline int __pthread_mutex_trylock(pthread_mutex_t *mutex) { #ifdef _RTL_POSIX_THREAD_PRIO_PROTECT /* if _RTL_POSIX_THREAD_PRIO_PROTECT, this code is protected by a spinlock */ +#ifdef _RTL_POSIX_APP_SCHEDULING + union posix_appsched_eventinfo event_info; +#endif if (mutex->protocol == PTHREAD_PRIO_PROTECT) { if (RTL_PRIO(RTL_CURRENT) > mutex->prioceiling) { return EINVAL; } - mutex->oldprio = RTL_PRIO (RTL_CURRENT); RTL_PRIO (RTL_CURRENT) = mutex->prioceiling; +#ifdef _RTL_POSIX_APP_SCHEDULING + event_info.mutex=mutex; + event_info.sched_priority= mutex->prioceiling; + generate_event(RTL_CURRENT,appscheduler(RTL_CURRENT), POSIX_APPSCHED_PRIORITY_INHERIT,&event_info,sizeof(event_info)); +#endif } #endif if (test_and_set_bit(0, &mutex->busy)) { @@ -144,9 +209,13 @@ { rtl_irqstate_t flags; int ret; +#ifdef _RTL_POSIX_APP_SCHEDULING + pthread_t self=pthread_self(); + union posix_appsched_eventinfo event_info; +#endif switch (mutex->type) { - case PTHREAD_MUTEX_SPINLOCK_NP: - rtl_no_interrupts (flags); + case PTHREAD_MUTEX_SPINLOCK_NP: + rtl_no_interrupts (flags); if (rtl_spin_trylock(&mutex->lock)) { rtl_restore_interrupts (flags); return EBUSY; @@ -157,6 +226,39 @@ break; case PTHREAD_MUTEX_NORMAL: default: +#ifdef _RTL_POSIX_APP_SCHEDULING + if (mutex->protocol == PTHREAD_APPSCHED_PROTOCOL){ + // Error check. + /*if (!mutex->valid) { + return EINVAL; + }*/ + if (appscheduler(self)!=mutex_appscheduler(mutex) || + mutex_owner(mutex)!=self) { + return EPERM; + } + + rtl_spin_lock_irqsave (&mutex->lock, flags); + if (mutex_owner(mutex)) { + ret=EBUSY; + } else { + //Mutex free. Thread gets blocked. + self->appsched.appsched_mutex_where_waiting=mutex; + self->appsched.status=TRYING_TO_LOCK_APPSCHED_MUTEX; + RTL_MARK_SUSPENDED(self); + //Inform to the scheduler the task is trying to lock the mutex. + event_info.mutex=mutex; + generate_event(self,mutex_appscheduler(mutex),POSIX_APPSCHED_TRY_LOCK_MUTEX,&event_info,sizeof(event_info)); + //Leave the CPU and let the appscheduler to execute + rtl_schedule(); + self->appsched.appsched_mutex_where_waiting=NULL; + // Has the task successfully locked the mutex ? + ret=((self==mutex_owner(mutex))? 0 : EBUSY); + } + + rtl_spin_unlock_irqrestore(&mutex->lock, flags); + return ret; + } +#endif #ifdef _RTL_POSIX_THREAD_PRIO_PROTECT rtl_spin_lock_irqsave (&mutex->lock, flags); #endif @@ -173,6 +274,10 @@ { rtl_irqstate_t flags; int ret; +#ifdef _RTL_POSIX_APP_SCHEDULING + pthread_t self=pthread_self(); + union posix_appsched_eventinfo event_info; +#endif switch (mutex->type) { case PTHREAD_MUTEX_SPINLOCK_NP: @@ -182,11 +287,38 @@ return 0; case PTHREAD_MUTEX_NORMAL: default: - if (!mutex->valid) { + if (!mutex->valid) { return EINVAL; } - rtl_spin_lock_irqsave (&mutex->lock, flags); +#ifdef _RTL_POSIX_APP_SCHEDULING + if (mutex->protocol == PTHREAD_APPSCHED_PROTOCOL){ + // Error check. + if (appscheduler(self)!=mutex_appscheduler(mutex)) { + rtl_spin_unlock_irqrestore (&mutex->lock, flags); + return EPERM; + } + self->appsched.appsched_mutex_where_waiting=mutex; + self->appsched.status=WAITING_TO_LOCK_APPSCHED_MUTEX; + RTL_MARK_SUSPENDED(self); + event_info.mutex=mutex; + if (mutex_owner(mutex)){ + //Inform to the scheduler the task has blocked at the mutex. + generate_event(self,mutex_appscheduler(mutex),POSIX_APPSCHED_BLOCK_AT_MUTEX,&event_info,sizeof(event_info)); + } else { + // Inform to the scheduler the task wants to lock the mutex. + generate_event(self,mutex_appscheduler(mutex),POSIX_APPSCHED_LOCK_MUTEX,&event_info,sizeof(event_info)); + } + //Leave the CPU and let the appscheduler to execute + rtl_schedule(); + // When the locking task resume execution here is with the + // mutex taken (it has been given in posix_appsched_execute_actions) + self->appsched.appsched_mutex_where_waiting=NULL; + rtl_spin_unlock_irqrestore (&mutex->lock, flags); + return 0; + } +#endif + while ((ret = __pthread_mutex_trylock(mutex))) { if (ret == EINVAL) { rtl_spin_unlock_irqrestore(&mutex->lock, flags); @@ -206,6 +338,10 @@ int pthread_mutex_unlock(pthread_mutex_t *mutex) { rtl_irqstate_t flags; +#ifdef _RTL_POSIX_APP_SCHEDULING + pthread_t self=pthread_self(); + union posix_appsched_eventinfo event_info; +#endif switch (mutex->type) { case PTHREAD_MUTEX_SPINLOCK_NP: @@ -220,9 +356,31 @@ } rtl_spin_lock_irqsave (&mutex->lock, flags); +#ifdef _RTL_POSIX_APP_SCHEDULING + if (mutex->protocol == PTHREAD_APPSCHED_PROTOCOL) { + if (appscheduler(self)!=mutex_appscheduler(mutex) || + mutex_owner(mutex)!=self) { + rtl_spin_unlock_irqrestore (&mutex->lock, flags); + return EPERM; + } + // Free the mutex. The thread gives up ownership of mutex. + mutex_owner(mutex)=NULL; + // Inform to the scheduler the task has unlocked the mutex. + event_info.mutex=mutex; + generate_event(self,mutex_appscheduler(mutex),POSIX_APPSCHED_UNLOCK_MUTEX,&event_info,sizeof(event_info)); + rtl_schedule(); + rtl_spin_unlock_irqrestore (&mutex->lock, flags); + return 0; + } +#endif #ifdef _RTL_POSIX_THREAD_PRIO_PROTECT if (mutex->protocol == PTHREAD_PRIO_PROTECT) { RTL_PRIO(RTL_CURRENT) = mutex->oldprio; +#ifdef _RTL_POSIX_APP_SCHEDULING + event_info.mutex=mutex; + event_info.sched_priority= mutex->oldprio; + generate_event(RTL_CURRENT,appscheduler(RTL_CURRENT), POSIX_APPSCHED_PRIORITY_UNINHERIT,&event_info,sizeof(event_info)); +#endif } #endif clear_bit (0, &mutex->busy); @@ -367,7 +525,7 @@ const pthread_condattr_t *attr) { rtl_wait_init(&cond->wait); - spin_lock_init(&cond->lock); + spin_lock_init(&cond->lock); return 0; } diff -BNru rtlinux-3.1/schedulers/rtl_sched.c appsched_rt/schedulers/rtl_sched.c --- rtlinux-3.1/schedulers/rtl_sched.c Tue Feb 18 08:48:24 2003 +++ appsched_rt/schedulers/rtl_sched.c Tue Feb 18 08:55:02 2003 @@ -3,8 +3,8 @@ large numbers of tasks. I think that large numbers of tasks requires a total redesign of scheduler and that the scheduler should optimize for < 40 threads and really for <10 - -*/ + + */ /* * RTLinux default scheduler * RTLinux has a modular scheduler and this may be replaced if desired. @@ -16,12 +16,13 @@ * Added user signals support - Dec, 2002 Josep Vidal (OCERA) * Added POSIX timers support - Dec, 2002 Josep Vidal (OCERA) * - * Fixed stack overflow when sending RTL_SIGNAL_SUSPEND signal. J. Vidal (OCERA) - * Fixed mutex bug when setting t->do_abort=0 on do_signal. J. Vidal (OCERA) + * Fixed stack overflow when sending RTL_SIGNAL_SUSPEND signal. J. Vidal (OCERA) + * Fixed mutex bug when setting t->do_abort=0 on do_signal. J. Vidal (OCERA) * Fixed long long casting in usleep P. Mendoza & J. Vidal (OCERA) + * thanks to I. Ripoll, P. Mendoza & P. Perez * See example/bug directory for more info. - * Thanks to I.Ripoll, P. Mendoza & P. Perez. - */ + */ + #include #include @@ -160,24 +161,24 @@ set_bit(signal, &thread->pending); #ifdef _RTL_POSIX_SIGNALS if ((signal >= RTL_SIGUSR1) && HIGHER_PRIORITY_THREAD(thread,pthread_self())) rtl_schedule(); -#endif +#endif return 0; } else if(thread != rtl_get_linux_thread(rtl_getcpuid())) { - return EINVAL; + return EINVAL; } else { /* the signal number means something else */ - /* TODO one range for local one for global */ - if((signal < RTL_LINUX_MIN_SIGNAL) - || (signal > RTL_LINUX_MAX_SIGNAL)) - return EINVAL; - else if(signal < RTL_LINUX_MIN_LOCAL_SIGNAL){ /* it's global */ - rtl_global_pend_irq (signal - RTL_LINUX_MIN_SIGNAL ); - } + /* TODO one range for local one for global */ + if((signal < RTL_LINUX_MIN_SIGNAL) + || (signal > RTL_LINUX_MAX_SIGNAL)) + return EINVAL; + else if(signal < RTL_LINUX_MIN_LOCAL_SIGNAL){ /* it's global */ + rtl_global_pend_irq (signal - RTL_LINUX_MIN_SIGNAL ); + } #ifdef CONFIG_SMP - else{ + else{ rtl_local_pend_vec(signal - RTL_LINUX_MIN_LOCAL_SIGNAL,rtl_getcpuid()); - } + } #endif - return 0; + return 0; } } @@ -240,6 +241,17 @@ /* rtl_printf("freeing %#x %#x\n", task->kmalloc_stack_bottom); */ kfree (task->kmalloc_stack_bottom); } + +#ifdef _RTL_POSIX_APP_SCHEDULING + if (appscheduler_thread(task) && task->appsched.events){ +/* rtl_printf("freeing appsched events %#x %#x\n", task->appsched.events); */ + kfree(task->appsched.events); + } + if (regular_thread(task) && task->appsched.appsched_param.posix_appsched_param){ +/* rtl_printf("freeing appsched params %#x %#x\n", task->appsched.appsched_param.posix_appsched_param); */ + kfree(task->appsched.appsched_param.posix_appsched_param); + } +#endif } @@ -288,7 +300,11 @@ rtl_sigfillset(&mask); pthread_sigmask(SIG_SETMASK,&mask,NULL); #endif + rtl_no_interrupts(flags); +#ifdef _RTL_POSIX_APP_SCHEDULING + generate_event(pthread_self(),appscheduler(pthread_self()),POSIX_APPSCHED_TERMINATE,NULL,0); +#endif pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); do_cleanups(self); @@ -302,9 +318,14 @@ rtl_printf("pthread_exit() returned!\n"); } - int sched_yield(void) { +#ifdef _RTL_POSIX_APP_SCHEDULING + int flags; + rtl_no_interrupts(flags); + generate_event(pthread_self(),appscheduler(pthread_self()),POSIX_APPSCHED_YIELD, NULL,0); + rtl_restore_interrupts(flags); +#endif rtl_schedule(); return 0; } @@ -404,35 +425,34 @@ static inline void do_signal(pthread_t t) { - rtl_irqstate_t flags; - rtl_no_interrupts(flags); - - if (test_and_clear_bit(RTL_SIGNAL_SUSPEND, &t->pending)) { - /* t->abort = 0; - t->abortdata = 0; - */ - do_abort(t); - RTL_MARK_SUSPENDED(t); - } - - if (test_and_clear_bit(RTL_SIGNAL_WAKEUP, &t->pending)) { - RTL_MARK_READY(t); - do_abort(t); - } - - if (test_and_clear_bit(RTL_SIGNAL_TIMER, &t->pending)) { - RTL_MARK_READY(t); - do_abort(t); - } - - if (!test_bit(RTL_SIGNAL_CANCEL, &t->blocked) && test_and_clear_bit(RTL_SIGNAL_CANCEL, &t->pending)) { - RTL_MARK_READY(t); - do_abort(t); - rtl_restore_interrupts(flags); - (*rtl_sigcancel_handler)(RTL_SIGNAL_CANCEL); - } - - rtl_restore_interrupts(flags); + rtl_irqstate_t flags; + rtl_no_interrupts(flags); + + if (test_and_clear_bit(RTL_SIGNAL_SUSPEND, &t->pending)) { + /* t->abort = 0; + t->abortdata = 0; */ + do_abort(t); + RTL_MARK_SUSPENDED(t); + } + + if (test_and_clear_bit(RTL_SIGNAL_WAKEUP, &t->pending)) { + RTL_MARK_READY(t); + do_abort(t); + } + + if (test_and_clear_bit(RTL_SIGNAL_TIMER, &t->pending)) { + RTL_MARK_READY(t); + do_abort(t); + } + + if (!test_bit(RTL_SIGNAL_CANCEL, &t->blocked) && test_and_clear_bit(RTL_SIGNAL_CANCEL, &t->pending)) { + RTL_MARK_READY(t); + do_abort(t); + rtl_restore_interrupts(flags); + (*rtl_sigcancel_handler)(RTL_SIGNAL_CANCEL); + } + + rtl_restore_interrupts(flags); } #ifdef _RTL_POSIX_SIGNALS @@ -440,12 +460,22 @@ int sig; unsigned long flags, initial_interrupt_state; void (*fun)(int)=NULL; +#ifdef _RTL_POSIX_APP_SCHEDULING + union posix_appsched_eventinfo event_info; +#endif rtl_no_interrupts(initial_interrupt_state); for (sig=RTL_MAX_SIGNAL;sig>=RTL_SIGUSR1;sig--){ if (test_bit(sig,&t->pending) && !test_bit(sig,&t->blocked)){ +#ifdef _RTL_POSIX_APP_SCHEDULING + event_info.siginfo.si_signo=sig; + if (appscheduler_thread(t)){ + generate_event(t,t,POSIX_APPSCHED_SIGNAL,&event_info,sizeof(event_info)); + } +#endif + if (rtl_sigact[sig].owner==t){ fun=rtl_sigact[sig].sa_handler; if (fun) { @@ -503,7 +532,7 @@ for (timer=get_timer_list_start();timer;timer=timer->next){ if (timer_expiration(timer,now,sched->clock->mode)){ expiration_notification(timer); - UPDATE_TIMER(timer); + UPDATE_TIMER(timer); } } #endif @@ -532,7 +560,12 @@ /* and find highest priority runnable task */ if ((t->pending & ~t->blocked) && (!new_task || - (t->sched_param.sched_priority > new_task->sched_param.sched_priority))) { + (t->sched_param.sched_priority > new_task->sched_param.sched_priority) +#ifdef _RTL_POSIX_APP_SCHEDULING + /* App scheduler always takes precedence over its scheduled threads*/ + || ((t->sched_param.sched_priority == new_task->sched_param.sched_priority) && (appscheduler(new_task) == t)) +#endif +)) { new_task = t; } } @@ -618,6 +651,19 @@ int pthread_suspend_np (pthread_t thread) { + +#ifdef _RTL_POSIX_APP_SCHEDULING + int flags; + if (regular_thread(thread)){ + if (!test_bit (RTL_THREAD_FINISHED, &thread->threadflags)) { + rtl_no_interrupts(flags); + generate_event(thread,appscheduler(thread),POSIX_APPSCHED_SUSPEND,NULL,0); + rtl_restore_interrupts(flags); + } + return 0; + } +#endif + if (thread == pthread_self()) { RTL_MARK_SUSPENDED (pthread_self()); rtl_schedule(); @@ -630,6 +676,17 @@ int pthread_wakeup_np (pthread_t thread) { + +#ifdef _RTL_POSIX_APP_SCHEDULING + int flags; + if (regular_thread(pthread_self())) { + rtl_no_interrupts(flags); + generate_event(thread,appscheduler(thread),POSIX_APPSCHED_READY,NULL,0); + rtl_restore_interrupts(flags); + return 0; + } +#endif + #ifdef CONFIG_SMP if (thread->cpu != rtl_getcpuid()) { pthread_kill(thread,RTL_SIGNAL_WAKEUP); @@ -725,6 +783,27 @@ task->resume_time = HRTIME_INFINITY; task->period = 0; task->sched_param = attr->sched_param; + +#ifdef _RTL_POSIX_APP_SCHEDULING + task->appsched.appsched_param= attr->appsched.appsched_param; + task->appsched.type = attr->appsched.type; + + if (task->appsched.type==PTHREAD_APPSCHEDULER) { + task->appsched.events_mask=0; + task->appsched.clockid=CLOCK_REALTIME; /* default clock */ + task->appsched.events=(event_queue_t *)kmalloc(sizeof(event_queue_t),GFP_KERNEL); + if (!task->appsched.events) return -1; + rtl_init_events_queue(task->appsched.events); + + } else { + task->appsched.events=NULL; + + if (task->appsched.type) {//(type==PTHREAD_REGULAR) + generate_event(task,appscheduler(task),POSIX_APPSCHED_NEW, NULL,0); + } + } +#endif + task->stack = stack_addr + stack_size / sizeof(int); rtl_init_stack(task,start_routine, arg,rtl_startup); rtl_no_interrupts(interrupt_state); @@ -992,6 +1071,12 @@ s -> rtl_linux_task . creator = 0; s -> rtl_linux_task . abort = 0; +#ifdef _RTL_POSIX_APP_SCHEDULING + s -> rtl_linux_task . appsched.appsched_param.posix_appscheduler = NULL; + s -> rtl_linux_task . appsched.type=0; + s -> rtl_linux_task . appsched.events=NULL; +#endif + s -> rtl_task_fpu_owner = &s->rtl_linux_task; s -> sched_flags = 0; rtl_posix_init (&s->rtl_linux_task); @@ -1055,7 +1140,7 @@ save_resume_time = th->resume_time; RTL_MARK_SUSPENDED(th); - __rtl_setup_timeout (th, gethrtime() + (long long) interval * 1000LL); + __rtl_setup_timeout (th, gethrtime() + (long long)interval * 1000LL); rtl_schedule(); pthread_testcancel(); @@ -1095,12 +1180,16 @@ RTL_MARK_SUSPENDED(self); __rtl_setup_timeout (self, timeout); ret = rtl_schedule(); + +#ifdef _RTL_POSIX_SIGNALS + clear_bit(RTL_THREAD_SIGNAL_INTERRUMPIBLE,&self->threadflags); +#endif pthread_testcancel(); if (RTL_TIMED_OUT(&ret)) { self->resume_time = save_resume_time; -#ifdef _RTL_POSIX_SIGNALS - clear_bit(RTL_THREAD_SIGNAL_INTERRUMPIBLE,&self->threadflags); +#ifdef _RTL_POSIX_APP_SCHEDULING + //generate_event(pthread_self(),appscheduler(pthread_self()),POSIX_APPSCHED_TIMEOUT,NULL,0); #endif rtl_restore_interrupts (irqstate); return 0; diff -BNru rtlinux-3.1/schedulers/rtl_timer.c appsched_rt/schedulers/rtl_timer.c --- rtlinux-3.1/schedulers/rtl_timer.c Tue Feb 18 08:48:23 2003 +++ appsched_rt/schedulers/rtl_timer.c Tue Feb 18 08:55:02 2003 @@ -13,7 +13,7 @@ #include #ifdef _RTL_POSIX_TIMERS -#define _RTL_POSIX_TIMERS_DEBUG +//#define _RTL_POSIX_TIMERS_DEBUG /* Timer List Manipulation. */ struct rtl_timer_struct *timer_list_start=NULL; @@ -106,7 +106,7 @@ int timer_settime(timer_t timer_id, int flags, const struct itimerspec *new_setting, struct itimerspec *old_setting){ hrtime_t now=0; - + if (!timer_id){ errno=EINVAL; return -1; @@ -132,7 +132,7 @@ errno=EINVAL; return -1; } - + /* Check that it_value is different from 0, to program the timer. IF both are 0 timer is disarmed. @@ -172,9 +172,12 @@ } - /* For now, the schedule is called allways */ - clear_bit (RTL_SCHED_TIMER_OK, &sched_data((timer_id->owner)->cpu)->sched_flags); - rtl_schedule(); + + /* For now, the scheduler isn't called */ + clear_bit (RTL_SCHED_TIMER_OK, &sched_data((timer_id->owner)->cpu)->sched_flags); + /* + rtl_schedule(); + */ return 0; } diff -BNru rtlinux-3.1/scripts/config.in appsched_rt/scripts/config.in --- rtlinux-3.1/scripts/config.in Tue Feb 18 08:48:24 2003 +++ appsched_rt/scripts/config.in Tue Feb 18 08:55:02 2003 @@ -40,7 +40,8 @@ bool 'RTLinux tracer support (experimental)' CONFIG_RTL_TRACER bool 'POSIX Signals' _RTL_POSIX_SIGNALS if [ "$_RTL_POSIX_SIGNALS" = "y" ]; then - bool 'POSIX Timers' _RTL_POSIX_TIMERS + bool 'POSIX Timers' _RTL_POSIX_TIMERS + bool 'POSIX-Compatible Application-Defined Scheduling' _RTL_POSIX_APP_SCHEDULING fi source main/arch/config.in