Add support for priority inheritance

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1581 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2009-03-08 23:33:41 +00:00
parent aafb6b8f42
commit 166b4da551
29 changed files with 634 additions and 130 deletions

View file

@ -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.

View file

@ -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;

View file

@ -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>

View file

@ -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>

6
TODO
View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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 */

View file

@ -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 */
}

View file

@ -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) */

View file

@ -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;

View file

@ -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;

View file

@ -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

View file

@ -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);

View file

@ -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.
*

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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. */

View file

@ -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

View file

@ -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

View file

@ -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;