summaryrefslogtreecommitdiffstats
path: root/nuttx
diff options
context:
space:
mode:
authorpatacongo <patacongo@7fd9a85b-ad96-42d3-883c-3090e2eb8679>2009-03-08 23:33:41 +0000
committerpatacongo <patacongo@7fd9a85b-ad96-42d3-883c-3090e2eb8679>2009-03-08 23:33:41 +0000
commit98f1f1514261a0675f5aef9d55fb1010b5092e14 (patch)
tree13c1a8443302b1e6527a50c27f5e1ba8ae1049ca /nuttx
parent8a85a86fdf13fb96e9a53177076c21f041eb652f (diff)
Add support for priority inheritance
git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@1581 7fd9a85b-ad96-42d3-883c-3090e2eb8679
Diffstat (limited to 'nuttx')
-rw-r--r--nuttx/ChangeLog2
-rw-r--r--nuttx/Documentation/NuttX.html4
-rw-r--r--nuttx/Documentation/NuttxPortingGuide.html9
-rw-r--r--nuttx/Documentation/NuttxUserGuide.html10
-rw-r--r--nuttx/TODO6
-rw-r--r--nuttx/arch/arm/src/common/up_reprioritizertr.c24
-rw-r--r--nuttx/arch/pjrc-8051/src/up_reprioritizertr.c54
-rw-r--r--nuttx/arch/sh/src/common/up_reprioritizertr.c24
-rw-r--r--nuttx/arch/sim/src/up_reprioritizertr.c24
-rw-r--r--nuttx/arch/z16/src/common/up_reprioritizertr.c24
-rw-r--r--nuttx/arch/z80/src/common/up_reprioritizertr.c24
-rw-r--r--nuttx/configs/README.txt4
-rw-r--r--nuttx/configs/sim/ostest/defconfig3
-rw-r--r--nuttx/examples/ostest/Makefile32
-rw-r--r--nuttx/examples/ostest/main.c12
-rw-r--r--nuttx/examples/ostest/ostest.h6
-rw-r--r--nuttx/examples/ostest/prioinherit.c292
-rw-r--r--nuttx/include/nuttx/sched.h5
-rw-r--r--nuttx/include/pthread.h6
-rw-r--r--nuttx/include/semaphore.h5
-rw-r--r--nuttx/sched/os_internal.h2
-rw-r--r--nuttx/sched/pthread_create.c6
-rw-r--r--nuttx/sched/pthread_setschedprio.c4
-rw-r--r--nuttx/sched/sched_setparam.c58
-rw-r--r--nuttx/sched/sem_destroy.c8
-rw-r--r--nuttx/sched/sem_post.c20
-rw-r--r--nuttx/sched/sem_wait.c40
-rw-r--r--nuttx/sched/task_restart.c49
-rw-r--r--nuttx/sched/task_setup.c7
29 files changed, 634 insertions, 130 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index d183e4f30b..532f448d6f 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 fef9520a39..f500035997 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 &lt;spudmonkey@racsa.co.cr&gt;
* 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 &lt;spudmonkey@racsa.co.cr&gt;
diff --git a/nuttx/Documentation/NuttxPortingGuide.html b/nuttx/Documentation/NuttxPortingGuide.html
index b47cd99ded..4c3f3ff79d 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 0dfa64a87b..5869beedf9 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 ea3e218d3f..763d088893 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 b802f2e848..edc2f9e1f3 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 b148e755c5..97d5682e08 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 dccc6ad4a6..58ba7a0d69 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 5f1d2a42cd..f68ff2a828 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 e9c6a8a1e0..5692ac12c2 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 72e550d89b..73272553e0 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 e9b930cb1b..cfd20b3b96 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 4ea688e85d..f6e766dd5b 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 adb875932f..d04de7bfec 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 636d8af130..a0c43416e4 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 c94412cc13..8c71906c5f 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 0000000000..818f46b752
--- /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 87cdc8127e..500ae0c973 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 a6cccc7860..44cd23c6a4 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 bd2a24db12..5372d42126 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 665d05e743..a9b1bfc856 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 f13f76b146..e515125738 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, &param);
diff --git a/nuttx/sched/pthread_setschedprio.c b/nuttx/sched/pthread_setschedprio.c
index d5a5705dcc..6d3beb1de9 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 e5a61c8568..20b0d68318 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 6dd60bc283..6635223038 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 186c3b87e1..ca20475989 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 ba223b1d4b..d0735d76e2 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 3d682eb3d9..c254dd3039 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 6b80d5db05..25a85394a9 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;