Module: xenomai-3 Branch: next Commit: 2396824e79a9bda913217f6892d8b6fc67ff9d8f URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=2396824e79a9bda913217f6892d8b6fc67ff9d8f
Author: Philippe Gerum <r...@xenomai.org> Date: Tue Feb 16 10:13:03 2016 +0100 lib/cobalt/mutex: add support for priority ceiling protocol --- configure.ac | 2 + include/boilerplate/libc.h | 19 +++ include/cobalt/pthread.h | 7 ++ lib/cobalt/cobalt.wrappers | 2 + lib/cobalt/init.c | 1 + lib/cobalt/internal.h | 8 ++ lib/cobalt/mutex.c | 301 +++++++++++++++++++++++++++++++++++--------- lib/cobalt/sched.c | 33 ++++- lib/cobalt/thread.c | 7 +- 9 files changed, 311 insertions(+), 69 deletions(-) diff --git a/configure.ac b/configure.ac index c6506b8..bc40ee9 100644 --- a/configure.ac +++ b/configure.ac @@ -514,6 +514,8 @@ save_LIBS="$LIBS" LIBS="$LIBS -lrt -lpthread" AC_CHECK_FUNCS([pthread_mutexattr_setprotocol \ pthread_mutexattr_getprotocol \ + pthread_mutexattr_getprioceiling \ + pthread_mutexattr_setprioceiling \ pthread_mutexattr_setrobust_np \ pthread_condattr_getclock \ pthread_condattr_setclock \ diff --git a/include/boilerplate/libc.h b/include/boilerplate/libc.h index d8b0334..4cd80b0 100644 --- a/include/boilerplate/libc.h +++ b/include/boilerplate/libc.h @@ -108,6 +108,25 @@ int pthread_mutexattr_getprotocol(const pthread_mutexattr_t * } #endif /* !HAVE_PTHREAD_MUTEXATTR_GETPROTOCOL */ +#ifndef HAVE_PTHREAD_MUTEXATTR_SETPRIOCEILING +static inline +int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr, + int prioceiling) +{ + return ENOSYS; +} +#endif /* !HAVE_PTHREAD_MUTEXATTR_SETPRIOCEILING */ + +#ifndef HAVE_PTHREAD_MUTEXATTR_GETPRIOCEILING +static inline +int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t * + __restrict attr, + int *__restrict prioceiling) +{ + return ENOSYS; +} +#endif /* !HAVE_PTHREAD_MUTEXATTR_GETPRIOCEILING */ + #ifndef HAVE_PTHREAD_ATTR_SETAFFINITY_NP #include <sched.h> static inline diff --git a/include/cobalt/pthread.h b/include/cobalt/pthread.h index 386c337..f1b1c8a 100644 --- a/include/cobalt/pthread.h +++ b/include/cobalt/pthread.h @@ -67,6 +67,13 @@ COBALT_DECL(int, pthread_mutex_trylock(pthread_mutex_t *mutex)); COBALT_DECL(int, pthread_mutex_unlock(pthread_mutex_t *mutex)); +COBALT_DECL(int, pthread_mutex_setprioceiling(pthread_mutex_t *__restrict mutex, + int prioceiling, + int *__restrict old_ceiling)); + +COBALT_DECL(int, pthread_mutex_getprioceiling(pthread_mutex_t *__restrict mutex, + int *__restrict old_ceiling)); + COBALT_DECL(int, pthread_cond_init (pthread_cond_t *cond, const pthread_condattr_t *attr)); diff --git a/lib/cobalt/cobalt.wrappers b/lib/cobalt/cobalt.wrappers index 0378abf..4f883f3 100644 --- a/lib/cobalt/cobalt.wrappers +++ b/lib/cobalt/cobalt.wrappers @@ -32,6 +32,8 @@ --wrap pthread_mutex_trylock --wrap pthread_mutex_timedlock --wrap pthread_mutex_unlock +--wrap pthread_mutex_setprioceiling +--wrap pthread_mutex_getprioceiling --wrap pthread_cond_init --wrap pthread_cond_destroy --wrap pthread_cond_wait diff --git a/lib/cobalt/init.c b/lib/cobalt/init.c index f260744..69d4763 100644 --- a/lib/cobalt/init.c +++ b/lib/cobalt/init.c @@ -177,6 +177,7 @@ static void __cobalt_init(void) sizeof(struct cobalt_sem_shadow)); cobalt_mutex_init(); + cobalt_sched_init(); cobalt_thread_init(); cobalt_print_init(); } diff --git a/lib/cobalt/internal.h b/lib/cobalt/internal.h index 9f58c6a..2d9c0b9 100644 --- a/lib/cobalt/internal.h +++ b/lib/cobalt/internal.h @@ -52,6 +52,8 @@ void cobalt_thread_init(void); int cobalt_thread_probe(pid_t pid); +void cobalt_sched_init(void); + void cobalt_print_init(void); void cobalt_print_init_atfork(void); @@ -85,4 +87,10 @@ int __cxa_guard_acquire(__guard*); void __cxa_guard_release(__guard*); void __cxa_guard_abort(__guard*); +extern int __cobalt_std_fifo_minpri, + __cobalt_std_fifo_maxpri; + +extern int __cobalt_std_rr_minpri, + __cobalt_std_rr_maxpri; + #endif /* _LIB_COBALT_INTERNAL_H */ diff --git a/lib/cobalt/mutex.c b/lib/cobalt/mutex.c index 9d8a914..1456099 100644 --- a/lib/cobalt/mutex.c +++ b/lib/cobalt/mutex.c @@ -99,6 +99,9 @@ void cobalt_mutex_init(void) * mutex, increase CONFIG_XENO_OPT_SHARED_HEAPSZ for a process-shared * mutex, or CONFIG_XENO_OPT_PRIVATE_HEAPSZ for a process-private mutex. * - EAGAIN, no registry slot available, check/raise CONFIG_XENO_OPT_REGISTRY_NRSLOTS. + * - ENOSYS, @a attr mentions priority protection + * (PTHREAD_PRIO_PROTECT), but the C library does not provide + * pthread_mutexattr_get/setprioceiling(). * * @see * <a href="http://www.opengroup.org/onlinepubs/000095399/functions/pthread_mutex_init.html"> @@ -117,7 +120,6 @@ COBALT_IMPL(int, pthread_mutex_init, (pthread_mutex_t *mutex, if (_mutex->magic == COBALT_MUTEX_MAGIC) { err = -XENOMAI_SYSCALL1(sc_cobalt_mutex_check_init, _mutex); - if (err) return err; } @@ -138,12 +140,19 @@ COBALT_IMPL(int, pthread_mutex_init, (pthread_mutex_t *mutex, err = pthread_mutexattr_getprotocol(attr, &tmp); if (err) return err; - if (tmp == PTHREAD_PRIO_PROTECT) { /* Prio ceiling unsupported */ - err = EINVAL; - return err; - } kmattr.protocol = tmp; + if (kmattr.protocol == PTHREAD_PRIO_PROTECT) { + err = pthread_mutexattr_getprioceiling(attr, &tmp); + if (err) + return err; + if (tmp == 0 || /* Could not cope with null minpri. */ + tmp < __cobalt_std_fifo_minpri || + tmp > __cobalt_std_fifo_maxpri) + return EINVAL; + kmattr.ceiling = tmp - 1; + } + err = -XENOMAI_SYSCALL2(sc_cobalt_mutex_init, _mutex, &kmattr); if (err) return err; @@ -251,7 +260,7 @@ static int __attribute__((cold)) cobalt_mutex_autoinit(pthread_mutex_t *mutex) * * @return 0 on success * @return an error number if: - * - EPERM, the caller context is invalid; + * - EPERM, the caller is not allowed to perform the operation; * - EINVAL, the mutex @a mx is invalid; * - EPERM, the mutex is not process-shared and does not belong to the current * process; @@ -270,7 +279,8 @@ COBALT_IMPL(int, pthread_mutex_lock, (pthread_mutex_t *mutex)) { struct cobalt_mutex_shadow *_mutex = &((union cobalt_mutex_union *)mutex)->shadow_mutex; - int status, ret; + struct xnthread_user_window *u_window; + int status, ret, lazy_protect = 0; xnhandle_t cur; cur = cobalt_get_current(); @@ -285,21 +295,28 @@ COBALT_IMPL(int, pthread_mutex_lock, (pthread_mutex_t *mutex)) * shadows and some debug features, so we must always obtain * them via a syscall. */ - cont: +start: status = cobalt_get_current_mode(); if ((status & (XNRELAX|XNWEAK|XNDEBUG)) == 0) { + if (_mutex->attr.protocol == PTHREAD_PRIO_PROTECT) + goto protect; +fast_path: ret = xnsynch_fast_acquire(mutex_get_ownerp(_mutex), cur); if (ret == 0) { _mutex->lockcnt = 1; return 0; } } else { +slow_path: ret = xnsynch_fast_owner_check(mutex_get_ownerp(_mutex), cur); if (ret == 0) ret = -EBUSY; } - if (ret == -EBUSY) + if (ret == -EBUSY) { + if (lazy_protect) + u_window->pp_pending = XN_NO_HANDLE; + switch(_mutex->attr.type) { case PTHREAD_MUTEX_NORMAL: break; @@ -313,6 +330,7 @@ COBALT_IMPL(int, pthread_mutex_lock, (pthread_mutex_t *mutex)) ++_mutex->lockcnt; return 0; } + } do ret = XENOMAI_SYSCALL1(sc_cobalt_mutex_lock, _mutex); @@ -322,12 +340,22 @@ COBALT_IMPL(int, pthread_mutex_lock, (pthread_mutex_t *mutex)) _mutex->lockcnt = 1; return -ret; - - autoinit: +protect: + u_window = cobalt_get_current_window(); + /* + * Can't nest lazy ceiling requests, have to take the slow + * path when this happens. + */ + if (u_window->pp_pending != XN_NO_HANDLE) + goto slow_path; + u_window->pp_pending = _mutex->handle; + lazy_protect = 1; + goto fast_path; +autoinit: ret = cobalt_mutex_autoinit(mutex); if (ret) return ret; - goto cont; + goto start; } /** @@ -344,7 +372,7 @@ COBALT_IMPL(int, pthread_mutex_lock, (pthread_mutex_t *mutex)) * * @return 0 on success; * @return an error number if: - * - EPERM, the caller context is invalid; + * - EPERM, the caller is not allowed to perform the operation; * - EINVAL, the mutex @a mx is invalid; * - EPERM, the mutex is not process-shared and does not belong to the current * process; @@ -366,7 +394,8 @@ COBALT_IMPL(int, pthread_mutex_timedlock, (pthread_mutex_t *mutex, { struct cobalt_mutex_shadow *_mutex = &((union cobalt_mutex_union *)mutex)->shadow_mutex; - int status, ret; + struct xnthread_user_window *u_window; + int status, ret, lazy_protect = 0; xnhandle_t cur; cur = cobalt_get_current(); @@ -377,21 +406,28 @@ COBALT_IMPL(int, pthread_mutex_timedlock, (pthread_mutex_t *mutex, goto autoinit; /* See __cobalt_pthread_mutex_lock() */ - cont: +start: status = cobalt_get_current_mode(); if ((status & (XNRELAX|XNWEAK|XNDEBUG)) == 0) { + if (_mutex->attr.protocol == PTHREAD_PRIO_PROTECT) + goto protect; +fast_path: ret = xnsynch_fast_acquire(mutex_get_ownerp(_mutex), cur); if (ret == 0) { _mutex->lockcnt = 1; return 0; } } else { +slow_path: ret = xnsynch_fast_owner_check(mutex_get_ownerp(_mutex), cur); if (ret == 0) ret = -EBUSY; } - if (ret == -EBUSY) + if (ret == -EBUSY) { + if (lazy_protect) + u_window->pp_pending = XN_NO_HANDLE; + switch(_mutex->attr.type) { case PTHREAD_MUTEX_NORMAL: break; @@ -406,6 +442,7 @@ COBALT_IMPL(int, pthread_mutex_timedlock, (pthread_mutex_t *mutex, ++_mutex->lockcnt; return 0; } + } do { ret = XENOMAI_SYSCALL2(sc_cobalt_mutex_timedlock, _mutex, to); @@ -414,12 +451,22 @@ COBALT_IMPL(int, pthread_mutex_timedlock, (pthread_mutex_t *mutex, if (ret == 0) _mutex->lockcnt = 1; return -ret; - - autoinit: +protect: + u_window = cobalt_get_current_window(); + /* + * Can't nest lazy ceiling requests, have to take the slow + * path when this happens. + */ + if (u_window->pp_pending != XN_NO_HANDLE) + goto slow_path; + u_window->pp_pending = _mutex->handle; + lazy_protect = 1; + goto fast_path; +autoinit: ret = cobalt_mutex_autoinit(mutex); if (ret) return ret; - goto cont; + goto start; } /** @@ -433,7 +480,7 @@ COBALT_IMPL(int, pthread_mutex_timedlock, (pthread_mutex_t *mutex, * * @return 0 on success; * @return an error number if: - * - EPERM, the caller context is invalid; + * - EPERM, the caller is not allowed to perform the operation; * - EINVAL, the mutex is invalid; * - EPERM, the mutex is not process-shared and does not belong to the current * process; @@ -451,7 +498,8 @@ COBALT_IMPL(int, pthread_mutex_trylock, (pthread_mutex_t *mutex)) { struct cobalt_mutex_shadow *_mutex = &((union cobalt_mutex_union *)mutex)->shadow_mutex; - int status, err; + struct xnthread_user_window *u_window; + int status, ret, lazy_protect = 0; xnhandle_t cur; cur = cobalt_get_current(); @@ -460,58 +508,75 @@ COBALT_IMPL(int, pthread_mutex_trylock, (pthread_mutex_t *mutex)) if (_mutex->magic != COBALT_MUTEX_MAGIC) goto autoinit; - - cont: +start: status = cobalt_get_current_mode(); if ((status & (XNRELAX|XNWEAK|XNDEBUG)) == 0) { - err = xnsynch_fast_acquire(mutex_get_ownerp(_mutex), cur); - if (err == 0) { + if (_mutex->attr.protocol == PTHREAD_PRIO_PROTECT) + goto protect; +fast_path: + ret = xnsynch_fast_acquire(mutex_get_ownerp(_mutex), cur); + if (ret == 0) { _mutex->lockcnt = 1; return 0; } } else { - err = xnsynch_fast_owner_check(mutex_get_ownerp(_mutex), cur); - if (err < 0) +slow_path: + ret = xnsynch_fast_owner_check(mutex_get_ownerp(_mutex), cur); + if (ret < 0) goto do_syscall; - err = -EBUSY; + ret = -EBUSY; } - if (err == -EBUSY && _mutex->attr.type == PTHREAD_MUTEX_RECURSIVE) { - if (_mutex->lockcnt == UINT32_MAX) - return EAGAIN; + if (ret == -EBUSY) { + if (lazy_protect) + u_window->pp_pending = XN_NO_HANDLE; - ++_mutex->lockcnt; - return 0; + if (_mutex->attr.type == PTHREAD_MUTEX_RECURSIVE) { + if (_mutex->lockcnt == UINT32_MAX) + return EAGAIN; + + ++_mutex->lockcnt; + return 0; + } } return EBUSY; do_syscall: - do { - err = XENOMAI_SYSCALL1(sc_cobalt_mutex_trylock, _mutex); - } while (err == -EINTR); + ret = XENOMAI_SYSCALL1(sc_cobalt_mutex_trylock, _mutex); + } while (ret == -EINTR); - if (!err) + if (ret == 0) _mutex->lockcnt = 1; - return -err; - - autoinit: - err = cobalt_mutex_autoinit(mutex); - if (err) - return err; - goto cont; + return -ret; +autoinit: + ret = cobalt_mutex_autoinit(mutex); + if (ret) + return ret; + goto start; +protect: + u_window = cobalt_get_current_window(); + /* + * Can't nest lazy ceiling requests, have to take the slow + * path when this happens. + */ + if (u_window->pp_pending != XN_NO_HANDLE) + goto slow_path; + u_window->pp_pending = _mutex->handle; + lazy_protect = 1; + goto fast_path; } /** * Unlock a mutex. * - * This service unlocks the mutex @a mx. If the mutex is of the @a - * PTHREAD_MUTEX_RECURSIVE @a type and the locking recursion count is greater - * than one, the lock recursion count is decremented and the mutex remains - * locked. + * This service unlocks the @a mutex. If @a mutex is of the @a + * PTHREAD_MUTEX_RECURSIVE and the locking recursion count is greater + * than one, the lock recursion count is decremented and the mutex + * remains locked. * * Attempting to unlock a mutex which is not locked or which is locked by * another thread than the current one yields the EPERM error, whatever the @@ -521,8 +586,8 @@ do_syscall: * * @return 0 on success; * @return an error number if: - * - EPERM, the caller context is invalid; - * - EINVAL, the mutex @a mx is invalid; + * - EPERM, the caller is not allowed to perform the operation; + * - EINVAL, the mutex @a mutex is invalid; * - EPERM, the mutex was not locked by the current thread. * * @see @@ -535,14 +600,14 @@ COBALT_IMPL(int, pthread_mutex_unlock, (pthread_mutex_t *mutex)) { struct cobalt_mutex_shadow *_mutex = &((union cobalt_mutex_union *)mutex)->shadow_mutex; + struct xnthread_user_window *u_window; struct cobalt_mutex_state *state; xnhandle_t cur; int err; if (_mutex->magic != COBALT_MUTEX_MAGIC) goto autoinit; - - cont: +start: cur = cobalt_get_current(); if (cur == XN_NO_HANDLE) return EPERM; @@ -562,21 +627,135 @@ COBALT_IMPL(int, pthread_mutex_unlock, (pthread_mutex_t *mutex)) if (cobalt_get_current_mode() & (XNWEAK|XNDEBUG)) goto do_syscall; - if (xnsynch_fast_release(&state->owner, cur)) + if (xnsynch_fast_release(&state->owner, cur)) { + if (_mutex->attr.protocol == PTHREAD_PRIO_PROTECT) + goto unprotect; return 0; + } do_syscall: - do { err = XENOMAI_SYSCALL1(sc_cobalt_mutex_unlock, _mutex); } while (err == -EINTR); return -err; - autoinit: +autoinit: err = cobalt_mutex_autoinit(mutex); if (err) return err; - goto cont; + goto start; +unprotect: + u_window = cobalt_get_current_window(); + u_window->pp_pending = XN_NO_HANDLE; + + return 0; +} + +/** + * Set a mutex's priority ceiling. + * + * This routine acquires the specified mutex, then changes the + * associated priority ceiling value and releases it. @a prioceiling + * must be between the values returned by sched_get_priority_min() and + * sched_get_priority_max(), inclusive. + * + * The Cobalt implementation applies the priority ceiling protocol + * using the previous ceiling value during this operation. The new + * priority ceiling will apply next time the @a mutex transitions from + * the unlocked to locked state. + * + * @param mutex the target mutex. + * + * @param prioceiling the new ceiling value. + * + * @param old_ceiling on success and if this parameter is non-NULL, + * the previous ceiling value is copied to this address. + * + * @return 0 on success; + * @return an error number if: + * - EPERM, the caller is not allowed to perform the operation; + * - EINVAL, @a mutex is invalid; + * - EINVAL, @a mutex is not of type PTHREAD_PRIO_PROTECT; + * - EINVAL, @a prioceiling is out of range; + * + * @see + * <a href="http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_mutex_setprioceiling.html"> + * Specification.</a> + * + * @apitags{xthread-only, switch-primary} + * + * @note If the calling thread's priority is higher than the mutex's + * new priority ceiling, the operation will nevertheless succeed; the + * Cobalt core never decreases the effective priority of a thread + * which locks a priority-protected mutex. + */ +COBALT_IMPL(int, pthread_mutex_setprioceiling, + (pthread_mutex_t *__restrict mutex, + int prioceiling, int *__restrict old_ceiling)) +{ + struct cobalt_mutex_shadow *_mutex = + &((union cobalt_mutex_union *)mutex)->shadow_mutex; + struct cobalt_mutex_state *state; + int ret; + + if (_mutex->magic != COBALT_MUTEX_MAGIC || + _mutex->attr.protocol != PTHREAD_PRIO_PROTECT) + return EINVAL; + + if (prioceiling < __cobalt_std_fifo_minpri || + prioceiling > __cobalt_std_fifo_maxpri) + return EINVAL; + + ret = __COBALT(pthread_mutex_lock(mutex)); + if (ret) + return ret; + + state = mutex_get_state(_mutex); + if (old_ceiling) + *old_ceiling = state->ceiling; + + state->ceiling = prioceiling; + + return __COBALT(pthread_mutex_unlock(mutex)); +} + +/** + * Get a mutex's priority ceiling. + * + * This routine retrieves the priority ceiling value of the specified + * mutex. + * + * @param mutex the target mutex. + * + * @param prioceiling on success, the current ceiling value is copied + * to this address. + * + * @return 0 on success; + * @return an error number if: + * - EINVAL, @a mutex is invalid; + * - EINVAL, @a mutex is not of type PTHREAD_PRIO_PROTECT; + * + * @see + * <a href="http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_mutex_getprioceiling.html"> + * Specification.</a> + * + * @apitags{thread-unrestricted} + */ +COBALT_IMPL(int, pthread_mutex_getprioceiling, + (pthread_mutex_t *__restrict mutex, int *__restrict prioceiling)) +{ + struct cobalt_mutex_shadow *_mutex = + &((union cobalt_mutex_union *)mutex)->shadow_mutex; + struct cobalt_mutex_state *state; + + if (_mutex->magic != COBALT_MUTEX_MAGIC || + _mutex->attr.protocol != PTHREAD_PRIO_PROTECT) + return EINVAL; + + state = mutex_get_state(_mutex); + *prioceiling = state->ceiling; + + return 0; } /** @@ -692,9 +871,9 @@ int pthread_mutexattr_settype(pthread_mutexattr_t * attr, int type); * This service stores, at the address @a proto, the value of the @a protocol * attribute in the mutex attributes object @a attr. * - * The @a protcol attribute may only be one of @a PTHREAD_PRIO_NONE or @a - * PTHREAD_PRIO_INHERIT. See pthread_mutexattr_setprotocol() for the meaning of - * these two constants. + * The @a protcol attribute may be one of @a PTHREAD_PRIO_NONE, @a + * PTHREAD_PRIO_INHERIT or @a PTHREAD_PRIO_PROTECT. See + * pthread_mutexattr_setprotocol() for the meaning of these constants. * * @param attr an initialized mutex attributes object; * @@ -727,8 +906,8 @@ int pthread_mutexattr_getprotocol(const pthread_mutexattr_t * attr, int *proto); * @a attr will not follow any priority protocol; * - PTHREAD_PRIO_INHERIT, meaning that a mutex created with the attributes * object @a attr, will follow the priority inheritance protocol. - * - * The value PTHREAD_PRIO_PROTECT (priority ceiling protocol) is unsupported. + * - PTHREAD_PRIO_PROTECT, meaning that a mutex created with the attributes + * object @a attr, will follow the priority protect protocol. * * @return 0 on success, * @return an error number if: diff --git a/lib/cobalt/sched.c b/lib/cobalt/sched.c index 7376110..b0292b5 100644 --- a/lib/cobalt/sched.c +++ b/lib/cobalt/sched.c @@ -80,7 +80,11 @@ COBALT_IMPL(int, sched_yield, (void)) * <a href="http://www.opengroup.org/onlinepubs/000095399/functions/sched_get_priority_min.html"> * Specification.</a> * - * @apitags{thread-unrestricted} + * @apitags{thread-unrestricted, switch-secondary} + * + * @note Fetching the minimum priority level of SCHED_FIFO, SCHED_RR + * or any Xenomai-specific policy never leads to a mode switch. Any + * other value of @a policy may switch the caller to secondary mode. */ COBALT_IMPL(int, sched_get_priority_min, (int policy)) { @@ -88,8 +92,9 @@ COBALT_IMPL(int, sched_get_priority_min, (int policy)) switch (policy) { case SCHED_FIFO: + return __cobalt_std_fifo_minpri; case SCHED_RR: - break; + return __cobalt_std_rr_minpri; default: ret = XENOMAI_SYSCALL1(sc_cobalt_sched_minprio, policy); if (ret >= 0) @@ -152,7 +157,11 @@ int sched_get_priority_min_ex(int policy) * <a href="http://www.opengroup.org/onlinepubs/000095399/functions/sched_get_priority_max.html"> * Specification.</a> * - * @apitags{thread-unrestricted} + * @apitags{thread-unrestricted, switch-secondary} + * + * @note Fetching the maximum priority level of SCHED_FIFO, SCHED_RR + * or any Xenomai-specific policy never leads to a mode switch. Any + * other value of @a policy may switch the caller to secondary mode. */ COBALT_IMPL(int, sched_get_priority_max, (int policy)) { @@ -160,8 +169,9 @@ COBALT_IMPL(int, sched_get_priority_max, (int policy)) switch (policy) { case SCHED_FIFO: + return __cobalt_std_fifo_maxpri; case SCHED_RR: - break; + return __cobalt_std_rr_maxpri; default: ret = XENOMAI_SYSCALL1(sc_cobalt_sched_maxprio, policy); if (ret >= 0) @@ -611,3 +621,18 @@ ssize_t sched_getconfig_np(int cpu, int policy, } /** @} */ + +int __cobalt_std_fifo_minpri, + __cobalt_std_fifo_maxpri; + +int __cobalt_std_rr_minpri, + __cobalt_std_rr_maxpri; + +void cobalt_sched_init(void) +{ + /* Fill in the standard priority limit cache. */ + __cobalt_std_fifo_minpri = __STD(sched_get_priority_min(SCHED_FIFO)); + __cobalt_std_fifo_maxpri = __STD(sched_get_priority_max(SCHED_FIFO)); + __cobalt_std_rr_minpri = __STD(sched_get_priority_min(SCHED_RR)); + __cobalt_std_rr_maxpri = __STD(sched_get_priority_max(SCHED_RR)); +} diff --git a/lib/cobalt/thread.c b/lib/cobalt/thread.c index aab2c81..e6b3eae 100644 --- a/lib/cobalt/thread.c +++ b/lib/cobalt/thread.c @@ -50,7 +50,7 @@ int cobalt_xlate_schedparam(int policy, const struct sched_param_ex *param_ex, struct sched_param *param) { - int std_policy, priority, std_maxpri; + int std_policy, priority; /* * Translates Cobalt scheduling parameters to native ones, @@ -77,9 +77,8 @@ int cobalt_xlate_schedparam(int policy, * "weak" (negative) priorities - which are only * meaningful for the Cobalt core - to regular values. */ - std_maxpri = __STD(sched_get_priority_max(SCHED_FIFO)); - if (priority > std_maxpri) - priority = std_maxpri; + if (priority > __cobalt_std_fifo_maxpri) + priority = __cobalt_std_fifo_maxpri; } if (priority < 0) _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org https://xenomai.org/mailman/listinfo/xenomai-git