9
0
Fork 0

Add 8052 IRQ test; Fix places where IDLE task could try to wait on semaphores

git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@61 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
patacongo 2007-03-14 18:58:21 +00:00
parent f5ebd97c7d
commit a911fb9e50
19 changed files with 565 additions and 88 deletions

View File

@ -4,13 +4,16 @@
* Support for Linux user mode simulation and TI
TMS320C5471 (Arm7) provided
0.1.1 2007-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
0.1.1 2007-03-14 Gregory Nutt <spudmonkey@racsa.co.cr>
* Corrected an error in interrupt level context switching
for C5471
* Added fgets() and gets() logic; verified c5471 console read.
* Corrected error in reading from serial port. Improper
use of semaphore can cause deadlock.
* Corrected error in reading from the C5471 serial port:
Improper use of semaphore can cause deadlock.
* Fixed an error in the memory cleanup: The idle task
cannot take sempahores (because it must always be ready
to run).
* Tasks can now accept a configurable maximum number of
input parameters (argc)
* _task_init() was divided into separate functions that
@ -24,5 +27,7 @@
were calling printf-like functions.
* Added strtok() and strtok_r()
* Added a simple shell called nsh (see examples/nsh).
* Many changes as part of 8052 bringup
* Platform support for 8052 is complete but not stable
when the timer interrupt is enabled. Seems to be an
issue when SP enters indirect address space.
* Documentation updates

View File

@ -3,12 +3,22 @@
<title>NuttX</title>
</head>
<body background="backgd.gif">
<hr>
<hr>
<center><h1><i>Under Construction</i></h1></center>
<hr>
<hr>
<h1>Overview</h1>
<center>
<hr><hr>
<h1><big><i>NuttX RTOS</i></big></h1>
<p>Last Updated: March 14, 2007</p>
<hr><hr>
<h1>Table of Contents</h1>
</center>
<li><a href="#overview">Overview</a></li>
<li><a href="#downloads">Downloads</a></li>
<li><a href="#platforms">Supported Platforms</a></li>
<li><a href="#footprint">Memory Footprint</a></li>
<li><a href="#licensing">Licensing</a></li>
<li><a href="#history">Release History</a></li>
<li><a href="#documentation">Other Documentation</a></li>
<a name="overview"><h1>Overview</h1></a>
<p>
<b>Goals</b>.
Nuttx is a real timed embedded operating system (RTOS).
@ -60,7 +70,7 @@
</p>
</ol>
<h1>Downloads</h1>
<a name="downloads"><h1>Downloads</h1></a>
<p>
The initial release of NuttX (nuttx-0.1.0) is avalable for download
@ -68,7 +78,7 @@
website.
</p>
<h1>Supported Platforms</h1>
<a name="platforms"><h1>Supported Platforms</h1></a>
<ul>
<li><b>Linux User Mode</b></li>
@ -95,7 +105,9 @@
and the <a href="http://sdcc.sourceforge.net/">SDCC</a> toolchain.
</p>
<p>
STATUS: This port will require a few more weeks before it is ready for prime time.
STATUS: This port is complete but not stable with timer interrupts enabled.
There seems to be some issue when the stack pointer enters into the indirect IRAM
address space during interrupt handling.
</p>
<li><b>Other ports</b></li>
<p>
@ -106,7 +118,7 @@
<blockquote>* A highly modified <a href="http://buildroot.uclibc.org/">buildroot</a>
is available that be used to build a NuttX-compatible arm-elf toolchain.</blockquote>
<h1>Memory Footprint</h1>
<a name="footprint"><h1>Memory Footprint</h1></a>
<p><b>C5471 (Arm7)</b>
The build for this ARM7 target that includes most of the OS features and
@ -118,11 +130,21 @@ is available that be used to build a NuttX-compatible arm-elf toolchain.</blockq
53272 428 3568 57268 dfb4 nuttx
</pre>
<p><b>87C52</b>
A reduced functionality OS test for the 8051 target requires only
about 18Kb (see <a href="codesize-070301.xls">spreadsheet</a> for details).
A reduced functionality OS test for the 8052 target requires only
about 18-19Kb:
</p>
<pre>
Stack starts at: 0x21 (sp set to 0x20) with 223 bytes available.
<h1>Licensing</h1>
Other memory:
Name Start End Size Max
---------------- -------- -------- -------- --------
PAGED EXT. RAM 0 256
EXTERNAL RAM 0x0100 0x02fd 510 7936
ROM/EPROM/FLASH 0x2100 0x6e55 19798 24384
</pre>
<a name="licensing"><h1>Licensing</h1></a>
<p>NuttX is available under the highly permissive
<a href="http://en.wikipedia.org/wiki/BSD_license">BSD license</a>.
@ -131,7 +153,45 @@ is available that be used to build a NuttX-compatible arm-elf toolchain.</blockq
without any concern for jeopardizing any proprietary software that
you may link with it.</p>
<h1>Other Documentation</h1>
<a name="history"><h1>Release History</h1></a>
<pre>
0.1.0 2007-03-09 Gregory Nutt <spudmonkey@racsa.co.cr>
* Initial Release
* Support for Linux user mode simulation and TI
TMS320C5471 (Arm7) provided
0.1.1 2007-03-14 Gregory Nutt <spudmonkey@racsa.co.cr>
* Corrected an error in interrupt level context switching
for C5471
* Added fgets() and gets() logic; verified c5471 console read.
* Corrected error in reading from the C5471 serial port:
Improper use of semaphore can cause deadlock.
* Fixed an error in the memory cleanup: The idle task
cannot take sempahores (because it must always be ready
to run).
* Tasks can now accept a configurable maximum number of
input parameters (argc)
* _task_init() was divided into separate functions that
require fewer parameters. This was necessary to keep
the stack usage down for the 8051/2 (which has only
256 bytes of stack).
* Attempts to use C5471 console from interrupt handlers
can casue errors. Added a special path for this case.
* Refuse calls to sem_wait and sem_trywait from interrupt
handlers. This was happening because interrupt handlers
were calling printf-like functions.
* Added strtok() and strtok_r()
* Added a simple shell called nsh (see examples/nsh).
* Platform support for 8052 is complete but not stable
when the timer interrupt is enabled. Seems to be an
issue when SP enters indirect address space.
* Documentation updates
</pre>
<a name="documentation"><h1>Other Documentation</h1></a>
<li><a href="NuttxUserGuide.html">User Guide</li>
<li><a href="NuttxPortingGuide.html">Porting Guide</li>

View File

@ -1,12 +1,19 @@
Nuttx-0.1.0
Nuttx-0.1.1
^^^^^^^^^^^
This is the initial. This initial includes the complete NuttX RTOS
with support for the Linux user mode simulation and the TI TMS320C5471
(Arm7) processor. Partial support for the 87C52 is included.
This is the second release of NuttX. This release includes the
following. See the ChangeLog for more detailed description of
the changes.
This release has been verified on both the Linux user-mode and C5471
platforms using the test program under examples/ostest. Test results
for the C5471 can be found in arch/c5471/doc/test-results.txt.
(1) General OS bugfixes (see the ChangeLog for details),
(2) bugfixes for the TI TMS320C5471 (Arm7) platform (see the
ChangeLog)
(3) Complete support for the 87C52. (However, the 87C52 release
is not stable enough for general usage).
(4) Added the beginning of a shell call NuttShell (nsh)
This tarball contains a complete CVS snapshot from March 9,2007.
This release has been verified on the Linux user-mode platform,
the Spectrum Digital TMS320C5471 EVM, and the PJRC 87C52 development
board using the test program under examples/ostest.
This tarball contains a complete CVS snapshot from March 14, 2007.

View File

@ -837,15 +837,19 @@ static ssize_t up_write(struct file *filep, const char *buffer, size_t buflen)
ssize_t ret = buflen;
/* We may receive console writes through this path from
* interrupt handlers! In this case, we will need to do
* things a little differently.
* interrupt handlers and from debug output in the IDLE task!
* In these cases, we will need to do things a little
* differently.
*/
if (up_interrupt_context())
if (up_interrupt_context() || getpid() == 0)
{
if (dev->isconsole)
{
return up_irqwrite(dev, buffer, buflen);
irqstate_t flags = irqsave();
ret = up_irqwrite(dev, buffer, buflen);
irqrestore(flags);
return ret;
}
else
{

View File

@ -68,10 +68,10 @@ CONFIG_ARCH_LEDS=y
CONFIG_8052_TIMER2=y
CONFIG_ARCH_BRINGUP=y
CONFIG_FRAME_DUMP=y
CONFIG_FRAME_DUMP=n
CONFIG_FRAME_DUMP_SHORT=n
CONFIG_SUPPRESS_INTERRUPTS=y
CONFIG_SWITCH_FRAME_DUMP=y
CONFIG_SWITCH_FRAME_DUMP=n
CONFIG_INTERRUPT_FRAME_DUMP=n
CONFIG_LED_DEBUG=n

View File

@ -65,7 +65,11 @@
*/
#define IRAM_BASE 0x0000
#define IRAM_SIZE 0x0100
#ifdef CONFIG_ARCH_8052
# define IRAM_SIZE 0x0100
#else
# define IRAM_SIZE 0x0080
#endif
#define STACK_BASE 0x0024
#define STACK_SIZE (IRAM_SIZE - STACK_BASE)

View File

@ -65,6 +65,11 @@ LINKLIBS =
LDPATHES = $(addprefix -L$(TOPDIR)/,$(dir $(LINKLIBS)))
LDLIBS = $(addprefix -l,$(notdir $(LINKLIBS)))
TESTSRCS = up_irqtest.c
TESTOBJS = $(TESTSRCS:.c=$(OBJEXT))
TESTLINKOBJS = up_head$(OBJEXT)
TESTEXTRAOBJS = up_savecontext$(OBJEXT) up_restorecontext$(OBJEXT)
IRAM_SIZE = 0x100
DEF_STACK_BASE = 0x24
LDFLAGS = --model-large --nostdlib \
@ -108,7 +113,7 @@ $(ASRCS) $(LINKASRCS): %$(ASMEXT): %.S
$(AOBJS) $(LINKOBJS): $(ASRCS) $(LINKASRCS)
$(AS) $(ASFLAGS) $<
$(COBJS): %$(OBJEXT): %.c
$(COBJS) $(TESTOBJS): %$(OBJEXT): %.c
$(CC) -c $(CFLAGS) $< -o $@
# Create a header file that contains addressing information needed by the code
@ -174,6 +179,15 @@ nuttx$(EXEEXT): pass1.ihx nuttx.ihx
packihx nuttx.ihx > $(TOPDIR)/nuttx$(EXEEXT)
@cp -f nuttx.map $(TOPDIR)/.
# This target builds a test program to verify interrupt context switching. irqtest is
# a PHONY target that just sets upt the up_irqtest build correctly
up_irqtest.ihx: $(TESTOBJS)
$(CC) $(LDFLAGS) -L. $(SDCCPATH) $(TESTLINKOBJS) $(TESTOBJS) $(TESTEXTRAOBJS) $(SDCCLIBS) -o $@
irqtest:
$(MAKE) TOPDIR=../../.. up_irqtest.ihx
# Build dependencies
.depend: Makefile up_mem.h $(DEPSRCS)

View File

@ -0,0 +1,269 @@
/************************************************************
* up_putc.c
*
* Copyright (C) 2007 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 Gregory Nutt 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 <nuttx/config.h>
#include <sys/types.h>
#include <nuttx/arch.h>
#include <8052.h>
#include "up_internal.h"
/************************************************************
* Definitions
************************************************************/
#define up_extint0 ((vector_t)PM2_VECTOR_EXTINT0)
#define up_timer0 ((vector_t)PM2_VECTOR_TIMER0)
#define up_extint1 ((vector_t)PM2_VECTOR_EXTINT1)
#define up_timer1 ((vector_t)PM2_VECTOR_TIMER1)
#define up_uart ((vector_t)PM2_VECTOR_UART)
#define up_timer2 ((vector_t)PM2_VECTOR_TIMER2)
/************************************************************
* Private Types
************************************************************/
typedef void (*vector_t)(void);
/************************************************************
* Public Variables
************************************************************/
boolean g_irqtest;
ubyte g_irqtos;
ubyte g_irqregs[REGS_SIZE];
int g_nirqs;
FAR struct xcptcontext *g_irqcontext;
/************************************************************
* Private Functions
************************************************************/
/************************************************************
* Name: utility functions
************************************************************/
static void _up_putc(ubyte ch) __naked
{
ch; /* To avoid unreferenced argument warning */
_asm
mov a, dpl
ljmp PM2_ENTRY_COUT
_endasm;
}
void _up_puthex(ubyte hex) __naked
{
hex; /* To avoid unreferenced argument warning */
_asm
mov a, dpl
ljmp PM2_ENTRY_PHEX
_endasm;
}
void _up_puthex16(int hex) __naked
{
hex; /* To avoid unreferenced argument warning */
_asm
ljmp PM2_ENTRY_PHEX16
_endasm;
}
void _up_putnl(void) __naked
{
_asm
ljmp PM2_ENTRY_NEWLINE
_endasm;
}
void _up_puts(__code char *ptr)
{
for (; *ptr; ptr++)
{
_up_putc(*ptr);
}
}
void _up_delay(ubyte milliseconds) __naked
{
_asm
mov r0, dpl
00001$: mov r1, #230
00002$: nop
nop
nop
nop
nop
nop
djnz r1, 00002$
djnz r0, 00001$
ret
_endasm;
}
/************************************************************
* Public Functions
************************************************************/
/************************************************************
* Name: os_start
*
* Description:
* "Fake" OS entry point.
*
************************************************************/
void os_start(void)
{
int i;
/* Disable all interrupts */
IE = 0;
/* Then verify all of the interrupt */
g_irqtest = FALSE;
up_extint0();
up_timer0();
#ifndef CONFIG_8052_TIMER2
up_timer0();
#endif
up_extint1();
up_timer1();
up_uart();
up_timer2();
/* Now a real interrupt ... */
/* Configure timer 0 */
TR0 = 0; /* Make sure timer 0 is stopped */
TF0 = 0; /* Clear the overflow flag */
TMOD &= 0xF0; /* Set to mode 0 (without changing timer1) */
TL0 = 0; /* Clear timer 0 value */
TH0 = 0;
TR0 = 1; /* Start the timer */
/* Start timer interrupts */
g_irqtest = TRUE;
g_nirqs = 0;
IE = 0x82; /* Enable interrupts */
/* Wait a about 500 MS */
_up_delay(500);
/* Disable the timer */
TR0 = 0; /* Stop timer 0 */
IE = 0; /* Disable interrupts */
_up_puts("IRQs in 500 MS=");
_up_puthex16(g_nirqs);
_up_putnl();
/* end of test */
_up_puts("Test complete");
_up_putnl();
for(;;);
}
/************************************************************
* Name: irq_dispatch
*
* Description:
* "Fake" IRQ dispatcher
*
***********************************************************/
void irq_dispatch(int irq, FAR void *context)
{
context;
if (g_irqtest)
{
g_nirqs++;
}
else
{
_up_puts("Dispatch IRQ=");
_up_puthex(irq);
_up_putnl();
}
}
/************************************************************
* Name: up_dumpstack / up_dumpframe
*
* Description:
* "Fake" debug routines if needed.
*
************************************************************/
void up_dumpstack(void)
{
}
void up_dumpframe(FAR struct xcptcontext *context)
{
}
/************************************************************
* Name: up_ledinit, up_ledon, up_ledoff
*
* Description:
* "Fake" LED routines if needed
*
************************************************************/
void up_ledinit(void)
{
}
void up_ledon(ubyte led)
{
led;
}
void up_ledoff(ubyte led)
{
led;
}

View File

@ -274,7 +274,7 @@ ubyte up_savecontext(FAR struct xcptcontext *context) _naked
/* Push the top of frame stack pointer. We need to
* decrement the current SP value by three to account
* for dpst+IE on the stack above the end of the frame.
* for dptr+IE on the stack above the end of the frame.
*/
mov a, sp

View File

@ -139,7 +139,6 @@ void up_timerinit(void)
TR0 = 1; /* Start the timer */
up_enable_irq(TIMER0_IRQ);
# warning "No support for timer 0 as the system timer"
#endif
}

View File

@ -122,11 +122,17 @@ int files_addreflist(FAR struct filelist *list)
{
if (list)
{
/* Increment the reference count on the list */
/* Increment the reference count on the list.
* NOTE: that we disable interrupts to do this
* (vs. taking the list semaphore). We do this
* because file cleanup operations often must be
* done from the IDLE task which cannot wait
* on semaphores.
*/
_files_semtake(list);
register irqstate_t flags = irqsave();
list->fl_crefs++;
_files_semgive(list);
irqrestore(flags);
}
return OK;
}
@ -138,14 +144,22 @@ int files_releaselist(FAR struct filelist *list)
int crefs;
if (list)
{
/* Decrement the reference count */
/* Decrement the reference count on the list.
* NOTE: that we disable interrupts to do this
* (vs. taking the list semaphore). We do this
* because file cleanup operations often must be
* done from the IDLE task which cannot wait
* on semaphores.
*/
_files_semtake(list);
register irqstate_t flags = irqsave();
crefs = --(list->fl_crefs);
_files_semgive(list);
irqrestore(flags);
/* If the count decrements to zero, then there is no reference
* to the structure and it should be deallocated.
* to the structure and it should be deallocated. Since there
* are references, it would be an error if any task still held
* a reference to the list's semaphore.
*/
if (crefs <= 0)

View File

@ -78,6 +78,11 @@ EXTERN void os_start(void); /* OS entry point called by boot logic */
EXTERN void mm_initialize(FAR void *heap_start, size_t heap_size);
EXTERN void mm_addregion(FAR void *heapstart, size_t heapsize);
/* Functions contained in mm_sem.c **************************/
EXTERN int mm_trysemaphore(void);
EXTERN void mm_givesemaphore(void);
#undef EXTERN
#ifdef __cplusplus
}

View File

@ -145,11 +145,17 @@ void lib_addreflist(FAR struct streamlist *list)
{
if (list)
{
/* Increment the reference count on the list */
/* Increment the reference count on the list.
* NOTE: that we disable interrupts to do this
* (vs. taking the list semaphore). We do this
* because file cleanup operations often must be
* done from the IDLE task which cannot wait
* on semaphores.
*/
_lib_semtake(list);
register irqstate_t flags = irqsave();
list->sl_crefs++;
_lib_semgive(list);
irqrestore(flags);
}
}
@ -163,14 +169,22 @@ void lib_releaselist(FAR struct streamlist *list)
int crefs;
if (list)
{
/* Decrement the reference count */
/* Decrement the reference count on the list.
* NOTE: that we disable interrupts to do this
* (vs. taking the list semaphore). We do this
* because file cleanup operations often must be
* done from the IDLE task which cannot wait
* on semaphores.
*/
_lib_semtake(list);
register irqstate_t flags = irqsave();
crefs = --(list->sl_crefs);
_lib_semgive(list);
irqrestore(flags);
/* If the count decrements to zero, then there is no reference
* to the structure and it should be deallocated.
* to the structure and it should be deallocated. Since there
* are references, it would be an error if any task still held
* a reference to the list's semaphore.
*/
if (crefs <= 0)

View File

@ -78,7 +78,11 @@ static int g_counts_held;
************************************************************/
/************************************************************
* mm_seminitialize
* Name: mm_seminitialize
*
* Description:
* Initialize the MM mutex
*
************************************************************/
void mm_seminitialize(void)
@ -94,7 +98,56 @@ void mm_seminitialize(void)
}
/************************************************************
* mm_takesemaphore
* Name: mm_trysemaphore
*
* Description:
* Try to take the MM mutex. This is called only from the
* OS in certain conditions when it is necessary to have
* exclusive access to the memory manager but it is
* impossible to wait on a semaphore (e.g., the idle process
* when it performs its background memory cleanup).
*
************************************************************/
#ifndef MM_TEST
int mm_trysemaphore(void)
{
pid_t my_pid = getpid();
/* Do I already have the semaphore? */
if (g_holder == my_pid)
{
/* Yes, just increment the number of references that I have */
g_counts_held++;
return OK;
}
else
{
/* Try to tak the semaphore (perhaps waiting) */
if (sem_trywait(&g_mm_semaphore) != 0)
{
return ERROR;
}
/* We have it. Claim the stak and return */
g_holder = my_pid;
g_counts_held = 1;
return OK;
}
}
#endif
/************************************************************
* Name: mm_takesemaphore
*
* Description:
* Take the MM mutex. This is the normal action before all
* memory management actions.
*
************************************************************/
void mm_takesemaphore(void)
@ -134,7 +187,11 @@ void mm_takesemaphore(void)
}
/************************************************************
* mm_givesemaphore
* Name: mm_givesemaphore
*
* Description:
* Release the MM mutex when it is not longer needed.
*
************************************************************/
void mm_givesemaphore(void)
@ -160,12 +217,21 @@ void mm_givesemaphore(void)
/* Nope, this is the last reference I have */
msemdbg("PID=%d giving\n", my_pid);
g_holder = -1;
g_holder = -1;
g_counts_held = 0;
ASSERT(sem_post(&g_mm_semaphore) == 0);
}
}
/************************************************************
* Name: mm_getsemaphore
*
* Description:
* Return the current value of the MM semaphore (for test
* purposes only)
*
************************************************************/
#ifdef MM_TEST
int mm_getsemaphore(void)
{

View File

@ -80,5 +80,5 @@ pid_t getpid(void)
* ready-to-run task list
*/
return ((_TCB*)g_readytorun.head)->pid;
return ((FAR _TCB*)g_readytorun.head)->pid;
}

View File

@ -134,8 +134,8 @@ typedef struct pidhash_s pidhash_t;
struct tasklist_s
{
DSEG dq_queue_t *list; /* Pointer to the task list */
boolean prioritized; /* TRUE if the list is prioritized */
DSEG volatile dq_queue_t *list; /* Pointer to the task list */
boolean prioritized; /* TRUE if the list is prioritized */
};
typedef struct tasklist_s tasklist_t;
@ -159,7 +159,7 @@ typedef struct tasklist_s tasklist_t;
* list is always the idle task.
*/
extern dq_queue_t g_readytorun;
extern volatile dq_queue_t g_readytorun;
/* This is the list of all tasks that are ready-to-run, but
* cannot be placed in the g_readytorun list because: (1) They
@ -168,16 +168,16 @@ extern dq_queue_t g_readytorun;
* disabled pre-emption.
*/
extern dq_queue_t g_pendingtasks;
extern volatile dq_queue_t g_pendingtasks;
/* This is the list of all tasks that are blocked waiting for a semaphore */
extern dq_queue_t g_waitingforsemaphore;
extern volatile dq_queue_t g_waitingforsemaphore;
/* This is the list of all tasks that are blocked waiting for a signal */
#ifndef CONFIG_DISABLE_SIGNALS
extern dq_queue_t g_waitingforsignal;
extern volatile dq_queue_t g_waitingforsignal;
#endif
/* This is the list of all tasks that are blocked waiting for a message
@ -185,7 +185,7 @@ extern dq_queue_t g_waitingforsignal;
*/
#ifndef CONFIG_DISABLE_MQUEUE
extern dq_queue_t g_waitingformqnotempty;
extern volatile dq_queue_t g_waitingformqnotempty;
#endif
/* This is the list of all tasks that are blocked waiting for a message
@ -193,14 +193,14 @@ extern dq_queue_t g_waitingformqnotempty;
*/
#ifndef CONFIG_DISABLE_MQUEUE
extern dq_queue_t g_waitingformqnotfull;
extern volatile dq_queue_t g_waitingformqnotfull;
#endif
/* This the list of all tasks that have been initialized, but not yet
* activated. NOTE: This is the only list that is not prioritized.
*/
extern dq_queue_t g_inactivetasks;
extern volatile dq_queue_t g_inactivetasks;
/* This is the list of dayed memory deallocations that need to be handled
* within the IDLE loop. These deallocations get queued by sched_free()
@ -208,11 +208,11 @@ extern dq_queue_t g_inactivetasks;
* handler.
*/
extern sq_queue_t g_delayeddeallocations;
extern volatile sq_queue_t g_delayeddeallocations;
/* This is the value of the last process ID assigned to a task */
extern pid_t g_lastpid;
extern volatile pid_t g_lastpid;
/* The following hash table is used for two things:
*

View File

@ -86,7 +86,7 @@
* list is always the idle task.
*/
dq_queue_t g_readytorun;
volatile dq_queue_t g_readytorun;
/* This is the list of all tasks that are ready-to-run, but
* cannot be placed in the g_readytorun list because: (1) They
@ -95,16 +95,16 @@ dq_queue_t g_readytorun;
* disabled pre-emption.
*/
dq_queue_t g_pendingtasks;
volatile dq_queue_t g_pendingtasks;
/* This is the list of all tasks that are blocked waiting for a semaphore */
dq_queue_t g_waitingforsemaphore;
volatile dq_queue_t g_waitingforsemaphore;
/* This is the list of all tasks that are blocked waiting for a signal */
#ifndef CONFIG_DISABLE_SIGNALS
dq_queue_t g_waitingforsignal;
volatile dq_queue_t g_waitingforsignal;
#endif
/* This is the list of all tasks that are blocked waiting for a message
@ -112,7 +112,7 @@ dq_queue_t g_waitingforsignal;
*/
#ifndef CONFIG_DISABLE_MQUEUE
dq_queue_t g_waitingformqnotempty;
volatile dq_queue_t g_waitingformqnotempty;
#endif
/* This is the list of all tasks that are blocked waiting for a message
@ -120,14 +120,14 @@ dq_queue_t g_waitingformqnotempty;
*/
#ifndef CONFIG_DISABLE_MQUEUE
dq_queue_t g_waitingformqnotfull;
volatile dq_queue_t g_waitingformqnotfull;
#endif
/* This the list of all tasks that have been initialized, but not yet
* activated. NOTE: This is the only list that is not prioritized.
*/
dq_queue_t g_inactivetasks;
volatile dq_queue_t g_inactivetasks;
/* This is the list of dayed memory deallocations that need to be handled
* within the IDLE loop. These deallocations get queued by sched_free()
@ -135,11 +135,11 @@ dq_queue_t g_inactivetasks;
* handler.
*/
sq_queue_t g_delayeddeallocations;
volatile sq_queue_t g_delayeddeallocations;
/* This is the value of the last process ID assigned to a task */
pid_t g_lastpid;
volatile pid_t g_lastpid;
/* The following hash table is used for two things:
*
@ -420,22 +420,35 @@ void os_start(void)
dbg("Beginning Idle Loop\n");
for (;;)
{
/* Check if there is anything in the delayed deallocation list. */
/* Check if there is anything in the delayed deallocation list.
* If there is deallocate it now. We must have exclusive access
* to the memory manager to do this BUT the idle task cannot
* wait on a semaphore. So we only do the cleanup now if we
* can get the semaphore -- and this should be possible because
* since we are running, no other task is!
*/
while (g_delayeddeallocations.head)
{
/* Remove the first delayed deallocation. */
if (mm_trysemaphore() == 0)
{
while (g_delayeddeallocations.head)
{
/* Remove the first delayed deallocation. */
irqstate_t saved_state = irqsave();
void *address = (void*)sq_remfirst(&g_delayeddeallocations);
irqrestore(saved_state);
irqstate_t saved_state = irqsave();
void *address = (void*)sq_remfirst(&g_delayeddeallocations);
irqrestore(saved_state);
/* Then deallocate it */
/* Then deallocate it */
if (address) sched_free(address);
}
if (address)
{
sched_free(address);
}
}
mm_givesemaphore();
}
/* Perform idle state operations */
/* Perform any processor-specific idle state operations */
up_idle();
}

View File

@ -83,10 +83,12 @@
void sched_free(FAR void *address)
{
/* Check if this is an attempt to deallocate memory from
* an exception handler.
* an exception handler. If this function is called from the
* IDLE task, then we must have exclusive access to the memory
* manager to do this.
*/
if (up_interrupt_context())
if (up_interrupt_context() || mm_trysemaphore() != 0)
{
/* Yes.. Delay the deallocation until a more appropriate time. */
@ -99,6 +101,7 @@ void sched_free(FAR void *address)
/* No.. just deallocate the memory now. */
kfree(address);
mm_givesemaphore();
}
}