atexit() functions now called when task killed by task delete; For MCUs with <= 64Kb of SRAM, CONFIG_MM_SMALL can be defined to reduce the memory allocation overhead
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3648 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
a155d4f576
commit
ae8cfb1bf1
19 changed files with 334 additions and 115 deletions
21
ChangeLog
21
ChangeLog
|
@ -1548,7 +1548,7 @@
|
|||
* sched/atexit.c and sched/exit.c: The atexit function is not frequently
|
||||
used. In order to save a few bytes, it is now conditioned on
|
||||
CONFIG_SCHED_ATEXIT. It your application is currently using atexit(),
|
||||
you will need to add CONFIG_SCHED_ATEXT to your configuration file.
|
||||
you will need to add CONFIG_SCHED_ATEXIT to your configuration file.
|
||||
* drivers/net/slip.c: Add a SLIP driver (untested on initial check-in).
|
||||
* configs/olimex-lpc1766stk/slip-httpd: An example that uses SLIP to
|
||||
provide a serial-port based THTTPD web server.
|
||||
|
@ -1770,7 +1770,22 @@
|
|||
the MPLAB debugger on PIC32; I will need to get a PICkit 3).
|
||||
* drivers/net/e1000.c/h: A PCI-based E1000 ethernet driver submitted
|
||||
by Yu Qiang.
|
||||
* lib/net/lib_inetaddr.c: An implementatino of the inet_addr() function
|
||||
submitted y Yu Qiang.
|
||||
* lib/net/lib_inetaddr.c: An implementation of the inet_addr() function
|
||||
submitted by Yu Qiang.
|
||||
* arch/arm/src/lpc31xx and arch/arm/include/lpc31xx: Renamed from lpc313x
|
||||
to make name space for other famiy members.
|
||||
* arch/arm/*/lpc31xx: Added support for the LPC315x family (untested).
|
||||
* sched/task_exithook.c: Functionality performed when a task exits or is
|
||||
deleted has been moved to a common file task_exithook.c. Now exit()
|
||||
functionality (like flushing I/O and calling registered atexit()
|
||||
functions, etc.) will be performed when a task is deleted as well.
|
||||
* mm/: Added support for CONFIG_MM_SMALL. Each memory allocation has a
|
||||
small allocation overhead. The size of that overhead is normally
|
||||
determined by the "width" of the address support by the MCU. MCUs
|
||||
that support 16-bit addressability have smaller overhead than devices
|
||||
that support 32-bit addressability. However, there are many MCUs
|
||||
that support 32-bit addressability *but* have internal SRAM of size
|
||||
less than or equal to 64Kb. In this case, CONFIG_MM_SMALL can be
|
||||
defined so that those MCUs will also benefit from the smaller, 16-
|
||||
bit-based allocation overhead.
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<tr align="center" bgcolor="#e4e4e4">
|
||||
<td>
|
||||
<h1><big><font color="#3c34ec"><i>NuttX RTOS</i></font></big></h1>
|
||||
<p>Last Updated: May 25, 2011</p>
|
||||
<p>Last Updated: May 28, 2011</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
@ -2313,8 +2313,24 @@ nuttx-6.4 2011-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
|
|||
the MPLAB debugger on PIC32; I will need to get a PICkit 3).
|
||||
* drivers/net/e1000.c/h: A PCI-based E1000 ethernet driver submitted
|
||||
by Yu Qiang.
|
||||
* lib/net/lib_inetaddr.c: An implementatino of the inet_addr() function
|
||||
submitted y Yu Qiang.
|
||||
* lib/net/lib_inetaddr.c: An implementation of the inet_addr() function
|
||||
submitted by Yu Qiang.
|
||||
* arch/arm/src/lpc31xx and arch/arm/include/lpc31xx: Renamed from lpc313x
|
||||
to make name space for other famiy members.
|
||||
* arch/arm/*/lpc31xx: Added support for the LPC315x family (untested).
|
||||
* sched/task_exithook.c: Functionality performed when a task exits or is
|
||||
deleted has been moved to a common file task_exithook.c. Now exit()
|
||||
functionality (like flushing I/O and calling registered atexit()
|
||||
functions, etc.) will be performed when a task is deleted as well.
|
||||
* mm/: Added support for CONFIG_MM_SMALL. Each memory allocation has a
|
||||
small allocation overhead. The size of that overhead is normally
|
||||
determined by the "width" of the address support by the MCU. MCUs
|
||||
that support 16-bit addressability have smaller overhead than devices
|
||||
that support 32-bit addressability. However, there are many MCUs
|
||||
that support 32-bit addressability *but* have internal SRAM of size
|
||||
less than or equal to 64Kb. In this case, CONFIG_MM_SMALL can be
|
||||
defined so that those MCUs will also benefit from the smaller, 16-
|
||||
bit-based allocation overhead.
|
||||
|
||||
apps-6.4 2011-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<h1><big><font color="#3c34ec">
|
||||
<i>NuttX RTOS Porting Guide</i>
|
||||
</font></big></h1>
|
||||
<p>Last Updated: May 25, 2011</p>
|
||||
<p>Last Updated: May 28, 2011</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
@ -3262,6 +3262,17 @@ build
|
|||
number of memory regions that the memory manager must
|
||||
handle and enables the API mm_addregion(start, end);
|
||||
</li>
|
||||
<li>
|
||||
<code>CONFIG_MM_SMALL</code>: Each memory allocation has a small allocation
|
||||
overhead. The size of that overhead is normally determined by
|
||||
the "width" of the address support by the MCU. MCUs that support
|
||||
16-bit addressability have smaller overhead than devices that
|
||||
support 32-bit addressability. However, there are many MCUs
|
||||
that support 32-bit addressability <i>but</i> have internal SRAM
|
||||
of size less than or equal to 64Kb. In this case, CONFIG_MM_SMALL
|
||||
can be defined so that those MCUs will also benefit from the
|
||||
smaller, 16-bit-based allocation overhead.
|
||||
</li>
|
||||
<li>
|
||||
<code>CONFIG_MSEC_PER_TICK</code>: The default system timer is 100Hz
|
||||
or <code>MSEC_PER_TICK</code>=10. This setting may be defined to inform NuttX
|
||||
|
|
33
TODO
33
TODO
|
@ -1,11 +1,11 @@
|
|||
NuttX TODO List (Last updated May 14, 2011)
|
||||
NuttX TODO List (Last updated May 28, 2011)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
nuttx/
|
||||
|
||||
(5) Task/Scheduler (sched/)
|
||||
(1) On-demand paging (sched/)
|
||||
(2) Memory Managment (mm/)
|
||||
(1) Memory Managment (mm/)
|
||||
(1) Signals (sched/, arch/)
|
||||
(1) pthreads (sched/)
|
||||
(1) C++ Support
|
||||
|
@ -40,7 +40,7 @@ nuttx/
|
|||
apps/
|
||||
|
||||
(5) Network Utilities (apps/netutils/)
|
||||
(4) NuttShell (NSH) (apps/nshlib)
|
||||
(5) NuttShell (NSH) (apps/nshlib)
|
||||
(3) Other Applications & Tests (apps/examples/)
|
||||
|
||||
o Task/Scheduler (sched/)
|
||||
|
@ -51,13 +51,12 @@ o Task/Scheduler (sched/)
|
|||
Status: Open
|
||||
Priority: Medium, required for good emulation of process/pthread model.
|
||||
|
||||
Description: atexit() supports registration of one function called on exit().
|
||||
Should task_delete() also cause atexit() function to be called?
|
||||
Update: atexit() is only built into the system if CONFIG_SCHED_ATEXT
|
||||
is defined in the configuration.
|
||||
Description: atexit() supports registration of only single function called on
|
||||
exit(). It should support multiple functions registered by atexit()
|
||||
or onexit() and these should be called in reverse order of
|
||||
registration when the task exits.
|
||||
Status: Open
|
||||
Priority: Low, task_delete() is non-standard and its behavior is
|
||||
unspecified.
|
||||
Priority: Low
|
||||
|
||||
Description: Implement sys/mman.h and functions
|
||||
Status: Open
|
||||
|
@ -121,13 +120,6 @@ o Memory Managment (mm/)
|
|||
Priority: Medium/Low, a good feature to prevent memory leaks but would
|
||||
have negative impact on memory usage and code size.
|
||||
|
||||
Description: Current logic adapts size_t for 16-bit address machines vs.
|
||||
32-bit address machines. But a small memory option should also
|
||||
be provided so that the small offset option can be used with
|
||||
32-bit machines that have small RAM memories (like the lpc2148)
|
||||
Status: Open
|
||||
Priority: High, a good feature enhancement.
|
||||
|
||||
o Signals (sched/, arch/)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -329,7 +321,7 @@ o Network (net/, drivers/net)
|
|||
Description: The interfaces used to leave/join IGMP multicast groups is non-standard.
|
||||
RFC3678 (IGMPv3) suggests ioctl() commands to do this (SIOCSIPMSFILTER) but
|
||||
also status that those APIs are historic. NuttX implements these ioctl
|
||||
commnands, but is non-standard because: (1) It does not support IGMPv3, and
|
||||
commands, but is non-standard because: (1) It does not support IGMPv3, and
|
||||
(2) it looks up drivers by their device name (eg., "eth0") vs IP address.
|
||||
|
||||
Linux uses setsockopt() to control multicast group membership using the
|
||||
|
@ -1196,6 +1188,13 @@ o NuttShell (NSH) (apps/nshlib)
|
|||
Status: Open
|
||||
Priority: Med-High
|
||||
|
||||
Descripton: The ifconfig command will not behave correctly is an interface
|
||||
is provided and there are multiple interfaces. It should only
|
||||
show status for the single interface on the command line; it will
|
||||
still show status for all interfaces.
|
||||
Status: Open
|
||||
Priority: Low (multiple network interfaces not fully supported yet anyway).
|
||||
|
||||
Description: Add support to NSH to run NXFLAT programs from a ROMFS file system
|
||||
Status: Open
|
||||
Priority: Low (enhancement)
|
||||
|
|
|
@ -81,5 +81,5 @@ static uint8_t sim_heap[SIM_HEAP_SIZE];
|
|||
void up_allocate_heap(void **heap_start, size_t *heap_size)
|
||||
{
|
||||
*heap_start = sim_heap;
|
||||
*heap_size = SIM_HEAP_SIZE;
|
||||
*heap_size = SIM_HEAP_SIZE;
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
* Included Files
|
||||
**************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <sys/types.h>
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
|
@ -64,7 +65,13 @@
|
|||
# define JB_PC (5)
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#define SIM_HEAP_SIZE (4*1024*1024)
|
||||
/* Size of the simulated heap */
|
||||
|
||||
#if CONFIG_MM_SMALL
|
||||
# define SIM_HEAP_SIZE (64*1024)
|
||||
#else
|
||||
# define SIM_HEAP_SIZE (4*1024*1024)
|
||||
#endif
|
||||
|
||||
/* These definitions characterize the compressed filesystem image */
|
||||
|
||||
|
|
|
@ -261,6 +261,15 @@ defconfig -- This is a configuration file similar to the Linux
|
|||
regions of memory to allocate from, this specifies the
|
||||
number of memory regions that the memory manager must
|
||||
handle and enables the API mm_addregion(start, end);
|
||||
CONFIG_MM_SMALL - Each memory allocation has a small allocation
|
||||
overhead. The size of that overhead is normally determined by
|
||||
the "width" of the address support by the MCU. MCUs that support
|
||||
16-bit addressability have smaller overhead than devices that
|
||||
support 32-bit addressability. However, there are many MCUs
|
||||
that support 32-bit addressability *but* have internal SRAM
|
||||
of size less than or equal to 64Kb. In this case, CONFIG_MM_SMALL
|
||||
can be defined so that those MCUs will also benefit from the
|
||||
smaller, 16-bit-based allocation overhead.
|
||||
CONFIG_MSEC_PER_TICK - The default system timer is 100Hz
|
||||
or MSEC_PER_TICK=10. This setting may be defined to
|
||||
inform NuttX that the processor hardware is providing
|
||||
|
|
|
@ -137,7 +137,7 @@ typedef union entry_u entry_t;
|
|||
* (if registered via atexit()).
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SCHED_ATEXT
|
||||
#ifdef CONFIG_SCHED_ATEXIT
|
||||
typedef void (*exitfunc_t)(void);
|
||||
#endif
|
||||
|
||||
|
@ -184,7 +184,7 @@ struct _TCB
|
|||
pid_t pid; /* This is the ID of the thread */
|
||||
start_t start; /* Thread start function */
|
||||
entry_t entry; /* Entry Point into the thread */
|
||||
#ifdef CONFIG_SCHED_ATEXT
|
||||
#ifdef CONFIG_SCHED_ATEXIT
|
||||
exitfunc_t exitfunc; /* Called if exit is called. */
|
||||
#endif
|
||||
#ifdef CONFIG_SCHED_WAITPID /* Experimental */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
* mm/mm_environment.h
|
||||
*
|
||||
* Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -76,6 +76,7 @@
|
|||
# define FAR /* Normally in compiler.h */
|
||||
# define CONFIG_CPP_HAVE_VARARGS 1 /* Normally in compiler.h */
|
||||
# define CONFIG_MM_REGIONS 2 /* Normally in config.h */
|
||||
# undef CONFIG_MM_SMALL /* Normally in config.h */
|
||||
# define CONFIG_CAN_PASS_STRUCTS 1 /* Normally in config.h */
|
||||
# undef CONFIG_SMALL_MEMORY /* Normally in config.h */
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
* mm/mm_initialize.c
|
||||
*
|
||||
* Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -124,7 +124,7 @@ void mm_initialize(FAR void *heapstart, size_t heapsize)
|
|||
}
|
||||
|
||||
/* Initialize the malloc semaphore to one (to support one-at-
|
||||
* a-time access to private data sets.
|
||||
* a-time access to private data sets).
|
||||
*/
|
||||
|
||||
mm_seminitialize();
|
||||
|
@ -155,20 +155,29 @@ void mm_initialize(FAR void *heapstart, size_t heapsize)
|
|||
void mm_addregion(FAR void *heapstart, size_t heapsize)
|
||||
{
|
||||
FAR struct mm_freenode_s *node;
|
||||
size_t heapbase;
|
||||
size_t heapend;
|
||||
uintptr_t heapbase;
|
||||
uintptr_t heapend;
|
||||
#if CONFIG_MM_REGIONS > 1
|
||||
int IDX = g_nregions;
|
||||
#else
|
||||
# define IDX 0
|
||||
#endif
|
||||
|
||||
/* If the MCU handles wide addresses but the memory manager
|
||||
* is configured for a small heap, then verify that the caller
|
||||
* not doing something crazy.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_MM_SMALL) && !defined(CONFIG_SMALL_MEMORY)
|
||||
DEBUGASSERT(heapsize <= MMSIZE_MAX+1);
|
||||
#endif
|
||||
|
||||
/* Adjust the provide heap start and size so that they are
|
||||
* both aligned with the MM_MIN_CHUNK size.
|
||||
*/
|
||||
|
||||
heapbase = MM_ALIGN_UP((size_t)heapstart);
|
||||
heapend = MM_ALIGN_DOWN((size_t)heapstart + (size_t)heapsize);
|
||||
heapbase = MM_ALIGN_UP((uintptr_t)heapstart);
|
||||
heapend = MM_ALIGN_DOWN((uintptr_t)heapstart + (uintptr_t)heapsize);
|
||||
heapsize = heapend - heapbase;
|
||||
|
||||
mlldbg("Region %d: base=%p size=%u\n", IDX+1, heapstart, heapsize);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/************************************************************************
|
||||
* mm/mm_internal.h
|
||||
*
|
||||
* Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -43,7 +43,24 @@
|
|||
/************************************************************************
|
||||
* Pre-processor Definitions
|
||||
************************************************************************/
|
||||
/* Configuration ********************************************************/
|
||||
/* If the MCU has a small (16-bit) address capability, then we will use
|
||||
* a smaller chunk header that contains 16-bit size/offset information.
|
||||
* We will also use the smaller header on MCUs with wider addresses if
|
||||
* CONFIG_MM_SMALL is selected. This configuration is common with MCUs
|
||||
* that have a large FLASH space, but only a tiny internal SRAM.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SMALL_MEMORY
|
||||
/* If the MCU has a small addressing capability, then for the smaller
|
||||
* chunk header.
|
||||
*/
|
||||
|
||||
# undef CONFIG_MM_SMALL
|
||||
# define CONFIG_MM_SMALL 1
|
||||
#endif
|
||||
|
||||
/* Chunk Header Definitions *********************************************/
|
||||
/* These definitions define the characteristics of allocator
|
||||
*
|
||||
* MM_MIN_SHIFT is used to define MM_MIN_CHUNK.
|
||||
|
@ -61,7 +78,7 @@
|
|||
* losses.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SMALL_MEMORY
|
||||
#ifdef CONFIG_MM_SMALL
|
||||
# define MM_MIN_SHIFT 4 /* 16 bytes */
|
||||
# define MM_MAX_SHIFT 15 /* 32 Kb */
|
||||
#else
|
||||
|
@ -84,7 +101,7 @@
|
|||
* an allocated chunk.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SMALL_MEMORY
|
||||
#ifdef CONFIG_MM_SMALL
|
||||
# define MM_ALLOC_BIT 0x8000
|
||||
#else
|
||||
# define MM_ALLOC_BIT 0x80000000
|
||||
|
@ -96,18 +113,30 @@
|
|||
* Public Types
|
||||
************************************************************************/
|
||||
|
||||
/* Determine the size of the chunk size/offset type */
|
||||
|
||||
#ifdef CONFIG_MM_SMALL
|
||||
typedef uint16_t mmsize_t;
|
||||
# define MMSIZE_MAX 0xffff
|
||||
#else
|
||||
typedef size_t mmsize_t;
|
||||
# define MMSIZE_MAX SIZE_MAX
|
||||
#endif
|
||||
|
||||
/* This describes an allocated chunk. An allocated chunk is
|
||||
* distinguished from a free chunk by bit 31 of the 'precding'
|
||||
* chunk size. If set, then this is an allocated chunk.
|
||||
* distinguished from a free chunk by bit 15/31 of the 'preceding' chunk
|
||||
* size. If set, then this is an allocated chunk.
|
||||
*/
|
||||
|
||||
struct mm_allocnode_s
|
||||
{
|
||||
size_t size; /* Size of this chunk */
|
||||
size_t preceding; /* Size of the preceding chunk */
|
||||
mmsize_t size; /* Size of this chunk */
|
||||
mmsize_t preceding; /* Size of the preceding chunk */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SMALL_MEMORY
|
||||
/* What is the size of the allocnode? */
|
||||
|
||||
#ifdef CONFIG_MM_SMALL
|
||||
# define SIZEOF_MM_ALLOCNODE 4
|
||||
#else
|
||||
# define SIZEOF_MM_ALLOCNODE 8
|
||||
|
@ -120,18 +149,25 @@ struct mm_allocnode_s
|
|||
|
||||
struct mm_freenode_s
|
||||
{
|
||||
size_t size; /* Size of this chunk */
|
||||
size_t preceding; /* Size of the preceding chunk */
|
||||
mmsize_t size; /* Size of this chunk */
|
||||
mmsize_t preceding; /* Size of the preceding chunk */
|
||||
FAR struct mm_freenode_s *flink; /* Supports a doubly linked list */
|
||||
FAR struct mm_freenode_s *blink;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SMALL_MEMORY
|
||||
# define SIZEOF_MM_FREENODE 8
|
||||
/* Free is the size of the freenode */
|
||||
|
||||
#ifdef CONFIG_MM_SMALL
|
||||
# ifdef CONFIG_SMALL_MEMORY
|
||||
# define SIZEOF_MM_FREENODE 8
|
||||
# else
|
||||
# define SIZEOF_MM_FREENODE 12
|
||||
# endif
|
||||
#else
|
||||
# define SIZEOF_MM_FREENODE 16
|
||||
# define SIZEOF_MM_FREENODE 16
|
||||
#endif
|
||||
#define CHECK_FREENODE_SIZE \
|
||||
|
||||
#define CHECK_FREENODE_SIZE \
|
||||
DEBUGASSERT(sizeof(struct mm_freenode_s) == SIZEOF_MM_FREENODE)
|
||||
|
||||
/* Normally defined in stdlib.h */
|
||||
|
|
|
@ -199,6 +199,6 @@ FAR void *malloc(size_t size)
|
|||
}
|
||||
|
||||
mm_givesemaphore();
|
||||
mvdbg("Allocated %p\n", ret);
|
||||
mvdbg("Allocated %p, size %d\n", ret, size);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ FAR void *memalign(size_t alignment, size_t size)
|
|||
* The do not include SIZEOF_MM_ALLOCNODE.
|
||||
*/
|
||||
|
||||
size = MM_ALIGN_UP(size); /* Make mutliples of our granule size */
|
||||
size = MM_ALIGN_UP(size); /* Make multiples of our granule size */
|
||||
allocsize = size + 2*alignment; /* Add double full alignment size */
|
||||
|
||||
/* Then malloc that size */
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
#define FAR
|
||||
#define CONFIG_MM_REGIONS 2
|
||||
#undef CONFIG_MM_SMALL
|
||||
#define CONFIG_CAN_PASS_STRUCTS 1
|
||||
#undef CONFIG_SMALL_MEMORY
|
||||
|
||||
|
|
|
@ -44,11 +44,11 @@ MISC_SRCS = os_start.c os_bringup.c errno_getptr.c errno_get.c errno_set.c \
|
|||
sched_setuppthreadfiles.c sched_releasefiles.c
|
||||
|
||||
TSK_SRCS = task_create.c task_init.c task_setup.c task_activate.c \
|
||||
task_start.c task_delete.c task_deletecurrent.c task_restart.c \
|
||||
exit.c atexit.c getpid.c sched_addreadytorun.c sched_removereadytorun.c \
|
||||
sched_addprioritized.c sched_mergepending.c sched_addblocked.c \
|
||||
sched_removeblocked.c sched_free.c sched_gettcb.c sched_verifytcb.c \
|
||||
sched_releasetcb.c
|
||||
task_start.c task_delete.c task_deletecurrent.c task_exithook.c \
|
||||
task_restart.c exit.c atexit.c getpid.c sched_addreadytorun.c \
|
||||
sched_removereadytorun.c sched_addprioritized.c sched_mergepending.c \
|
||||
sched_addblocked.c sched_removeblocked.c sched_free.c sched_gettcb.c \
|
||||
sched_verifytcb.c sched_releasetcb.c
|
||||
|
||||
SCHED_SRCS = sched_setparam.c sched_setpriority.c sched_getparam.c \
|
||||
sched_setscheduler.c sched_getscheduler.c \
|
||||
|
|
59
sched/exit.c
59
sched/exit.c
|
@ -67,7 +67,7 @@
|
|||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functionss
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -78,68 +78,29 @@
|
|||
* Function: exit
|
||||
*
|
||||
* Description:
|
||||
* The exit() function causes normal process termination
|
||||
* and the value of status & 0377 is returned to the parent.
|
||||
* The exit() function causes normal process termination and the value of
|
||||
* status & 0377 to be returned to the parent.
|
||||
*
|
||||
* All functions registered with atexit() and on_exit() are
|
||||
* called, in the reverse order of their registration.
|
||||
* All functions registered with atexit() and on_exit() are called, in the
|
||||
* reverse order of their registration.
|
||||
*
|
||||
* All open streams are flushed and closed. Files created
|
||||
* by tmpfile() are removed.
|
||||
* All open streams are flushed and closed.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void exit(int status)
|
||||
{
|
||||
#if CONFIG_NFILE_STREAMS > 0 || defined(CONFIG_SCHED_WAITPID) || defined(CONFIG_SCHED_ATEXIT)
|
||||
_TCB *tcb = (_TCB*)g_readytorun.head;
|
||||
#endif
|
||||
|
||||
/* Only the lower 8 bits of the exit status are used */
|
||||
/* Only the lower 8-bits of status are used */
|
||||
|
||||
status &= 0xff;
|
||||
|
||||
/* Flush all streams (File descriptors will be closed when
|
||||
* the TCB is deallocated.
|
||||
*/
|
||||
/* Perform common task termination logic */
|
||||
|
||||
#if CONFIG_NFILE_STREAMS > 0
|
||||
(void)lib_flushall(tcb->streams);
|
||||
#endif
|
||||
task_exithook(tcb, status);
|
||||
|
||||
/* Wakeup any tasks waiting for this task to exit */
|
||||
|
||||
#ifdef CONFIG_SCHED_WAITPID /* Experimental */
|
||||
while (tcb->exitsem.semcount < 0)
|
||||
{
|
||||
/* "If more than one thread is suspended in waitpid() awaiting
|
||||
* termination of the same process, exactly one thread will return
|
||||
* the process status at the time of the target process termination."
|
||||
* Hmmm.. what do we return to the others?
|
||||
*/
|
||||
|
||||
if (tcb->stat_loc)
|
||||
{
|
||||
*tcb->stat_loc = status << 8;
|
||||
tcb->stat_loc = NULL;
|
||||
}
|
||||
|
||||
/* Wake up the thread */
|
||||
|
||||
sem_post(&tcb->exitsem);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If an exit function was registered, call it now. */
|
||||
|
||||
#ifdef CONFIG_SCHED_ATEXIT
|
||||
if (tcb->exitfunc)
|
||||
{
|
||||
(*tcb->exitfunc)();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Then "really" exit */
|
||||
/* Then "really" exit. Only the lower 8 bits of the exit status are used. */
|
||||
|
||||
_exit(status);
|
||||
}
|
||||
|
|
|
@ -265,6 +265,7 @@ extern void task_start(void);
|
|||
extern int task_schedsetup(FAR _TCB *tcb, int priority, start_t start,
|
||||
main_t main);
|
||||
extern int task_argsetup(FAR _TCB *tcb, const char *name, const char *argv[]);
|
||||
extern void task_exithook(FAR _TCB *tcb, int status);
|
||||
extern int task_deletecurrent(void);
|
||||
#ifndef CONFIG_CUSTOM_STACK
|
||||
extern int kernel_thread(const char *name, int priority,
|
||||
|
|
|
@ -140,14 +140,9 @@ int task_delete(pid_t pid)
|
|||
PANIC(OSERR_BADDELETESTATE);
|
||||
}
|
||||
|
||||
saved_state = irqsave();
|
||||
|
||||
/* Inform the instrumentation layer that the task has stopped */
|
||||
|
||||
sched_note_stop(dtcb);
|
||||
|
||||
/* Remove the task from the OS's tasks lists. */
|
||||
|
||||
saved_state = irqsave();
|
||||
dq_rem((FAR dq_entry_t*)dtcb, (dq_queue_t*)g_tasklisttable[dtcb->task_state].list);
|
||||
dtcb->task_state = TSTATE_TASK_INVALID;
|
||||
irqrestore(saved_state);
|
||||
|
@ -156,11 +151,12 @@ int task_delete(pid_t pid)
|
|||
|
||||
sched_unlock();
|
||||
|
||||
/* Deallocate anything left in the TCB's queues */
|
||||
/* Perform common task termination logic (flushing streams, calling
|
||||
* functions registered by at_exit/on_exit, etc.). I suppose EXIT_SUCCESS
|
||||
* is an appropriate return value???
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_DISABLE_SIGNALS
|
||||
sig_cleanup(dtcb); /* Deallocate Signal lists */
|
||||
#endif
|
||||
task_exithook(dtcb, EXIT_SUCCESS);
|
||||
|
||||
/* Deallocate its TCB */
|
||||
|
||||
|
|
157
sched/task_exithook.c
Normal file
157
sched/task_exithook.c
Normal file
|
@ -0,0 +1,157 @@
|
|||
/****************************************************************************
|
||||
* sched/task_exithook.c
|
||||
*
|
||||
* Copyright (C) 2011 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 <nuttx/config.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <debug.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/fs.h>
|
||||
|
||||
#include "os_internal.h"
|
||||
#include "sig_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Type Declarations
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Global Variables
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Variables
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Function: task_hook
|
||||
*
|
||||
* Description:
|
||||
* This function implements some of the internal logic of exit() and
|
||||
* task_delete(). This function performs some cleanup and other actions
|
||||
* required when a task exists:
|
||||
*
|
||||
* - All open streams are flushed and closed.
|
||||
* - All functions registered with atexit() and on_exit() are called, in
|
||||
* the reverse order of their registration.
|
||||
*
|
||||
* When called from exit(), the tcb still resides at the head of the ready-
|
||||
* to-run list. The following logic is safe because we will not be
|
||||
* returning from the exit() call.
|
||||
*
|
||||
* When called from task_delete() we are operating on a different thread;
|
||||
* on the thread that called task_delete(). In this case, task_delete
|
||||
* will have already removed the tcb from the ready-to-run list to prevent
|
||||
* any further action on this task.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void task_exithook(FAR _TCB *tcb, int status)
|
||||
{
|
||||
/* Inform the instrumentation layer that the task has stopped */
|
||||
|
||||
sched_note_stop(tcb);
|
||||
|
||||
/* Flush all streams (File descriptors will be closed when
|
||||
* the TCB is deallocated).
|
||||
*/
|
||||
|
||||
#if CONFIG_NFILE_STREAMS > 0
|
||||
(void)lib_flushall(tcb->streams);
|
||||
#endif
|
||||
|
||||
/* Deallocate anything left in the TCB's queues */
|
||||
|
||||
#ifndef CONFIG_DISABLE_SIGNALS
|
||||
sig_cleanup(tcb); /* Deallocate Signal lists */
|
||||
#endif
|
||||
|
||||
/* Wakeup any tasks waiting for this task to exit */
|
||||
|
||||
#ifdef CONFIG_SCHED_WAITPID /* Experimental */
|
||||
while (tcb->exitsem.semcount < 0)
|
||||
{
|
||||
/* "If more than one thread is suspended in waitpid() awaiting
|
||||
* termination of the same process, exactly one thread will return
|
||||
* the process status at the time of the target process termination."
|
||||
* Hmmm.. what do we return to the others?
|
||||
*/
|
||||
|
||||
if (tcb->stat_loc)
|
||||
{
|
||||
*tcb->stat_loc = status << 8;
|
||||
tcb->stat_loc = NULL;
|
||||
}
|
||||
|
||||
/* Wake up the thread */
|
||||
|
||||
sem_post(&tcb->exitsem);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If an exit function was registered, call it now. NOTE: In the case
|
||||
* of task_delete(), the exit function will *not* be called on the thread
|
||||
* execution of the task being deleted!
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SCHED_ATEXIT
|
||||
if (tcb->exitfunc)
|
||||
{
|
||||
(*tcb->exitfunc)();
|
||||
}
|
||||
#endif
|
||||
}
|
Loading…
Reference in a new issue