diff options
29 files changed, 634 insertions, 130 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index d183e4f30..532f448d6 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -650,5 +650,7 @@ * Restructured parts of the uIP port for correct compilation with ZDS-II * eZ80Acclaim!: Complete basic integration of the eZ80F91 EMAC driver. The driver is basically functional and should mature prior to the 0.4.3 release. + * Implemented priority inheritance logic for POSIX semaphores. Because the pthread + mutexes are built on semaphores, they will have this property as well. diff --git a/nuttx/Documentation/NuttX.html b/nuttx/Documentation/NuttX.html index fef9520a3..f50003599 100644 --- a/nuttx/Documentation/NuttX.html +++ b/nuttx/Documentation/NuttX.html @@ -285,7 +285,7 @@ <td><br></td> <td> <p> - <li>Realtime, deterministic.</li> + <li>Realtime, deterministic, with support for priority inheritance</li> </p> </tr> @@ -1371,6 +1371,8 @@ nuttx-0.4.3 2009-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr> * Restructured parts of the uIP port for correct compilation with ZDS-II * eZ80Acclaim!: Complete basic integration of the eZ80F91 EMAC driver. The driver is basically functional and should mature prior to the 0.4.3 release. + * Implemented priority inheritance logic for POSIX semaphores. Because the pthread + mutexes are built on semaphores, they will have this property as well. pascal-0.1.3 2009-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr> diff --git a/nuttx/Documentation/NuttxPortingGuide.html b/nuttx/Documentation/NuttxPortingGuide.html index b47cd99de..4c3f3ff79 100644 --- a/nuttx/Documentation/NuttxPortingGuide.html +++ b/nuttx/Documentation/NuttxPortingGuide.html @@ -12,7 +12,7 @@ <h1><big><font color="#3c34ec"> <i>NuttX RTOS Porting Guide</i> </font></big></h1> - <p>Last Updated: December 5, 2008</p> + <p>Last Updated: March 8, 2009</p> </td> </tr> </table> @@ -1623,8 +1623,13 @@ The system can be re-made subsequently by just typing <code>make</code>. provides /dev/console. Enables stdout, stderr, stdin. </li> <li> - <code>CONFIG_MUTEX_TYPES</code>: Set to enabled support for recursive and + <code>CONFIG_MUTEX_TYPES</code>: Set to enable support for recursive and errorcheck mutexes. Enables <code>pthread_mutexattr_settype()</code>. + </li> + <li> + <code>CONFIG_PRIORITY_INHERITANCE </code>: Set to enable support for + priority inheritance on mutexes and semaphores. + </li> </ul> <p> diff --git a/nuttx/Documentation/NuttxUserGuide.html b/nuttx/Documentation/NuttxUserGuide.html index 0dfa64a87..5869beedf 100644 --- a/nuttx/Documentation/NuttxUserGuide.html +++ b/nuttx/Documentation/NuttxUserGuide.html @@ -13,7 +13,7 @@ <h1><big><font color="#3c34ec"><i>NuttX Operating System<p>User's Manual</i></font></big></h1> <p><small>by</small></p> <p>Gregory Nutt<p> - <p>Last Updated: November 18, 2008</p> + <p>Last Updated: March 8, 2009</p> </td> </tr> </table> @@ -1718,9 +1718,11 @@ interface of the same name. <p> Some operating systems avoid priority inversion by <I>automatically</I> increasing the priority of the low-priority <I>Task C</I> (the operable - buzz-word for this behavior is <I>priority inheritance</I>). NuttX does not - support this behavior. As a consequence, it is left to the designer to - provide implementations that will not suffer from priority inversion. + buzz-word for this behavior is <I>priority inheritance</I>). NuttX + supports this behavior, but only if <code>CONFIG_PRIORITY_INHERITANCE</code> + is defined in your OS configuration file. If <code>CONFIG_PRIORITY_INHERITANCE</code> + is not defined, then it is left to the designer to provide implementations + that will not suffer from priority inversion. The designer may, as examples: </p> <ul> diff --git a/nuttx/TODO b/nuttx/TODO index ea3e218d3..763d08889 100644 --- a/nuttx/TODO +++ b/nuttx/TODO @@ -1,7 +1,7 @@ NuttX TODO List (Last updated February 19, 2009) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - (7) Task/Scheduler (sched/) + (6) Task/Scheduler (sched/) (1) Dynamic loader (N/A) (2) Memory Managment (mm/) (1) Signals (sched/, arch/) @@ -53,10 +53,6 @@ o Task/Scheduler (sched/) Status: Open Priority: Low - Description: Implement priority inheritance - Status: Open - Priority: Medium, this is a good feature for realtime systems. - Description: Several APIs do not set errno. Need to review all APIs. Status: Open Priority: Medium, required for standard compliance (but makes the diff --git a/nuttx/arch/arm/src/common/up_reprioritizertr.c b/nuttx/arch/arm/src/common/up_reprioritizertr.c index b802f2e84..edc2f9e1f 100644 --- a/nuttx/arch/arm/src/common/up_reprioritizertr.c +++ b/nuttx/arch/arm/src/common/up_reprioritizertr.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/arm/src/common/up_reprioritizertr.c * - * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> * * Redistribution and use in source and binary forms, with or without @@ -85,14 +85,27 @@ void up_reprioritize_rtr(_TCB *tcb, ubyte priority) { /* Verify that the caller is sane */ - if (tcb->task_state < FIRST_READY_TO_RUN_STATE || - tcb->task_state > LAST_READY_TO_RUN_STATE || - priority < SCHED_PRIORITY_MIN || +#if CONFIG_DEBUG /* We only check parameters when debug is enabled */ + if (priority < SCHED_PRIORITY_MIN || priority > SCHED_PRIORITY_MAX) { PANIC(OSERR_BADREPRIORITIZESTATE); } else +#endif + if (tcb->task_state < FIRST_READY_TO_RUN_STATE || + tcb->task_state > LAST_READY_TO_RUN_STATE) + { + /* This is a hack and needs to be fixed.. here some taks is reprioritizing + * another task that is not running. Here we just set the priority of + * the task -- BUT some of the other states are also prioritized and the + * waiting task should also be re-ordered in the prioritized wiating list. + * As a consequence, the other task is still waiting at the lower priority. + */ + + tcb->sched_priority = priority; + } + else { _TCB *rtcb = (_TCB*)g_readytorun.head; boolean switch_needed; @@ -109,6 +122,9 @@ void up_reprioritize_rtr(_TCB *tcb, ubyte priority) /* Setup up the new task priority */ tcb->sched_priority = (ubyte)priority; +#ifdef CONFIG_PRIORITY_INHERITANCE + tcb->base_priority = (ubyte)priority; +#endif /* Return the task to the specified blocked task list. * sched_addreadytorun will return TRUE if the task was diff --git a/nuttx/arch/pjrc-8051/src/up_reprioritizertr.c b/nuttx/arch/pjrc-8051/src/up_reprioritizertr.c index b148e755c..97d5682e0 100644 --- a/nuttx/arch/pjrc-8051/src/up_reprioritizertr.c +++ b/nuttx/arch/pjrc-8051/src/up_reprioritizertr.c @@ -1,7 +1,7 @@ -/************************************************************ +/**************************************************************************** * up_reprioritizertr.c * - * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> * * 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,11 +31,11 @@ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * - ************************************************************/ + ****************************************************************************/ -/************************************************************ +/**************************************************************************** * Included Files - ************************************************************/ + ****************************************************************************/ #include <nuttx/config.h> #include <sys/types.h> @@ -45,23 +45,23 @@ #include "os_internal.h" #include "up_internal.h" -/************************************************************ +/**************************************************************************** * Private Definitions - ************************************************************/ + ****************************************************************************/ -/************************************************************ +/**************************************************************************** * Private Data - ************************************************************/ + ****************************************************************************/ -/************************************************************ +/**************************************************************************** * Private Funtions - ************************************************************/ + ****************************************************************************/ -/************************************************************ +/**************************************************************************** * Public Funtions - ************************************************************/ + ****************************************************************************/ -/************************************************************ +/**************************************************************************** * Name: up_reprioritize_rtr * * Description: @@ -79,20 +79,33 @@ * tcb: The TCB of the task that has been reprioritized * priority: The new task priority * - ************************************************************/ + ****************************************************************************/ void up_reprioritize_rtr(FAR _TCB *tcb, ubyte priority) { /* Verify that the caller is sane */ - if (tcb->task_state < FIRST_READY_TO_RUN_STATE || - tcb->task_state > LAST_READY_TO_RUN_STATE || - priority < SCHED_PRIORITY_MIN || +#if CONFIG_DEBUG /* We only check parameters when debug is enabled */ + if (priority < SCHED_PRIORITY_MIN || priority > SCHED_PRIORITY_MAX) { PANIC(OSERR_BADREPRIORITIZESTATE); } else +#endif + if (tcb->task_state < FIRST_READY_TO_RUN_STATE || + tcb->task_state > LAST_READY_TO_RUN_STATE) + { + /* This is a hack and needs to be fixed.. here some taks is reprioritizing + * another task that is not running. Here we just set the priority of + * the task -- BUT some of the other states are also prioritized and the + * waiting task should also be re-ordered in the prioritized wiating list. + * As a consequence, the other task is still waiting at the lower priority. + */ + + tcb->sched_priority = priority; + } + else { FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; boolean switch_needed; @@ -109,6 +122,9 @@ void up_reprioritize_rtr(FAR _TCB *tcb, ubyte priority) /* Setup up the new task priority */ tcb->sched_priority = (ubyte)priority; +#ifdef CONFIG_PRIORITY_INHERITANCE + tcb->base_priority = (ubyte)priority; +#endif /* Return the task to the specified blocked task list. * sched_addreadytorun will return TRUE if the task was diff --git a/nuttx/arch/sh/src/common/up_reprioritizertr.c b/nuttx/arch/sh/src/common/up_reprioritizertr.c index dccc6ad4a..58ba7a0d6 100644 --- a/nuttx/arch/sh/src/common/up_reprioritizertr.c +++ b/nuttx/arch/sh/src/common/up_reprioritizertr.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/sh/src/common/up_reprioritizertr.c * - * Copyright (C) 2008 Gregory Nutt. All rights reserved. + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> * * Redistribution and use in source and binary forms, with or without @@ -85,14 +85,27 @@ void up_reprioritize_rtr(_TCB *tcb, ubyte priority) { /* Verify that the caller is sane */ - if (tcb->task_state < FIRST_READY_TO_RUN_STATE || - tcb->task_state > LAST_READY_TO_RUN_STATE || - priority < SCHED_PRIORITY_MIN || +#if CONFIG_DEBUG /* We only check parameters when debug is enabled */ + if (priority < SCHED_PRIORITY_MIN || priority > SCHED_PRIORITY_MAX) { PANIC(OSERR_BADREPRIORITIZESTATE); } else +#endif + if (tcb->task_state < FIRST_READY_TO_RUN_STATE || + tcb->task_state > LAST_READY_TO_RUN_STATE) + { + /* This is a hack and needs to be fixed.. here some taks is reprioritizing + * another task that is not running. Here we just set the priority of + * the task -- BUT some of the other states are also prioritized and the + * waiting task should also be re-ordered in the prioritized wiating list. + * As a consequence, the other task is still waiting at the lower priority. + */ + + tcb->sched_priority = priority; + } + else { _TCB *rtcb = (_TCB*)g_readytorun.head; boolean switch_needed; @@ -109,6 +122,9 @@ void up_reprioritize_rtr(_TCB *tcb, ubyte priority) /* Setup up the new task priority */ tcb->sched_priority = (ubyte)priority; +#ifdef CONFIG_PRIORITY_INHERITANCE + tcb->base_priority = (ubyte)priority; +#endif /* Return the task to the specified blocked task list. * sched_addreadytorun will return TRUE if the task was diff --git a/nuttx/arch/sim/src/up_reprioritizertr.c b/nuttx/arch/sim/src/up_reprioritizertr.c index 5f1d2a42c..f68ff2a82 100644 --- a/nuttx/arch/sim/src/up_reprioritizertr.c +++ b/nuttx/arch/sim/src/up_reprioritizertr.c @@ -1,7 +1,7 @@ /**************************************************************************** * up_reprioritizertr.c * - * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> * * Redistribution and use in source and binary forms, with or without @@ -85,14 +85,27 @@ void up_reprioritize_rtr(_TCB *tcb, ubyte priority) { /* Verify that the caller is sane */ - if (tcb->task_state < FIRST_READY_TO_RUN_STATE || - tcb->task_state > LAST_READY_TO_RUN_STATE || - priority < SCHED_PRIORITY_MIN || +#if CONFIG_DEBUG /* We only check parameters when debug is enabled */ + if (priority < SCHED_PRIORITY_MIN || priority > SCHED_PRIORITY_MAX) { PANIC(OSERR_BADREPRIORITIZESTATE); } else +#endif + if (tcb->task_state < FIRST_READY_TO_RUN_STATE || + tcb->task_state > LAST_READY_TO_RUN_STATE) + { + /* This is a hack and needs to be fixed.. here some taks is reprioritizing + * another task that is not running. Here we just set the priority of + * the task -- BUT some of the other states are also prioritized and the + * waiting task should also be re-ordered in the prioritized wiating list. + * As a consequence, the other task is still waiting at the lower priority. + */ + + tcb->sched_priority = priority; + } + else { _TCB *rtcb = (_TCB*)g_readytorun.head; boolean switch_needed; @@ -109,6 +122,9 @@ void up_reprioritize_rtr(_TCB *tcb, ubyte priority) /* Setup up the new task priority */ tcb->sched_priority = (ubyte)priority; +#ifdef CONFIG_PRIORITY_INHERITANCE + tcb->base_priority = (ubyte)priority; +#endif /* Return the task to the specified blocked task list. * sched_addreadytorun will return TRUE if the task was diff --git a/nuttx/arch/z16/src/common/up_reprioritizertr.c b/nuttx/arch/z16/src/common/up_reprioritizertr.c index e9c6a8a1e..5692ac12c 100644 --- a/nuttx/arch/z16/src/common/up_reprioritizertr.c +++ b/nuttx/arch/z16/src/common/up_reprioritizertr.c @@ -1,7 +1,7 @@ /**************************************************************************** * common/up_reprioritizertr.c * - * Copyright (C) 2008 Gregory Nutt. All rights reserved. + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> * * Redistribution and use in source and binary forms, with or without @@ -89,14 +89,27 @@ void up_reprioritize_rtr(FAR _TCB *tcb, ubyte priority) { /* Verify that the caller is sane */ - if (tcb->task_state < FIRST_READY_TO_RUN_STATE || - tcb->task_state > LAST_READY_TO_RUN_STATE || - priority < SCHED_PRIORITY_MIN || +#if CONFIG_DEBUG /* We only check parameters when debug is enabled */ + if (priority < SCHED_PRIORITY_MIN || priority > SCHED_PRIORITY_MAX) { PANIC(OSERR_BADREPRIORITIZESTATE); } else +#endif + if (tcb->task_state < FIRST_READY_TO_RUN_STATE || + tcb->task_state > LAST_READY_TO_RUN_STATE) + { + /* This is a hack and needs to be fixed.. here some taks is reprioritizing + * another task that is not running. Here we just set the priority of + * the task -- BUT some of the other states are also prioritized and the + * waiting task should also be re-ordered in the prioritized wiating list. + * As a consequence, the other task is still waiting at the lower priority. + */ + + tcb->sched_priority = priority; + } + else { FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; boolean switch_needed; @@ -113,6 +126,9 @@ void up_reprioritize_rtr(FAR _TCB *tcb, ubyte priority) /* Setup up the new task priority */ tcb->sched_priority = (ubyte)priority; +#ifdef CONFIG_PRIORITY_INHERITANCE + tcb->base_priority = (ubyte)priority; +#endif /* Return the task to the specified blocked task list. * sched_addreadytorun will return TRUE if the task was diff --git a/nuttx/arch/z80/src/common/up_reprioritizertr.c b/nuttx/arch/z80/src/common/up_reprioritizertr.c index 72e550d89..73272553e 100644 --- a/nuttx/arch/z80/src/common/up_reprioritizertr.c +++ b/nuttx/arch/z80/src/common/up_reprioritizertr.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/z80/src/common/up_reprioritizertr.c * - * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> * * Redistribution and use in source and binary forms, with or without @@ -90,14 +90,27 @@ void up_reprioritize_rtr(FAR _TCB *tcb, ubyte priority) { /* Verify that the caller is sane */ - if (tcb->task_state < FIRST_READY_TO_RUN_STATE || - tcb->task_state > LAST_READY_TO_RUN_STATE || - priority < SCHED_PRIORITY_MIN || +#if CONFIG_DEBUG /* We only check parameters when debug is enabled */ + if (priority < SCHED_PRIORITY_MIN || priority > SCHED_PRIORITY_MAX) { PANIC(OSERR_BADREPRIORITIZESTATE); } else +#endif + if (tcb->task_state < FIRST_READY_TO_RUN_STATE || + tcb->task_state > LAST_READY_TO_RUN_STATE) + { + /* This is a hack and needs to be fixed.. here some taks is reprioritizing + * another task that is not running. Here we just set the priority of + * the task -- BUT some of the other states are also prioritized and the + * waiting task should also be re-ordered in the prioritized wiating list. + * As a consequence, the other task is still waiting at the lower priority. + */ + + tcb->sched_priority = priority; + } + else { FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; boolean switch_needed; @@ -114,6 +127,9 @@ void up_reprioritize_rtr(FAR _TCB *tcb, ubyte priority) /* Setup up the new task priority */ tcb->sched_priority = (ubyte)priority; +#ifdef CONFIG_PRIORITY_INHERITANCE + tcb->base_priority = (ubyte)priority; +#endif /* Return the task to the specified blocked task list. * sched_addreadytorun will return TRUE if the task was diff --git a/nuttx/configs/README.txt b/nuttx/configs/README.txt index e9b930cb1..cfd20b3b9 100644 --- a/nuttx/configs/README.txt +++ b/nuttx/configs/README.txt @@ -195,8 +195,10 @@ 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 + CONFIG_MUTEX_TYPES - Set to enable support for recursive and errorcheck mutexes. Enables pthread_mutexattr_settype(). + CONFIG_PRIORITY_INHERITANCE - Set to enable support for + priority inheritance on mutexes and semaphores. 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/nuttx/configs/sim/ostest/defconfig b/nuttx/configs/sim/ostest/defconfig index 4ea688e85..f6e766dd5 100644 --- a/nuttx/configs/sim/ostest/defconfig +++ b/nuttx/configs/sim/ostest/defconfig @@ -1,7 +1,7 @@ ############################################################################ # configs/sim/ostest/defconfig # -# Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. +# Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. # Author: Gregory Nutt <spudmonkey@racsa.co.cr> # # Redistribution and use in source and binary forms, with or without @@ -98,6 +98,7 @@ CONFIG_JULIAN_TIME=n CONFIG_DEV_CONSOLE=y CONFIG_DEV_LOWCONSOLE=n CONFIG_MUTEX_TYPES=y +CONFIG_PRIORITY_INHERITANCE=n # # The following can be used to disable categories of diff --git a/nuttx/examples/ostest/Makefile b/nuttx/examples/ostest/Makefile index adb875932..d04de7bfe 100644 --- a/nuttx/examples/ostest/Makefile +++ b/nuttx/examples/ostest/Makefile @@ -1,7 +1,7 @@ ############################################################################ # examples/ostest/Makefile # -# Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. +# Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. # Author: Gregory Nutt <spudmonkey@racsa.co.cr> # # Redistribution and use in source and binary forms, with or without @@ -39,35 +39,47 @@ ASRCS = AOBJS = $(ASRCS:.S=$(OBJEXT)) CSRCS = main.c dev_null.c + ifneq ($(CONFIG_DISABLE_PTHREAD),y) CSRCS += cancel.c cond.c mutex.c sem.c barrier.c ifneq ($(CONFIG_RR_INTERVAL),0) CSRCS += roundrobin.c -endif +endif # CONFIG_RR_INTERVAL ifeq ($(CONFIG_MUTEX_TYPES),y) CSRCS += rmutex.c -endif -endif +endif # CONFIG_MUTEX_TYPES +endif # CONFIG_DISABLE_PTHREAD + ifneq ($(CONFIG_DISABLE_SIGNALS),y) CSRCS += sighand.c ifneq ($(CONFIG_DISABLE_PTHREAD),y) ifneq ($(CONFIG_DISABLE_CLOCK),y) CSRCS += timedwait.c -endif -endif -endif +endif # CONFIG_DISABLE_CLOCK +endif # CONFIG_DISABLE_PTHREAD +endif # CONFIG_DISABLE_SIGNALS + ifneq ($(CONFIG_DISABLE_MQUEUE),y) ifneq ($(CONFIG_DISABLE_PTHREAD),y) CSRCS += mqueue.c ifneq ($(CONFIG_DISABLE_CLOCK),y) CSRCS += timedmqueue.c -endif -endif -endif +endif # CONFIG_DISABLE_CLOCK +endif # CONFIG_DISABLE_PTHREAD +endif # CONFIG_DISABLE_MQUEUE + ifneq ($(CONFIG_DISABLE_POSIX_TIMERS),y) CSRCS += posixtimer.c endif +ifneq ($(CONFIG_DISABLE_SIGNALS),y) +ifneq ($(CONFIG_DISABLE_PTHREAD),y) +ifeq ($(CONFIG_PRIORITY_INHERITANCE),y) +CSRCS += prioinherit.c +endif # CONFIG_PRIORITY_INHERITANCE +endif # CONFIG_DISABLE_PTHREAD +endif # CONFIG_DISABLE_SIGNALS + COBJS = $(CSRCS:.c=$(OBJEXT)) SRCS = $(ASRCS) $(CSRCS) diff --git a/nuttx/examples/ostest/main.c b/nuttx/examples/ostest/main.c index 636d8af13..a0c43416e 100644 --- a/nuttx/examples/ostest/main.c +++ b/nuttx/examples/ostest/main.c @@ -1,7 +1,7 @@ /**************************************************************************** - * main.c + * ostest/main.c * - * Copyright (C) 2007, 2008, 2009 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> * * Redistribution and use in source and binary forms, with or without @@ -382,6 +382,14 @@ static int user_main(int argc, char *argv[]) check_test_memory_usage(); #endif +#if defined(CONFIG_PRIORITY_INHERITANCE) && !defined(CONFIG_DISABLE_SIGNALS) && !defined(CONFIG_DISABLE_PTHREAD) + /* Verify priority inheritance */ + + printf("\nuser_main: priority inheritance test\n"); + priority_inheritance(); + check_test_memory_usage(); +#endif /* CONFIG_PRIORITY_INHERITANCE && !CONFIG_DISABLE_SIGNALS && !CONFIG_DISABLE_PTHREAD */ + /* Compare memory usage at time user_start started until * user_main exits. These should not be identical, but should * be similar enough that we can detect any serious OS memory diff --git a/nuttx/examples/ostest/ostest.h b/nuttx/examples/ostest/ostest.h index c94412cc1..8c71906c5 100644 --- a/nuttx/examples/ostest/ostest.h +++ b/nuttx/examples/ostest/ostest.h @@ -1,7 +1,7 @@ /**************************************************************************** * examples/ostest/ostest.h * - * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> * * Redistribution and use in source and binary forms, with or without @@ -135,4 +135,8 @@ extern void rr_test(void); extern void barrier_test(void); +/* prioinherit.c ************************************************************/ + +extern void priority_inheritance(void); + #endif /* __OSTEST_H */ diff --git a/nuttx/examples/ostest/prioinherit.c b/nuttx/examples/ostest/prioinherit.c new file mode 100644 index 000000000..818f46b75 --- /dev/null +++ b/nuttx/examples/ostest/prioinherit.c @@ -0,0 +1,292 @@ +/**************************************************************************** + * examples/ostest/prioinherit.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <sys/types.h> +#include <stdio.h> +#include <unistd.h> +#include <semaphore.h> +#include <pthread.h> + +#include "ostest.h" + +#if defined(CONFIG_PRIORITY_INHERITANCE) && !defined(CONFIG_DISABLE_SIGNALS) && !defined(CONFIG_DISABLE_PTHREAD) + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static sem_t g_sem; +static volatile int g_middle = 0; + +/**************************************************************************** + * Name: highpri_thread + ****************************************************************************/ + +static void *highpri_thread(void *parameter) +{ + int ret; + + printf("highpri_thread: Thread %d started\n"); + + ret = sem_wait(&g_sem); + if (ret != 0) + { + printf("highpri_thread: sem_take failed: %d\n", ret); + } + else if (g_middle == 1) + { + printf("highpri_thread: Success midpri_thread is still running!\n"); + } + else + { + printf("highpri_thread: ERROR -- midpri_thread has already exited!\n"); + } + + sem_post(&g_sem); + printf("medpri_thread: Okay... I'm done!\n"); + fflush(stdout); + return NULL; +} + +/**************************************************************************** + * Name: medpri_thread + ****************************************************************************/ + +static void *medpri_thread(void *parameter) +{ + volatile long i; + + printf("medpri_thread: Thread %d started ... I won't let go of the CPU!\n"); + g_middle = 1; + for (i = 0; i < 0x7ffffff; i++); + printf("medpri_thread: Okay... I'm done!\n"); + fflush(stdout); + return NULL; +} + +/**************************************************************************** + * Name: lowpri_thread + ****************************************************************************/ + +static void *lowpri_thread(void *parameter) +{ + void *retval = (void*)-1; + int ret; + + printf("lowpri_thread: Thread %d started\n"); + + ret = sem_wait(&g_sem); + if (ret != 0) + { + printf("lowpri_thread: sem_take failed: %d\n", ret); + } + else + { + /* Hang on to the thread until the middle priority thread runs */ + + while (g_middle == 0) + { + printf("lowpri_thread: Waiting for the midle pri task to run\n"); + printf("lowpri_thread: I still have the semaphore\n"); + sleep(1); + } + + /* The middle priority task is running, let go of the semaphore */ + + if (g_middle == 1) + { + /* Good.. the middle priority task is still running but we got priority! */ + + retval = NULL; + } + else + { + printf("lowpri_thread: ERROR the middle priority task has already exitted!\n"); + } + } + + printf("lowpri_thread: Letting go of the semaphore\n"); + sem_post(&g_sem); + printf("lowpri_thread: Okay... I'm done!\n"); + fflush(stdout); + return retval; +} +#endif /* CONFIG_PRIORITY_INHERITANCE && !CONFIG_DISABLE_SIGNALS && !CONFIG_DISABLE_PTHREAD */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: priority_inheritance + ****************************************************************************/ + +void priority_inheritance(void) +{ +#if defined(CONFIG_PRIORITY_INHERITANCE) && !defined(CONFIG_DISABLE_SIGNALS) && !defined(CONFIG_DISABLE_PTHREAD) + pthread_t lowpri; + pthread_t medpri; + pthread_t highpri; + pthread_addr_t result; + pthread_attr_t attr; + struct sched_param sparam; + int my_pri; + int max_pri; + int mid_pri; + int min_pri; + int status; + + printf("priority_inheritance: Started\n"); + + status = sched_getparam (getpid(), &sparam); + if (status != 0) + { + printf("priority_inheritance: sched_getparam failed\n"); + sparam.sched_priority = PTHREAD_DEFAULT_PRIORITY; + } + my_pri = sparam.sched_priority; + + max_pri = sched_get_priority_max(SCHED_FIFO); + min_pri = sched_get_priority_min(SCHED_FIFO); + mid_pri = my_pri - 1; + + sem_init(&g_sem, 0, 1); + + /* Start the low priority task */ + + printf("priority_inheritance: Starting lowpri_thread at %d\n", min_pri); + status = pthread_attr_init(&attr); + if (status != 0) + { + printf("priority_inheritance: pthread_attr_init failed, status=%d\n", status); + } + sparam.sched_priority = min_pri; + status = pthread_attr_setschedparam(&attr,& sparam); + if (status != OK) + { + printf("priority_inheritance: pthread_attr_setschedparam failed, status=%d\n", status); + } + else + { + printf("priority_inheritance: Set lowpri_thread priority to %d\n", sparam.sched_priority); + } + + status = pthread_create(&lowpri, &attr, lowpri_thread, NULL); + if (status != 0) + { + printf("priority_inheritance: pthread_create failed, status=%d\n", status); + } + + printf("priority_inheritance: Waiting...\n"); + sleep(5); + + /* Start the medium priority task */ + + printf("priority_inheritance: Starting medpri_thread at %d\n", mid_pri); + status = pthread_attr_init(&attr); + if (status != 0) + { + printf("priority_inheritance: pthread_attr_init failed, status=%d\n", status); + } + + sparam.sched_priority = mid_pri; + status = pthread_attr_setschedparam(&attr,& sparam); + if (status != OK) + { + printf("priority_inheritance: pthread_attr_setschedparam failed, status=%d\n", status); + } + else + { + printf("priority_inheritance: Set medpri_thread priority to %d\n", sparam.sched_priority); + } + + status = pthread_create(&medpri, &attr, medpri_thread, NULL); + if (status != 0) + { + printf("priority_inheritance: pthread_create failed, status=%d\n", status); + } + + /* Start the high priority task */ + + printf("priority_inheritance: Starting highpri_thread at %d\n", max_pri); + status = pthread_attr_init(&attr); + if (status != 0) + { + printf("priority_inheritance: pthread_attr_init failed, status=%d\n", status); + } + + sparam.sched_priority = max_pri; + status = pthread_attr_setschedparam(&attr,& sparam); + if (status != OK) + { + printf("priority_inheritance: pthread_attr_setschedparam failed, status=%d\n", status); + } + else + { + printf("priority_inheritance: Set highpri_thread priority to %d\n", sparam.sched_priority); + } + + status = pthread_create(&medpri, &attr, highpri_thread, NULL); + if (status != 0) + { + printf("priority_inheritance: pthread_create failed, status=%d\n", status); + } + + /* Wait for all thread instances to complete */ + + printf("priority_inheritance: Waiting for highpri_thread to complete\n"); + (void)pthread_join(highpri, &result); + printf("priority_inheritance: Waiting for medpri_thread to complete\n"); + (void)pthread_join(medpri, &result); + printf("priority_inheritance: Waiting for lowpri_thread to complete\n"); + (void)pthread_join(lowpri, &result); + + printf("priority_inheritance: Finished\n"); + sem_destroy(&g_sem); + fflush(stdout); +#endif /* CONFIG_PRIORITY_INHERITANCE && !CONFIG_DISABLE_SIGNALS && !CONFIG_DISABLE_PTHREAD */ +} diff --git a/nuttx/include/nuttx/sched.h b/nuttx/include/nuttx/sched.h index 87cdc8127..500ae0c97 100644 --- a/nuttx/include/nuttx/sched.h +++ b/nuttx/include/nuttx/sched.h @@ -1,7 +1,7 @@ /******************************************************************************** * nuttx/sched.h * - * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> * * Redistribution and use in source and binary forms, with or without @@ -177,6 +177,9 @@ struct _TCB entry_t entry; /* Entry Point into the thread */ exitfunc_t exitfunc; /* Called if exit is called. */ ubyte sched_priority; /* Current priority of the thread */ +#ifdef CONFIG_PRIORITY_INHERITANCE + ubyte base_priority; /* "Normal" priority of the thread */ +#endif ubyte task_state; /* Current state of the thread */ uint16 flags; /* Misc. general status flags */ sint16 lockcount; /* 0=preemptable (not-locked) */ diff --git a/nuttx/include/pthread.h b/nuttx/include/pthread.h index a6cccc786..44cd23c6a 100644 --- a/nuttx/include/pthread.h +++ b/nuttx/include/pthread.h @@ -1,7 +1,7 @@ /******************************************************************************** * pthread.h * - * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> * * Redistribution and use in source and binary forms, with or without @@ -155,14 +155,14 @@ typedef pthread_addr_t any_t; typedef pthread_addr_t (*pthread_startroutine_t)(pthread_addr_t); typedef pthread_startroutine_t pthread_func_t; -struct pthread_addr_s +struct pthread_attr_s { size_t stacksize; /* Size of the stack allocated for the pthead */ sint16 priority; /* Priority of the pthread */ ubyte policy; /* Pthread scheduler policy */ ubyte inheritsched; /* Inherit parent prio/policy? */ }; -typedef struct pthread_addr_s pthread_attr_t; +typedef struct pthread_attr_s pthread_attr_t; typedef pid_t pthread_t; diff --git a/nuttx/include/semaphore.h b/nuttx/include/semaphore.h index bd2a24db1..5372d4212 100644 --- a/nuttx/include/semaphore.h +++ b/nuttx/include/semaphore.h @@ -1,7 +1,7 @@ /**************************************************************************** * include/semaphore.h * - * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> * * Redistribution and use in source and binary forms, with or without @@ -64,6 +64,9 @@ struct sem_s { sint16 semcount; /* >0 -> Num counts available */ /* <0 -> Num tasks waiting for semaphore */ +#ifdef CONFIG_PRIORITY_INHERITANCE + void *holder; /* Holder TCB (actual type is _TCB) */ +#endif }; typedef struct sem_s sem_t; diff --git a/nuttx/sched/os_internal.h b/nuttx/sched/os_internal.h index 665d05e74..a9b1bfc85 100644 --- a/nuttx/sched/os_internal.h +++ b/nuttx/sched/os_internal.h @@ -1,7 +1,7 @@ /**************************************************************************** * sched/os_internal.h * - * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> * * Redistribution and use in source and binary forms, with or without diff --git a/nuttx/sched/pthread_create.c b/nuttx/sched/pthread_create.c index f13f76b14..e51512573 100644 --- a/nuttx/sched/pthread_create.c +++ b/nuttx/sched/pthread_create.c @@ -1,7 +1,7 @@ /**************************************************************************** - * pthread_create.c + * sched/pthread_create.c * - * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> * * Redistribution and use in source and binary forms, with or without @@ -303,7 +303,7 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr, if (attr->inheritsched == PTHREAD_INHERIT_SCHED) { - /* Get the priority of this thread. */ + /* Get the priority for this thread. */ struct sched_param param; status = sched_getparam(0, ¶m); diff --git a/nuttx/sched/pthread_setschedprio.c b/nuttx/sched/pthread_setschedprio.c index d5a5705dc..6d3beb1de 100644 --- a/nuttx/sched/pthread_setschedprio.c +++ b/nuttx/sched/pthread_setschedprio.c @@ -1,7 +1,7 @@ /**************************************************************************** * pthread_schedsetprio.c * - * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> * * 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. * diff --git a/nuttx/sched/sched_setparam.c b/nuttx/sched/sched_setparam.c index e5a61c856..20b0d6831 100644 --- a/nuttx/sched/sched_setparam.c +++ b/nuttx/sched/sched_setparam.c @@ -1,7 +1,7 @@ -/************************************************************ - * sched_setparam.c +/**************************************************************************** + * sched/sched_setparam.c * - * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> * * 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,11 +31,11 @@ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * - ************************************************************/ + ****************************************************************************/ -/************************************************************ +/**************************************************************************** * Included Files - ************************************************************/ + ****************************************************************************/ #include <nuttx/config.h> #include <sys/types.h> @@ -44,35 +44,35 @@ #include <nuttx/arch.h> #include "os_internal.h" -/************************************************************ +/**************************************************************************** * Definitions - ************************************************************/ + ****************************************************************************/ -/************************************************************ +/**************************************************************************** * Private Type Declarations - ************************************************************/ + ****************************************************************************/ -/************************************************************ +/**************************************************************************** * Global Variables - ************************************************************/ + ****************************************************************************/ -/************************************************************ +/**************************************************************************** * Private Variables - ************************************************************/ + ****************************************************************************/ -/************************************************************ +/**************************************************************************** * Private Function Prototypes - ************************************************************/ + ****************************************************************************/ -/************************************************************ +/**************************************************************************** * Private Functions - ************************************************************/ + ****************************************************************************/ -/************************************************************ +/**************************************************************************** * Public Functions - ************************************************************/ + ****************************************************************************/ -/************************************************************ +/**************************************************************************** * Name: sched_setparam * * Description: @@ -100,7 +100,7 @@ * * Assumptions: * - ************************************************************/ + ****************************************************************************/ int sched_setparam(pid_t pid, const struct sched_param *param) { @@ -185,6 +185,9 @@ int sched_setparam(pid_t pid, const struct sched_param *param) /* Change the task priority */ tcb->sched_priority = (ubyte)sched_priority; +#ifdef CONFIG_PRIORITY_INHERITANCE + tcb->base_priority = (ubyte)sched_priority; +#endif } break; @@ -218,6 +221,9 @@ int sched_setparam(pid_t pid, const struct sched_param *param) /* Change the task priority */ tcb->sched_priority = (ubyte)sched_priority; +#ifdef CONFIG_PRIORITY_INHERITANCE + tcb->base_priority = (ubyte)sched_priority; +#endif /* Put it back into the ready-to-run task list */ @@ -241,6 +247,9 @@ int sched_setparam(pid_t pid, const struct sched_param *param) /* Change the task priority */ tcb->sched_priority = (ubyte)sched_priority; +#ifdef CONFIG_PRIORITY_INHERITANCE + tcb->base_priority = (ubyte)sched_priority; +#endif /* Put it back into the prioritized list at the correct * position @@ -256,6 +265,9 @@ int sched_setparam(pid_t pid, const struct sched_param *param) /* Just change the task's priority */ tcb->sched_priority = (ubyte)sched_priority; +#ifdef CONFIG_PRIORITY_INHERITANCE + tcb->base_priority = (ubyte)sched_priority; +#endif } break; } diff --git a/nuttx/sched/sem_destroy.c b/nuttx/sched/sem_destroy.c index 6dd60bc28..663522303 100644 --- a/nuttx/sched/sem_destroy.c +++ b/nuttx/sched/sem_destroy.c @@ -1,7 +1,7 @@ /**************************************************************************** * sched/sem_destroy.c * - * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> * * Redistribution and use in source and binary forms, with or without @@ -103,7 +103,8 @@ int sem_destroy (FAR sem_t *sem) { /* There is really no particular action that we need * take to destroy a semaphore. We will just reset - * the count to some reasonable value (1). + * the count to some reasonable value (1) and release + * ownership. * * Check if other threads are waiting on the semaphore. * In this case, the behavior is undefined. We will: @@ -114,6 +115,9 @@ int sem_destroy (FAR sem_t *sem) { sem->semcount = 1; } +#ifdef CONFIG_PRIORITY_INHERITANCE + sem->holder = NULL; +#endif ret = OK; } diff --git a/nuttx/sched/sem_post.c b/nuttx/sched/sem_post.c index 186c3b87e..ca2047598 100644 --- a/nuttx/sched/sem_post.c +++ b/nuttx/sched/sem_post.c @@ -1,7 +1,7 @@ /**************************************************************************** * sched/sem_post.c * - * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> * * Redistribution and use in source and binary forms, with or without @@ -104,6 +104,9 @@ int sem_post(FAR sem_t *sem) { +#ifdef CONFIG_PRIORITY_INHERITANCE + FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; +#endif FAR _TCB *stcb; STATUS ret = ERROR; irqstate_t saved_state; @@ -122,6 +125,9 @@ int sem_post(FAR sem_t *sem) /* Perform the semaphore unlock operation. */ ASSERT(sem->semcount < SEM_VALUE_MAX); +#ifdef CONFIG_PRIORITY_INHERITANCE + sem->holder = NULL; +#endif sem->semcount++; /* If the result of of semaphore unlock is non-positive, then @@ -151,6 +157,18 @@ int sem_post(FAR sem_t *sem) up_unblock_task(stcb); } } + + /* Check if we need to drop our priority. Our priority could have + * been boosted while we held the semaphore. + */ + +#ifdef CONFIG_PRIORITY_INHERITANCE + if (rtcb->sched_priority != rtcb->base_priority) + { + up_reprioritize_rtr(rtcb, rtcb->base_priority); + } +#endif + ret = OK; /* Interrupts may now be enabled. */ diff --git a/nuttx/sched/sem_wait.c b/nuttx/sched/sem_wait.c index ba223b1d4..d0735d76e 100644 --- a/nuttx/sched/sem_wait.c +++ b/nuttx/sched/sem_wait.c @@ -1,7 +1,7 @@ /**************************************************************************** * sched/sem_wait.c * - * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> * * Redistribution and use in source and binary forms, with or without @@ -98,6 +98,9 @@ int sem_wait(FAR sem_t *sem) { FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; +#ifdef CONFIG_PRIORITY_INHERITANCE + FAR _TCB *htcb; +#endif int ret = ERROR; irqstate_t saved_state; @@ -125,6 +128,9 @@ int sem_wait(FAR sem_t *sem) /* It is, let the task take the semaphore. */ sem->semcount--; +#ifdef CONFIG_PRIORITY_INHERITANCE + sem->holder = rtcb; +#endif rtcb->waitsem = NULL; ret = OK; } @@ -144,7 +150,7 @@ int sem_wait(FAR sem_t *sem) PANIC(OSERR_BADWAITSEM); } - /* Handle the POSIX semaphore */ + /* Handle the POSIX semaphore (but don't set the owner yet) */ sem->semcount--; @@ -152,11 +158,36 @@ int sem_wait(FAR sem_t *sem) rtcb->waitsem = sem; + /* If priority inheritance is enabled, then check the priority of + * the holder of the semaphore. + */ + +#ifdef CONFIG_PRIORITY_INHERITANCE + /* Disable context switching. The following operations must be + * atomic with regard to the scheduler. + */ + + sched_lock(); + htcb = sem->holder; + if (htcb && htcb->sched_priority < rtcb->sched_priority) + { + /* Raise the priority of the holder of the semaphore. This + * cannot cause a context switch because we have preemption + * disabled. The task will be marked "pending" and the switch + * will occur during up_block_task() processing. + */ + + up_reprioritize_rtr(htcb, rtcb->sched_priority); + } +#endif /* Add the TCB to the prioritized semaphore wait queue */ *get_errno_ptr() = 0; up_block_task(rtcb, TSTATE_WAIT_SEM); +#ifdef CONFIG_PRIORITY_INHERITANCE + sched_unlock(); +#endif /* When we resume at this point, either (1) the semaphore has been * assigned to this thread of execution, or (2) the semaphore wait * has been interrupted by a signal. We can detect the latter case @@ -165,6 +196,11 @@ int sem_wait(FAR sem_t *sem) if (*get_errno_ptr() != EINTR) { + /* We hold the semaphore */ + +#ifdef CONFIG_PRIORITY_INHERITANCE + sem->holder = rtcb; +#endif ret = OK; } else diff --git a/nuttx/sched/task_restart.c b/nuttx/sched/task_restart.c index 3d682eb3d..c254dd303 100644 --- a/nuttx/sched/task_restart.c +++ b/nuttx/sched/task_restart.c @@ -1,7 +1,7 @@ -/************************************************************ - * task_restart.c +/**************************************************************************** + * sched/task_restart.c * - * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> * * 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,11 +31,11 @@ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * - ************************************************************/ + ****************************************************************************/ -/************************************************************ +/**************************************************************************** * Included Files - ************************************************************/ + ****************************************************************************/ #include <nuttx/config.h> #include <sys/types.h> @@ -44,35 +44,35 @@ #include "os_internal.h" #include "sig_internal.h" -/************************************************************ +/**************************************************************************** * Definitions - ************************************************************/ + ****************************************************************************/ -/************************************************************ +/**************************************************************************** * Private Type Declarations - ************************************************************/ + ****************************************************************************/ -/************************************************************ +/**************************************************************************** * Global Variables - ************************************************************/ + ****************************************************************************/ -/************************************************************ +/**************************************************************************** * Private Variables - ************************************************************/ + ****************************************************************************/ -/************************************************************ +/**************************************************************************** * Private Function Prototypes - ************************************************************/ + ****************************************************************************/ -/************************************************************ +/**************************************************************************** * Private Functions - ************************************************************/ + ****************************************************************************/ -/************************************************************ +/**************************************************************************** * Public Functions - ************************************************************/ + ****************************************************************************/ -/************************************************************ +/**************************************************************************** * Name: task_restart * * Description: @@ -94,7 +94,7 @@ * (2) The pid is not associated with any task known to * the system. * - ************************************************************/ + ****************************************************************************/ STATUS task_restart(pid_t pid) { @@ -149,6 +149,9 @@ STATUS task_restart(pid_t pid) /* Reset the task priority */ tcb->sched_priority = tcb->init_priority; +#ifdef CONFIG_PRIORITY_INHERITANCE + tcb->base_priority = tcb->init_priority; +#endif /* Re-initialize the processor-specific portion of the TCB * This will reset the entry point and the start-up parameters diff --git a/nuttx/sched/task_setup.c b/nuttx/sched/task_setup.c index 6b80d5db0..25a85394a 100644 --- a/nuttx/sched/task_setup.c +++ b/nuttx/sched/task_setup.c @@ -1,7 +1,7 @@ /**************************************************************************** - * task_setup.c + * sched/task_setup.c * - * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> * * Redistribution and use in source and binary forms, with or without @@ -184,6 +184,9 @@ STATUS task_schedsetup(FAR _TCB *tcb, int priority, tcb->init_priority = (ubyte)priority; tcb->sched_priority = (ubyte)priority; +#ifdef CONFIG_PRIORITY_INHERITANCE + tcb->base_priority = (ubyte)priority; +#endif tcb->start = start; tcb->entry.main = main; |