Interrupts must be disabled in all low level context switches

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@89 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2007-03-19 14:22:43 +00:00
parent 5719b443ff
commit 50dcba1464
7 changed files with 58 additions and 17 deletions

View File

@ -76,10 +76,11 @@
static void _up_dumponexit(FAR _TCB *tcb, FAR void *arg) static void _up_dumponexit(FAR _TCB *tcb, FAR void *arg)
{ {
int i; int i;
dbg(" TCB=%p name=%s\n", tcb, tcb->name);
lldbg(" TCB=%p name=%s\n", tcb, tcb->argv[0]);
if (tcb->filelist) if (tcb->filelist)
{ {
dbg(" filelist refcount=%d\n", lldbg(" filelist refcount=%d\n",
tcb->filelist->fl_crefs); tcb->filelist->fl_crefs);
for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++) for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++)
@ -87,7 +88,7 @@ static void _up_dumponexit(FAR _TCB *tcb, FAR void *arg)
struct inode *inode = tcb->filelist->fl_files[i].f_inode; struct inode *inode = tcb->filelist->fl_files[i].f_inode;
if (inode) if (inode)
{ {
dbg(" fd=%d refcount=%d\n", lldbg(" fd=%d refcount=%d\n",
i, inode->i_crefs); i, inode->i_crefs);
} }
} }
@ -95,7 +96,7 @@ static void _up_dumponexit(FAR _TCB *tcb, FAR void *arg)
if (tcb->streams) if (tcb->streams)
{ {
dbg(" streamlist refcount=%d\n", lldbg(" streamlist refcount=%d\n",
tcb->streams->sl_crefs); tcb->streams->sl_crefs);
for (i = 0; i < CONFIG_NFILE_STREAMS; i++) for (i = 0; i < CONFIG_NFILE_STREAMS; i++)
@ -103,7 +104,7 @@ static void _up_dumponexit(FAR _TCB *tcb, FAR void *arg)
struct file_struct *filep = &tcb->streams->sl_streams[i]; struct file_struct *filep = &tcb->streams->sl_streams[i];
if (filep->fs_filedes >= 0) if (filep->fs_filedes >= 0)
{ {
dbg(" fd=%d nbytes=%d\n", lldbg(" fd=%d nbytes=%d\n",
filep->fs_filedes, filep->fs_filedes,
filep->fs_bufpos - filep->fs_bufstart); filep->fs_bufpos - filep->fs_bufstart);
} }
@ -128,11 +129,12 @@ static void _up_dumponexit(FAR _TCB *tcb, FAR void *arg)
void _exit(int status) void _exit(int status)
{ {
_TCB* tcb = (_TCB*)g_readytorun.head; _TCB* tcb = (_TCB*)g_readytorun.head;
irqstate_t flags = irqsave();
dbg("TCB=%p exitting\n", tcb); lldbg("TCB=%p exitting\n", tcb);
#if defined(CONFIG_DUMP_ON_EXIT) && defined(CONFIG_DEBUG) #if defined(CONFIG_DUMP_ON_EXIT) && defined(CONFIG_DEBUG)
dbg("Other tasks:\n"); lldbg("Other tasks:\n");
sched_foreach(_up_dumponexit, NULL); sched_foreach(_up_dumponexit, NULL);
#endif #endif
@ -162,7 +164,7 @@ void _exit(int status)
*/ */
tcb = (_TCB*)g_readytorun.head; tcb = (_TCB*)g_readytorun.head;
dbg("New Active Task TCB=%p\n", tcb); lldbg("New Active Task TCB=%p\n", tcb);
/* Then switch contexts */ /* Then switch contexts */

View File

@ -76,7 +76,7 @@
static void _up_dumponexit(FAR _TCB *tcb, FAR void *arg) static void _up_dumponexit(FAR _TCB *tcb, FAR void *arg)
{ {
int i; int i;
dbg(" TCB=%p name=%s\n", tcb, tcb->name); dbg(" TCB=%p name=%s\n", tcb, tcb->argv[0]);
if (tcb->filelist) if (tcb->filelist)
{ {
dbg(" filelist refcount=%d\n", dbg(" filelist refcount=%d\n",
@ -128,8 +128,9 @@ static void _up_dumponexit(FAR _TCB *tcb, FAR void *arg)
void _exit(int status) void _exit(int status)
{ {
_TCB* tcb = (_TCB*)g_readytorun.head; _TCB* tcb = (_TCB*)g_readytorun.head;
irqstate_t flags = irqsave();
dbg("TCB=%p exitting\n", tcb); lldbg("TCB=%p exitting\n", tcb);
#if defined(CONFIG_DUMP_ON_EXIT) && defined(CONFIG_DEBUG) #if defined(CONFIG_DUMP_ON_EXIT) && defined(CONFIG_DEBUG)
dbg("Other tasks:\n"); dbg("Other tasks:\n");
@ -162,7 +163,7 @@ void _exit(int status)
*/ */
tcb = (_TCB*)g_readytorun.head; tcb = (_TCB*)g_readytorun.head;
dbg("New Active Task TCB=%p\n", tcb); lldbg("New Active Task TCB=%p\n", tcb);
/* Then switch contexts */ /* Then switch contexts */

View File

@ -41,6 +41,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sched.h> #include <sched.h>
#include <debug.h> #include <debug.h>
#include <8052.h>
#include <nuttx/arch.h> #include <nuttx/arch.h>
#include "os_internal.h" #include "os_internal.h"
#include "up_internal.h" #include "up_internal.h"
@ -76,6 +77,12 @@ void _exit(int status)
dbg("TCB=%p exitting\n", tcb); dbg("TCB=%p exitting\n", tcb);
/* Disable interrupts. Interrupts will remain disabled until
* the new task is resumed below when the save IE is restored.
*/
EA = 0;
/* Remove the tcb task from the ready-to-run list. We can /* Remove the tcb task from the ready-to-run list. We can
* ignore the return value because we know that a context * ignore the return value because we know that a context
* switch is needed. * switch is needed.

View File

@ -200,6 +200,10 @@ EXTERN void up_release_stack(FAR _TCB *dtcb);
* but has been prepped to execute. Move the TCB to the * but has been prepped to execute. Move the TCB to the
* ready-to-run list, restore its context, and start execution. * ready-to-run list, restore its context, and start execution.
* *
* This function is called only from the NuttX scheduling
* logic. Interrupts will always be disabled when this
* function is called.
*
* Inputs: * Inputs:
* tcb: Refers to the tcb to be unblocked. This tcb is * tcb: Refers to the tcb to be unblocked. This tcb is
* in one of the waiting tasks lists. It must be moved to * in one of the waiting tasks lists. It must be moved to
@ -218,6 +222,10 @@ EXTERN void up_unblock_task(FAR _TCB *tcb);
* the ready to run list must be stopped. Save its context * the ready to run list must be stopped. Save its context
* and move it to the inactive list specified by task_state. * and move it to the inactive list specified by task_state.
* *
* This function is called only from the NuttX scheduling
* logic. Interrupts will always be disabled when this
* function is called.
*
* Inputs: * Inputs:
* tcb: Refers to a task in the ready-to-run list (normally * tcb: Refers to a task in the ready-to-run list (normally
* the task at the the head of the list). It most be * the task at the the head of the list). It most be
@ -241,6 +249,10 @@ EXTERN void up_block_task(FAR _TCB *tcb, tstate_t task_state);
* context switch if a new task is placed at the head of * context switch if a new task is placed at the head of
* the ready to run list. * the ready to run list.
* *
* This function is called only from the NuttX scheduling
* logic. Interrupts will always be disabled when this
* function is called.
*
************************************************************/ ************************************************************/
EXTERN void up_release_pending(void); EXTERN void up_release_pending(void);
@ -259,6 +271,10 @@ EXTERN void up_release_pending(void);
* the priority of the current, running task and it now has the * the priority of the current, running task and it now has the
* priority. * priority.
* *
* This function is called only from the NuttX scheduling
* logic. Interrupts will always be disabled when this
* function is called.
*
* Inputs: * Inputs:
* tcb: The TCB of the task that has been reprioritized * tcb: The TCB of the task that has been reprioritized
* priority: The new task priority * priority: The new task priority
@ -274,6 +290,11 @@ EXTERN void up_reprioritize_rtr(FAR _TCB *tcb, ubyte priority);
* This function causes the currently executing task to cease * This function causes the currently executing task to cease
* to exist. This is a special case of task_delete(). * to exist. This is a special case of task_delete().
* *
* Unlike other UP APIs, this function may be called
* directly from user programs in various states. The
* implementation of this function should diable interrupts
* before performing scheduling operations.
*
************************************************************/ ************************************************************/
/* Prototype is in unistd.h */ /* Prototype is in unistd.h */

View File

@ -175,7 +175,9 @@ int sched_setparam(pid_t pid, const struct sched_param *param)
{ {
/* A context switch will occur. */ /* A context switch will occur. */
irqstate_t flags = irqsave();
up_reprioritize_rtr(tcb, (ubyte)sched_priority); up_reprioritize_rtr(tcb, (ubyte)sched_priority);
irqrestore(flags);
} }
/* Otherwise, we can just change priority since it has no effect */ /* Otherwise, we can just change priority since it has no effect */
@ -202,7 +204,9 @@ int sched_setparam(pid_t pid, const struct sched_param *param)
{ {
/* A context switch will occur. */ /* A context switch will occur. */
irqstate_t flags = irqsave();
up_reprioritize_rtr(tcb, (ubyte)sched_priority); up_reprioritize_rtr(tcb, (ubyte)sched_priority);
irqrestore(flags);
} }
/* Otherwise, we can just change priority and re-schedule (since it /* Otherwise, we can just change priority and re-schedule (since it

View File

@ -93,6 +93,10 @@ STATUS sched_unlock(void)
if (rtcb && !up_interrupt_context()) if (rtcb && !up_interrupt_context())
{ {
/* Prevent context switches throughout the following */
irqstate_t flags = irqsave();
/* Decrement the preemption lock counter */ /* Decrement the preemption lock counter */
if (rtcb->lockcount) if (rtcb->lockcount)
@ -117,6 +121,7 @@ STATUS sched_unlock(void)
up_release_pending(); up_release_pending();
} }
} }
irqrestore(flags);
} }
return OK; return OK;
} }

View File

@ -90,9 +90,10 @@
STATUS task_activate(FAR _TCB *tcb) STATUS task_activate(FAR _TCB *tcb)
{ {
#ifdef CONFIG_SCHED_INSTRUMENTATION
irqstate_t flags = irqsave(); irqstate_t flags = irqsave();
#ifdef CONFIG_SCHED_INSTRUMENTATION
/* Check if this is really a re-start */ /* Check if this is really a re-start */
if (tcb->task_state != TSTATE_TASK_INACTIVE) if (tcb->task_state != TSTATE_TASK_INACTIVE)
@ -109,9 +110,9 @@ STATUS task_activate(FAR _TCB *tcb)
*/ */
sched_note_start(tcb); sched_note_start(tcb);
irqrestore(flags);
#endif #endif
up_unblock_task(tcb); up_unblock_task(tcb);
irqrestore(flags);
return OK; return OK;
} }