diff --git a/include/pthread.h b/include/pthread.h index 07ff707c1b2b1..999af40f1f749 100644 --- a/include/pthread.h +++ b/include/pthread.h @@ -279,9 +279,12 @@ typedef struct pthread_cond_s pthread_cond_t; struct pthread_mutexattr_s { uint8_t pshared : 1; /* PTHREAD_PROCESS_PRIVATE or PTHREAD_PROCESS_SHARED */ -#ifdef CONFIG_PRIORITY_INHERITANCE +#if defined(CONFIG_PRIORITY_INHERITANCE) || defined(CONFIG_PRIORITY_PROTECT) uint8_t proto : 2; /* See PTHREAD_PRIO_* definitions */ #endif +#ifdef CONFIG_PRIORITY_PROTECT + uint8_t ceiling; /* Priority ceiling */ +#endif #ifdef CONFIG_PTHREAD_MUTEX_TYPES uint8_t type : 2; /* Type of the mutex. See PTHREAD_MUTEX_* definitions */ #endif @@ -612,6 +615,14 @@ int pthread_mutexattr_getrobust(FAR const pthread_mutexattr_t *attr, FAR int *robust); int pthread_mutexattr_setrobust(FAR pthread_mutexattr_t *attr, int robust); +int pthread_mutexattr_getprioceiling(FAR const pthread_mutexattr_t *attr, + FAR int *prioceiling); +int pthread_mutexattr_setprioceiling(FAR pthread_mutexattr_t *attr, + int prioceiling); +int pthread_mutex_getprioceiling(FAR const pthread_mutex_t *mutex, + FAR int *prioceiling); +int pthread_mutex_setprioceiling(FAR pthread_mutex_t *mutex, + int prioceiling, FAR int *old_ceiling); /* The following routines create, delete, lock and unlock mutexes. */ diff --git a/libs/libc/libc.csv b/libs/libc/libc.csv index 097a95e8fe3f8..1374e6714bbe8 100644 --- a/libs/libc/libc.csv +++ b/libs/libc/libc.csv @@ -217,11 +217,15 @@ "pthread_gettid_np","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","pid_t","pthread_t" "pthread_key_create","pthread.h","!defined(CONFIG_DISABLE_PTHREAD) && CONFIG_TLS_NELEM > 0","int","FAR pthread_key_t *","FAR void (*) (void *)|FAR void *" "pthread_key_delete","pthread.h","!defined(CONFIG_DISABLE_PTHREAD) && CONFIG_TLS_NELEM > 0","int","pthread_key_t" +"pthread_mutex_getprioceiling","pthread.h","!defined(CONFIG_DISABLE_PTHREAD) && defined(CONFIG_PRIORITY_PROTECT)","int","FAR const pthread_mutex_t *","FAR int *" "pthread_mutex_lock","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_mutex_t *" +"pthread_mutex_setprioceiling","pthread.h","!defined(CONFIG_DISABLE_PTHREAD) && defined(CONFIG_PRIORITY_PROTECT)","int","FAR pthread_mutex_t *","int","FAR int *" "pthread_mutexattr_destroy","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_mutexattr_t *" +"pthread_mutexattr_getprioceiling","pthread.h","!defined(CONFIG_DISABLE_PTHREAD) && defined(CONFIG_PRIORITY_PROTECT)","int","FAR pthread_mutexattr_t *","FAR int *" "pthread_mutexattr_getpshared","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_mutexattr_t *","FAR int *" "pthread_mutexattr_gettype","pthread.h","!defined(CONFIG_DISABLE_PTHREAD) && defined(CONFIG_PTHREAD_MUTEX_TYPES)","int","FAR const pthread_mutexattr_t *","FAR int *" "pthread_mutexattr_init","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_mutexattr_t *" +"pthread_mutexattr_setprioceiling","pthread.h","!defined(CONFIG_DISABLE_PTHREAD) && defined(CONFIG_PRIORITY_PROTECT)","int","FAR pthread_mutexattr_t *","int" "pthread_mutexattr_setpshared","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_mutexattr_t *","int " "pthread_mutexattr_settype","pthread.h","!defined(CONFIG_DISABLE_PTHREAD) && defined(CONFIG_PTHREAD_MUTEX_TYPES)","int","FAR pthread_mutexattr_t *","int" "pthread_once","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_once_t*","CODE void (*)(void)" diff --git a/libs/libc/pthread/CMakeLists.txt b/libs/libc/pthread/CMakeLists.txt index 43d5d6babbd36..2055fcb067cdd 100644 --- a/libs/libc/pthread/CMakeLists.txt +++ b/libs/libc/pthread/CMakeLists.txt @@ -79,7 +79,11 @@ if(NOT CONFIG_DISABLE_PTHREAD) pthread_mutexattr_gettype.c pthread_mutexattr_setrobust.c pthread_mutexattr_getrobust.c + pthread_mutexattr_setprioceiling.c + pthread_mutexattr_getprioceiling.c pthread_mutex_lock.c + pthread_mutex_setprioceiling.c + pthread_mutex_getprioceiling.c pthread_once.c pthread_yield.c pthread_atfork.c diff --git a/libs/libc/pthread/Make.defs b/libs/libc/pthread/Make.defs index 5ae7667650e79..51b9992ccd8c9 100644 --- a/libs/libc/pthread/Make.defs +++ b/libs/libc/pthread/Make.defs @@ -51,7 +51,9 @@ CSRCS += pthread_mutexattr_getpshared.c pthread_mutexattr_setpshared.c CSRCS += pthread_mutexattr_setprotocol.c pthread_mutexattr_getprotocol.c CSRCS += pthread_mutexattr_settype.c pthread_mutexattr_gettype.c CSRCS += pthread_mutexattr_setrobust.c pthread_mutexattr_getrobust.c +CSRCS += pthread_mutexattr_setprioceiling.c pthread_mutexattr_getprioceiling.c CSRCS += pthread_mutex_lock.c +CSRCS += pthread_mutex_setprioceiling.c pthread_mutex_getprioceiling.c CSRCS += pthread_once.c pthread_yield.c pthread_atfork.c CSRCS += pthread_rwlockattr_init.c pthread_rwlockattr_destroy.c CSRCS += pthread_rwlockattr_getpshared.c pthread_rwlockattr_setpshared.c diff --git a/libs/libc/pthread/pthread_mutex_getprioceiling.c b/libs/libc/pthread/pthread_mutex_getprioceiling.c new file mode 100644 index 0000000000000..e621227c903e9 --- /dev/null +++ b/libs/libc/pthread/pthread_mutex_getprioceiling.c @@ -0,0 +1,64 @@ +/**************************************************************************** + * libs/libc/pthread/pthread_mutex_getprioceiling.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_mutex_getprioceiling + * + * Description: + * Return the mutex priority ceiling from the mutex. + * + * Input Parameters: + * mutex - The mutex to query + * prioceiling - Location to return the mutex priority ceiling + * + * Returned Value: + * 0, if the mutex type was successfully return in 'prioceiling', or + * EINVAL, if any NULL pointers provided. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_mutex_getprioceiling(FAR const pthread_mutex_t *mutex, + FAR int *prioceiling) +{ +#ifdef CONFIG_PRIORITY_PROTECT +# ifdef CONFIG_PTHREAD_MUTEX_TYPES + return -nxrmutex_getprioceiling(&mutex->mutex, prioceiling); +# else + return -nxmutex_getprioceiling(&mutex->mutex, prioceiling); +# endif +#else + return EINVAL; +#endif +} diff --git a/libs/libc/pthread/pthread_mutex_setprioceiling.c b/libs/libc/pthread/pthread_mutex_setprioceiling.c new file mode 100644 index 0000000000000..04751883d627d --- /dev/null +++ b/libs/libc/pthread/pthread_mutex_setprioceiling.c @@ -0,0 +1,74 @@ +/**************************************************************************** + * libs/libc/pthread/pthread_mutex_setprioceiling.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_mutex_setprioceiling + * + * Description: + * Set the priority ceiling of a mutex. + * + * Input Parameters: + * mutex - The mutex in which to set the mutex priority ceiling. + * prioceiling - The mutex priority ceiling value to set. + * old_ceiling - Location to return the mutex ceiling priority set before. + * + * Returned Value: + * 0, indicating the mutex priority ceiling was successfully set, or + * EINVAL, indicating 'mutex' or 'old_ceiling' is NULL, or 'prioceiling' + * is out of range. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_mutex_setprioceiling(FAR pthread_mutex_t *mutex, + int prioceiling, FAR int *old_ceiling) +{ + int ret = EINVAL; + +#ifdef CONFIG_PRIORITY_PROTECT + ret = pthread_mutex_lock(mutex); + if (ret != OK) + { + return ret; + } + +# ifdef CONFIG_PTHREAD_MUTEX_TYPES + ret = -nxrmutex_setprioceiling(&mutex->mutex, prioceiling, old_ceiling); +# else + ret = -nxmutex_setprioceiling(&mutex->mutex, prioceiling, old_ceiling); +# endif + pthread_mutex_unlock(mutex); +#endif + return ret; +} diff --git a/libs/libc/pthread/pthread_mutexattr_getprioceiling.c b/libs/libc/pthread/pthread_mutexattr_getprioceiling.c new file mode 100644 index 0000000000000..7c518a59448d1 --- /dev/null +++ b/libs/libc/pthread/pthread_mutexattr_getprioceiling.c @@ -0,0 +1,63 @@ +/**************************************************************************** + * libs/libc/pthread/pthread_mutexattr_getprioceiling.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_mutexattr_getprioceiling + * + * Description: + * Return the mutex ceiling priority from the mutex attributes. + * + * Input Parameters: + * attr - The mutex attributes to query + * prioceiling - Location to return the mutex ceiling priority + * + * Returned Value: + * 0, if the mutex type was successfully return in 'prioceiling', or + * EINVAL, if any NULL pointers provided. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_mutexattr_getprioceiling(FAR const pthread_mutexattr_t *attr, + FAR int *prioceiling) +{ +#ifdef CONFIG_PRIORITY_PROTECT + if (attr != NULL && prioceiling != NULL) + { + *prioceiling = attr->ceiling; + return OK; + } +#endif + + return EINVAL; +} diff --git a/libs/libc/pthread/pthread_mutexattr_getprotocol.c b/libs/libc/pthread/pthread_mutexattr_getprotocol.c index 991d15f698107..c883d6bb371d8 100644 --- a/libs/libc/pthread/pthread_mutexattr_getprotocol.c +++ b/libs/libc/pthread/pthread_mutexattr_getprotocol.c @@ -53,13 +53,13 @@ int pthread_mutexattr_getprotocol(FAR const pthread_mutexattr_t *attr, { DEBUGASSERT(attr != NULL && protocol != NULL); -#ifdef CONFIG_PRIORITY_INHERITANCE +#if defined(CONFIG_PRIORITY_INHERITANCE) || defined(CONFIG_PRIORITY_PROTECT) linfo("Returning %d\n", attr->proto); *protocol = attr->proto; #else linfo("Returning %d\n", PTHREAD_PRIO_NONE); *protocol = PTHREAD_PRIO_NONE; -#endif /* CONFIG_PRIORITY_INHERITANCE */ +#endif /* CONFIG_PRIORITY_INHERITANCE || CONFIG_PRIORITY_PROTECT */ return 0; } diff --git a/libs/libc/pthread/pthread_mutexattr_init.c b/libs/libc/pthread/pthread_mutexattr_init.c index fda92d93a1f9a..66c9a9f722e15 100644 --- a/libs/libc/pthread/pthread_mutexattr_init.c +++ b/libs/libc/pthread/pthread_mutexattr_init.c @@ -27,6 +27,7 @@ #include #include #include +#include /**************************************************************************** * Public Functions @@ -60,6 +61,11 @@ int pthread_mutexattr_init(FAR pthread_mutexattr_t *attr) { attr->pshared = 0; +#ifdef CONFIG_PRIORITY_PROTECT + attr->proto = PTHREAD_PRIO_NONE; + attr->ceiling = sched_get_priority_min(SCHED_FIFO); +#endif + #ifdef CONFIG_PRIORITY_INHERITANCE # ifdef CONFIG_PTHREAD_MUTEX_DEFAULT_PRIO_INHERIT attr->proto = PTHREAD_PRIO_INHERIT; diff --git a/libs/libc/pthread/pthread_mutexattr_setprioceiling.c b/libs/libc/pthread/pthread_mutexattr_setprioceiling.c new file mode 100644 index 0000000000000..dd011ebd0a365 --- /dev/null +++ b/libs/libc/pthread/pthread_mutexattr_setprioceiling.c @@ -0,0 +1,65 @@ +/**************************************************************************** + * libs/libc/pthread/pthread_mutexattr_setprioceiling.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: pthread_mutexattr_setprioceiling + * + * Description: + * Set the mutex ceiling priority in the mutex attributes. + * + * Input Parameters: + * attr - The mutex attributes in which to set the mutex type. + * prioceiling - The mutex ceiling priority value to set. + * + * Returned Value: + * 0, if the mutex type was successfully set in 'attr', or + * EINVAL, if 'attr' is NULL or 'prioceiling' out of range. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_mutexattr_setprioceiling(FAR pthread_mutexattr_t *attr, + int prioceiling) +{ +#ifdef CONFIG_PRIORITY_PROTECT + if (attr && prioceiling >= sched_get_priority_min(SCHED_FIFO) && + prioceiling <= sched_get_priority_max(SCHED_FIFO)) + { + attr->ceiling = prioceiling; + return OK; + } +#endif + + return EINVAL; +} diff --git a/libs/libc/pthread/pthread_mutexattr_setprotocol.c b/libs/libc/pthread/pthread_mutexattr_setprotocol.c index d9acfd9fb5cd9..28c53772d51d2 100644 --- a/libs/libc/pthread/pthread_mutexattr_setprotocol.c +++ b/libs/libc/pthread/pthread_mutexattr_setprotocol.c @@ -59,15 +59,32 @@ int pthread_mutexattr_setprotocol(FAR pthread_mutexattr_t *attr, switch (protocol) { case PTHREAD_PRIO_NONE: -#ifdef CONFIG_PRIORITY_INHERITANCE +#if defined(CONFIG_PRIORITY_INHERITANCE) || defined(CONFIG_PRIORITY_PROTECT) + attr->proto = PTHREAD_PRIO_INHERIT; +#endif + break; + case PTHREAD_PRIO_INHERIT: - attr->proto = protocol; +#ifdef CONFIG_PRIORITY_INHERITANCE + attr->proto = PTHREAD_PRIO_INHERIT; + break; +#else + return ENOTSUP; #endif /* CONFIG_PRIORITY_INHERITANCE */ - return OK; + + case PTHREAD_PRIO_PROTECT: +#ifdef CONFIG_PRIORITY_PROTECT + attr->proto = PTHREAD_PRIO_PROTECT; + break; +#else + return ENOTSUP; +#endif /* CONFIG_PRIORITY_PROTECT */ default: return ENOTSUP; } + + return OK; } return EINVAL; diff --git a/sched/pthread/pthread_mutexinit.c b/sched/pthread/pthread_mutexinit.c index 0222dc2556acc..2ba7143f3a3ed 100644 --- a/sched/pthread/pthread_mutexinit.c +++ b/sched/pthread/pthread_mutexinit.c @@ -55,62 +55,61 @@ int pthread_mutex_init(FAR pthread_mutex_t *mutex, FAR const pthread_mutexattr_t *attr) { -#ifdef CONFIG_PTHREAD_MUTEX_TYPES - uint8_t type = PTHREAD_MUTEX_DEFAULT; -#endif -#ifndef CONFIG_PTHREAD_MUTEX_UNSAFE -#ifdef CONFIG_PTHREAD_MUTEX_DEFAULT_UNSAFE - uint8_t flags = 0; -#else - uint8_t flags = _PTHREAD_MFLAGS_ROBUST; -#endif -#endif - int ret = OK; int status; sinfo("mutex=%p attr=%p\n", mutex, attr); if (!mutex) { - ret = EINVAL; + return EINVAL; } - else + + /* Initialize the mutex like a semaphore with initial count = 1 */ + + status = mutex_init(&mutex->mutex); + if (status < 0) { - /* Were attributes specified? If so, use them */ + return -status; + } + + /* Were attributes specified? If so, use them */ - if (attr) - { #ifdef CONFIG_PTHREAD_MUTEX_TYPES - type = attr->type; + mutex->type = attr ? attr->type : PTHREAD_MUTEX_DEFAULT; #endif -#ifdef CONFIG_PTHREAD_MUTEX_BOTH - flags = attr->robust == PTHREAD_MUTEX_ROBUST ? - _PTHREAD_MFLAGS_ROBUST : 0; +#ifndef CONFIG_PTHREAD_MUTEX_UNSAFE + mutex->flink = NULL; +# ifdef CONFIG_PTHREAD_MUTEX_BOTH + mutex->flags = attr && attr->robust == PTHREAD_MUTEX_ROBUST ? + _PTHREAD_MFLAGS_ROBUST : 0; +# else + mutex->flags = 0; +# endif #endif - } - /* Initialize the mutex like a semaphore with initial count = 1 */ - - status = mutex_init(&mutex->mutex); +#if defined(CONFIG_PRIORITY_INHERITANCE) || defined(CONFIG_PRIORITY_PROTECT) + if (attr) + { + status = mutex_set_protocol(&mutex->mutex, attr->proto); if (status < 0) { - ret = -status; + mutex_destroy(&mutex->mutex); + return -status; } -#ifndef CONFIG_PTHREAD_MUTEX_UNSAFE - /* Initial internal fields of the mutex */ - - mutex->flink = NULL; - mutex->flags = flags; -#endif - -#ifdef CONFIG_PTHREAD_MUTEX_TYPES - /* Set up attributes unique to the mutex type */ - - mutex->type = type; -#endif +# ifdef CONFIG_PRIORITY_PROTECT + if (attr->proto == PTHREAD_PRIO_PROTECT) + { + status = mutex_setprioceiling(&mutex->mutex, attr->ceiling, NULL); + if (status < 0) + { + mutex_destroy(&mutex->mutex); + return -status; + } + } +# endif } +#endif - sinfo("Returning %d\n", ret); - return ret; + return 0; }