diff --git a/ChangeLog b/ChangeLog index 993b71c9249..a47f3effb6d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -356,3 +356,5 @@ deletion logic (timer_delete.c) and one in stream logic (lib_init.c). 0.3.11 2008-xx-xx Gregory Nutt + + * Add support for recursive mutexes. diff --git a/Documentation/NuttX.html b/Documentation/NuttX.html index a0f552e8d7d..3a48481f2e5 100644 --- a/Documentation/NuttX.html +++ b/Documentation/NuttX.html @@ -8,7 +8,7 @@

NuttX RTOS

-

Last Updated: May 15, 2008

+

Last Updated: May 31, 2008

@@ -1007,11 +1007,13 @@ buildroot-0.1.0 2007-03-09 <spudmonkey@racsa.co.cr>
diff --git a/Documentation/NuttxPortingGuide.html b/Documentation/NuttxPortingGuide.html index d59315db9c3..44059c231df 100644 --- a/Documentation/NuttxPortingGuide.html +++ b/Documentation/NuttxPortingGuide.html @@ -1408,6 +1408,9 @@ The system can be re-made subsequently by just typing make. CONFIG_DEV_CONSOLE: Set if architecture-specific logic provides /dev/console. Enables stdout, stderr, stdin. +
  • + CONFIG_MUTEX_TYPES: Set to enabled support for recursive and + errorcheck mutexes. Enables pthread_mutexattr_settype().

    diff --git a/Documentation/NuttxUserGuide.html b/Documentation/NuttxUserGuide.html index a5ef33f1b34..554915b7722 100644 --- a/Documentation/NuttxUserGuide.html +++ b/Documentation/NuttxUserGuide.html @@ -21,7 +21,7 @@ User's Manual

    Gregory Nutt

    -Last Update: Februrary 2, 2008 +Last Update: May 31, 2008

    1.0 Introduction

    @@ -3434,32 +3434,34 @@ be sent.
  • 2.9.27 pthread_mutexattr_destroy
  • 2.9.28 pthread_mutexattr_getpshared
  • 2.9.29 pthread_mutexattr_setpshared
  • -
  • 2.9.30 pthread_mutex_init
  • -
  • 2.9.31 pthread_mutex_destroy
  • -
  • 2.9.32 pthread_mutex_lock
  • -
  • 2.9.33 pthread_mutex_trylock
  • -
  • 2.9.34 pthread_mutex_unlock
  • -
  • 2.9.35 pthread_condattr_init
  • -
  • 2.9.36 pthread_condattr_destroy
  • -
  • 2.9.37 pthread_cond_init
  • -
  • 2.9.38 pthread_cond_destroy
  • -
  • 2.9.39 pthread_cond_broadcast
  • -
  • 2.9.40 pthread_cond_signal
  • -
  • 2.9.41 pthread_cond_wait
  • -
  • 2.9.42 pthread_cond_timedwait
  • -
  • 2.9.43 pthread_barrierattr_init
  • -
  • 2.9.44 pthread_barrierattr_destroy
  • -
  • 2.9.45 pthread_barrierattr_setpshared
  • -
  • 2.9.46 pthread_barrierattr_getpshared
  • -
  • 2.9.47 pthread_barrier_init
  • -
  • 2.9.48 pthread_barrier_destroy
  • -
  • 2.9.49 pthread_barrier_wait
  • -
  • 2.9.50 pthread_once
  • -
  • 2.9.51 pthread_kill
  • -
  • 2.9.52 pthread_sigmask
  • +
  • 2.9.30 pthread_mutexattr_gettype
  • +
  • 2.9.31 pthread_mutexattr_settype
  • +
  • 2.9.32 pthread_mutex_init
  • +
  • 2.9.33 pthread_mutex_destroy
  • +
  • 2.9.34 pthread_mutex_lock
  • +
  • 2.9.35 pthread_mutex_trylock
  • +
  • 2.9.36 pthread_mutex_unlock
  • +
  • 2.9.37 pthread_condattr_init
  • +
  • 2.9.38 pthread_condattr_destroy
  • +
  • 2.9.39 pthread_cond_init
  • +
  • 2.9.40 pthread_cond_destroy
  • +
  • 2.9.41 pthread_cond_broadcast
  • +
  • 2.9.42 pthread_cond_signal
  • +
  • 2.9.43 pthread_cond_wait
  • +
  • 2.9.44 pthread_cond_timedwait
  • +
  • 2.9.45 pthread_barrierattr_init
  • +
  • 2.9.46 pthread_barrierattr_destroy
  • +
  • 2.9.47 pthread_barrierattr_setpshared
  • +
  • 2.9.48 pthread_barrierattr_getpshared
  • +
  • 2.9.49 pthread_barrier_init
  • +
  • 2.9.50 pthread_barrier_destroy
  • +
  • 2.9.51 pthread_barrier_wait
  • +
  • 2.9.52 pthread_once
  • +
  • 2.9.53 pthread_kill
  • +
  • 2.9.54 pthread_sigmask
  • - No support for the ollowing pthread interfaces is provided by NuttX: + No support for the following pthread interfaces is provided by NuttX:

    +
  • pthread_mutex_destroy
  • pthread_mutex_init
  • pthread_mutex_lock
  • pthread_mutex_trylock
  • diff --git a/configs/README.txt b/configs/README.txt index fc4b4cce9c4..ba746ce6873 100644 --- a/configs/README.txt +++ b/configs/README.txt @@ -180,6 +180,8 @@ defconfig -- This is a configuration file similar to the Linux CONFIG_JULIAN_TIME - Enables Julian time conversions CONFIG_DEV_CONSOLE - Set if architecture-specific logic provides /dev/console. Enables stdout, stderr, stdin. + CONFIG_MUTEX_TYPES - Set to enabled support for recursive and + errorcheck mutexes. Enables pthread_mutexattr_settype(). The following can be used to disable categories of APIs supported by the OS. If the compiler supports weak functions, then it diff --git a/configs/sim/nettest/Make.defs b/configs/sim/nettest/Make.defs index 28069e16a36..d0cd57f864e 100644 --- a/configs/sim/nettest/Make.defs +++ b/configs/sim/nettest/Make.defs @@ -35,6 +35,8 @@ include ${TOPDIR}/.config +HOSTOS = ${shell uname -o} + ifneq ("${CONFIG_DEBUG}","y") ARCHOPTIMIZATION = -g else @@ -62,7 +64,12 @@ AFLAGS = $(CFLAGS) -D__ASSEMBLY__ OBJEXT = .o LIBEXT = .a -EXEEXT = + +ifeq ($(HOSTOS),Cygwin) + EXEEXT = .exe +else + EXEEXT = +endif ifeq ("${CONFIG_DEBUG}","y") LDFLAGS += -g diff --git a/configs/sim/ostest/Make.defs b/configs/sim/ostest/Make.defs index 28069e16a36..d0cd57f864e 100644 --- a/configs/sim/ostest/Make.defs +++ b/configs/sim/ostest/Make.defs @@ -35,6 +35,8 @@ include ${TOPDIR}/.config +HOSTOS = ${shell uname -o} + ifneq ("${CONFIG_DEBUG}","y") ARCHOPTIMIZATION = -g else @@ -62,7 +64,12 @@ AFLAGS = $(CFLAGS) -D__ASSEMBLY__ OBJEXT = .o LIBEXT = .a -EXEEXT = + +ifeq ($(HOSTOS),Cygwin) + EXEEXT = .exe +else + EXEEXT = +endif ifeq ("${CONFIG_DEBUG}","y") LDFLAGS += -g diff --git a/configs/sim/pashello/Make.defs b/configs/sim/pashello/Make.defs index 9f23c5da8d9..8b300eed627 100644 --- a/configs/sim/pashello/Make.defs +++ b/configs/sim/pashello/Make.defs @@ -35,6 +35,8 @@ include ${TOPDIR}/.config +HOSTOS = ${shell uname -o} + ifneq ("${CONFIG_DEBUG}","y") ARCHOPTIMIZATION = -g else @@ -62,7 +64,12 @@ AFLAGS = $(CFLAGS) -D__ASSEMBLY__ OBJEXT = .o LIBEXT = .a -EXEEXT = + +ifeq ($(HOSTOS),Cygwin) + EXEEXT = .exe +else + EXEEXT = +endif ifeq ("${CONFIG_DEBUG}","y") LDFLAGS += -g diff --git a/include/pthread.h b/include/pthread.h index 6ce1e956458..a6cccc7860c 100644 --- a/include/pthread.h +++ b/include/pthread.h @@ -70,6 +70,36 @@ #define PTHREAD_PROCESS_PRIVATE 0 #define PTHREAD_PROCESS_SHARED 1 +/* Values for the mutext type attribute: + * + * PTHREAD_MUTEX_NORMAL: This type of mutex does not detect deadlock. A thread + * attempting to relock this mutex without first unlocking it will deadlock. + * Attempting to unlock a mutex locked by a different thread results in undefined + * behavior. Attempting to unlock an unlocked mutex results in undefined behavior. + * PTHREAD_MUTEX_ERRORCHECK + * This type of mutex provides error checking. A thread attempting to relock this + * mutex without first unlocking it will return with an error. A thread attempting + * to unlock a mutex which another thread has locked will return with an error. A + * thread attempting to unlock an unlocked mutex will return with an error. + * PTHREAD_MUTEX_RECURSIVE + * A thread attempting to relock this mutex without first unlocking it will succeed + * in locking the mutex. The relocking deadlock which can occur with mutexes of type + * PTHREAD_MUTEX_NORMAL cannot occur with this type of mutex. Multiple locks of this + * mutex require the same number of unlocks to release the mutex before another thread + * can acquire the mutex. A thread attempting to unlock a mutex which another thread + * has locked will return with an error. A thread attempting to unlock an unlocked + * mutex will return with an error. + * PTHREAD_MUTEX_DEFAULT + * An implementation is allowed to map this mutex to one of the other mutex types. + */ + +#ifdef CONFIG_MUTEX_TYPES +# define PTHREAD_MUTEX_NORMAL 0 +# define PTHREAD_MUTEX_ERRORCHECK 1 +# define PTHREAD_MUTEX_RECURSIVE 2 +# define PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_NORMAL +#endif + /* Valid ranges for the pthread stacksize attribute */ #define PTHREAD_STACK_MIN CONFIG_PTHREAD_STACK_MIN @@ -123,7 +153,7 @@ typedef FAR void *pthread_addr_t; typedef pthread_addr_t any_t; typedef pthread_addr_t (*pthread_startroutine_t)(pthread_addr_t); -typedef pthread_startroutine_t pthread_func_t; +typedef pthread_startroutine_t pthread_func_t; struct pthread_addr_s { @@ -147,17 +177,29 @@ typedef struct pthread_cond_s pthread_cond_t; struct pthread_mutexattr_s { - int pshared; + ubyte pshared; /* PTHREAD_PROCESS_PRIVATE or PTHREAD_PROCESS_SHARED */ +#ifdef CONFIG_MUTEX_TYPES + ubyte type; /* Type of the mutex. See PTHREAD_MUTEX_* definitions */ +#endif }; typedef struct pthread_mutexattr_s pthread_mutexattr_t; struct pthread_mutex_s { - int pid; - sem_t sem; + int pid; /* ID of the holder of the mutex */ + sem_t sem; /* Semaphore underlying the implementation of the mutex */ +#ifdef CONFIG_MUTEX_TYPES + ubyte type; /* Type of the mutex. See PTHREAD_MUTEX_* definitions */ + int nlocks; /* The number of recursive locks held */ +#endif }; typedef struct pthread_mutex_s pthread_mutex_t; -#define PTHREAD_MUTEX_INITIALIZER {0, {1, 0xffff}} + +#ifdef CONFIG_MUTEX_TYPES +# define PTHREAD_MUTEX_INITIALIZER {0, {1, 0xffff}, PTHREAD_MUTEX_DEFAULT, 0} +#else +# define PTHREAD_MUTEX_INITIALIZER {0, {1, 0xffff}} +#endif struct pthread_barrierattr_s { @@ -268,7 +310,7 @@ EXTERN int pthread_setschedprio(pthread_t thread, int prio); /* Thread-specific Data Interfaces */ EXTERN int pthread_key_create(FAR pthread_key_t *key, - CODE void (*destructor)(FAR void*)); + CODE void (*destructor)(FAR void*)); EXTERN int pthread_setspecific(pthread_key_t key, FAR void *value); EXTERN FAR void *pthread_getspecific(pthread_key_t key); EXTERN int pthread_key_delete(pthread_key_t key); @@ -279,6 +321,10 @@ EXTERN int pthread_mutexattr_init(FAR pthread_mutexattr_t *attr); EXTERN int pthread_mutexattr_destroy(FAR pthread_mutexattr_t *attr); EXTERN int pthread_mutexattr_getpshared(FAR pthread_mutexattr_t *attr, FAR int *pshared); EXTERN int pthread_mutexattr_setpshared(FAR pthread_mutexattr_t *attr, int pshared); +#ifdef CONFIG_MUTEX_TYPES +EXTERN int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type); +EXTERN int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type); +#endif /* The following routines create, delete, lock and unlock mutexes. */ diff --git a/sched/Makefile b/sched/Makefile index ad5286f0168..461bc56d050 100644 --- a/sched/Makefile +++ b/sched/Makefile @@ -105,6 +105,9 @@ PTHREAD_SRCS = pthread_attrinit.c pthread_attrdestroy.c \ ifneq ($(CONFIG_DISABLE_SIGNALS),y) PTHREAD_SRCS += pthread_condtimedwait.c pthread_kill.c pthread_sigmask.c endif +ifeq ($(CONFIG_MUTEX_TYPES),y) +PTHREAD_SRCS += pthread_mutexattrsettype.c pthread_mutexattrgettype.c pthread_mutexattrverifytype.c +endif SEM_SRCS = sem_initialize.c sem_init.c sem_destroy.c\ sem_open.c sem_close.c sem_unlink.c \ sem_wait.c sem_trywait.c sem_post.c sem_getvalue.c \ diff --git a/sched/pthread_internal.h b/sched/pthread_internal.h index ec7c5ed717a..8a417179d60 100644 --- a/sched/pthread_internal.h +++ b/sched/pthread_internal.h @@ -1,7 +1,7 @@ -/************************************************************ +/**************************************************************************** * pthread_internal.h * - * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -14,7 +14,7 @@ * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. - * 3. Neither the name Gregory Nutt nor the names of its contributors may be + * 3. Neither the name NuttX nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * @@ -31,26 +31,26 @@ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * - ************************************************************/ + ****************************************************************************/ #ifndef __PTHREAD_INTERNAL_H #define __PTHREAD_INTERNAL_H -/************************************************************ +/**************************************************************************** * Included Files - ************************************************************/ + ****************************************************************************/ #include #include #include -/************************************************************ +/**************************************************************************** * Definitions - ************************************************************/ + ****************************************************************************/ -/************************************************************ +/**************************************************************************** * Public Type Declarations - ************************************************************/ + ****************************************************************************/ /* The following defines an entry in the pthread logic's * local data set. Note that this structure is used to @@ -76,9 +76,9 @@ struct join_s }; typedef struct join_s join_t; -/************************************************************ +/**************************************************************************** * Public Variables - ************************************************************/ + ****************************************************************************/ /* This is the head of a private singly linked list. It * is used to retain information about the spawned threads. @@ -103,9 +103,9 @@ extern ubyte g_pthread_num_keys; extern FAR pthread_attr_t g_default_pthread_attr; -/************************************************************ +/**************************************************************************** * Public Function Prototypes - ************************************************************/ + ****************************************************************************/ #ifdef __cplusplus #define EXTERN extern "C" @@ -122,6 +122,10 @@ EXTERN int pthread_givesemaphore(sem_t *sem); EXTERN FAR join_t *pthread_removejoininfo(pid_t pid); EXTERN int pthread_takesemaphore(sem_t *sem); +#ifdef CONFIG_MUTEX_TYPES +EXTERN int pthread_mutexattr_verifytype(int type); +#endif + #undef EXTERN #ifdef __cplusplus } diff --git a/sched/pthread_mutexattrgettype.c b/sched/pthread_mutexattrgettype.c new file mode 100644 index 00000000000..fb01c23833a --- /dev/null +++ b/sched/pthread_mutexattrgettype.c @@ -0,0 +1,100 @@ +/**************************************************************************** + * sched/pthread_mutexattrgettype.c + * + * Copyright (C) 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include "pthread_internal.h" + +#ifdef CONFIG_MUTEX_TYPES + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: pthread_mutexattr_gettype + * + * Description: + * Return the mutex type from the mutex attributes. + * + * Parameters: + * attr - The mutex attributes to query + * type - Location to return the mutex type + * + * Return Value: + * 0, if the mutex type was successfully return in 'type', or + * EINVAL, if any NULL pointers provided. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type) +{ + if (attr && type) + { + *type = attr->type; + return 0; + } + return EINVAL; +} + +#endif /* CONFIG_MUTEX_TYPES */ diff --git a/sched/pthread_mutexattrinit.c b/sched/pthread_mutexattrinit.c index 85b1e953d1e..b023bee3e87 100644 --- a/sched/pthread_mutexattrinit.c +++ b/sched/pthread_mutexattrinit.c @@ -96,6 +96,9 @@ int pthread_mutexattr_init(FAR pthread_mutexattr_t *attr) else { attr->pshared = 0; +#ifdef CONFIG_MUTEX_TYPES + attr->type = PTHREAD_MUTEX_DEFAULT; +#endif } sdbg("Returning %d\n", ret); diff --git a/sched/pthread_mutexattrsettype.c b/sched/pthread_mutexattrsettype.c new file mode 100644 index 00000000000..c50316c3c78 --- /dev/null +++ b/sched/pthread_mutexattrsettype.c @@ -0,0 +1,100 @@ +/**************************************************************************** + * sched/pthread_mutexattrsettype.c + * + * Copyright (C) 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include "pthread_internal.h" + +#ifdef CONFIG_MUTEX_TYPES + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: pthread_mutexattr_settype + * + * Description: + * Set the mutex type in the mutex attributes. + * + * Parameters: + * attr - The mutex attributes in which to set the mutex type. + * type - The mutex type value to set. + * + * Return Value: + * 0, if the mutex type was successfully set in 'attr', or + * EINVAL, if 'attr' is NULL or 'type' unrecognized. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) +{ + if (attr && pthread_mutexattr_verifytype(type) == OK) + { + attr->type = type; + return 0; + } + return EINVAL; +} + +#endif /* CONFIG_MUTEX_TYPES */ diff --git a/sched/pthread_mutexattrverifytype.c b/sched/pthread_mutexattrverifytype.c new file mode 100644 index 00000000000..e089be08856 --- /dev/null +++ b/sched/pthread_mutexattrverifytype.c @@ -0,0 +1,95 @@ +/**************************************************************************** + * sched/pthread_mutexattrverifytype.c + * + * Copyright (C) 2008 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "pthread_internal.h" + +#ifdef CONFIG_MUTEX_TYPES + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Global Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: pthread_mutexattr_verifytype + * + * Description: + * Verify that 'type' is a supported mutex type. + * + * Parameters: + * type - Mutex type to test + * + * Return Value: + * 0 (OK), if 'type' is a valid mutex type, or + * -1 (ERROR) if it is not. + * + * Assumptions: + * + ****************************************************************************/ + +int pthread_mutexattr_verifytype(int type) +{ + /* The depends on the value assigments in pthread.h */ + + return (type >= PTHREAD_MUTEX_NORMAL && type <= PTHREAD_MUTEX_RECURSIVE); +} + +#endif /* CONFIG_MUTEX_TYPES */ diff --git a/sched/pthread_mutexinit.c b/sched/pthread_mutexinit.c index 5234c988f38..92591fac6d1 100644 --- a/sched/pthread_mutexinit.c +++ b/sched/pthread_mutexinit.c @@ -85,8 +85,11 @@ int pthread_mutex_init(FAR pthread_mutex_t *mutex, FAR pthread_mutexattr_t *attr) { - int ret = OK; int pshared = 0; +#ifdef CONFIG_MUTEX_TYPES + ubyte type = PTHREAD_MUTEX_DEFAULT; +#endif + int ret = OK; int status; sdbg("mutex=0x%p attr=0x%p\n", mutex, attr); @@ -102,6 +105,9 @@ int pthread_mutex_init(FAR pthread_mutex_t *mutex, FAR pthread_mutexattr_t *attr if (attr) { pshared = attr->pshared; +#ifdef CONFIG_MUTEX_TYPES + type = attr->type; +#endif } /* Indicate that the semaphore is not held by any thread. */ @@ -117,6 +123,13 @@ int pthread_mutex_init(FAR pthread_mutex_t *mutex, FAR pthread_mutexattr_t *attr } } + /* Set up attributes unique to the mutex type */ + +#ifdef CONFIG_MUTEX_TYPES + mutex->type = type; + mutex->nlocks = 0; +#endif + sdbg("Returning %d\n", ret); return ret; } diff --git a/sched/pthread_mutexlock.c b/sched/pthread_mutexlock.c index d47d468f106..753aa2c6b14 100644 --- a/sched/pthread_mutexlock.c +++ b/sched/pthread_mutexlock.c @@ -108,8 +108,25 @@ int pthread_mutex_lock(FAR pthread_mutex_t *mutex) if (mutex->pid == mypid) { - sdbg("Returning EDEADLK\n"); - ret = EDEADLK; + /* Yes.. Is this a recursive mutex? */ + +#ifdef CONFIG_MUTEX_TYPES + if (mutex->type == PTHREAD_MUTEX_RECURSIVE) + { + /* Yes... just increment the number of locks held and return success */ + + mutex->nlocks++; + } + else +#endif + { + /* No, then we would deadlock... return an error (default behavior + * is like PTHREAD_MUTEX_ERRORCHECK) + */ + + sdbg("Returning EDEADLK\n"); + ret = EDEADLK; + } } else { @@ -123,7 +140,10 @@ int pthread_mutex_lock(FAR pthread_mutex_t *mutex) if (!ret) { - mutex->pid = mypid; + mutex->pid = mypid; +#ifdef CONFIG_MUTEX_TYPES + mutex->nlocks = 1; +#endif } } sched_unlock(); @@ -133,6 +153,3 @@ int pthread_mutex_lock(FAR pthread_mutex_t *mutex) return ret; } - - - diff --git a/sched/pthread_mutexunlock.c b/sched/pthread_mutexunlock.c index 1184fc804c6..f01f7761eb8 100644 --- a/sched/pthread_mutexunlock.c +++ b/sched/pthread_mutexunlock.c @@ -107,14 +107,38 @@ int pthread_mutex_unlock(FAR pthread_mutex_t *mutex) if (mutex->pid != (int)getpid()) { + /* No... return an error (default behavior is like PTHREAD_MUTEX_ERRORCHECK) */ + sdbg("Holder=%d returning EPERM\n", mutex->pid); ret = EPERM; } + + + /* Yes, the caller owns the semaphore.. Is this a recursive mutex? */ + +#ifdef CONFIG_MUTEX_TYPES + else if (mutex->type == PTHREAD_MUTEX_RECURSIVE && mutex->nlocks > 1) + { + /* This is a recursive mutex and we there are multiple locks held. Retain + * the mutex lock, just decrement the count of locks held, and return + * success. + */ + mutex->nlocks--; + } +#endif + + /* This is either a non-recursive mutex or is the outermost unlock of + * a recursive mutex. + */ + else { - /* Nulllify the pid and post the semaphore */ + /* Nullify the pid and lock count then post the semaphore */ - mutex->pid = 0; + mutex->pid = 0; +#ifdef CONFIG_MUTEX_TYPES + mutex->nlocks = 0; +#endif ret = pthread_givesemaphore((sem_t*)&mutex->sem); } sched_unlock();