aboutsummaryrefslogtreecommitdiff
path: root/nuttx
diff options
context:
space:
mode:
authorLorenz Meier <lm@inf.ethz.ch>2013-02-17 09:14:12 -0800
committerLorenz Meier <lm@inf.ethz.ch>2013-02-17 09:14:12 -0800
commit520a2b417410bed7db6f08a3a69f3bcccc55910b (patch)
tree2365774545ed145c307630b63cb5f075fca71c21 /nuttx
parent2745c3276f5c2377a9713555c5941b17912b6ce7 (diff)
parentcaa11f0bbb7f30679c5c01a64e1d0f6d8627db9d (diff)
downloadpx4-firmware-520a2b417410bed7db6f08a3a69f3bcccc55910b.tar.gz
px4-firmware-520a2b417410bed7db6f08a3a69f3bcccc55910b.tar.bz2
px4-firmware-520a2b417410bed7db6f08a3a69f3bcccc55910b.zip
Merge pull request #198 from PX4/nuttx-merge-5596
Nuttx merge 5596
Diffstat (limited to 'nuttx')
-rw-r--r--nuttx/ChangeLog101
-rw-r--r--nuttx/Kconfig55
-rw-r--r--nuttx/README.txt55
-rw-r--r--nuttx/ReleaseNotes320
-rw-r--r--nuttx/TODO86
-rw-r--r--nuttx/arch/arm/src/armv7-m/Toolchain.defs42
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_assert.c7
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_reprioritizertr.c13
-rw-r--r--nuttx/arch/arm/src/common/up_exit.c46
-rw-r--r--nuttx/arch/arm/src/common/up_initialize.c14
-rw-r--r--nuttx/arch/arm/src/common/up_internal.h17
-rw-r--r--nuttx/arch/arm/src/stm32/chip/stm32_spi.h8
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_adc.c315
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_adc.h6
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_i2c.c91
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_otgfsdev.c129
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_serial.c12
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_spi.c51
-rw-r--r--nuttx/arch/arm/src/stm32/stm32_usbdev.c14
-rw-r--r--nuttx/binfmt/Kconfig5
-rw-r--r--nuttx/binfmt/binfmt_execmodule.c61
-rw-r--r--nuttx/binfmt/binfmt_internal.h2
-rw-r--r--nuttx/binfmt/libelf/libelf_read.c2
-rw-r--r--nuttx/binfmt/libnxflat/libnxflat_read.c2
-rw-r--r--nuttx/configs/README.txt2
-rwxr-xr-xnuttx/configs/px4fmu/nsh/defconfig1
-rwxr-xr-xnuttx/configs/px4io/io/defconfig1
-rw-r--r--nuttx/drivers/Kconfig8
-rw-r--r--nuttx/drivers/lcd/mio283qt2.c6
-rw-r--r--nuttx/drivers/lcd/ssd1289.c6
-rw-r--r--nuttx/drivers/loop.c2
-rw-r--r--nuttx/drivers/mmcsd/mmcsd_debug.c4
-rw-r--r--nuttx/drivers/mmcsd/mmcsd_spi.c10
-rw-r--r--nuttx/drivers/mtd/at25.c16
-rw-r--r--nuttx/drivers/net/enc28j60.c96
-rw-r--r--nuttx/drivers/serial/Kconfig3
-rw-r--r--nuttx/drivers/serial/serial.c221
-rw-r--r--nuttx/drivers/syslog/ramlog.c6
-rw-r--r--nuttx/drivers/usbdev/Kconfig44
-rw-r--r--nuttx/drivers/usbdev/cdcacm.c137
-rw-r--r--nuttx/drivers/usbdev/pl2303.c129
-rw-r--r--nuttx/drivers/usbdev/usbdev_trace.c4
-rw-r--r--nuttx/drivers/usbdev/usbmsc.h8
-rw-r--r--nuttx/fs/Kconfig42
-rw-r--r--nuttx/fs/fat/fs_configfat.c14
-rw-r--r--nuttx/fs/fat/fs_fat32.c3
-rw-r--r--nuttx/fs/fat/fs_fat32util.c4
-rw-r--r--nuttx/fs/fs_fdopen.c13
-rw-r--r--nuttx/fs/fs_files.c101
-rw-r--r--nuttx/fs/fs_syslog.c59
-rw-r--r--nuttx/fs/nxffs/nxffs_dump.c2
-rw-r--r--nuttx/graphics/nxfonts/nxfonts_getfont.c2
-rw-r--r--nuttx/include/assert.h21
-rw-r--r--nuttx/include/debug.h37
-rw-r--r--nuttx/include/nuttx/fs/fs.h90
-rw-r--r--nuttx/include/nuttx/lib.h9
-rw-r--r--nuttx/include/nuttx/net/net.h87
-rw-r--r--nuttx/include/nuttx/sched.h199
-rw-r--r--nuttx/include/nuttx/serial/serial.h76
-rw-r--r--nuttx/include/nuttx/syslog.h6
-rw-r--r--nuttx/include/nuttx/usb/cdcacm.h12
-rw-r--r--nuttx/include/nuttx/usb/usbdev_trace.h5
-rw-r--r--nuttx/include/syslog.h (renamed from nuttx/sched/env_dupenv.c)88
-rw-r--r--nuttx/libc/lib.csv6
-rw-r--r--nuttx/libc/misc/lib_dbg.c36
-rw-r--r--nuttx/libc/misc/lib_dumpbuffer.c8
-rw-r--r--nuttx/libc/misc/lib_init.c134
-rw-r--r--nuttx/libc/stdio/Make.defs2
-rw-r--r--nuttx/libc/stdio/lib_fgets.c2
-rw-r--r--nuttx/libc/stdio/lib_libflushall.c2
-rw-r--r--nuttx/libc/stdio/lib_libfread.c4
-rw-r--r--nuttx/libc/stdio/lib_lowsyslog.c (renamed from nuttx/libc/stdio/lib_lowprintf.c)18
-rw-r--r--nuttx/libc/stdio/lib_printf.c4
-rw-r--r--nuttx/libc/stdio/lib_syslog.c (renamed from nuttx/libc/stdio/lib_rawprintf.c)23
-rw-r--r--nuttx/libc/stdio/lib_syslogstream.c15
-rw-r--r--nuttx/net/net_poll.c160
-rw-r--r--nuttx/net/net_sockets.c100
-rw-r--r--nuttx/net/send.c2
-rw-r--r--nuttx/sched/Kconfig27
-rw-r--r--nuttx/sched/Makefile34
-rw-r--r--nuttx/sched/env_clearenv.c8
-rw-r--r--nuttx/sched/env_dup.c68
-rw-r--r--nuttx/sched/env_findvar.c33
-rw-r--r--nuttx/sched/env_getenv.c14
-rw-r--r--nuttx/sched/env_internal.h36
-rw-r--r--nuttx/sched/env_release.c67
-rw-r--r--nuttx/sched/env_removevar.c56
-rw-r--r--nuttx/sched/env_setenv.c59
-rw-r--r--nuttx/sched/env_unsetenv.c62
-rw-r--r--nuttx/sched/group_childstatus.c (renamed from nuttx/sched/task_childstatus.c)129
-rw-r--r--nuttx/sched/group_create.c276
-rw-r--r--nuttx/sched/group_find.c (renamed from nuttx/sched/env_share.c)116
-rw-r--r--nuttx/sched/group_internal.h (renamed from nuttx/sched/sched_setuppthreadfiles.c)124
-rw-r--r--nuttx/sched/group_join.c227
-rw-r--r--nuttx/sched/group_leave.c366
-rw-r--r--nuttx/sched/group_setupidlefiles.c (renamed from nuttx/sched/sched_setupidlefiles.c)34
-rw-r--r--nuttx/sched/group_setupstreams.c (renamed from nuttx/sched/sched_setupstreams.c)45
-rw-r--r--nuttx/sched/group_setuptaskfiles.c (renamed from nuttx/sched/sched_setuptaskfiles.c)105
-rw-r--r--nuttx/sched/group_signal.c163
-rw-r--r--nuttx/sched/mq_sndinternal.c2
-rw-r--r--nuttx/sched/os_internal.h35
-rw-r--r--nuttx/sched/os_start.c23
-rw-r--r--nuttx/sched/pthread_create.c74
-rw-r--r--nuttx/sched/pthread_join.c2
-rw-r--r--nuttx/sched/sched_getfiles.c7
-rw-r--r--nuttx/sched/sched_getsockets.c7
-rw-r--r--nuttx/sched/sched_getstreams.c7
-rw-r--r--nuttx/sched/sched_releasetcb.c17
-rw-r--r--nuttx/sched/sched_waitid.c149
-rw-r--r--nuttx/sched/sched_waitpid.c167
-rw-r--r--nuttx/sched/sig_action.c27
-rw-r--r--nuttx/sched/task_create.c41
-rw-r--r--nuttx/sched/task_exithook.c318
-rw-r--r--nuttx/sched/task_init.c66
-rw-r--r--nuttx/sched/task_posixspawn.c1
-rw-r--r--nuttx/sched/task_reparent.c177
-rw-r--r--nuttx/sched/task_setup.c58
-rw-r--r--nuttx/sched/task_start.c9
-rw-r--r--nuttx/sched/task_starthook.c (renamed from nuttx/sched/sched_releasefiles.c)92
-rw-r--r--nuttx/sched/task_vfork.c9
-rw-r--r--nuttx/sched/timer_initialize.c2
-rw-r--r--nuttx/tools/mkconfig.c22
122 files changed, 4636 insertions, 2269 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index 99f6d4a52..5bdd1aad8 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -3800,7 +3800,7 @@
* configs/stm32f4discovery/elf: Enable support/test of the PATH
to find executables using a relative path.
-6.25 2013-xx-xx Gregory Nutt <gnutt@nuttx.org>
+6.25 2013-02-01 Gregory Nutt <gnutt@nuttx.org>
* graphics/: Adds 5x8 monospace font. This tiny font is useful for graph
labels and for small bitmapped display. Contributed by Petteri
@@ -3833,7 +3833,7 @@
* drivers/usbhost/usbhost_hidkbd.c: Correct a logic error in how
tasks waiting for read data are awakened.
* libc/misc/lib_kbdencode.c and lib_kbddecode.c: Now handles keypress
- events too. However, the USB HID keyboard drier has not yet been
+ events too. However, the USB HID keyboard driver has not yet been
updated to detect key release events. That is kind of tricky in
the USB HID keyboard report data.
* configs/mcu123-214x/nsh: Converted to use the kconfig-frontends
@@ -3857,7 +3857,7 @@
buildroot toolchains: They may be EABI or OABI.
* include/nuttx/progmem and arch/arm/src/stm32/stm32_flash.c:
Fix a counting bug plus change interface to use either relative
- or absolut FLASH addressing (from Freddie Chopin).
+ or absolute FLASH addressing (from Freddie Chopin).
* libc/misc/Make.defs: Fix error in conditional for KBD CODEC.
* libc/Kconfig and configs/*/defconfig (several): The default
setting should be CONFIG_LIB_KBDCODEC=n
@@ -3868,7 +3868,7 @@
* tools/configure.bat: configure.bat is a small Windows batch
file that can be used as a replacement for configure.sh in a
Windows native environment. configure.bat is actually just a
- thin layer that execuates configure.exe if it is available. If
+ thin layer that executes configure.exe if it is available. If
configure.exe is not available, then configure.bat will attempt
to build it first.
* arch/arm/src/lpc17xx/lpc17_syscon.h: Correct some typos in bit
@@ -3918,12 +3918,12 @@
the scenario: (1) sched_lock() is called increments the lockcount
on the current TCB (i.e., the one at the head of the ready to run
list), (2) sched_mergepending is called which may change the task
- at the head of the readytorun list, then (2) sched_unlock() is called
+ at the head of the ready-to-run list, then (3) sched_unlock() is called
which decrements the lockcount on the wrong TCB. The failure case
that I saw was that pre-emption got disabled in the IDLE thread,
locking up the whole system.
* sched/sched_waitpid.c: Use SIGCHLD instead of a semaphore. This
- is a much more spec-compliant implemenation. However, there are
+ is a much more spec-compliant implementation. However, there are
some issues with overruning signals because NuttX does not support
queueing of signals (POSIX does not require it). I think it may
need to.
@@ -3959,7 +3959,7 @@
CONFIG_APPS_BINDIR rename CONFIG_FS_BINFS
* include/nuttx/binfmt/builtin.h: Some of the content of
apps/include/apps.h moved to include/nuttx/binfmt/builtin.h
- * binfmt/libbuiltin/libbuiltin_utils.c: Move utility builtin
+ * binfmt/libbuiltin/libbuiltin_utils.c: Move builtin
utility functions from apps/builtin/exec_builtins.c to
binfmt/libbuiltin/libbuiltin_utils.c
* binfmt/builtin.c and binfmt/libbuiltin: Add a binary "loader"
@@ -3985,7 +3985,7 @@
* arch/arm/src/[many]: More LPC1788 definitions from Rommel
Marcelo incorporated.
* configs/open1788: Board configuration for the Wave Share
- Open1788 board. Still fragmentary (contribnuted by Rommel
+ Open1788 board. Still fragmentary (contributed by Rommel
Marcelo, adapted to use kconfig-frontends.
* net/send(): Add logic to work around delayed ACKs by splitting
packets (contributed by Yan T.).
@@ -4011,11 +4011,92 @@
* arch/armv7-m/up_hardfault.c: Fail if a hardfault occurs
while CONFIG_ARM7VM_USEBASEPRI=y.
* arch/arm/src/stm32/stm32_serial.c: Add support for USART
- single wire more (Contributed by the PX4 team).
+ single wire mode (Contributed by the PX4 team).
* sched/: Implement support for retaining child task status after
the child task exists. This is behavior required by POSIX.
But in NuttX is only enabled with CONFIG_SCHED_HAVE_PARENT and
CONFIG_SCHED_CHILD_STATUS
* Add support for keyboard encode to the keypad test (from
Denis Carikli).
-
+ * configs/olimex-lpc1766stk/nettest: Configuration converted to
+ use the kconfig-frontends tools.
+ * net/net_poll.c: Split net_poll() to create psock_poll() too.
+ * net/net_poll.c: Fix poll/select issure reported by Qiang:
+ poll_interrupt() must call net_lostconnection() when a
+ loss of connection is reported. Otherwise, the system will
+ not know that the connection has been lost.
+ * sched/group_create.c, group_join.c, and group_leave.c: Add
+ support for task groups.
+ * sched/group_signal.c and task_exithook.c: Send signal to all
+ members for the parent task group.
+ * include/nuttx/sched.h and sched/env_*.c: Move environment
+ variables into task group structure.
+ * sched/: Lots of file changed. Don't keep the parent task's
+ task ID in the child task's TCB. Instead, keep the parent
+ task group IN the child task's task group.
+ * fs/, sched/, include/nuttx/sched.h, and include/nutts/fs/fs.h:
+ Move file data from the TCB to the task group structure.
+ * libc/stdio/, sched/, include/nuttx/lib.h, and include/nutts/fs/fs.h:
+ Move stream data from the TCB to the task group structure.
+ * net/, sched/, and include/nuttx/net/net.h: Move socket data
+ from the TCB to the task group structure.
+ * sched/task_starthook.c, sched/task_start.c, and include/nuttx/sched.h:
+ Add a task start hook that will be called before the task main
+ is started. This can be used to schedule C++ constructors to run
+ automatically in the context of the new task.
+ * binfmt/binfmt_execmodule: Execute constructors as a start hook.
+ * sched/os_start.c: Fix ordering of group initialization.
+ * configs/stm32f4discovery/usbnsh: Add an NSH STM32F4Discovery
+ configuration that uses USB CDC/ACM for the NSH console.
+ * configs/stm32f4discovery/nsh: Converted to use the kconfig-frontends
+ tools.
+ * configs/*/src/up_userleds.c: Fix a error that was cloned into
+ all STM32 user LED code. The wrong definitions were being used
+ to set LEDs on or off.
+ * arch/*/common/up_internal.h and arch/*/common/up_initialize.c:
+ Serial was driver was not being built if there is no console
+ device. Obviously, the serial driver may be needed even in
+ this case.
+ * arch/arm/src/stm32/stm32_serial.c: If there is a serial console,
+ it would be ttyS0 and the others would be ttyS1-5. If there
+ is not serial console, was labeling them ttyS1-6; now labels them
+ ttyS0-5.
+ * fs/fs_syslog.c: Can't handle SYSLOG output to character device from
+ the IDLE task (because it can't block). syslog_putc now returns EOF
+ on failure and sets errno. Fixed some errors in error handling.
+ * libc/stdio/lib_syslogstream.c: Checking of return value from
+ syslog_putc was bogus. Switching to EOF for all errors solves
+ this.
+ * arch/arm/src/lm/chip/lm4f_memorymap.h: More LM4F changes from
+ Jose Pablo Carballo.
+ * drivers/serial/serial.c, include/nuttx/serial/serial.h,
+ drivers/usbdev/cdcacm.c, and drivers/pl2303.c: Add support for
+ removable serial devices (like USB serial). This support is enabled
+ by CONFIG_SERIAL_REMOVABLE.
+ * arch/*/src/*/Toolchain.defs: Change assignment so that we can
+ override CROSSDEV with a make command line argument.
+ * include/assert.h: Mark assertion functions as non-returning.
+ * arch/*/src/*/up_assert.h: Mark _up_assert() as non-returning.
+ * drivers/mtd/at25.c: When the AT25 device was not available the
+ initialization did not fail like it should. From Petteri Aimonen.
+ * fs/fat/fs_configfat.c: Fix some errors in FAT formatting logic
+ for large devices and for FAT32. From Petteri Aimonen.
+ * fs/fat/fs_fat32util.c: Fix an initialization error found by
+ Petteri Aimonen. freecount and next freecount initialization were
+ reversed.
+ * drivers/mmcsd/mmcsd_spi.c: Some SD cards will appear busy until
+ switched to SPI mode for first time. Having a pull-up resistor on
+ MISO may avoid this problem, but this patch makes it work also
+ without pull-up. From Petteri Aimonen.
+ * fs/fat/fs_fat32.c: Fix a compilation error when FAT_DMAMEMORY=y.
+ From Petteri Aimonen.
+ * arch/arm/src/stm32/chip/stm32_spi.h: STM32F4 max SPI clock freq is
+ 37.5 MHz. Patch from Petteri Aimonen.
+ * arch/arm/src/stm32/stm32_spi.c: Fixes for SPI DMA work on the
+ STM32F4. Includes untested additions for the F1 implementation as
+ well. From Petteri Aimonen.
+
+6.26 2013-xx-xx Gregory Nutt <gnutt@nuttx.org>
+
+ * drivers/serial/serial.c: Correct some race conditions when checking
+ for disconnection of a removable serial device.
diff --git a/nuttx/Kconfig b/nuttx/Kconfig
index 10d624efb..af743b9db 100644
--- a/nuttx/Kconfig
+++ b/nuttx/Kconfig
@@ -297,26 +297,21 @@ config DEBUG
---help---
Enables built-in debug features. Selecting this option will (1) Enable
debug assertions in the code, (2) enable extended parameter testing in
- many functions, and (3) enable support for debug output. Note that enabling
- this option by itself does not produce debug output. Debug output must
- also be selected on a subsystem-by-subsystem basis.
+ many functions, and (3) enable support for debug output to the SYSLOG.
+ Note that enabling this option by itself does not produce debug output.
+ Debug output must also be selected on a subsystem-by-subsystem basis.
if DEBUG
config DEBUG_VERBOSE
bool "Enable Debug Verbose Output"
default n
---help---
- Enables verbose debug output (assuming debug output is enabled). As a
- general rule, when DEBUG is enabled only errors will be reported in the debug
- output. But if you also enable DEBUG_VERBOSE, then very chatty (and
- often annoying) output will be generated. This means there are two levels
- of debug output: errors-only and everything.
-
-config DEBUG_ENABLE
- bool "Enable Debug Controls"
- default n
- ---help---
- Support an interface to dynamically enable or disable debug output.
+ Enables verbose debug output (assuming debug featurses are enabled).
+ As a general rule, when DEBUG is enabled only errors will be
+ reported in the debug SYSLOG output. But if you also enable
+ DEBUG_VERBOSE, then very chatty (and often annoying) output will be
+ generated. This means there are two levels of debug output:
+ errors-only and everything.
comment "Subsystem Debug Options"
@@ -324,58 +319,58 @@ config DEBUG_MM
bool "Enable Memory Manager Debug Output"
default n
---help---
- Enable memory management debug output (disabled by default)
+ Enable memory management debug SYSLOG output (disabled by default)
config DEBUG_SCHED
bool "Enable Scheduler Debug Output"
default n
---help---
- Enable OS debug output (disabled by default)
+ Enable OS debug SYSLOG output (disabled by default)
config DEBUG_PAGING
bool "Enable Demand Paging Debug Output"
default n
depends on PAGING
---help---
- Enable demand paging debug output (disabled by default)
+ Enable demand paging debug SYSLOG output (disabled by default)
config DEBUG_NET
bool "Enable Network Debug Output"
default n
depends on NET
---help---
- Enable network debug output (disabled by default)
+ Enable network debug SYSLOG output (disabled by default)
config DEBUG_USB
bool "Enable USB Debug Output"
default n
depends on USBDEV || USBHOST
---help---
- Enable usb debug output (disabled by default)
+ Enable usb debug SYSLOG output (disabled by default)
config DEBUG_FS
bool "Enable File System Debug Output"
default n
---help---
- Enable file system debug output (disabled by default)
+ Enable file system debug SYSLOG output (disabled by default)
config DEBUG_LIB
bool "Enable C Library Debug Output"
default n
---help---
- Enable C library debug output (disabled by default)
+ Enable C library debug SYSLOG output (disabled by default)
config DEBUG_BINFMT
bool "Enable Binary Loader Debug Output"
default n
---help---
- Enable binary loader debug output (disabled by default)
+ Enable binary loader debug SYSLOG output (disabled by default)
config DEBUG_GRAPHICS
bool "Enable Graphics Debug Output"
default n
---help---
- Enable NX graphics debug output (disabled by default)
+ Enable NX graphics debug SYSLOG output (disabled by default)
comment "Driver Debug Options"
@@ -384,21 +379,21 @@ config DEBUG_LCD
default n
depends on LCD
---help---
- Enable low level debug output from the LCD driver (disabled by default)
+ Enable low level debug SYSLOG output from the LCD driver (disabled by default)
config DEBUG_INPUT
bool "Enable Input Device Debug Output"
default n
depends on INPUT
---help---
- Enable low level debug output from the input device drivers such as
+ Enable low level debug SYSLOG output from the input device drivers such as
mice and touchscreens (disabled by default)
config DEBUG_ANALOG
bool "Enable Analog Device Debug Output"
default n
---help---
- Enable low level debug output from the analog device drivers such as
+ Enable low level debug SYSLOG output from the analog device drivers such as
A/D and D/A converters (disabled by default)
config DEBUG_I2C
@@ -406,27 +401,27 @@ config DEBUG_I2C
default n
depends on I2C
---help---
- Enable I2C driver debug output (disabled by default)
+ Enable I2C driver debug SYSLOG output (disabled by default)
config DEBUG_SPI
bool "Enable SPI Debug Output"
default n
depends on SPI
---help---
- Enable I2C driver debug output (disabled by default)
+ Enable I2C driver debug SYSLOG output (disabled by default)
config DEBUG_DMA
bool "Enable DMA Debug Output"
default n
---help---
- Enable DMA-releated debug output (disabled by default)
+ Enable DMA-releated debug SYSLOG output (disabled by default)
config DEBUG_WATCHDOG
bool "Enable Watchdog Timer Debug Output"
default n
depends on WATCHDOG
---help---
- Enable watchdog timer debug output (disabled by default)
+ Enable watchdog timer debug SYSLOG output (disabled by default)
endif
diff --git a/nuttx/README.txt b/nuttx/README.txt
index 2ff473fa0..da1ed10c6 100644
--- a/nuttx/README.txt
+++ b/nuttx/README.txt
@@ -280,8 +280,14 @@ NuttX Configuration Tool
make menuconfig
- This make target will bring up NuttX configuration menus. The
- 'menuconfig' target depends on two things:
+ This make target will bring up NuttX configuration menus.
+
+ WARNING: Never do 'make menuconfig' on a configuration that has
+ not been converted to use the kconfig-frontends tools! This will
+ damage your configuration (see
+ http://www.nuttx.org/doku.php?id=wiki:howtos:convertconfig).
+
+ The 'menuconfig' make target depends on two things:
1. The Kconfig configuration data files that appear in almost all
NuttX directories. These data files are the part that is still
@@ -319,6 +325,22 @@ NuttX Configuration Tool
This is pretty straight forward for creating new configurations
but may be less intuitive for modifying existing configurations.
+Refreshing Configurations with 'make oldconfig'
+-----------------------------------------------
+
+ Whenever you use a configuration, you really should always do
+ the following *before* you make NuttX:
+
+ make oldconfig
+
+ This will make sure that the configuration is up-to-date in
+ the event that it has lapsed behind the current NuttX development.
+
+ WARNING: Never do 'make oldconfig' (OR 'make menuconfig') on a
+ configuration that has not been converted to use the kconfig-frontends
+ tools! This will damage your configuration (see
+ http://www.nuttx.org/doku.php?id=wiki:howtos:convertconfig).
+
Incompatibilities with Older Configurations
-------------------------------------------
@@ -501,8 +523,21 @@ NuttX Buildroot Toolchain
Disadvantages: This tool chain is not was well supported as some other
toolchains. GNU tools are not my priority and so the buildroot tools
- often get behind. For example, the is still no EABI support in the
- NuttX buildroot toolchain for ARM.
+ often get behind. For example, until recently there was no EABI support
+ in the NuttX buildroot toolchain for ARM.
+
+ NOTE: For Cortex-M3/4, there are OABI and EABI versions of the buildroot
+ toolchains. If you are using the older OABI toolchain the prefix for
+ the tools will be arm-nuttx-elf-; for the EABI toolchin the prefix will
+ be arm-nuttx-eabi-. If you are using the older OABI toolchain with
+ an ARM Cortex-M3/4, you will need to set CONFIG_ARMV7M_OABI_TOOLCHAIN
+ in the .config file in order to pick the right tool prefix.
+
+ If the make system ever picks the wrong prefix for your toolchain, you
+ can always specify the prefix on the command to override the default
+ like:
+
+ make CROSSDEV=arm-nuttx-elf
SHELLS
^^^^^^
@@ -1159,17 +1194,9 @@ apps
|- NxWidgets/
| `- README.txt
|- system/
- | |- i2c/README.txt
- | |- free/README.txt
- | |- install
- | | `- README.txt
- | |- poweroff
- | | `- README.txt
- | |- ramtron
- | | `- README.txt
- | |- sdcard
+ | |- i2c
| | `- README.txt
- | `- sysinfo
+ | `- install
| `- README.txt
`- README.txt
diff --git a/nuttx/ReleaseNotes b/nuttx/ReleaseNotes
index 02cb8158d..4e8768b96 100644
--- a/nuttx/ReleaseNotes
+++ b/nuttx/ReleaseNotes
@@ -3440,3 +3440,323 @@ Bugfixes (see the change log for details). Some of these are very important
* Applications: Modbus fixes from Freddie Chopin.
As well as other, less critical bugs (see the ChangeLog for details)
+
+NuttX-6.25
+^^^^^^^^^^
+
+The 92nd release of NuttX, Version 6.25, was made on February 1, 2013,
+and is available for download from the SourceForge website. Note
+that release consists of two tarballs: nuttx-6.25.tar.gz and
+apps-6.25.tar.gz. Both may be needed (see the top-level nuttx/README.txt
+file for build information).
+
+This release corresponds with SVN release number: r5595
+
+Note that all SVN information has been stripped from the tarballs. If you
+need the SVN configuration information, you should check out directly from
+SVN. Revision r5595 should equivalent to release 6.25 of NuttX:
+
+ svn checkout -r5595 svn://svn.code.sf.net/p/nuttx/code/trunk nuttx-code
+
+Or (HTTP):
+
+ svn checkout -r5595 http://svn.code.sf.net/p/nuttx/code/trunk nuttx-code
+
+Additional new features and extended functionality:
+
+ * OS Initialization
+
+ - Removed support for CONFIG_BUILTIN_APP_START. This is not really a
+ useful feature and creates a violation of the OS layered
+ architecture.
+
+ * Task Creation:
+
+ - Implement a simple vfork(). In NuttX-6.25, this interface is
+ available only for ARM7/9, ARMv7-M (Cortext-M3/4), and MIPS32
+ (PIC32MX) platforms.
+ - exec() now sets the priority of the new task to the same priority as
+ the parent task (instead of the arbirtrary value of 50).
+ - New, partially complient implementations of execv() and execl().
+ These are only partially compliant because they do not overlay any
+ existing "process space" but rather create the new task and exit().
+ - Add a complete implementation of posix_spawn(). This standard
+ interface is a better match for an MMU-less architecture than are
+ vfork() plus execv() or execl().
+ - Add a task start hook that will be called before the task main
+ is started. This can be used, for example, to schedule C++
+ static constructors to run automatically in the context of the
+ new task.
+
+ * Task Parentage
+
+ - Repartitioned tasking data structures. All shared resources are now
+ collected together in a "task group". A task group includes the
+ original task plus all of the pthreads created by the task.
+ - Added support for remember the parent "task group" when a new task is
+ started.
+ - Added optional support to record the membership of each thread in
+ the "task group".
+ - Implement support for retaining child task status in the "task group"
+ after the child task exists. This is behavior required by POSIX.
+ But in NuttX is only enabled with CONFIG_SCHED_HAVE_PARENT and
+ CONFIG_SCHED_CHILD_STATUS
+ - Add internal logic to "reparent" a task. This is useful,
+ for example, where the child task is created through a trampoline
+ task that redirects I/O. Reparenting allows the caller of posix_spawn()
+ to be reparented for the eventual child thread.
+ - Added support for SIGCHLD. Sent to all members of the parent task
+ group when the file member of the child task group exits.
+ - If SIGCHLD and retention of child task exist status are enabled, then
+ a more spec-compliant version of waitpid() is enabled.
+ - New interfaces waitid() and wait() are also enabled when SIGCHLD
+ is enabled.
+
+ * File System
+
+ - dup() and dup2() can new be used with opened files in a mounted file
+ system. This supports re-direction of output in NSH to files.
+ - The binfs file system was moved from apps/builtin to fs/binfs. The
+ binfs file system was extended to support execution of "builtin
+ applications" using exec(), execv(), execl(), or posix_spawn().
+ - Added logic based on SIGCHLD to automatically unload and clean-up
+ after running a task that was loaded into memory.
+
+ * Binary Formats
+
+ - Much of the logic for "builtin applications" was moved from
+ apps/builtin to nuttx/binfmt/libbuiltin. Includes some extensions
+ contributed by Mike Smith.
+ - A binary loader was added for builtin applications to support
+ execution of "builtin applications" using exec(), execv(),
+ execl(), or posix_spawn().
+
+ * Drivers:
+
+ - Added logic to marshal and serialized "out-of-band" keyboard
+ commands (such as cursor controls and key release events) intermixed
+ with normal ASCII keypress data. The encoding is partially integrated
+ in the HID keyboard driver and the decoding full integrated into the
+ apps/examples hidkbd and keypadtest (the latter contributed by Denis
+ Carlikli).
+ - Driver for the UG-2864HSWEG01 OLED contributed by Darcy Gong.
+ - Add support for removable serial devices (like USB serial). This
+ support is enabled by CONFIG_SERIAL_REMOVABLE.
+
+ * ARMv7-M:
+
+ - Added an option to use the BASEPRI register to disable interrupts
+ (instead of the PRIMASK). This eliminates some innocuous hardfaults
+ that interfere with some debug tools. You need to switch to the
+ BASEPRI method only if you have such tool interference.
+
+ * STM32 Drivers
+
+ - Bring STM32 F1 DMA capabilities up to par with the STM32 F2/F4
+ (contributed by Mike Smith).
+ - Add support for USART single wire mode (Contributed by the PX4
+ team).
+ - Updates to support for SPI DMA on the STM32 F1/F2/F4. From
+ Petteri Aimonen.
+
+ * STM32 Boards:
+
+ - New configuration to support the UG-2864HSWEG01 OLED on the
+ STM32F4Discovery board.
+ - Added a posix_spawn() test configuration for the STM32F4Discovery.
+
+ * LM3S/LM4F
+
+ - Files and directories repartitioned to support both LM3S and LM4F
+ using the STM32 organization as a model.
+ - Partial definitions for the LM4F contributed by Jose Pablo Carballo
+ (this is still a work in progress).
+
+ * LM3S Boards
+
+ - Added scripts and documentation to use OpenOCD with the LM3S (from
+ Jose Pablo Carballo).
+
+ * LPC176x/LPC178x
+
+ - Files and directories repartitioned to support both LPC175x/LPC176x
+ and the LPC177x/LPC178x families using the STM32 organization as a
+ model. The LPC1788 port is a work in progress by Rommel Marcelo.
+
+ * LPC176x/LPC178x Boards:
+
+ - Added a configuration to support the Wave Share Open1788 board.
+ This is still a work in progress by Rommel Marcelo.
+
+ * LPC2148 Boards:
+
+ - Add basic support for the The0.net ZP213x/4xPA board (with the LPC2148
+ and the UG_2864AMBAG01 OLED).
+ - Add an nxlines configuration for the ZP213x/4xPA (with the LPC2148
+ and the UG_2864AMBAG01).
+
+ * Simulator:
+
+ - Add an nxlines configuration for the simulator.
+
+ * Networking:
+
+ - Add logic to work around delayed ACKs by splitting packets
+ (contributed by Yan T.).
+ - Split net_poll() to create the internal interface psock_poll().
+
+ * LCDs:
+
+ - Added support for LCD1602 alphanumeric LCD (HD4468OU controller).
+
+ * Graphics:
+
+ - Added 5x8 monospace font. This tiny font is useful for graph
+ labels and for small bitmapped display. Contributed by Petteri
+ Aimonen.
+
+ * Build System:
+
+ - Add an options to better manage toolchain prefixes.
+ - Redesigned how the context targer works in the apps/ directory.
+ The old design caused lots of problems when changing configurations
+ because there is no easy way to get the system to rebuild the
+ context. This change should solve most the problems and eliminate
+ questions like "Why don't I see my builtin application in NSH?"
+
+ * Kconfig Files:
+
+ - There are several new configurations that use the kconfig-frontends
+ tools and several older configurations that have been converted to
+ use these tools. There is still a long way to go before the conversion
+ is complete:
+
+ configs/sim/nxwm
+ configs/sim/nsh
+ configs/stm3220g-eval/nxwm
+ configs/stm32f4discovery/posix_spawn
+ configs/olimex-lpc1766stk/nsh
+ configs/olimex-lpc1766stk/hidkbd
+ configs/olimex-lpc1766stk/nettest
+ configs/open1788/ostest
+ configs/stm32f4discovery/nsh
+ configs/stm32f4discovery/usbnsh
+ configs/lm326965-ek (all configurations)
+ configs/mcu123-214x/nsh
+ configs/ubw32/ostest
+
+ * Tools:
+
+ - tools/kconfig.bat: Kludge to run kconfig-frontends from a DOS shell.
+ - tools/configure.c: configure.c can be used to build a work-alike
+ program as a replacement for configure.sh. This work-alike
+ program would be used in environments that do not support Bash
+ scripting (such as the Windows native environment).
+ - tools/configure.bat: configure.bat is a small Windows batch
+ file that can be used as a replacement for configure.sh in a
+ Windows native environment. configure.bat is actually just a
+ thin layer that executes configure.exe if it is available. If
+ configure.exe is not available, then configure.bat will attempt
+ to build it first.
+
+ * Applications:
+
+ - New and modified examples:
+
+ apps/examples/wlan: Remove non-functional example.
+ apps/examples/ostest: Added a test of vfork(). Extend signal
+ handler test to catch death-of-child signals (SIGCHLD). Add a
+ test for waitpid(), waitid(), and wait().
+ apps/exampes/posix_spawn: Added a test of posix_spawn().
+
+ - NSH:
+
+ NSH now supports re-direction of I/O to files (but still not from).
+ The block driver source argument to the mount command is now
+ optional for file systems that do not require a block driver.
+ NSH can now execute a program from a file system using posix_spawn().
+ Added support for a login script. The init.d/rcS script will be
+ executed once when NSH starts; the .nshrc script will be executed
+ for each session: Once for serial, once for each USB connection,
+ once for each Telnet session.
+
+ - Supports a new daemon that can be used to monitor USB trace outpout.
+ - Removed non-functional wlan example.
+
+Bugfixes (see the ChangeLog for details). Some of these are very important:
+
+ * Tasking:
+
+ - Fixed a *critical* task exit bug. Here is the failure scenario:
+ (1) sched_lock() is called increments the lockcount on the current
+ TCB (i.e., the one at the head of the ready to run list), (2)
+ sched_mergepending is called which may change the task at the head
+ of the ready-to-run list, then (3) sched_unlock() is called which
+ decrements the lockcount on the wrong TCB. The failure case that
+ I saw was that pre-emption got disabled in the IDLE thread, locking
+ up the whole system.
+
+ * Signals:
+
+ - sigtimedwait() would return a bad signal number if the signal was
+ already pending when the function was called.
+
+ * Drivers:
+
+ - Some SD cards will appear busy until switched to SPI mode for
+ first time. Having a pull-up resistor on MISO may avoid this
+ problem, but this fix from Petteri Aimonen makes it work also
+ without pull-up.
+
+ * STM32 Drivers:
+
+ - STM32 FLASH driver counting error (from Freddie Chopin).
+ - STM32 F4 maximum SPI frequency was wrong (corrected by Petteri
+ Aimonen).
+
+ * STM32 Boards
+
+ - Due to cloning of untested code, the logic to control on-board
+ LEDs did not work on any STM32 boards.
+ - Serial devices number /dev/ttyS0-5 is there is a serial console,
+ but /dev/ttyS1-6 if there is no serial console.
+
+ * Binary Formats
+
+ - C++ static constructors execute now using a start taskhook
+ so that they execute in the context of the child task (instead
+ of in the context of the parent task).
+
+ * File Systems:
+
+ - Several FAT-related bugs fixed by Petteri Aimonen.
+
+ * Networking:
+
+ - Fix poll/select issure reported by Qiang: poll_interrupt() must call
+ net_lostconnection() when a loss of connection is reported. Otherwise,
+ the system will not remember that the connection has been lost and will
+ hang waiting on a unconnected socket later.
+ - Similar issues corrected for recvfrom() and send().
+ - Telnetd would hang in a loop if recv() ever returned a value <= 0.
+
+ * Libraries:
+
+ - fread() could hang on certain error conditions.
+ - Can't handle SYSLOG output to a character device from the IDLE task
+ (because the IDLE task can't block).
+
+ * Build System:
+
+ - Serial was driver was not being built if there is no console
+ device. Obviously, the serial driver may be needed even in
+ this case.
+
+ * Additional Bugfixes:
+
+ - sig_timedwait() and clock_time2ticks.c: Timing "rounding" logic
+ - ARM9 Compilation issue with low vectors.
+ - readline() return value
+ - Others as detailed in the ChangeLog: HID keyboard, LPC17xx bit
+ definitions, strndup(), PL2303, SYSLOG error handling, AT25,
+ apps/examples.
diff --git a/nuttx/TODO b/nuttx/TODO
index c302760ab..b5958f397 100644
--- a/nuttx/TODO
+++ b/nuttx/TODO
@@ -1,4 +1,4 @@
-NuttX TODO List (Last updated January 23, 2013)
+NuttX TODO List (Last updated January 30, 2013)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This file summarizes known NuttX bugs, limitations, inconsistencies with
@@ -7,14 +7,14 @@ standards, things that could be improved, and ideas for enhancements.
nuttx/
(11) Task/Scheduler (sched/)
- (1) Memory Managment (mm/)
+ (2) Memory Managment (mm/)
(3) Signals (sched/, arch/)
(2) pthreads (sched/)
(2) C++ Support
(6) Binary loaders (binfmt/)
- (17) Network (net/, drivers/net)
+ (16) Network (net/, drivers/net)
(4) USB (drivers/usbdev, drivers/usbhost)
- (12) Libraries (libc/, )
+ (11) Libraries (libc/, )
(9) File system/Generic drivers (fs/, drivers/)
(5) Graphics subystem (graphics/)
(1) Pascal add-on (pcode/)
@@ -161,25 +161,6 @@ o Task/Scheduler (sched/)
Status: Open
Priority: Medium Low for now
- Title: IMPROVED TASK CONTROL BLOCK STRUCTURE
- Description: All task resources that are shared amongst threads have
- their own "break-away", reference-counted structure. The
- Task Control Block (TCB) of each thread holds a reference
- to each breakaway structure (see include/nuttx/sched.h).
- It would be more efficent to have one reference counted
- structure that holds all of the shared resources.
-
- These are the current shared structures:
- - Environment varaibles (struct environ_s)
- - PIC data space and address environments (struct dspace_s)
- - File descriptors (struct filelist)
- - FILE streams (struct streamlist)
- - Sockets (struct socketlist)
- Status: Open
- Priority: Low. This is an enhancement. It would slight reduce
- memory usage but would also increase coupling. These
- resources are nicely modular now.
-
Title: ISSUES WITH atexit() AND on_exit()
Description: These functions execute with the following bad properties:
@@ -212,6 +193,16 @@ o Task/Scheduler (sched/)
Status: Open
Priority: Low (it might as well be low since it isn't going to be fixed).
+ Title: errno IS NOT SHARED AMONG THREADS
+ Description: In NuttX, the errno value is unique for each thread. But for
+ bug-for-bug compatibility, the same errno should be shared by
+ the task and each thread that it creates. It is *very* easy
+ to make this change: Just move the pterrno field from
+ _TCB to struct task_group_s. However, I am still not sure
+ if this should be done or not.
+ Status: Open
+ Priority: Low
+
o Memory Managment (mm/)
^^^^^^^^^^^^^^^^^^^^^^
@@ -278,6 +269,19 @@ 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.
+ Title: CONTAINER ALLOCATOR
+ Description: There are several places where the logic requires allocation of
+ a tiny structure that just contains pointers to other things or
+ small amounts of data that needs to be bundled together. There
+ are examples net/net_poll.c and numerous other places.
+
+ I am wondering if it would not be good create a pool of generic
+ containers (say void *[4]). There re-use these when we need
+ small containers. The code in sched/task_childstatus.c might
+ be generalized for this purpose.
+ Status: Open
+ Priority: Very low (I am not even sure that this is a good idea yet).
+
o Signals (sched/, arch/)
^^^^^^^^^^^^^^^^^^^^^^^
@@ -413,6 +417,9 @@ o Binary loaders (binfmt/)
Description: Not all of the NXFLAT test under apps/examples/nxflat are working.
Most simply do not compile yet. tests/mutex runs okay but
outputs garbage on completion.
+
+ Update: 13-27-1, tests/mutex crashed with a memory corruption
+ problem the last time that I ran it.
Status: Open
Priority: High
@@ -667,21 +674,6 @@ o Network (net/, drivers/net)
Status: Open
Priority: Low... fix defconfig files as necessary.
- Title: net_poll() DOES NOT HANDLE LOSS-OF-CONNECTION CORRECTLY
- Description: When a loss of connection is detected by any logic waiting on the
- networking events, the function net_lostconnection() must be called.
- That function just sets some bits in the socket structure so that
- it remembers that the connection is lost.
-
- That is currently done in recvfrom(), send(), and net_monitor.c. But
- it is not done in the net_poll() logic; that logic correctly sets
- the POLLHUP status, but it does not call net_lostconnection(). As a
- result, if recv() is called after the poll() or select(), the system
- will hang because the recv() does not know that the connection has
- been lost.
- Status: Open
- Priority: High
-
o USB (drivers/usbdev, drivers/usbhost)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -820,19 +812,6 @@ o Libraries (libc/)
Status: Open
Priority: ??
- Title: SYSLOG INTEGRATION
- Description: There are the beginnings of some system logging capabilities (see
- drivers/syslog, fs/fs_syslog.c, and libc/stdio/lib_librawprintf.c and
- lib_liblowprintf.c. For NuttX, SYSLOG is a concept and includes,
- extends, and replaces the legacy NuttX debug ouput. Some additional
- integration is required to formalized this. For example:
-
- o lib_rawprintf() shjould be renamed syslog().
- o debug.h should be renamed syslog.h
- o And what about lib_lowprintf()? llsyslog?
- Status: Open
- Priority: Low -- more of a roadmap
-
Title: FLOATING POINT FORMATS
Description: Only the %f floating point format is supported. Others are accepted
but treated like %f.
@@ -1526,11 +1505,6 @@ o ARM/STM32 (arch/arm/src/stm32/)
Status: Open
Priority: Low
- Title: STM32 F4 USB OTG FS DEVICE-SIDE DRIVER
- Description: This driver is reported to be buggy and to need some TLC.
- Status: Open
- Priority: High
-
o AVR (arch/avr)
^^^^^^^^^^^^^^
diff --git a/nuttx/arch/arm/src/armv7-m/Toolchain.defs b/nuttx/arch/arm/src/armv7-m/Toolchain.defs
index 45ee9e36c..4de5b49f4 100644
--- a/nuttx/arch/arm/src/armv7-m/Toolchain.defs
+++ b/nuttx/arch/arm/src/armv7-m/Toolchain.defs
@@ -1,7 +1,7 @@
############################################################################
# arch/arm/src/armv7-m/Toolchain.defs
#
-# Copyright (C) 2012 Gregory Nutt. All rights reserved.
+# Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
@@ -141,8 +141,8 @@ endif
# Atollic toolchain under Windows
ifeq ($(CONFIG_ARMV7M_TOOLCHAIN),ATOLLIC)
- CROSSDEV = arm-atollic-eabi-
- ARCROSSDEV = arm-atollic-eabi-
+ CROSSDEV ?= arm-atollic-eabi-
+ ARCROSSDEV ?= arm-atollic-eabi-
ifneq ($(CONFIG_WINDOWS_NATIVE),y)
WINTOOL = y
endif
@@ -161,12 +161,12 @@ endif
ifeq ($(CONFIG_ARMV7M_TOOLCHAIN),BUILDROOT)
ifeq ($(CONFIG_ARMV7M_OABI_TOOLCHAIN),y)
- CROSSDEV = arm-nuttx-elf-
- ARCROSSDEV = arm-nuttx-elf-
+ CROSSDEV ?= arm-nuttx-elf-
+ ARCROSSDEV ?= arm-nuttx-elf-
ARCHCPUFLAGS = -mtune=cortex-m3 -march=armv7-m -mfloat-abi=soft
else
- CROSSDEV = arm-nuttx-eabi-
- ARCROSSDEV = arm-nuttx-eabi-
+ CROSSDEV ?= arm-nuttx-eabi-
+ ARCROSSDEV ?= arm-nuttx-eabi-
ARCHCPUFLAGS = -mcpu=cortex-m3 -mthumb -mfloat-abi=soft
endif
MAXOPTIMIZATION = -Os
@@ -175,8 +175,8 @@ endif
# Code Red RedSuite under Linux
ifeq ($(CONFIG_ARMV7M_TOOLCHAIN),CODEREDL)
- CROSSDEV = arm-none-eabi-
- ARCROSSDEV = arm-none-eabi-
+ CROSSDEV ?= arm-none-eabi-
+ ARCROSSDEV ?= arm-none-eabi-
ifeq ($(CONFIG_ARCH_CORTEXM4),y)
ifeq ($(CONFIG_ARCH_FPU),y)
ARCHCPUFLAGS = -mcpu=cortex-m4 -mthumb -march=armv7e-m -mfpu=fpv4-sp-d16 -mfloat-abi=hard
@@ -191,8 +191,8 @@ endif
# Code Red RedSuite under Windows
ifeq ($(CONFIG_ARMV7M_TOOLCHAIN),CODEREDW)
- CROSSDEV = arm-none-eabi-
- ARCROSSDEV = arm-none-eabi-
+ CROSSDEV ?= arm-none-eabi-
+ ARCROSSDEV ?= arm-none-eabi-
ifneq ($(CONFIG_WINDOWS_NATIVE),y)
WINTOOL = y
endif
@@ -210,8 +210,8 @@ endif
# CodeSourcery under Linux
ifeq ($(CONFIG_ARMV7M_TOOLCHAIN),CODESOURCERYL)
- CROSSDEV = arm-none-eabi-
- ARCROSSDEV = arm-none-eabi-
+ CROSSDEV ?= arm-none-eabi-
+ ARCROSSDEV ?= arm-none-eabi-
ARCHCPUFLAGS = -mcpu=cortex-m3 -mthumb -mfloat-abi=soft
MAXOPTIMIZATION = -O2
endif
@@ -219,8 +219,8 @@ endif
# CodeSourcery under Windows
ifeq ($(CONFIG_ARMV7M_TOOLCHAIN),CODESOURCERYW)
- CROSSDEV = arm-none-eabi-
- ARCROSSDEV = arm-none-eabi-
+ CROSSDEV ?= arm-none-eabi-
+ ARCROSSDEV ?= arm-none-eabi-
ifneq ($(CONFIG_WINDOWS_NATIVE),y)
WINTOOL = y
endif
@@ -230,8 +230,8 @@ endif
# devkitARM under Windows
ifeq ($(CONFIG_ARMV7M_TOOLCHAIN),DEVKITARM)
- CROSSDEV = arm-eabi-
- ARCROSSDEV = arm-eabi-
+ CROSSDEV ?= arm-eabi-
+ ARCROSSDEV ?= arm-eabi-
ifneq ($(CONFIG_WINDOWS_NATIVE),y)
WINTOOL = y
endif
@@ -241,8 +241,8 @@ endif
# Generic GNU EABI toolchain on OS X, Linux or any typical Posix system
ifeq ($(CONFIG_ARMV7M_TOOLCHAIN),GNU_EABI)
- CROSSDEV = arm-none-eabi-
- ARCROSSDEV = arm-none-eabi-
+ CROSSDEV ?= arm-none-eabi-
+ ARCROSSDEV ?= arm-none-eabi-
MAXOPTIMIZATION = -O3
ifeq ($(CONFIG_ARCH_CORTEXM4),y)
ifeq ($(CONFIG_ARCH_FPU),y)
@@ -258,8 +258,8 @@ endif
# Raisonance RIDE7 under Windows
ifeq ($(CONFIG_ARMV7M_TOOLCHAIN),RAISONANCE)
- CROSSDEV = arm-none-eabi-
- ARCROSSDEV = arm-none-eabi-
+ CROSSDEV ?= arm-none-eabi-
+ ARCROSSDEV ?= arm-none-eabi-
ifneq ($(CONFIG_WINDOWS_NATIVE),y)
WINTOOL = y
endif
diff --git a/nuttx/arch/arm/src/armv7-m/up_assert.c b/nuttx/arch/arm/src/armv7-m/up_assert.c
index ab30b09f3..b40b1090c 100644
--- a/nuttx/arch/arm/src/armv7-m/up_assert.c
+++ b/nuttx/arch/arm/src/armv7-m/up_assert.c
@@ -62,7 +62,7 @@
#ifdef CONFIG_ARCH_STACKDUMP
# undef lldbg
-# define lldbg lib_lowprintf
+# define lldbg lowsyslog
#endif
/* The following is just intended to keep some ugliness out of the mainline
@@ -70,7 +70,7 @@
*
* CONFIG_TASK_NAME_SIZE > 0 && <-- The task has a name
* (defined(CONFIG_DEBUG) || <-- And the debug is enabled (lldbg used)
- * defined(CONFIG_ARCH_STACKDUMP) <-- Or lib_lowprintf() is used
+ * defined(CONFIG_ARCH_STACKDUMP) <-- Or lowsyslog() is used
*/
#undef CONFIG_PRINT_TASKNAME
@@ -267,7 +267,8 @@ static void up_dumpstate(void)
* Name: _up_assert
****************************************************************************/
-static void _up_assert(int errorcode) /* noreturn_function */
+static void _up_assert(int errorcode) noreturn_function;
+static void _up_assert(int errorcode)
{
/* Are we in an interrupt handler or the idle task? */
diff --git a/nuttx/arch/arm/src/armv7-m/up_reprioritizertr.c b/nuttx/arch/arm/src/armv7-m/up_reprioritizertr.c
index f1c961b15..9a971f064 100644
--- a/nuttx/arch/arm/src/armv7-m/up_reprioritizertr.c
+++ b/nuttx/arch/arm/src/armv7-m/up_reprioritizertr.c
@@ -1,7 +1,7 @@
/****************************************************************************
* arch/arm/src/armv7-m/up_reprioritizertr.c
*
- * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2012-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -89,9 +89,14 @@ void up_reprioritize_rtr(_TCB *tcb, uint8_t 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 ||
- priority > SCHED_PRIORITY_MAX)
+ tcb->task_state > LAST_READY_TO_RUN_STATE
+#if SCHED_PRIORITY_MIN > 0
+ || priority < SCHED_PRIORITY_MIN
+#endif
+#if SCHED_PRIORITY_MAX < UINT8_MAX
+ || priority > SCHED_PRIORITY_MAX
+#endif
+ )
{
PANIC(OSERR_BADREPRIORITIZESTATE);
}
diff --git a/nuttx/arch/arm/src/common/up_exit.c b/nuttx/arch/arm/src/common/up_exit.c
index 6f6d54f76..16f5c4442 100644
--- a/nuttx/arch/arm/src/common/up_exit.c
+++ b/nuttx/arch/arm/src/common/up_exit.c
@@ -1,7 +1,7 @@
/****************************************************************************
* common/up_exit.c
*
- * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 201-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -75,7 +75,11 @@
#if defined(CONFIG_DUMP_ON_EXIT) && defined(CONFIG_DEBUG)
static void _up_dumponexit(FAR _TCB *tcb, FAR void *arg)
{
-#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NFILE_STREAMS > 0
+#if CONFIG_NFILE_DESCRIPTORS > 0
+ FAR struct filelist *filelist;
+#if CONFIG_NFILE_STREAMS > 0
+ FAR struct streamlist *streamlist;
+#endif
int i;
#endif
@@ -83,42 +87,32 @@ static void _up_dumponexit(FAR _TCB *tcb, FAR void *arg)
sdbg(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state);
#if CONFIG_NFILE_DESCRIPTORS > 0
- if (tcb->filelist)
+ filelist = tcb->group->tg_filelist;
+ for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++)
{
- sdbg(" filelist refcount=%d\n",
- tcb->filelist->fl_crefs);
-
- for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++)
+ struct inode *inode = filelist->fl_files[i].f_inode;
+ if (inode)
{
- struct inode *inode = tcb->filelist->fl_files[i].f_inode;
- if (inode)
- {
- sdbg(" fd=%d refcount=%d\n",
- i, inode->i_crefs);
- }
+ sdbg(" fd=%d refcount=%d\n",
+ i, inode->i_crefs);
}
}
#endif
#if CONFIG_NFILE_STREAMS > 0
- if (tcb->streams)
+ streamlist = tcb->group->tg_streamlist;
+ for (i = 0; i < CONFIG_NFILE_STREAMS; i++)
{
- sdbg(" streamlist refcount=%d\n",
- tcb->streams->sl_crefs);
-
- for (i = 0; i < CONFIG_NFILE_STREAMS; i++)
+ struct file_struct *filep = &streamlist->sl_streams[i];
+ if (filep->fs_filedes >= 0)
{
- struct file_struct *filep = &tcb->streams->sl_streams[i];
- if (filep->fs_filedes >= 0)
- {
#if CONFIG_STDIO_BUFFER_SIZE > 0
- sdbg(" fd=%d nbytes=%d\n",
- filep->fs_filedes,
- filep->fs_bufpos - filep->fs_bufstart);
+ sdbg(" fd=%d nbytes=%d\n",
+ filep->fs_filedes,
+ filep->fs_bufpos - filep->fs_bufstart);
#else
- sdbg(" fd=%d\n", filep->fs_filedes);
+ sdbg(" fd=%d\n", filep->fs_filedes);
#endif
- }
}
}
#endif
diff --git a/nuttx/arch/arm/src/common/up_initialize.c b/nuttx/arch/arm/src/common/up_initialize.c
index 80f9b1193..0ea3fcd35 100644
--- a/nuttx/arch/arm/src/common/up_initialize.c
+++ b/nuttx/arch/arm/src/common/up_initialize.c
@@ -1,7 +1,7 @@
/****************************************************************************
* arch/arm/src/common/up_initialize.c
*
- * Copyright (C) 2007-2010, 2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2010, 2012-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -161,11 +161,17 @@ void up_initialize(void)
devnull_register(); /* Standard /dev/null */
#endif
- /* Initialize the console device driver */
+ /* Initialize the serial device driver */
-#if defined(USE_SERIALDRIVER)
+#ifdef USE_SERIALDRIVER
up_serialinit();
-#elif defined(CONFIG_DEV_LOWCONSOLE)
+#endif
+
+ /* Initialize the console device driver (if it is other than the standard
+ * serial driver).
+ */
+
+#if defined(CONFIG_DEV_LOWCONSOLE)
lowconsole_init();
#elif defined(CONFIG_RAMLOG_CONSOLE)
ramlog_consoleinit();
diff --git a/nuttx/arch/arm/src/common/up_internal.h b/nuttx/arch/arm/src/common/up_internal.h
index 55071345f..8a24f003e 100644
--- a/nuttx/arch/arm/src/common/up_internal.h
+++ b/nuttx/arch/arm/src/common/up_internal.h
@@ -1,7 +1,7 @@
/****************************************************************************
* common/up_internal.h
*
- * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -63,7 +63,10 @@
#undef CONFIG_SUPPRESS_UART_CONFIG /* DEFINED: Do not reconfig UART */
#undef CONFIG_DUMP_ON_EXIT /* DEFINED: Dump task state on exit */
-/* Determine which (if any) console driver to use */
+/* Determine which (if any) console driver to use. If a console is enabled
+ * and no other console device is specified, then a serial console is
+ * assumed.
+ */
#if !defined(CONFIG_DEV_CONSOLE) || CONFIG_NFILE_DESCRIPTORS == 0
# undef USE_SERIALDRIVER
@@ -84,6 +87,16 @@
# endif
#endif
+/* If some other device is used as the console, then the serial driver may
+ * still be needed. Let's assume that if the upper half serial driver is
+ * built, then the lower half will also be needed. There is no need for
+ * the early serial initialization in this case.
+ */
+
+#if !defined(USE_SERIALDRIVER) && defined(CONFIG_STANDARD_SERIAL)
+# define USE_SERIALDRIVER 1
+#endif
+
/* Determine which device to use as the system logging device */
#ifndef CONFIG_SYSLOG
diff --git a/nuttx/arch/arm/src/stm32/chip/stm32_spi.h b/nuttx/arch/arm/src/stm32/chip/stm32_spi.h
index d80c447bb..7731d03b0 100644
--- a/nuttx/arch/arm/src/stm32/chip/stm32_spi.h
+++ b/nuttx/arch/arm/src/stm32/chip/stm32_spi.h
@@ -47,7 +47,13 @@
* Pre-processor Definitions
************************************************************************************/
-#define STM32_SPI_CLK_MAX 18000000UL /* Maximum allowed speed as per specifications for all SPIs */
+/* Maximum allowed speed as per specifications for all SPIs */
+
+#if defined(CONFIG_STM32_STM32F40XX)
+# define STM32_SPI_CLK_MAX 37500000UL
+#else
+# define STM32_SPI_CLK_MAX 18000000UL
+#endif
/* Register Offsets *****************************************************************/
diff --git a/nuttx/arch/arm/src/stm32/stm32_adc.c b/nuttx/arch/arm/src/stm32/stm32_adc.c
index 844f1fd0f..b5033b057 100644
--- a/nuttx/arch/arm/src/stm32/stm32_adc.c
+++ b/nuttx/arch/arm/src/stm32/stm32_adc.c
@@ -118,25 +118,12 @@ struct stm32_dev_s
uint32_t freq; /* The desired frequency of conversions */
#endif
uint8_t chanlist[ADC_MAX_SAMPLES];
-#ifdef CONFIG_ADC_DMA
- const unsigned int rxdma_channel; /* DMA channel assigned */
- DMA_HANDLE rxdma; /* currently-open receive DMA stream */
- bool rxenable; /* DMA-based reception en/disable */
- uint32_t rxdmanext; /* Next byte in the DMA buffer to be read */
- int32_t *const rxfifo; /* Receive DMA buffer */
-#endif
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
-# ifdef CONFIG_ADC_DMA
-static int16_t g_adc3dmarxfifo[ADC_MAX_SAMPLES];
-# endif
-
-
-
/* ADC Register access */
static uint32_t adc_getreg(struct stm32_dev_s *priv, int offset);
@@ -179,15 +166,6 @@ static int adc_timinit(FAR struct stm32_dev_s *priv);
static void adc_startconv(FAR struct stm32_dev_s *priv, bool enable);
#endif
-#ifdef CONFIG_ADC_DMA
-static int up_dma_setup(struct adc_dev_s *dev);
-static void up_dma_shutdown(struct adc_dev_s *dev);
-//static int up_dma_receive(struct uart_dev_s *dev, uint32_t *status);
-//static void up_dma_rxint(struct uart_dev_s *dev, bool enable);
-//static bool up_dma_rxavailable(struct uart_dev_s *dev);
-static void up_dma_rxcallback(DMA_HANDLE handle, uint8_t status, FAR struct adc_dev_s *dev);
-#endif
-
/****************************************************************************
* Private Data
****************************************************************************/
@@ -284,10 +262,6 @@ static struct stm32_dev_s g_adcpriv3 =
.pclck = ADC3_TIMER_PCLK_FREQUENCY,
.freq = CONFIG_STM32_ADC3_SAMPLE_FREQUENCY,
#endif
-#ifdef CONFIG_ADC_DMA
- .rxdma_channel = DMAMAP_ADC3_2,
- .rxfifo = g_adc3dmarxfifo,
-#endif
};
static struct adc_dev_s g_adcdev3 =
@@ -569,7 +543,7 @@ static int adc_timinit(FAR struct stm32_dev_s *priv)
* So ( prescaler = pclck / 65535 / freq ) would be optimal.
*/
- prescaler = 128;//(priv->pclck / priv->freq + 65534) / 65535;
+ prescaler = (priv->pclck / priv->freq + 65534) / 65535;
/* We need to decrement the prescaler value by one, but only, the value does
* not underflow.
@@ -591,7 +565,7 @@ static int adc_timinit(FAR struct stm32_dev_s *priv)
timclk = priv->pclck / prescaler;
- reload = priv->freq;//timclk / priv->freq;
+ reload = timclk / priv->freq;
if (reload < 1)
{
adbg("WARNING: Reload value underflowed.\n");
@@ -720,10 +694,10 @@ static int adc_timinit(FAR struct stm32_dev_s *priv)
case 4: /* TimerX TRGO event */
{
-#warning "TRGO support not yet implemented"
-
+ /* TODO: TRGO support not yet implemented */
/* Set the event TRGO */
+ ccenable = 0;
egr = GTIM_EGR_TG;
/* Set the duty cycle by writing to the CCR register for this channel */
@@ -936,139 +910,6 @@ static void adc_rccreset(struct stm32_dev_s *priv, bool reset)
irqrestore(flags);
}
-/****************************************************************************
- * Name: up_dma_setup
- *
- * Description:
- *
- ****************************************************************************/
-
-#ifdef CONFIG_ADC_DMA
-static int up_dma_setup(FAR struct adc_dev_s *dev)
-{
-
- FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
- int result;
- uint32_t regval;
-
-//
-// result = up_setup(dev);
-// if (result != OK)
-// {
-// return result;
-// }
-
- /* Acquire the DMA channel. This should always succeed. */
-
- priv->rxdma = stm32_dmachannel(priv->rxdma_channel);
-
- /* Configure for circular DMA reception into the RX fifo */
-
- stm32_dmasetup(priv->rxdma,
- priv->base + STM32_ADC_DR_OFFSET,
- (uint32_t)priv->rxfifo,
- 4,//buffersize
- DMA_SCR_DIR_P2M |
- DMA_SCR_CIRC |
- DMA_SCR_MINC |
- DMA_SCR_PSIZE_16BITS |
- DMA_SCR_MSIZE_16BITS |
- DMA_SCR_PBURST_SINGLE |
- DMA_SCR_MBURST_SINGLE);
-
- /* Reset our DMA shadow pointer to match the address just
- * programmed above.
- */
-
- //priv->rxdmanext = 0;
-
- /* Enable DMA for the ADC */
-
- /* Start the DMA channel, and arrange for callbacks at the half and
- * full points in the FIFO. This ensures that we have half a FIFO
- * worth of time to claim bytes before they are overwritten.
- */
-
- stm32_dmastart(priv->rxdma, up_dma_rxcallback, (void *)dev, false);
-
- return OK;
-}
-#endif
-/****************************************************************************
- * Name: up_dma_rxcallback
- *
- * Description:
-
- *
- ****************************************************************************/
-
-#ifdef CONFIG_ADC_DMA
-static void up_dma_rxcallback(DMA_HANDLE handle, uint8_t status, FAR struct adc_dev_s *dev)
-{
- //struct up_dev_s *priv = (struct up_dev_s*)arg;
- //uint32_t regval;
- FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
- //struct stm32_dma_s *dmast = (struct stm32_dma_s *)handle;
-
- //if (priv->rxenable && up_dma_rxavailable(&priv->dev))
- {
- /* Give the ADC data to the ADC driver. adc_receive accepts 3 parameters:
- *
- * 1) The first is the ADC device instance for this ADC block.
- * 2) The second is the channel number for the data, and
- * 3) The third is the converted data for the channel.
- */
-
-
- adc_receive(dev, 10, (int32_t)g_adc3dmarxfifo[1]);
- adc_receive(dev, 11, (int32_t)g_adc3dmarxfifo[2]);
- adc_receive(dev, 12, (int32_t)g_adc3dmarxfifo[3]);
- adc_receive(dev, 13, (int32_t)g_adc3dmarxfifo[0]);
-
-
- /* Set the channel number of the next channel that will complete conversion */
-
- priv->current++;
-
- if (priv->current >= priv->nchannels)
- {
- /* Restart the conversion sequence from the beginning */
-
- priv->current = 0;
- }
-
-
- }
-}
-#endif
-
-/****************************************************************************
- * Name: up_dma_shutdown
- *
- * Description:
- * Disable the DMA
- *
- ****************************************************************************/
-
-#ifdef CONFIG_ADC_DMA
-static void up_dma_shutdown(struct adc_dev_s *dev)
-{
-
- FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
-
-
- /* Stop the DMA channel */
-
- stm32_dmastop(priv->rxdma);
-
- /* Release the DMA channel */
-
- stm32_dmafree(priv->rxdma);
- priv->rxdma = NULL;
-}
-#endif
-
-
/*******************************************************************************
* Name: adc_enable
*
@@ -1089,7 +930,7 @@ static void adc_enable(FAR struct stm32_dev_s *priv, bool enable)
{
uint32_t regval;
- // avdbg("enable: %d\n", enable);
+ avdbg("enable: %d\n", enable);
regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
if (enable)
@@ -1123,12 +964,14 @@ static void adc_reset(FAR struct adc_dev_s *dev)
uint32_t regval;
int offset;
int i;
+#ifdef ADC_HAVE_TIMER
int ret;
+#endif
avdbg("intf: ADC%d\n", priv->intf);
flags = irqsave();
- /* Enable ADC reset state */
+ /* Enable ADC reset state */
adc_rccreset(priv, true);
@@ -1146,7 +989,6 @@ static void adc_reset(FAR struct adc_dev_s *dev)
adc_putreg(priv, STM32_ADC_LTR_OFFSET, 0x00000000);
-
/* Initialize the same sample time for each ADC 55.5 cycles
*
* During sample cycles channel selection bits must remain unchanged.
@@ -1179,8 +1021,16 @@ static void adc_reset(FAR struct adc_dev_s *dev)
regval |= ADC_CR1_AWDEN;
regval |= (priv->chanlist[0] << ADC_CR1_AWDCH_SHIFT);
+ /* Enable interrupt flags */
+
+ regval |= ADC_CR1_ALLINTS;
+
#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+ /* Enable or disable Overrun interrupt */
+
+ regval &= ~ADC_CR1_OVRIE;
+
/* Set the resolution of the conversion */
regval |= ACD_CR1_RES_12BIT;
@@ -1229,12 +1079,6 @@ static void adc_reset(FAR struct adc_dev_s *dev)
{
regval |= (uint32_t)priv->chanlist[i] << offset;
}
- /* Set the number of conversions */
-
- DEBUGASSERT(priv->nchannels <= ADC_MAX_SAMPLES);
-
- regval |= (((uint32_t)priv->nchannels-1) << ADC_SQR1_L_SHIFT);
- adc_putreg(priv, STM32_ADC_SQR1_OFFSET, regval);
/* ADC CCR configuration */
@@ -1246,7 +1090,12 @@ static void adc_reset(FAR struct adc_dev_s *dev)
putreg32(regval, STM32_ADC_CCR);
#endif
+ /* Set the number of conversions */
+ DEBUGASSERT(priv->nchannels <= ADC_MAX_SAMPLES);
+
+ regval |= (((uint32_t)priv->nchannels-1) << ADC_SQR1_L_SHIFT);
+ adc_putreg(priv, STM32_ADC_SQR1_OFFSET, regval);
/* Set the channel index of the first conversion */
@@ -1270,29 +1119,24 @@ static void adc_reset(FAR struct adc_dev_s *dev)
adc_enable(priv, true);
#else
-#ifdef CONFIG_ADC_DMA
- //nothing
-#else
adc_startconv(priv, true);
-#endif
#endif /* CONFIG_STM32_STM32F10XX */
#endif /* ADC_HAVE_TIMER */
-
irqrestore(flags);
-// avdbg("SR: 0x%08x CR1: 0x%08x CR2: 0x%08x\n",
-// adc_getreg(priv, STM32_ADC_SR_OFFSET),
-// adc_getreg(priv, STM32_ADC_CR1_OFFSET),
-// adc_getreg(priv, STM32_ADC_CR2_OFFSET));
-// avdbg("SQR1: 0x%08x SQR2: 0x%08x SQR3: 0x%08x\n",
-// adc_getreg(priv, STM32_ADC_SQR1_OFFSET),
-// adc_getreg(priv, STM32_ADC_SQR2_OFFSET),
-// adc_getreg(priv, STM32_ADC_SQR3_OFFSET));
-//#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
-// avdbg("CCR: 0x%08x\n",
-// getreg32(STM32_ADC_CCR));
-//#endif
+ avdbg("SR: 0x%08x CR1: 0x%08x CR2: 0x%08x\n",
+ adc_getreg(priv, STM32_ADC_SR_OFFSET),
+ adc_getreg(priv, STM32_ADC_CR1_OFFSET),
+ adc_getreg(priv, STM32_ADC_CR2_OFFSET));
+ avdbg("SQR1: 0x%08x SQR2: 0x%08x SQR3: 0x%08x\n",
+ adc_getreg(priv, STM32_ADC_SQR1_OFFSET),
+ adc_getreg(priv, STM32_ADC_SQR2_OFFSET),
+ adc_getreg(priv, STM32_ADC_SQR3_OFFSET));
+#if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+ avdbg("CCR: 0x%08x\n",
+ getreg32(STM32_ADC_CCR));
+#endif
}
/****************************************************************************
@@ -1314,86 +1158,21 @@ static int adc_setup(FAR struct adc_dev_s *dev)
{
FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
int ret;
- uint32_t regval;
-
-
- /* the adc seems to need a full reset to be enabled correctly */
- adc_reset(dev);
-#ifndef CONFIG_ADC_DMA
/* Attach the ADC interrupt */
ret = irq_attach(priv->irq, priv->isr);
if (ret == OK)
{
+ /* Make sure that the ADC device is in the powered up, reset state */
+
+ adc_reset(dev);
+
/* Enable the ADC interrupt */
avdbg("Enable the ADC interrupt: irq=%d\n", priv->irq);
up_enable_irq(priv->irq);
}
-#endif
-
-#ifdef CONFIG_ADC_DMA
- up_dma_setup(dev);
-
-
-//#ifndef ADC_HAVE_TIMER
-// /*disable external trigger*/
-// regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
-// regval |= ACD_CR2_EXTEN_NONE;
-// //regval |= ADC_CR1_DISCEN;
-// adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval);
-//#else
-// /*enable external trigger*/
-// regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
-// regval |=ADC_CR2_EXTSEL_T4CC4;
-// regval |=ACD_CR2_EXTEN_BOTH;
-// //regval |= ADC_CR2_CONT;
-// adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval);
-//#endif
-
-
- /*enable scan mode*/
- regval = adc_getreg(priv, STM32_ADC_CR1_OFFSET);
- regval |= ADC_CR1_SCAN;
- //regval |= ADC_CR1_DISCEN;
- adc_putreg(priv, STM32_ADC_CR1_OFFSET, regval);
-
- /* Enable DMA request after last transfer (Single-ADC mode) */
- //ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE);
- regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
- regval |= ADC_CR2_DDS;
- adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval);
-
- /* Enable ADC3 DMA */
- // ADC_DMACmd(ADC3, ENABLE);
- regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
- regval |= ADC_CR2_DMA;
- adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval);
-#endif
-
-
-#ifndef ADC_HAVE_TIMER
- /*set continuous conversion */
- regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
- regval |= ADC_CR2_CONT;
- adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval);
-#endif
-
- /* Enable ADC3 */
- //ADC_Cmd(ADC3, ENABLE);
- regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
- regval |= ADC_CR2_ADON;
- adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval);
-
-//// /*start conversion*/
-// regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
-// regval |= ADC_CR2_SWSTART;
-// adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval);
-
-
-
-
return ret;
}
@@ -1415,24 +1194,14 @@ static void adc_shutdown(FAR struct adc_dev_s *dev)
{
FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
-#ifdef CONFIG_ADC_DMA
- up_dma_shutdown(dev);
-#endif
-
-#ifdef ADC_HAVE_TIMER
- /* stop adc timer */
- adc_timstart(priv, false);
-#endif
+ /* Disable ADC interrupts and detach the ADC interrupt handler */
- /* power down ADC */
- adc_enable(priv, false);
+ up_disable_irq(priv->irq);
+ irq_detach(priv->irq);
- adc_rxint(dev, false);
+ /* Disable and reset the ADC module */
- /* Disable ADC interrupts and detach the ADC interrupt handler */
- up_disable_irq(priv->irq);
-// irq_detach(priv->irq);
- // XXX Why is irq_detach here commented out?
+ adc_rccreset(priv, true);
}
/****************************************************************************
diff --git a/nuttx/arch/arm/src/stm32/stm32_adc.h b/nuttx/arch/arm/src/stm32/stm32_adc.h
index 7b6c13b33..060fcdfb9 100644
--- a/nuttx/arch/arm/src/stm32/stm32_adc.h
+++ b/nuttx/arch/arm/src/stm32/stm32_adc.h
@@ -161,6 +161,12 @@
#if defined(CONFIG_STM32_ADC1) || defined(CONFIG_STM32_ADC2) || defined(CONFIG_STM32_ADC3)
+/* DMA support is not yet implemented for this driver */
+
+#ifdef CONFIG_ADC_DMA
+# warning "DMA is not supported by the current driver"
+#endif
+
/* Timer configuration: If a timer trigger is specified, then get information
* about the timer.
*/
diff --git a/nuttx/arch/arm/src/stm32/stm32_i2c.c b/nuttx/arch/arm/src/stm32/stm32_i2c.c
index a4b10b55c..82ae6af5f 100644
--- a/nuttx/arch/arm/src/stm32/stm32_i2c.c
+++ b/nuttx/arch/arm/src/stm32/stm32_i2c.c
@@ -107,11 +107,11 @@
#if !defined(CONFIG_STM32_I2CTIMEOSEC) && !defined(CONFIG_STM32_I2CTIMEOMS)
# define CONFIG_STM32_I2CTIMEOSEC 0
-# define CONFIG_STM32_I2CTIMEOMS 500 /* Default is 500 milliseconds */
+# define CONFIG_STM32_I2CTIMEOMS 500 /* Default is 500 milliseconds */
#elif !defined(CONFIG_STM32_I2CTIMEOSEC)
# define CONFIG_STM32_I2CTIMEOSEC 0 /* User provided milliseconds */
#elif !defined(CONFIG_STM32_I2CTIMEOMS)
-# define CONFIG_STM32_I2CTIMEOMS 0 /* User provided seconds */
+# define CONFIG_STM32_I2CTIMEOMS 0 /* User provided seconds */
#endif
/* Interrupt wait time timeout in system timer ticks */
@@ -141,7 +141,7 @@
#endif
/* I2C event trace logic. NOTE: trace uses the internal, non-standard, low-level
- * debug interface lib_rawprintf() but does not require that any other debug
+ * debug interface syslog() but does not require that any other debug
* is enabled.
*/
@@ -219,31 +219,31 @@ struct stm32_i2c_config_s
struct stm32_i2c_priv_s
{
const struct stm32_i2c_config_s *config; /* Port configuration */
- int refs; /* Referernce count */
- sem_t sem_excl; /* Mutual exclusion semaphore */
+ int refs; /* Referernce count */
+ sem_t sem_excl; /* Mutual exclusion semaphore */
#ifndef CONFIG_I2C_POLLED
- sem_t sem_isr; /* Interrupt wait semaphore */
+ sem_t sem_isr; /* Interrupt wait semaphore */
#endif
- volatile uint8_t intstate; /* Interrupt handshake (see enum stm32_intstate_e) */
+ volatile uint8_t intstate; /* Interrupt handshake (see enum stm32_intstate_e) */
- uint8_t msgc; /* Message count */
- struct i2c_msg_s *msgv; /* Message list */
- uint8_t *ptr; /* Current message buffer */
- int dcnt; /* Current message length */
- uint16_t flags; /* Current message flags */
+ uint8_t msgc; /* Message count */
+ struct i2c_msg_s *msgv; /* Message list */
+ uint8_t *ptr; /* Current message buffer */
+ int dcnt; /* Current message length */
+ uint16_t flags; /* Current message flags */
/* I2C trace support */
#ifdef CONFIG_I2C_TRACE
- int tndx; /* Trace array index */
- uint32_t start_time; /* Time when the trace was started */
+ int tndx; /* Trace array index */
+ uint32_t start_time; /* Time when the trace was started */
/* The actual trace data */
struct stm32_trace_s trace[CONFIG_I2C_NTRACE];
#endif
- uint32_t status; /* End of transfer SR2|SR1 status */
+ uint32_t status; /* End of transfer SR2|SR1 status */
};
/* I2C Device, Instance */
@@ -281,7 +281,7 @@ static void stm32_i2c_tracenew(FAR struct stm32_i2c_priv_s *priv, uint32_t statu
static void stm32_i2c_traceevent(FAR struct stm32_i2c_priv_s *priv,
enum stm32_trace_e event, uint32_t parm);
static void stm32_i2c_tracedump(FAR struct stm32_i2c_priv_s *priv);
-#endif
+#endif /* CONFIG_I2C_TRACE */
static void stm32_i2c_setclock(FAR struct stm32_i2c_priv_s *priv,
uint32_t frequency);
static inline void stm32_i2c_sendstart(FAR struct stm32_i2c_priv_s *priv);
@@ -291,7 +291,7 @@ static inline uint32_t stm32_i2c_getstatus(FAR struct stm32_i2c_priv_s *priv);
#ifdef I2C1_FSMC_CONFLICT
static inline uint32_t stm32_i2c_disablefsmc(FAR struct stm32_i2c_priv_s *priv);
static inline void stm32_i2c_enablefsmc(uint32_t ahbenr);
-#endif
+#endif /* I2C1_FSMC_CONFLICT */
static int stm32_i2c_isr(struct stm32_i2c_priv_s * priv);
#ifndef CONFIG_I2C_POLLED
#ifdef CONFIG_STM32_I2C1
@@ -582,15 +582,14 @@ static inline int stm32_i2c_sem_waitdone(FAR struct stm32_i2c_priv_s *priv, int
abstime.tv_sec++;
abstime.tv_nsec -= 1000 * 1000 * 1000;
}
-#else
- #if CONFIG_STM32_I2CTIMEOMS > 0
- abstime.tv_nsec += CONFIG_STM32_I2CTIMEOMS * 1000 * 1000;
- if (abstime.tv_nsec > 1000 * 1000 * 1000)
- {
- abstime.tv_sec++;
- abstime.tv_nsec -= 1000 * 1000 * 1000;
- }
- #endif
+
+#elif CONFIG_STM32_I2CTIMEOMS > 0
+ abstime.tv_nsec += CONFIG_STM32_I2CTIMEOMS * 1000 * 1000;
+ if (abstime.tv_nsec > 1000 * 1000 * 1000)
+ {
+ abstime.tv_sec++;
+ abstime.tv_nsec -= 1000 * 1000 * 1000;
+ }
#endif
/* Wait until either the transfer is complete or the timeout expires */
@@ -866,11 +865,11 @@ static void stm32_i2c_tracedump(FAR struct stm32_i2c_priv_s *priv)
struct stm32_trace_s *trace;
int i;
- lib_rawprintf("Elapsed time: %d\n", clock_systimer() - priv->start_time);
+ syslog("Elapsed time: %d\n", clock_systimer() - priv->start_time);
for (i = 0; i <= priv->tndx; i++)
{
trace = &priv->trace[i];
- lib_rawprintf("%2d. STATUS: %08x COUNT: %3d EVENT: %2d PARM: %08x TIME: %d\n",
+ syslog("%2d. STATUS: %08x COUNT: %3d EVENT: %2d PARM: %08x TIME: %d\n",
i+1, trace->status, trace->count, trace->event, trace->parm,
trace->time - priv->start_time);
}
@@ -932,7 +931,7 @@ static void stm32_i2c_setclock(FAR struct stm32_i2c_priv_s *priv, uint32_t frequ
{
/* Fast mode speed calculation with Tlow/Thigh = 16/9 */
-#ifdef CONFIG_I2C_DUTY16_9
+#ifdef CONFIG_STM32_I2C_DUTY16_9
speed = (uint16_t)(STM32_PCLK1_FREQUENCY / (frequency * 25));
/* Set DUTY and fast speed bits */
@@ -1071,7 +1070,7 @@ static inline uint32_t stm32_i2c_disablefsmc(FAR struct stm32_i2c_priv_s *priv)
/* Is this I2C1 */
-#ifdef CONFIG_STM32_I2C2
+#if defined(CONFIG_STM32_I2C2) || defined(CONFIG_STM32_I2C3)
if (priv->config->base == STM32_I2C1_BASE)
#endif
{
@@ -1198,26 +1197,29 @@ static int stm32_i2c_isr(struct stm32_i2c_priv_s *priv)
{
stm32_i2c_traceevent(priv, I2CEVENT_RCVBYTE, priv->dcnt);
+ /* No interrupts or context switches may occur in the following
+ * sequence. Otherwise, additional bytes may be sent by the
+ * device.
+ */
+
#ifdef CONFIG_I2C_POLLED
irqstate_t state = irqsave();
#endif
-
/* Receive a byte */
*priv->ptr++ = stm32_i2c_getreg(priv, STM32_I2C_DR_OFFSET);
/* Disable acknowledge when last byte is to be received */
+ priv->dcnt--;
if (priv->dcnt == 1)
{
stm32_i2c_modifyreg(priv, STM32_I2C_CR1_OFFSET, I2C_CR1_ACK, 0);
}
- priv->dcnt--;
#ifdef CONFIG_I2C_POLLED
irqrestore(state);
#endif
-
}
}
@@ -1408,7 +1410,6 @@ static int stm32_i2c_init(FAR struct stm32_i2c_priv_s *priv)
/* Enable power and reset the peripheral */
modifyreg32(STM32_RCC_APB1ENR, 0, priv->config->clk_bit);
-
modifyreg32(STM32_RCC_APB1RSTR, 0, priv->config->reset_bit);
modifyreg32(STM32_RCC_APB1RSTR, priv->config->reset_bit, 0);
@@ -1428,10 +1429,10 @@ static int stm32_i2c_init(FAR struct stm32_i2c_priv_s *priv)
/* Attach ISRs */
#ifndef CONFIG_I2C_POLLED
- irq_attach(priv->config->ev_irq, priv->config->isr);
- irq_attach(priv->config->er_irq, priv->config->isr);
- up_enable_irq(priv->config->ev_irq);
- up_enable_irq(priv->config->er_irq);
+ irq_attach(priv->config->ev_irq, priv->config->isr);
+ irq_attach(priv->config->er_irq, priv->config->isr);
+ up_enable_irq(priv->config->ev_irq);
+ up_enable_irq(priv->config->er_irq);
#endif
/* Set peripheral frequency, where it must be at least 2 MHz for 100 kHz
@@ -1461,17 +1462,23 @@ static int stm32_i2c_deinit(FAR struct stm32_i2c_priv_s *priv)
stm32_i2c_putreg(priv, STM32_I2C_CR1_OFFSET, 0);
+ /* Unconfigure GPIO pins */
+
stm32_unconfiggpio(priv->config->scl_pin);
stm32_unconfiggpio(priv->config->sda_pin);
+ /* Disable and detach interrupts */
+
#ifndef CONFIG_I2C_POLLED
up_disable_irq(priv->config->ev_irq);
up_disable_irq(priv->config->er_irq);
irq_detach(priv->config->ev_irq);
irq_detach(priv->config->er_irq);
#endif
- modifyreg32(STM32_RCC_APB1ENR, priv->config->clk_bit, 0);
+ /* Disable clocking */
+
+ modifyreg32(STM32_RCC_APB1ENR, priv->config->clk_bit, 0);
return OK;
}
@@ -1623,7 +1630,9 @@ static int stm32_i2c_process(FAR struct i2c_dev_s *dev, FAR struct i2c_msg_s *ms
*/
stm32_i2c_clrstart(priv);
- // XXX also clear busy flag in case of timeout
+
+ /* Clear busy flag in case of timeout */
+
status = priv->status & 0xffff;
}
else
@@ -2070,4 +2079,4 @@ out:
return ret;
}
-#endif /* defined(CONFIG_STM32_I2C1) || defined(CONFIG_STM32_I2C2) || defined(CONFIG_STM32_I2C3) */
+#endif /* CONFIG_STM32_I2C1 || CONFIG_STM32_I2C2 || CONFIG_STM32_I2C3 */
diff --git a/nuttx/arch/arm/src/stm32/stm32_otgfsdev.c b/nuttx/arch/arm/src/stm32/stm32_otgfsdev.c
index 94772b693..bcce3ce60 100644
--- a/nuttx/arch/arm/src/stm32/stm32_otgfsdev.c
+++ b/nuttx/arch/arm/src/stm32/stm32_otgfsdev.c
@@ -146,15 +146,6 @@
# error "CONFIG_USBDEV_EP3_TXFIFO_SIZE is out of range"
#endif
-/* REVISIT! This forces a hack that polls DTXFSTS for space in the Tx FIFO.
- * Enabling this option is a BAD thing. It will cause inline waits inside
- * of the USB interrupt handler. The correct way to handle this is to
- * enable the correct TxFIFO interrupt and wait until the Tx FIFO is empty.
- * Unfortunately, the interrupt driven logic is not working... Please fix!
- */
-
-#define ENABLE_DTXFSTS_POLLHACK 1
-
/* Debug ***********************************************************************/
/* Trace error codes */
@@ -184,8 +175,9 @@
#define STM32_TRACEERR_NOEP 0x18
#define STM32_TRACEERR_NOTCONFIGURED 0x19
#define STM32_TRACEERR_EPOUTQEMPTY 0x1a
-#define STM32_TRACEERR_EPINQEMPTY 0x1b
+#define STM32_TRACEERR_EPINREQEMPTY 0x1b
#define STM32_TRACEERR_NOOUTSETUP 0x1c
+#define STM32_TRACEERR_POLLTIMEOUT 0x1d
/* Trace interrupt codes */
@@ -432,7 +424,6 @@ struct stm32_usbdev_s
uint8_t stalled:1; /* 1: Protocol stalled */
uint8_t selfpowered:1; /* 1: Device is self powered */
- uint8_t connected:1; /* 1: Host connected */
uint8_t addressed:1; /* 1: Peripheral address has been set */
uint8_t configured:1; /* 1: Class driver has been configured */
uint8_t wakeup:1; /* 1: Device remote wake-up */
@@ -508,7 +499,7 @@ static void stm32_ep0out_ctrlsetup(FAR struct stm32_usbdev_s *priv);
static void stm32_txfifo_write(FAR struct stm32_ep_s *privep,
FAR uint8_t *buf, int nbytes);
static void stm32_epin_transfer(FAR struct stm32_ep_s *privep,
- FAR uint8_t *buf, int nbytes);
+ FAR uint8_t *buf, int nbytes);
static void stm32_epin_request(FAR struct stm32_usbdev_s *priv,
FAR struct stm32_ep_s *privep);
@@ -962,7 +953,7 @@ static void stm32_txfifo_write(FAR struct stm32_ep_s *privep,
regval |= ((uint32_t)*buf++) << 16;
regval |= ((uint32_t)*buf++) << 24;
- /* Then write the packed data to the TxFIFO */
+ /* Then write the packet data to the TxFIFO */
stm32_putreg(regval, regaddr);
}
@@ -1082,9 +1073,6 @@ static void stm32_epin_request(FAR struct stm32_usbdev_s *priv,
struct stm32_req_s *privreq;
uint32_t regaddr;
uint32_t regval;
-#ifdef ENABLE_DTXFSTS_POLLHACK
- int32_t timeout;
-#endif
uint8_t *buf;
int nbytes;
int nwords;
@@ -1113,7 +1101,7 @@ static void stm32_epin_request(FAR struct stm32_usbdev_s *priv,
privreq = stm32_rqpeek(privep);
if (!privreq)
{
- usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EPINQEMPTY), privep->epphy);
+ usbtrace(TRACE_DEVERROR(STM32_TRACEERR_EPINREQEMPTY), privep->epphy);
/* There is no TX transfer in progress and no new pending TX
* requests to send. To stop transmitting any data on a particular
@@ -1151,13 +1139,20 @@ static void stm32_epin_request(FAR struct stm32_usbdev_s *priv,
privep->zlp = true;
}
- /* Loop while there are still bytes to be transferred (or a zero-length-
- * packet, ZLP, to be sent). The loop will also be terminated if there
- * is insufficient space remaining in the TxFIFO to send a complete
- * packet.
+ /* Add one more packet to the TxFIFO. We will wait for the transfer
+ * complete event before we add the next packet (or part of a packet
+ * to the TxFIFO).
+ *
+ * The documentation says that we can can multiple packets to the TxFIFO,
+ * but it seems that we need to get the transfer complete event before
+ * we can add the next (or maybe I have got something wrong?)
*/
+#if 0
while (privreq->req.xfrd < privreq->req.len || privep->zlp)
+#else
+ if (privreq->req.xfrd < privreq->req.len || privep->zlp)
+#endif
{
/* Get the number of bytes left to be sent in the request */
@@ -1219,25 +1214,9 @@ static void stm32_epin_request(FAR struct stm32_usbdev_s *priv,
regaddr = STM32_OTGFS_DTXFSTS(privep->epphy);
-#ifdef ENABLE_DTXFSTS_POLLHACK
- /* If ENABLE_DTXFSTS_POLLHACK is enabled , then poll DTXFSTS until
- * space in the TxFIFO is available. If it doesn't become available,
- * in a reasonable amount of time, then just pretend that it is.
- */
-
- for (timeout = 250000; timeout > 0; timeout--)
- {
- regval = stm32_getreg(regaddr);
- if ((regval & OTGFS_DTXFSTS_MASK) >= nwords)
- {
- break;
- }
- }
-#else
- /* If ENABLE_DTXFSTS_POLLHACK is not enabled, then check once for
- * space in the TxFIFO. If space in the TxFIFO is not available,
- * then set up an interrupt to resume the transfer when the TxFIFO
- * is empty.
+ /* Check for space in the TxFIFO. If space in the TxFIFO is not
+ * available, then set up an interrupt to resume the transfer when
+ * the TxFIFO is empty.
*/
regval = stm32_getreg(regaddr);
@@ -1253,11 +1232,12 @@ static void stm32_epin_request(FAR struct stm32_usbdev_s *priv,
empmsk |= OTGFS_DIEPEMPMSK(privep->epphy);
stm32_putreg(empmsk, STM32_OTGFS_DIEPEMPMSK);
- /* Terminate the transfer loop */
+ /* Terminate the transfer. We will try again when the TxFIFO empty
+ * interrupt is received.
+ */
- break;
+ return;
}
-#endif
/* Transfer data to the TxFIFO */
@@ -1290,11 +1270,12 @@ static void stm32_epin_request(FAR struct stm32_usbdev_s *priv,
if (privreq->req.xfrd >= privreq->req.len && !privep->zlp)
{
usbtrace(TRACE_COMPLETE(privep->epphy), privreq->req.xfrd);
- stm32_req_complete(privep, OK);
- /* The endpoint is no longer transferring data */
+ /* We are finished with the request (although the transfer has not
+ * yet completed).
+ */
- privep->active = false;
+ stm32_req_complete(privep, OK);
}
}
@@ -2690,7 +2671,7 @@ static inline void stm32_epin_txfifoempty(FAR struct stm32_usbdev_s *priv, int e
FAR struct stm32_ep_s *privep = &priv->epin[epno];
/* Continue processing the write request queue. This may mean sending
- * more dat from the exisiting request or terminating the current requests
+ * more data from the exisiting request or terminating the current requests
* and (perhaps) starting the IN transfer from the next write request.
*/
@@ -2741,9 +2722,11 @@ static inline void stm32_epin_interrupt(FAR struct stm32_usbdev_s *priv)
mask = stm32_getreg(STM32_OTGFS_DIEPMSK);
- /* Check for FIFO not empty. Bits n corresponds to endpoint n.
- * That condition corresponds to bit 7 of the DIEPINT interrupt
- * status register.
+ /* Check if the TxFIFO not empty interrupt is enabled for this
+ * endpoint in the DIEPMSK register. Bits n corresponds to
+ * endpoint n in the register. That condition corresponds to
+ * bit 7 of the DIEPINT interrupt status register. There is
+ * no TXFE bit in the mask register, so we fake one here.
*/
empty = stm32_getreg(STM32_OTGFS_DIEPEMPMSK);
@@ -2763,11 +2746,13 @@ static inline void stm32_epin_interrupt(FAR struct stm32_usbdev_s *priv)
if ((diepint & OTGFS_DIEPINT_XFRC) != 0)
{
- usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPIN_XFRC), (uint16_t)diepint);
+ usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPIN_XFRC),
+ (uint16_t)diepint);
- /* It is possible that logic may be waiting for a the TxFIFO to become
- * empty. We disable the TxFIFO empty interrupt here; it will be
- * re-enabled if there is still insufficient space in the TxFIFO.
+ /* It is possible that logic may be waiting for a the
+ * TxFIFO to become empty. We disable the TxFIFO empty
+ * interrupt here; it will be re-enabled if there is still
+ * insufficient space in the TxFIFO.
*/
empty &= ~OTGFS_DIEPEMPMSK(epno);
@@ -2828,7 +2813,7 @@ static inline void stm32_epin_interrupt(FAR struct stm32_usbdev_s *priv)
usbtrace(TRACE_INTDECODE(STM32_TRACEINTID_EPIN_TXFE), (uint16_t)diepint);
/* If we were waiting for TxFIFO to become empty, the we might have both
- * XFRC and TXFE interrups pending. Since we do the same thing for both
+ * XFRC and TXFE interrupts pending. Since we do the same thing for both
* cases, ignore the TXFE if we have already processed the XFRC.
*/
@@ -2886,6 +2871,13 @@ static inline void stm32_resumeinterrupt(FAR struct stm32_usbdev_s *priv)
/* Restore full power -- whatever that means for this particular board */
stm32_usbsuspend((struct usbdev_s *)priv, true);
+
+ /* Notify the class driver of the resume event */
+
+ if (priv->driver)
+ {
+ CLASS_RESUME(priv->driver, &priv->usbdev);
+ }
}
/*******************************************************************************
@@ -2900,7 +2892,16 @@ static inline void stm32_suspendinterrupt(FAR struct stm32_usbdev_s *priv)
{
#ifdef CONFIG_USBDEV_LOWPOWER
uint32_t regval;
+#endif
+
+ /* Notify the class driver of the suspend event */
+
+ if (priv->driver)
+ {
+ CLASS_SUSPEND(priv->driver, &priv->usbdev);
+ }
+#ifdef CONFIG_USBDEV_LOWPOWER
/* OTGFS_DSTS_SUSPSTS is set as long as the suspend condition is detected
* on USB. Check if we are still have the suspend condition, that we are
* connected to the host, and that we have been configured.
@@ -2908,9 +2909,7 @@ static inline void stm32_suspendinterrupt(FAR struct stm32_usbdev_s *priv)
regval = stm32_getreg(STM32_OTGFS_DSTS);
- if ((regval & OTGFS_DSTS_SUSPSTS) != 0 &&
- priv->connected &&
- devstate == DEVSTATE_CONFIGURED)
+ if ((regval & OTGFS_DSTS_SUSPSTS) != 0 && devstate == DEVSTATE_CONFIGURED)
{
/* Switch off OTG FS clocking. Setting OTGFS_PCGCCTL_STPPCLK stops the
* PHY clock.
@@ -4957,8 +4956,9 @@ static void stm32_hwinitialize(FAR struct stm32_usbdev_s *priv)
/* At startup the core is in FS mode. */
- /* Disable the USB global interrupt by clearing GINTMSK in the global OTG
- * FS AHB configuration register.
+ /* Disable global interrupts by clearing the GINTMASK bit in the GAHBCFG
+ * register; Set the TXFELVL bit in the GAHBCFG register so that TxFIFO
+ * interrupts will occur when the TxFIFO is truly empty (not just half full).
*/
stm32_putreg(OTGFS_GAHBCFG_TXFELVL, STM32_OTGFS_GAHBCFG);
@@ -5074,6 +5074,7 @@ static void stm32_hwinitialize(FAR struct stm32_usbdev_s *priv)
stm32_putreg(0, STM32_OTGFS_DIEPMSK);
stm32_putreg(0, STM32_OTGFS_DOEPMSK);
+ stm32_putreg(0, STM32_OTGFS_DIEPEMPMSK);
stm32_putreg(0xffffffff, STM32_OTGFS_DAINT);
stm32_putreg(0, STM32_OTGFS_DAINTMSK);
@@ -5155,10 +5156,13 @@ static void stm32_hwinitialize(FAR struct stm32_usbdev_s *priv)
stm32_putreg(regval, STM32_OTGFS_GINTMSK);
/* Enable the USB global interrupt by setting GINTMSK in the global OTG
- * FS AHB configuration register.
+ * FS AHB configuration register; Set the TXFELVL bit in the GAHBCFG
+ * register so that TxFIFO interrupts will occur when the TxFIFO is truly
+ * empty (not just half full).
*/
- stm32_putreg(OTGFS_GAHBCFG_GINTMSK | OTGFS_GAHBCFG_TXFELVL, STM32_OTGFS_GAHBCFG);
+ stm32_putreg(OTGFS_GAHBCFG_GINTMSK | OTGFS_GAHBCFG_TXFELVL,
+ STM32_OTGFS_GAHBCFG);
}
/*******************************************************************************
@@ -5314,6 +5318,7 @@ void up_usbuninitialize(void)
stm32_putreg(0, STM32_OTGFS_DIEPMSK);
stm32_putreg(0, STM32_OTGFS_DOEPMSK);
+ stm32_putreg(0, STM32_OTGFS_DIEPEMPMSK);
stm32_putreg(0, STM32_OTGFS_DAINTMSK);
stm32_putreg(0xffffffff, STM32_OTGFS_DAINT);
diff --git a/nuttx/arch/arm/src/stm32/stm32_serial.c b/nuttx/arch/arm/src/stm32/stm32_serial.c
index 6aaecb2d9..c91f6a6d7 100644
--- a/nuttx/arch/arm/src/stm32/stm32_serial.c
+++ b/nuttx/arch/arm/src/stm32/stm32_serial.c
@@ -2077,7 +2077,8 @@ void up_serialinit(void)
{
#ifdef HAVE_UART
char devname[16];
- unsigned i, j;
+ unsigned i;
+ unsigned minor = 0;
#ifdef CONFIG_PM
int ret;
#endif
@@ -2094,6 +2095,7 @@ void up_serialinit(void)
#if CONSOLE_UART > 0
(void)uart_register("/dev/console", &uart_devs[CONSOLE_UART - 1]->dev);
(void)uart_register("/dev/ttyS0", &uart_devs[CONSOLE_UART - 1]->dev);
+ minor = 1;
/* If we need to re-initialise the console to enable DMA do that here. */
@@ -2107,19 +2109,19 @@ void up_serialinit(void)
strcpy(devname, "/dev/ttySx");
- for (i = 0, j = 1; i < STM32_NUSART; i++)
+ for (i = 0; i < STM32_NUSART; i++)
{
- /* don't create a device for the console - we did that above */
+ /* Don't create a device for the console - we did that above */
if ((uart_devs[i] == 0) || (uart_devs[i]->dev.isconsole))
{
continue;
}
- /* register USARTs as devices in increasing order */
+ /* Register USARTs as devices in increasing order */
- devname[9] = '0' + j++;
+ devname[9] = '0' + minor++;
(void)uart_register(devname, &uart_devs[i]->dev);
}
#endif /* HAVE UART */
diff --git a/nuttx/arch/arm/src/stm32/stm32_spi.c b/nuttx/arch/arm/src/stm32/stm32_spi.c
index 8de698cd5..b4a4f36ab 100644
--- a/nuttx/arch/arm/src/stm32/stm32_spi.c
+++ b/nuttx/arch/arm/src/stm32/stm32_spi.c
@@ -130,14 +130,28 @@
/* DMA channel configuration */
-#define SPI_RXDMA16_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_16BITS|DMA_CCR_PSIZE_16BITS|DMA_CCR_MINC )
-#define SPI_RXDMA8_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS |DMA_CCR_PSIZE_8BITS |DMA_CCR_MINC )
-#define SPI_RXDMA16NULL_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS |DMA_CCR_PSIZE_16BITS )
-#define SPI_RXDMA8NULL_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS |DMA_CCR_PSIZE_8BITS )
-#define SPI_TXDMA16_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_16BITS|DMA_CCR_PSIZE_16BITS|DMA_CCR_MINC|DMA_CCR_DIR)
-#define SPI_TXDMA8_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS |DMA_CCR_PSIZE_8BITS |DMA_CCR_MINC|DMA_CCR_DIR)
-#define SPI_TXDMA16NULL_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS |DMA_CCR_PSIZE_16BITS |DMA_CCR_DIR)
-#define SPI_TXDMA8NULL_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS |DMA_CCR_PSIZE_8BITS |DMA_CCR_DIR)
+#if defined(CONFIG_STM32_STM32F10XX)
+# define SPI_RXDMA16_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_16BITS|DMA_CCR_PSIZE_16BITS|DMA_CCR_MINC )
+# define SPI_RXDMA8_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS |DMA_CCR_PSIZE_8BITS |DMA_CCR_MINC )
+# define SPI_RXDMA16NULL_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS |DMA_CCR_PSIZE_16BITS )
+# define SPI_RXDMA8NULL_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS |DMA_CCR_PSIZE_8BITS )
+# define SPI_TXDMA16_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_16BITS|DMA_CCR_PSIZE_16BITS|DMA_CCR_MINC|DMA_CCR_DIR)
+# define SPI_TXDMA8_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS |DMA_CCR_PSIZE_8BITS |DMA_CCR_MINC|DMA_CCR_DIR)
+# define SPI_TXDMA16NULL_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS |DMA_CCR_PSIZE_16BITS |DMA_CCR_DIR)
+# define SPI_TXDMA8NULL_CONFIG (SPI_DMA_PRIO|DMA_CCR_MSIZE_8BITS |DMA_CCR_PSIZE_8BITS |DMA_CCR_DIR)
+#elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX)
+# define SPI_RXDMA16_CONFIG (SPI_DMA_PRIO|DMA_SCR_MSIZE_16BITS|DMA_SCR_PSIZE_16BITS|DMA_SCR_MINC|DMA_SCR_DIR_P2M)
+# define SPI_RXDMA8_CONFIG (SPI_DMA_PRIO|DMA_SCR_MSIZE_8BITS |DMA_SCR_PSIZE_8BITS |DMA_SCR_MINC|DMA_SCR_DIR_P2M)
+# define SPI_RXDMA16NULL_CONFIG (SPI_DMA_PRIO|DMA_SCR_MSIZE_8BITS |DMA_SCR_PSIZE_16BITS |DMA_SCR_DIR_P2M)
+# define SPI_RXDMA8NULL_CONFIG (SPI_DMA_PRIO|DMA_SCR_MSIZE_8BITS |DMA_SCR_PSIZE_8BITS |DMA_SCR_DIR_P2M)
+# define SPI_TXDMA16_CONFIG (SPI_DMA_PRIO|DMA_SCR_MSIZE_16BITS|DMA_SCR_PSIZE_16BITS|DMA_SCR_MINC|DMA_SCR_DIR_M2P)
+# define SPI_TXDMA8_CONFIG (SPI_DMA_PRIO|DMA_SCR_MSIZE_8BITS |DMA_SCR_PSIZE_8BITS |DMA_SCR_MINC|DMA_SCR_DIR_M2P)
+# define SPI_TXDMA16NULL_CONFIG (SPI_DMA_PRIO|DMA_SCR_MSIZE_8BITS |DMA_SCR_PSIZE_16BITS |DMA_SCR_DIR_M2P)
+# define SPI_TXDMA8NULL_CONFIG (SPI_DMA_PRIO|DMA_SCR_MSIZE_8BITS |DMA_SCR_PSIZE_8BITS |DMA_SCR_DIR_M2P)
+#else
+# error "Unknown STM32 DMA"
+#endif
+
/* Debug ****************************************************************************/
/* Check if (non-standard) SPI debug is enabled */
@@ -550,6 +564,21 @@ static inline void spi_dmarxwakeup(FAR struct stm32_spidev_s *priv)
#endif
/************************************************************************************
+ * Name: spi_dmatxwakeup
+ *
+ * Description:
+ * Signal that DMA is complete
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_STM32_SPI_DMA
+static inline void spi_dmatxwakeup(FAR struct stm32_spidev_s *priv)
+{
+ (void)sem_post(&priv->txsem);
+}
+#endif
+
+/************************************************************************************
* Name: spi_dmarxcallback
*
* Description:
@@ -1183,8 +1212,8 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
FAR void *rxbuffer, size_t nwords)
{
FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev;
- uint16_t rxdummy = 0xffff;
- uint16_t txdummy;
+ static uint16_t rxdummy = 0xffff;
+ static const uint16_t txdummy = 0xffff;
spivdbg("txbuffer=%p rxbuffer=%p nwords=%d\n", txbuffer, rxbuffer, nwords);
DEBUGASSERT(priv && priv->spibase);
@@ -1330,6 +1359,8 @@ static void spi_portinitialize(FAR struct stm32_spidev_s *priv)
priv->rxdma = stm32_dmachannel(priv->rxch);
priv->txdma = stm32_dmachannel(priv->txch);
DEBUGASSERT(priv->rxdma && priv->txdma);
+
+ spi_putreg(priv, STM32_SPI_CR2_OFFSET, SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN);
#endif
/* Enable spi */
diff --git a/nuttx/arch/arm/src/stm32/stm32_usbdev.c b/nuttx/arch/arm/src/stm32/stm32_usbdev.c
index 602de3824..d13ac8f96 100644
--- a/nuttx/arch/arm/src/stm32/stm32_usbdev.c
+++ b/nuttx/arch/arm/src/stm32/stm32_usbdev.c
@@ -2346,6 +2346,13 @@ static void stm32_suspend(struct stm32_usbdev_s *priv)
{
uint16_t regval;
+ /* Notify the class driver of the suspend event */
+
+ if (priv->driver)
+ {
+ CLASS_SUSPEND(priv->driver, &priv->usbdev);
+ }
+
/* Disable ESOF polling, disable the SUSP interrupt, and enable the WKUP
* interrupt. Clear any pending WKUP interrupt.
*/
@@ -2411,6 +2418,13 @@ static void stm32_initresume(struct stm32_usbdev_s *priv)
/* Reset FSUSP bit and enable normal interrupt handling */
stm32_putreg(STM32_CNTR_SETUP, STM32_USB_CNTR);
+
+ /* Notify the class driver of the resume event */
+
+ if (priv->driver)
+ {
+ CLASS_RESUME(priv->driver, &priv->usbdev);
+ }
}
/****************************************************************************
diff --git a/nuttx/binfmt/Kconfig b/nuttx/binfmt/Kconfig
index 8d6c0bb18..6e5f7c251 100644
--- a/nuttx/binfmt/Kconfig
+++ b/nuttx/binfmt/Kconfig
@@ -72,9 +72,10 @@ config PIC
config BINFMT_CONSTRUCTORS
bool "C++ Static Constructor Support"
default n
- depends on HAVE_CXX && ELF # FIX ME: Currently only supported for ELF
+ depends on HAVE_CXX && SCHED_STARTHOOK && ELF
---help---
- Build in support for C++ constructors in loaded modules.
+ Build in support for C++ constructors in loaded modules. Currently
+ only support for ELF binary formats.
config SYMTAB_ORDEREDBYNAME
bool "Symbol Tables Ordered by Name"
diff --git a/nuttx/binfmt/binfmt_execmodule.c b/nuttx/binfmt/binfmt_execmodule.c
index afa445abb..10068b482 100644
--- a/nuttx/binfmt/binfmt_execmodule.c
+++ b/nuttx/binfmt/binfmt_execmodule.c
@@ -58,6 +58,14 @@
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
+/* If C++ constructors are used, then CONFIG_SCHED_STARTHOOK must also be
+ * selected be the start hook is used to schedule execution of the
+ * constructors.
+ */
+
+#if defined(CONFIG_BINFMT_CONSTRUCTORS) && !defined(CONFIG_SCHED_STARTHOOK)
+# errror "CONFIG_SCHED_STARTHOOK must be defined to use constructors"
+#endif
/****************************************************************************
* Private Function Prototypes
@@ -75,7 +83,9 @@
* Name: exec_ctors
*
* Description:
- * Execute C++ static constructors.
+ * Execute C++ static constructors. This function is registered as a
+ * start hook and runs on the thread of the newly created task before
+ * the new task's main function is called.
*
* Input Parameters:
* loadinfo - Load state information
@@ -87,26 +97,12 @@
****************************************************************************/
#ifdef CONFIG_BINFMT_CONSTRUCTORS
-static inline int exec_ctors(FAR const struct binary_s *binp)
+static void exec_ctors(FAR void *arg)
{
+ FAR const struct binary_s *binp = (FAR const struct binary_s *)arg;
binfmt_ctor_t *ctor = binp->ctors;
-#ifdef CONFIG_ADDRENV
- hw_addrenv_t oldenv;
- int ret;
-#endif
int i;
- /* Instantiate the address enviroment containing the constructors */
-
-#ifdef CONFIG_ADDRENV
- ret = up_addrenv_select(binp->addrenv, &oldenv);
- if (ret < 0)
- {
- bdbg("up_addrenv_select() failed: %d\n", ret);
- return ret;
- }
-#endif
-
/* Execute each constructor */
for (i = 0; i < binp->nctors; i++)
@@ -116,14 +112,6 @@ static inline int exec_ctors(FAR const struct binary_s *binp)
(*ctor)();
ctor++;
}
-
- /* Restore the address enviroment */
-
-#ifdef CONFIG_ADDRENV
- return up_addrenv_restore(oldenv);
-#else
- return OK;
-#endif
}
#endif
@@ -139,7 +127,7 @@ static inline int exec_ctors(FAR const struct binary_s *binp)
*
* Returned Value:
* This is an end-user function, so it follows the normal convention:
- * Returns the PID of the exec'ed module. On failure, it.returns
+ * Returns the PID of the exec'ed module. On failure, it returns
* -1 (ERROR) and sets errno appropriately.
*
****************************************************************************/
@@ -229,22 +217,19 @@ int exec_module(FAR const struct binary_s *binp)
}
#endif
- /* Get the assigned pid before we start the task */
-
- pid = tcb->pid;
-
- /* Execute all of the C++ static constructors */
+ /* Setup a start hook that will execute all of the C++ static constructors
+ * on the newly created thread. The struct binary_s must persist at least
+ * until the new task has been started.
+ */
#ifdef CONFIG_BINFMT_CONSTRUCTORS
- ret = exec_ctors(binp);
- if (ret < 0)
- {
- err = -ret;
- bdbg("exec_ctors() failed: %d\n", ret);
- goto errout_with_stack;
- }
+ task_starthook(tcb, exec_ctors, (FAR void *)binp);
#endif
+ /* Get the assigned pid before we start the task */
+
+ pid = tcb->pid;
+
/* Then activate the task at the provided priority */
ret = task_activate(tcb);
diff --git a/nuttx/binfmt/binfmt_internal.h b/nuttx/binfmt/binfmt_internal.h
index 4fab9724d..fa750543a 100644
--- a/nuttx/binfmt/binfmt_internal.h
+++ b/nuttx/binfmt/binfmt_internal.h
@@ -71,7 +71,7 @@ EXTERN FAR struct binfmt_s *g_binfmts;
* Public Function Prototypes
***********************************************************************/
-/* Dump the contents of strtuc binary_s */
+/* Dump the contents of struct binary_s */
#if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_BINFMT)
EXTERN int dump_module(FAR const struct binary_s *bin);
diff --git a/nuttx/binfmt/libelf/libelf_read.c b/nuttx/binfmt/libelf/libelf_read.c
index f4b725183..25ee7ba29 100644
--- a/nuttx/binfmt/libelf/libelf_read.c
+++ b/nuttx/binfmt/libelf/libelf_read.c
@@ -54,7 +54,7 @@
****************************************************************************/
#undef ELF_DUMP_READDATA /* Define to dump all file data read */
-#define DUMPER lib_rawprintf /* If ELF_DUMP_READDATA is defined, this
+#define DUMPER syslog /* If ELF_DUMP_READDATA is defined, this
* is the API used to dump data */
/****************************************************************************
diff --git a/nuttx/binfmt/libnxflat/libnxflat_read.c b/nuttx/binfmt/libnxflat/libnxflat_read.c
index 8deeb0805..103a81f81 100644
--- a/nuttx/binfmt/libnxflat/libnxflat_read.c
+++ b/nuttx/binfmt/libnxflat/libnxflat_read.c
@@ -55,7 +55,7 @@
****************************************************************************/
#undef NXFLAT_DUMP_READDATA /* Define to dump all file data read */
-#define DUMPER lib_rawprintf /* If NXFLAT_DUMP_READDATA is defined, this
+#define DUMPER syslog /* If NXFLAT_DUMP_READDATA is defined, this
* is the API used to dump data */
/****************************************************************************
diff --git a/nuttx/configs/README.txt b/nuttx/configs/README.txt
index 1b78567a3..8d9bb381f 100644
--- a/nuttx/configs/README.txt
+++ b/nuttx/configs/README.txt
@@ -261,7 +261,7 @@ defconfig -- This is a configuration file similar to the Linux
CONFIG_DEBUG - enables built-in debug options
CONFIG_DEBUG_VERBOSE - enables verbose debug output
- CCONFIG_DEBUG_ENABLE - Support an interface to enable or disable debug output.
+ CCONFIG_SYSLOG_ENABLE - Support an interface to enable or disable debug output.
CONFIG_DEBUG_SYMBOLS - build without optimization and with
debug symbols (needed for use with a debugger).
CONFIG_DEBUG_SCHED - enable OS debug output (disabled by
diff --git a/nuttx/configs/px4fmu/nsh/defconfig b/nuttx/configs/px4fmu/nsh/defconfig
index fd783dec5..5a54e350c 100755
--- a/nuttx/configs/px4fmu/nsh/defconfig
+++ b/nuttx/configs/px4fmu/nsh/defconfig
@@ -246,6 +246,7 @@ CONFIG_AT24XX_MTD_BLOCKSIZE=256
#
CONFIG_SERIAL_TERMIOS=y
CONFIG_SERIAL_CONSOLE_REINIT=y
+CONFIG_STANDARD_SERIAL=y
CONFIG_USART1_SERIAL_CONSOLE=y
CONFIG_USART2_SERIAL_CONSOLE=n
diff --git a/nuttx/configs/px4io/io/defconfig b/nuttx/configs/px4io/io/defconfig
index 30ec5be08..1185813db 100755
--- a/nuttx/configs/px4io/io/defconfig
+++ b/nuttx/configs/px4io/io/defconfig
@@ -159,6 +159,7 @@ CONFIG_STM32_ADC3=n
# CONFIG_USARTn_2STOP - Two stop bits
#
CONFIG_SERIAL_TERMIOS=y
+CONFIG_STANDARD_SERIAL=y
CONFIG_USART1_SERIAL_CONSOLE=y
CONFIG_USART2_SERIAL_CONSOLE=n
diff --git a/nuttx/drivers/Kconfig b/nuttx/drivers/Kconfig
index 3ced01b58..f3d2c871a 100644
--- a/nuttx/drivers/Kconfig
+++ b/nuttx/drivers/Kconfig
@@ -3,6 +3,14 @@
# see misc/tools/kconfig-language.txt.
#
+config DISABLE_POLL
+ bool "Disable driver poll interfaces"
+ default n
+ ---help---
+ The sizes of drivers can be reduced if the poll() method is not
+ supported. If you do not use poll() or select(), then you can
+ select DISABLE_POLL to reduce the code footprint by a small amount.
+
config DEV_NULL
bool "Enable /dev/null"
default y
diff --git a/nuttx/drivers/lcd/mio283qt2.c b/nuttx/drivers/lcd/mio283qt2.c
index 1758e230c..4c8835eef 100644
--- a/nuttx/drivers/lcd/mio283qt2.c
+++ b/nuttx/drivers/lcd/mio283qt2.c
@@ -495,14 +495,14 @@ static void mio283qt2_dumprun(FAR const char *msg, FAR uint16_t *run, size_t npi
{
int i, j;
- lib_rawprintf("\n%s:\n", msg);
+ syslog("\n%s:\n", msg);
for (i = 0; i < npixels; i += 16)
{
up_putc(' ');
- lib_rawprintf(" ");
+ syslog(" ");
for (j = 0; j < 16; j++)
{
- lib_rawprintf(" %04x", *run++);
+ syslog(" %04x", *run++);
}
up_putc('\n');
}
diff --git a/nuttx/drivers/lcd/ssd1289.c b/nuttx/drivers/lcd/ssd1289.c
index e42b5bded..d78688be5 100644
--- a/nuttx/drivers/lcd/ssd1289.c
+++ b/nuttx/drivers/lcd/ssd1289.c
@@ -497,14 +497,14 @@ static void ssd1289_dumprun(FAR const char *msg, FAR uint16_t *run, size_t npixe
{
int i, j;
- lib_rawprintf("\n%s:\n", msg);
+ syslog("\n%s:\n", msg);
for (i = 0; i < npixels; i += 16)
{
up_putc(' ');
- lib_rawprintf(" ");
+ syslog(" ");
for (j = 0; j < 16; j++)
{
- lib_rawprintf(" %04x", *run++);
+ syslog(" %04x", *run++);
}
up_putc('\n');
}
diff --git a/nuttx/drivers/loop.c b/nuttx/drivers/loop.c
index b5b5d82d8..4744ae0dd 100644
--- a/nuttx/drivers/loop.c
+++ b/nuttx/drivers/loop.c
@@ -268,7 +268,7 @@ static ssize_t loop_write(FAR struct inode *inode, const unsigned char *buffer,
size_t start_sector, unsigned int nsectors)
{
FAR struct loop_struct_s *dev;
- size_t nbyteswritten;
+ ssize_t nbyteswritten;
off_t offset;
int ret;
diff --git a/nuttx/drivers/mmcsd/mmcsd_debug.c b/nuttx/drivers/mmcsd/mmcsd_debug.c
index 0bd7f896e..8cb5b2a2a 100644
--- a/nuttx/drivers/mmcsd/mmcsd_debug.c
+++ b/nuttx/drivers/mmcsd/mmcsd_debug.c
@@ -56,9 +56,9 @@
/* This needs to match the logic in include/debug.h */
#ifdef CONFIG_CPP_HAVE_VARARGS
-# define message(format, arg...) lib_rawprintf(format, ##arg)
+# define message(format, arg...) syslog(format, ##arg)
#else
-# define message lib_rawprintf
+# define message syslog
#endif
/****************************************************************************
diff --git a/nuttx/drivers/mmcsd/mmcsd_spi.c b/nuttx/drivers/mmcsd/mmcsd_spi.c
index d437b7fea..3d4cf1dd1 100644
--- a/nuttx/drivers/mmcsd/mmcsd_spi.c
+++ b/nuttx/drivers/mmcsd/mmcsd_spi.c
@@ -1,7 +1,7 @@
/****************************************************************************
* drivers/mmcsd/mmcsd_spi.c
*
- * Copyright (C) 2008-2010, 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2008-2010, 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -409,10 +409,14 @@ static uint32_t mmcsd_sendcmd(FAR struct mmcsd_slot_s *slot,
int ret;
int i;
- /* Wait until the card is not busy */
+ /* Wait until the card is not busy. Some SD cards will not enter the IDLE
+ * state until CMD0 is sent for the first time, switching the card to SPI
+ * mode. Having a pull-up resistor on MISO may avoid this problem, but
+ * this check makes it work also without the pull-up.
+ */
ret = mmcsd_waitready(slot);
- if (ret != OK)
+ if (ret != OK && cmd != &g_cmd0)
{
return ret;
}
diff --git a/nuttx/drivers/mtd/at25.c b/nuttx/drivers/mtd/at25.c
index e35b794a5..c58b16122 100644
--- a/nuttx/drivers/mtd/at25.c
+++ b/nuttx/drivers/mtd/at25.c
@@ -691,14 +691,16 @@ FAR struct mtd_dev_s *at25_initialize(FAR struct spi_dev_s *dev)
kfree(priv);
priv = NULL;
}
-
- /* Unprotect all sectors */
+ else
+ {
+ /* Unprotect all sectors */
- at25_writeenable(priv);
- SPI_SELECT(priv->dev, SPIDEV_FLASH, true);
- (void)SPI_SEND(priv->dev, AT25_WRSR);
- (void)SPI_SEND(priv->dev, AT25_SR_UNPROT);
- SPI_SELECT(priv->dev, SPIDEV_FLASH, false);
+ at25_writeenable(priv);
+ SPI_SELECT(priv->dev, SPIDEV_FLASH, true);
+ (void)SPI_SEND(priv->dev, AT25_WRSR);
+ (void)SPI_SEND(priv->dev, AT25_SR_UNPROT);
+ SPI_SELECT(priv->dev, SPIDEV_FLASH, false);
+ }
}
/* Return the implementation-specific state structure as the MTD device */
diff --git a/nuttx/drivers/net/enc28j60.c b/nuttx/drivers/net/enc28j60.c
index 2346ee2d6..203259aeb 100644
--- a/nuttx/drivers/net/enc28j60.c
+++ b/nuttx/drivers/net/enc28j60.c
@@ -179,10 +179,10 @@
/* Debug ********************************************************************/
#ifdef CONFIG_ENC28J60_REGDEBUG
-# define enc_wrdump(a,v) lib_lowprintf("ENC28J60: %02x<-%02x\n", a, v);
-# define enc_rddump(a,v) lib_lowprintf("ENC28J60: %02x->%02x\n", a, v);
-# define enc_cmddump(c) lib_lowprintf("ENC28J60: CMD: %02x\n", c);
-# define enc_bmdump(c,b,s) lib_lowprintf("ENC28J60: CMD: %02x buffer: %p length: %d\n", c,b,s);
+# define enc_wrdump(a,v) lowsyslog("ENC28J60: %02x<-%02x\n", a, v);
+# define enc_rddump(a,v) lowsyslog("ENC28J60: %02x->%02x\n", a, v);
+# define enc_cmddump(c) lowsyslog("ENC28J60: CMD: %02x\n", c);
+# define enc_bmdump(c,b,s) lowsyslog("ENC28J60: CMD: %02x buffer: %p length: %d\n", c,b,s);
#else
# define enc_wrdump(a,v)
# define enc_rddump(a,v)
@@ -773,56 +773,56 @@ static int enc_waitbreg(FAR struct enc_driver_s *priv, uint8_t ctrlreg,
#if 0 /* Sometimes useful */
static void enc_rxdump(FAR struct enc_driver_s *priv)
{
- lib_lowprintf("Rx Registers:\n");
- lib_lowprintf(" EIE: %02x EIR: %02x\n",
- enc_rdgreg(priv, ENC_EIE), enc_rdgreg(priv, ENC_EIR));
- lib_lowprintf(" ESTAT: %02x ECON1: %02x ECON2: %02x\n",
- enc_rdgreg(priv, ENC_ESTAT), enc_rdgreg(priv, ENC_ECON1),
- enc_rdgreg(priv, ENC_ECON2));
- lib_lowprintf(" ERXST: %02x %02x\n",
- enc_rdbreg(priv, ENC_ERXSTH), enc_rdbreg(priv, ENC_ERXSTL));
- lib_lowprintf(" ERXND: %02x %02x\n",
- enc_rdbreg(priv, ENC_ERXNDH), enc_rdbreg(priv, ENC_ERXNDL));
- lib_lowprintf(" ERXRDPT: %02x %02x\n",
- enc_rdbreg(priv, ENC_ERXRDPTH), enc_rdbreg(priv, ENC_ERXRDPTL));
- lib_lowprintf(" ERXFCON: %02x EPKTCNT: %02x\n",
- enc_rdbreg(priv, ENC_ERXFCON), enc_rdbreg(priv, ENC_EPKTCNT));
- lib_lowprintf(" MACON1: %02x MACON3: %02x\n",
- enc_rdbreg(priv, ENC_MACON1), enc_rdbreg(priv, ENC_MACON3));
- lib_lowprintf(" MAMXFL: %02x %02x\n",
- enc_rdbreg(priv, ENC_MAMXFLH), enc_rdbreg(priv, ENC_MAMXFLL));
- lib_lowprintf(" MAADR: %02x:%02x:%02x:%02x:%02x:%02x\n",
- enc_rdbreg(priv, ENC_MAADR1), enc_rdbreg(priv, ENC_MAADR2),
- enc_rdbreg(priv, ENC_MAADR3), enc_rdbreg(priv, ENC_MAADR4),
- enc_rdbreg(priv, ENC_MAADR5), enc_rdbreg(priv, ENC_MAADR6));
+ lowsyslog("Rx Registers:\n");
+ lowsyslog(" EIE: %02x EIR: %02x\n",
+ enc_rdgreg(priv, ENC_EIE), enc_rdgreg(priv, ENC_EIR));
+ lowsyslog(" ESTAT: %02x ECON1: %02x ECON2: %02x\n",
+ enc_rdgreg(priv, ENC_ESTAT), enc_rdgreg(priv, ENC_ECON1),
+ enc_rdgreg(priv, ENC_ECON2));
+ lowsyslog(" ERXST: %02x %02x\n",
+ enc_rdbreg(priv, ENC_ERXSTH), enc_rdbreg(priv, ENC_ERXSTL));
+ lowsyslog(" ERXND: %02x %02x\n",
+ enc_rdbreg(priv, ENC_ERXNDH), enc_rdbreg(priv, ENC_ERXNDL));
+ lowsyslog(" ERXRDPT: %02x %02x\n",
+ enc_rdbreg(priv, ENC_ERXRDPTH), enc_rdbreg(priv, ENC_ERXRDPTL));
+ lowsyslog(" ERXFCON: %02x EPKTCNT: %02x\n",
+ enc_rdbreg(priv, ENC_ERXFCON), enc_rdbreg(priv, ENC_EPKTCNT));
+ lowsyslog(" MACON1: %02x MACON3: %02x\n",
+ enc_rdbreg(priv, ENC_MACON1), enc_rdbreg(priv, ENC_MACON3));
+ lowsyslog(" MAMXFL: %02x %02x\n",
+ enc_rdbreg(priv, ENC_MAMXFLH), enc_rdbreg(priv, ENC_MAMXFLL));
+ lowsyslog(" MAADR: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ enc_rdbreg(priv, ENC_MAADR1), enc_rdbreg(priv, ENC_MAADR2),
+ enc_rdbreg(priv, ENC_MAADR3), enc_rdbreg(priv, ENC_MAADR4),
+ enc_rdbreg(priv, ENC_MAADR5), enc_rdbreg(priv, ENC_MAADR6));
}
#endif
#if 0 /* Sometimes useful */
static void enc_txdump(FAR struct enc_driver_s *priv)
{
- lib_lowprintf("Tx Registers:\n");
- lib_lowprintf(" EIE: %02x EIR: %02x ESTAT: %02x\n",
- enc_rdgreg(priv, ENC_EIE), enc_rdgreg(priv, ENC_EIR),);
- lib_lowprintf(" ESTAT: %02x ECON1: %02x\n",
- enc_rdgreg(priv, ENC_ESTAT), enc_rdgreg(priv, ENC_ECON1));
- lib_lowprintf(" ETXST: %02x %02x\n",
- enc_rdbreg(priv, ENC_ETXSTH), enc_rdbreg(priv, ENC_ETXSTL));
- lib_lowprintf(" ETXND: %02x %02x\n",
- enc_rdbreg(priv, ENC_ETXNDH), enc_rdbreg(priv, ENC_ETXNDL));
- lib_lowprintf(" MACON1: %02x MACON3: %02x MACON4: %02x\n",
- enc_rdbreg(priv, ENC_MACON1), enc_rdbreg(priv, ENC_MACON3),
- enc_rdbreg(priv, ENC_MACON4));
- lib_lowprintf(" MACON1: %02x MACON3: %02x MACON4: %02x\n",
- enc_rdbreg(priv, ENC_MACON1), enc_rdbreg(priv, ENC_MACON3),
- enc_rdbreg(priv, ENC_MACON4));
- lib_lowprintf(" MABBIPG: %02x MAIPG %02x %02x\n",
- enc_rdbreg(priv, ENC_MABBIPG), enc_rdbreg(priv, ENC_MAIPGH),
- enc_rdbreg(priv, ENC_MAIPGL));
- lib_lowprintf(" MACLCON1: %02x MACLCON2: %02x\n",
- enc_rdbreg(priv, ENC_MACLCON1), enc_rdbreg(priv, ENC_MACLCON2));
- lib_lowprintf(" MAMXFL: %02x %02x\n",
- enc_rdbreg(priv, ENC_MAMXFLH), enc_rdbreg(priv, ENC_MAMXFLL));
+ lowsyslog("Tx Registers:\n");
+ lowsyslog(" EIE: %02x EIR: %02x ESTAT: %02x\n",
+ enc_rdgreg(priv, ENC_EIE), enc_rdgreg(priv, ENC_EIR),);
+ lowsyslog(" ESTAT: %02x ECON1: %02x\n",
+ enc_rdgreg(priv, ENC_ESTAT), enc_rdgreg(priv, ENC_ECON1));
+ lowsyslog(" ETXST: %02x %02x\n",
+ enc_rdbreg(priv, ENC_ETXSTH), enc_rdbreg(priv, ENC_ETXSTL));
+ lowsyslog(" ETXND: %02x %02x\n",
+ enc_rdbreg(priv, ENC_ETXNDH), enc_rdbreg(priv, ENC_ETXNDL));
+ lowsyslog(" MACON1: %02x MACON3: %02x MACON4: %02x\n",
+ enc_rdbreg(priv, ENC_MACON1), enc_rdbreg(priv, ENC_MACON3),
+ enc_rdbreg(priv, ENC_MACON4));
+ lowsyslog(" MACON1: %02x MACON3: %02x MACON4: %02x\n",
+ enc_rdbreg(priv, ENC_MACON1), enc_rdbreg(priv, ENC_MACON3),
+ enc_rdbreg(priv, ENC_MACON4));
+ lowsyslog(" MABBIPG: %02x MAIPG %02x %02x\n",
+ enc_rdbreg(priv, ENC_MABBIPG), enc_rdbreg(priv, ENC_MAIPGH),
+ enc_rdbreg(priv, ENC_MAIPGL));
+ lowsyslog(" MACLCON1: %02x MACLCON2: %02x\n",
+ enc_rdbreg(priv, ENC_MACLCON1), enc_rdbreg(priv, ENC_MACLCON2));
+ lowsyslog(" MAMXFL: %02x %02x\n",
+ enc_rdbreg(priv, ENC_MAMXFLH), enc_rdbreg(priv, ENC_MAMXFLL));
}
#endif
diff --git a/nuttx/drivers/serial/Kconfig b/nuttx/drivers/serial/Kconfig
index a1e0dff49..119923a69 100644
--- a/nuttx/drivers/serial/Kconfig
+++ b/nuttx/drivers/serial/Kconfig
@@ -10,6 +10,9 @@ config DEV_LOWCONSOLE
---help---
Use the simple, low-level, write-only serial console driver (minimal support)
+config SERIAL_REMOVABLE
+ bool
+
config 16550_UART
bool "16550 UART Chip support"
default n
diff --git a/nuttx/drivers/serial/serial.c b/nuttx/drivers/serial/serial.c
index 8987f01b8..0fed1d6c5 100644
--- a/nuttx/drivers/serial/serial.c
+++ b/nuttx/drivers/serial/serial.c
@@ -1,7 +1,7 @@
/************************************************************************************
* drivers/serial/serial.c
*
- * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -158,7 +158,11 @@ static void uart_pollnotify(FAR uart_dev_t *dev, pollevent_t eventset)
struct pollfd *fds = dev->fds[i];
if (fds)
{
+#ifdef CONFIG_SERIAL_REMOVABLE
+ fds->revents |= ((fds->events | (POLLERR|POLLHUP)) & eventset);
+#else
fds->revents |= (fds->events & eventset);
+#endif
if (fds->revents != 0)
{
fvdbg("Report events: %02x\n", fds->revents);
@@ -208,18 +212,40 @@ static int uart_putxmitchar(FAR uart_dev_t *dev, int ch)
*/
flags = irqsave();
- dev->xmitwaiting = true;
+#ifdef CONFIG_SERIAL_REMOVABLE
+ /* Check if the removable device is no longer connected while we
+ * have interrupts off. We do not want the transition to occur
+ * as a race condition before we begin the wait.
+ */
+
+ if (dev->disconnected)
+ {
+ irqrestore(flags);
+ return -ENOTCONN;
+ }
+#endif
/* Wait for some characters to be sent from the buffer with the TX
* interrupt enabled. When the TX interrupt is enabled, uart_xmitchars
* should execute and remove some of the data from the TX buffer.
*/
+ dev->xmitwaiting = true;
uart_enabletxint(dev);
ret = uart_takesem(&dev->xmitsem, true);
uart_disabletxint(dev);
irqrestore(flags);
+#ifdef CONFIG_SERIAL_REMOVABLE
+ /* Check if the removable device was disconnected while we were
+ * waiting.
+ */
+
+ if (dev->disconnected)
+ {
+ return -ENOTCONN;
+ }
+#endif
/* Check if we were awakened by signal. */
if (ret < 0)
@@ -288,6 +314,17 @@ static ssize_t uart_write(FAR struct file *filep, FAR const char *buffer, size_t
if (up_interrupt_context() || getpid() == 0)
{
+#ifdef CONFIG_SERIAL_REMOVABLE
+ /* If the removable device is no longer connected, refuse to write to
+ * the device.
+ */
+
+ if (dev->disconnected)
+ {
+ return -ENOTCONN;
+ }
+#endif
+
/* up_putc() will be used to generate the output in a busy-wait loop.
* up_putc() is only available for the console device.
*/
@@ -317,6 +354,20 @@ static ssize_t uart_write(FAR struct file *filep, FAR const char *buffer, size_t
return ret;
}
+#ifdef CONFIG_SERIAL_REMOVABLE
+ /* If the removable device is no longer connected, refuse to write to the
+ * device. This check occurs after taking the xmit.sem because the
+ * disconnection event might have occurred while we were waiting for
+ * access to the transmit buffers.
+ */
+
+ if (dev->disconnected)
+ {
+ uart_givesem(&dev->xmit.sem);
+ return -ENOTCONN;
+ }
+#endif
+
/* Loop while we still have data to copy to the transmit buffer.
* we add data to the head of the buffer; uart_xmitchars takes the
* data from the end of the buffer.
@@ -392,9 +443,13 @@ static ssize_t uart_write(FAR struct file *filep, FAR const char *buffer, size_t
uart_givesem(&dev->xmit.sem);
- /* Were we interrupted by a signal? That should be the only condition that
- * uart_putxmitchar() should return an error.
- */
+ /* uart_putxmitchar() might return an error under one of two
+ * conditions: (1) The wait for buffer space might have been
+ * interrupted by a signal (ret should be -EINTR), or (2) if
+ * CONFIG_SERIAL_REMOVABLE is defined, then uart_putxmitchar()
+ * might also return if the serial device was disconnected
+ * (wtih -ENOTCONN).
+ */
if (ret < 0)
{
@@ -413,11 +468,11 @@ static ssize_t uart_write(FAR struct file *filep, FAR const char *buffer, size_t
}
else
{
- /* No data was transferred. Return -EINTR. The VFS layer will
- * set the errno value appropriately).
+ /* No data was transferred. Return the negated error. The VFS layer
+ * will set the errno value appropriately).
*/
- nread = -EINTR;
+ nread = -ret;
}
}
@@ -458,6 +513,22 @@ static ssize_t uart_read(FAR struct file *filep, FAR char *buffer, size_t buflen
while (recvd < buflen)
{
+#ifdef CONFIG_SERIAL_REMOVABLE
+ /* If the removable device is no longer connected, refuse to read any
+ * further from the device.
+ */
+
+ if (dev->disconnected)
+ {
+ if (recvd == 0)
+ {
+ recvd = -ENOTCONN;
+ }
+
+ break;
+ }
+#endif
+
/* Check if there is more data to return in the circular buffer.
* NOTE: Rx interrupt handling logic may aynchronously increment
* the head index but must not modify the tail index. The tail
@@ -548,6 +619,7 @@ static ssize_t uart_read(FAR struct file *filep, FAR char *buffer, size_t buflen
{
recvd = -EAGAIN;
}
+
break;
}
#else
@@ -599,20 +671,41 @@ static ssize_t uart_read(FAR struct file *filep, FAR char *buffer, size_t buflen
*/
flags = irqsave();
- dev->recvwaiting = true;
- uart_enablerxint(dev);
+#ifdef CONFIG_SERIAL_REMOVABLE
+ /* Check if the removable device is no longer connected while
+ * we have interrupts off. We do not want the transition to
+ * occur as a race condition before we begin the wait.
+ */
+
+ if (dev->disconnected)
+ {
+ uart_enablerxint(dev);
+ irqrestore(flags);
+ ret = -ENOTCONN;
+ break;
+ }
+#endif
/* Now wait with the Rx interrupt re-enabled. NuttX will
* automatically re-enable global interrupts when this thread
* goes to sleep.
*/
+ dev->recvwaiting = true;
+ uart_enablerxint(dev);
ret = uart_takesem(&dev->recvsem, true);
irqrestore(flags);
- /* Was a signal received while waiting for data to be received? */
+ /* Was a signal received while waiting for data to be
+ * received? Was a removable device disconnected while
+ * we were waiting?
+ */
+#ifdef CONFIG_SERIAL_REMOVABLE
+ if (ret < 0 || dev->disconnected)
+#else
if (ret < 0)
+#endif
{
/* POSIX requires that we return after a signal is received.
* If some bytes were read, we need to return the number of bytes
@@ -626,7 +719,11 @@ static ssize_t uart_read(FAR struct file *filep, FAR char *buffer, size_t buflen
* set the errno value appropriately.
*/
+#ifdef CONFIG_SERIAL_REMOVABLE
+ recvd = dev->disconnected ? -ENOTCONN : -EINTR;
+#else
recvd = -EINTR;
+#endif
}
break;
@@ -852,12 +949,12 @@ int uart_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup)
if (ndx != dev->xmit.tail)
{
- eventset |= POLLOUT;
+ eventset |= (fds->events & POLLOUT);
}
uart_givesem(&dev->xmit.sem);
- /* Check if the receive buffer is empty
+ /* Check if the receive buffer is empty.
*
* Get exclusive access to the recv buffer indices. NOTE: that we do not
* let this wait be interrupted by a signal (we probably should, but that
@@ -867,11 +964,20 @@ int uart_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup)
(void)uart_takesem(&dev->recv.sem, false);
if (dev->recv.head != dev->recv.tail)
{
- eventset |= POLLIN;
+ eventset |= (fds->events & POLLIN);
}
uart_givesem(&dev->recv.sem);
+#ifdef CONFIG_SERIAL_REMOVABLE
+ /* Check if a removable device has been disconnected. */
+
+ if (dev->disconnected)
+ {
+ eventset |= (POLLERR|POLLHUP);
+ }
+#endif
+
if (eventset)
{
uart_pollnotify(dev, eventset);
@@ -971,6 +1077,7 @@ static int uart_close(FAR struct file *filep)
{
uart_shutdown(dev); /* Disable the UART */
}
+
irqrestore(flags);
uart_givesem(&dev->closesem);
@@ -1004,6 +1111,19 @@ static int uart_open(FAR struct file *filep)
return ret;
}
+#ifdef CONFIG_SERIAL_REMOVABLE
+ /* If the removable device is no longer connected, refuse to open the
+ * device. We check this after obtaining the close semaphore because
+ * we might have been waiting when the device was disconnected.
+ */
+
+ if (dev->disconnected)
+ {
+ ret = -ENOTCONN;
+ goto errout_with_sem;
+ }
+#endif
+
/* Start up serial port */
/* Increment the count of references to the device. */
@@ -1145,10 +1265,12 @@ int uart_register(FAR const char *path, FAR uart_dev_t *dev)
void uart_datareceived(FAR uart_dev_t *dev)
{
- /* Awaken any awaiting read() operations */
+ /* Is there a thread waiting for read data? */
if (dev->recvwaiting)
{
+ /* Yes... wake it up */
+
dev->recvwaiting = false;
(void)sem_post(&dev->recvsem);
}
@@ -1172,8 +1294,12 @@ void uart_datareceived(FAR uart_dev_t *dev)
void uart_datasent(FAR uart_dev_t *dev)
{
+ /* Is there a thread waiting for space in xmit.buffer? */
+
if (dev->xmitwaiting)
{
+ /* Yes... wake it up */
+
dev->xmitwaiting = false;
(void)sem_post(&dev->xmitsem);
}
@@ -1183,4 +1309,69 @@ void uart_datasent(FAR uart_dev_t *dev)
uart_pollnotify(dev, POLLOUT);
}
+/************************************************************************************
+ * Name: uart_connected
+ *
+ * Description:
+ * Serial devices (like USB serial) can be removed. In that case, the "upper
+ * half" serial driver must be informed that there is no longer a valid serial
+ * channel associated with the driver.
+ *
+ * In this case, the driver will terminate all pending transfers wint ENOTCONN and
+ * will refuse all further transactions while the "lower half" is disconnected.
+ * The driver will continue to be registered, but will be in an unusable state.
+ *
+ * Conversely, the "upper half" serial driver needs to know when the serial
+ * device is reconnected so that it can resume normal operations.
+ *
+ * Assumptions/Limitations:
+ * This function may be called from an interrupt handler.
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_SERIAL_REMOVABLE
+void uart_connected(FAR uart_dev_t *dev, bool connected)
+{
+ irqstate_t flags;
+
+ /* Is the device disconnected? */
+
+ flags = irqsave();
+ dev->disconnected = !connected;
+ if (!connected)
+ {
+ /* Yes.. wake up all waiting threads. Each thread should detect the
+ * disconnection and return the ENOTCONN error.
+ */
+
+ /* Is there a thread waiting for space in xmit.buffer? */
+
+ if (dev->xmitwaiting)
+ {
+ /* Yes... wake it up */
+
+ dev->xmitwaiting = false;
+ (void)sem_post(&dev->xmitsem);
+ }
+
+ /* Is there a thread waiting for read data? */
+
+ if (dev->recvwaiting)
+ {
+ /* Yes... wake it up */
+
+ dev->recvwaiting = false;
+ (void)sem_post(&dev->recvsem);
+ }
+
+ /* Notify all poll/select waiters that and hangup occurred */
+
+ uart_pollnotify(dev, (POLLERR|POLLHUP));
+ }
+
+ irqrestore(flags);
+}
+#endif
+
+
diff --git a/nuttx/drivers/syslog/ramlog.c b/nuttx/drivers/syslog/ramlog.c
index b3a2ad0f5..08bbbfb59 100644
--- a/nuttx/drivers/syslog/ramlog.c
+++ b/nuttx/drivers/syslog/ramlog.c
@@ -726,10 +726,10 @@ int ramlog_sysloginit(void)
*
* Description:
* This is the low-level system logging interface. The debugging/syslogging
- * interfaces are lib_rawprintf() and lib_lowprinf(). The difference is
- * the lib_rawprintf() writes to fd=1 (stdout) and lib_lowprintf() uses
+ * interfaces are syslog() and lowsyslog(). The difference is that
+ * the syslog() internface writes to fd=1 (stdout) whereas lowsyslog() uses
* a lower level interface that works from interrupt handlers. This
- * function is a a low-level interface used to implement lib_lowprintf()
+ * function is a a low-level interface used to implement lowsyslog()
* when CONFIG_RAMLOG_SYSLOG=y and CONFIG_SYSLOG=y
*
****************************************************************************/
diff --git a/nuttx/drivers/usbdev/Kconfig b/nuttx/drivers/usbdev/Kconfig
index 70c7a04f0..0752bb791 100644
--- a/nuttx/drivers/usbdev/Kconfig
+++ b/nuttx/drivers/usbdev/Kconfig
@@ -148,12 +148,21 @@ config COMPOSITE_VERSIONNO
endif
menuconfig PL2303
- bool "Emulates the Prolific PL2303 serial/USB converter"
+ bool "Prolific PL2303 serial/USB converter emulation"
default n
+ select SERIAL_REMOVABLE
---help---
This logic emulates the Prolific PL2303 serial/USB converter
if PL2303
+
+config PL2303_CONSOLE
+ bool "PL2303 console device"
+ default n
+ ---help---
+ Register the USB device as /dev/console so that is will be used
+ as the console device.
+
config PL2303_EPINTIN
int "Logical endpoint numbers"
default 1
@@ -208,18 +217,27 @@ config PL2303_VENDORSTR
config PL2303_PRODUCTSTR
string "Product string"
- default "USBdev Serial"
+ default "PL2303 Emulation"
endif
menuconfig CDCACM
bool "USB Modem (CDC ACM) support"
default n
+ select SERIAL_REMOVABLE
---help---
Enables USB Modem (CDC ACM) support
if CDCACM
+
+config CDCACM_CONSOLE
+ bool "CDC/ACM console device"
+ default n
+ ---help---
+ Register the USB device as /dev/console so that is will be used
+ as the console device.
+
config CDCACM_COMPOSITE
- bool "CDCACM composite support"
+ bool "CDC/ACM composite support"
default n
depends on USBDEV_COMPOSITE
---help---
@@ -256,10 +274,10 @@ config CDCACM_EP0MAXPACKET
config CDCACM_EPINTIN
int "Hardware endpoint that supports interrupt IN operation"
- default 2
+ default 1
---help---
The logical 7-bit address of a hardware endpoint that supports
- interrupt IN operation. Default 2.
+ interrupt IN operation. Default 1.
config CDCACM_EPINTIN_FSSIZE
int "Endpoint in full speed size"
@@ -277,10 +295,10 @@ config CDCACM_EPINTIN_HSSIZE
config CDCACM_EPBULKOUT
int "Endpoint bulk out"
- default 0
+ default 3
---help---
The logical 7-bit address of a hardware endpoint that supports
- bulk OUT operation
+ bulk OUT operation. Default: 3
config CDCACM_EPBULKOUT_FSSIZE
int "Endpoint bulk out full speed size"
@@ -298,10 +316,10 @@ config CDCACM_EPBULKOUT_HSSIZE
config CDCACM_EPBULKIN
int "Endpoint bulk in"
- default 0
+ default 2
---help---
The logical 7-bit address of a hardware endpoint that supports
- bulk IN operation
+ bulk IN operation. Default: 2
config CDCACM_EPBULKIN_FSSIZE
int "Endpoint bulk in full speed size"
@@ -336,7 +354,7 @@ config CDCACM_RXBUFSIZE
Size of the serial receive/transmit buffers
config CDCACM_TXBUFSIZE
- bool "Transmit buffer size"
+ int "Transmit buffer size"
default 256
---help---
Size of the serial receive/transmit buffers
@@ -364,7 +382,7 @@ config CDCACM_VENDORSTR
config CDCACM_PRODUCTSTR
string "Product string"
- default "USBdev Serial"
+ default "CDC/ACM Serial"
endif
menuconfig USBMSC
@@ -479,8 +497,8 @@ config USBMSC_PRODUCTID
default 0x00
config USBMSC_PRODUCTSTR
- string "Mass stroage product string"
- default "Mass stroage"
+ string "Mass storage product string"
+ default "Mass Storage"
config USBMSC_VERSIONNO
hex "USB MSC Version Number"
diff --git a/nuttx/drivers/usbdev/cdcacm.c b/nuttx/drivers/usbdev/cdcacm.c
index 97c9d7c77..cb8679976 100644
--- a/nuttx/drivers/usbdev/cdcacm.c
+++ b/nuttx/drivers/usbdev/cdcacm.c
@@ -1,7 +1,7 @@
/****************************************************************************
* drivers/usbdev/cdcacm.c
*
- * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -188,6 +188,12 @@ static int cdcacm_setup(FAR struct usbdevclass_driver_s *driver,
size_t outlen);
static void cdcacm_disconnect(FAR struct usbdevclass_driver_s *driver,
FAR struct usbdev_s *dev);
+#ifdef CONFIG_SERIAL_REMOVABLE
+static void cdcacm_suspend(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev);
+static void cdcacm_resume(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev);
+#endif
/* UART Operations **********************************************************/
@@ -211,8 +217,13 @@ static const struct usbdevclass_driverops_s g_driverops =
cdcacm_unbind, /* unbind */
cdcacm_setup, /* setup */
cdcacm_disconnect, /* disconnect */
+#ifdef CONFIG_SERIAL_REMOVABLE
+ cdcacm_suspend, /* suspend */
+ cdcacm_resume, /* resume */
+#else
NULL, /* suspend */
NULL, /* resume */
+#endif
};
/* Serial port **************************************************************/
@@ -570,6 +581,14 @@ static void cdcacm_resetconfig(FAR struct cdcacm_dev_s *priv)
priv->config = CDCACM_CONFIGIDNONE;
+ /* Inform the "upper half" driver that there is no (functional) USB
+ * connection.
+ */
+
+#ifdef CONFIG_SERIAL_REMOVABLE
+ uart_connected(&priv->serdev, false);
+#endif
+
/* Disable endpoints. This should force completion of all pending
* transfers.
*/
@@ -731,10 +750,20 @@ static int cdcacm_setconfig(FAR struct cdcacm_dev_s *priv, uint8_t config)
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RDSUBMIT), (uint16_t)-ret);
goto errout;
}
+
priv->nrdq++;
}
+ /* We are successfully configured */
+
priv->config = config;
+
+ /* Inform the "upper half" driver that we are "open for business" */
+
+#ifdef CONFIG_SERIAL_REMOVABLE
+ uart_connected(&priv->serdev, true);
+#endif
+
return OK;
errout:
@@ -823,6 +852,7 @@ static void cdcacm_rdcomplete(FAR struct usbdev_ep_s *ep,
{
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RDSUBMIT), (uint16_t)-req->result);
}
+
irqrestore(flags);
}
@@ -932,6 +962,7 @@ static int cdcacm_bind(FAR struct usbdevclass_driver_s *driver,
ret = -ENOMEM;
goto errout;
}
+
priv->ctrlreq->callback = cdcacm_ep0incomplete;
/* Pre-allocate all endpoints... the endpoints will not be functional
@@ -1575,12 +1606,20 @@ static void cdcacm_disconnect(FAR struct usbdevclass_driver_s *driver,
}
#endif
- /* Reset the configuration */
+ /* Inform the "upper half serial driver that we have lost the USB serial
+ * connection.
+ */
flags = irqsave();
+#ifdef CONFIG_SERIAL_REMOVABLE
+ uart_connected(&priv->serdev, false);
+#endif
+
+ /* Reset the configuration */
+
cdcacm_resetconfig(priv);
- /* Clear out all data in the circular buffer */
+ /* Clear out all outgoing data in the circular buffer */
priv->serdev.xmit.head = 0;
priv->serdev.xmit.tail = 0;
@@ -1596,6 +1635,79 @@ static void cdcacm_disconnect(FAR struct usbdevclass_driver_s *driver,
}
/****************************************************************************
+ * Name: cdcacm_suspend
+ *
+ * Description:
+ * Handle the USB suspend event.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SERIAL_REMOVABLE
+static void cdcacm_suspend(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev)
+{
+ FAR struct cdcacm_dev_s *priv;
+
+ usbtrace(TRACE_CLASSSUSPEND, 0);
+
+#ifdef CONFIG_DEBUG
+ if (!driver || !dev)
+ {
+ usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0);
+ return;
+ }
+#endif
+
+ /* Extract reference to private data */
+
+ priv = ((FAR struct cdcacm_driver_s*)driver)->dev;
+
+ /* And let the "upper half" driver now that we are suspended */
+
+ uart_connected(&priv->serdev, false);
+}
+#endif
+
+/****************************************************************************
+ * Name: cdcacm_resume
+ *
+ * Description:
+ * Handle the USB resume event.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SERIAL_REMOVABLE
+static void cdcacm_resume(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev)
+{
+ FAR struct cdcacm_dev_s *priv;
+
+ usbtrace(TRACE_CLASSRESUME, 0);
+
+#ifdef CONFIG_DEBUG
+ if (!driver || !dev)
+ {
+ usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0);
+ return;
+ }
+#endif
+
+ /* Extract reference to private data */
+
+ priv = ((FAR struct cdcacm_driver_s*)driver)->dev;
+
+ /* Are we still configured? */
+
+ if (priv->config != CDCACM_CONFIGIDNONE)
+ {
+ /* Yes.. let the "upper half" know that have resumed */
+
+ uart_connected(&priv->serdev, true);
+ }
+}
+#endif
+
+/****************************************************************************
* Serial Device Methods
****************************************************************************/
@@ -2045,12 +2157,17 @@ int cdcacm_classobject(int minor, FAR struct usbdevclass_driver_s **classdev)
/* Initialize the serial driver sub-structure */
- priv->serdev.recv.size = CONFIG_CDCACM_RXBUFSIZE;
- priv->serdev.recv.buffer = priv->rxbuffer;
- priv->serdev.xmit.size = CONFIG_CDCACM_TXBUFSIZE;
- priv->serdev.xmit.buffer = priv->txbuffer;
- priv->serdev.ops = &g_uartops;
- priv->serdev.priv = priv;
+ /* The initial state is disconnected */
+
+#ifdef CONFIG_SERIAL_REMOVABLE
+ priv->serdev.disconnected = true;
+#endif
+ priv->serdev.recv.size = CONFIG_CDCACM_RXBUFSIZE;
+ priv->serdev.recv.buffer = priv->rxbuffer;
+ priv->serdev.xmit.size = CONFIG_CDCACM_TXBUFSIZE;
+ priv->serdev.xmit.buffer = priv->txbuffer;
+ priv->serdev.ops = &g_uartops;
+ priv->serdev.priv = priv;
/* Initialize the USB class driver structure */
@@ -2148,7 +2265,7 @@ int cdcacm_initialize(int minor, FAR void **handle)
*
* Description:
* Un-initialize the USB storage class driver. This function is used
- * internally by the USB composite driver to unitialized the CDC/ACM
+ * internally by the USB composite driver to unitialize the CDC/ACM
* driver. This same interface is available (with an untyped input
* parameter) when the CDC/ACM driver is used standalone.
*
diff --git a/nuttx/drivers/usbdev/pl2303.c b/nuttx/drivers/usbdev/pl2303.c
index d10539fa7..7b07a9cba 100644
--- a/nuttx/drivers/usbdev/pl2303.c
+++ b/nuttx/drivers/usbdev/pl2303.c
@@ -343,6 +343,12 @@ static int usbclass_setup(FAR struct usbdevclass_driver_s *driver,
size_t outlen);
static void usbclass_disconnect(FAR struct usbdevclass_driver_s *driver,
FAR struct usbdev_s *dev);
+#ifdef CONFIG_SERIAL_REMOVABLE
+static void usbclass_suspend(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev);
+static void usbclass_resume(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev);
+#endif
/* Serial port *************************************************************/
@@ -366,8 +372,13 @@ static const struct usbdevclass_driverops_s g_driverops =
usbclass_unbind, /* unbind */
usbclass_setup, /* setup */
usbclass_disconnect, /* disconnect */
+#ifdef CONFIG_SERIAL_REMOVABLE
+ usbclass_suspend, /* suspend */
+ usbclass_resume, /* resume */
+#else
NULL, /* suspend */
NULL, /* resume */
+#endif
};
/* Serial port *************************************************************/
@@ -983,6 +994,14 @@ static void usbclass_resetconfig(FAR struct pl2303_dev_s *priv)
priv->config = PL2303_CONFIGIDNONE;
+ /* Inform the "upper half" driver that there is no (functional) USB
+ * connection.
+ */
+
+#ifdef CONFIG_SERIAL_REMOVABLE
+ uart_connected(&priv->serdev, false);
+#endif
+
/* Disable endpoints. This should force completion of all pending
* transfers.
*/
@@ -1112,10 +1131,20 @@ static int usbclass_setconfig(FAR struct pl2303_dev_s *priv, uint8_t config)
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RDSUBMIT), (uint16_t)-ret);
goto errout;
}
+
priv->nrdq++;
}
+ /* We are successfully configured */
+
priv->config = config;
+
+ /* Inform the "upper half" driver that we are "open for business" */
+
+#ifdef CONFIG_SERIAL_REMOVABLE
+ uart_connected(&priv->serdev, true);
+#endif
+
return OK;
errout:
@@ -1844,12 +1873,20 @@ static void usbclass_disconnect(FAR struct usbdevclass_driver_s *driver,
}
#endif
- /* Reset the configuration */
+ /* Inform the "upper half serial driver that we have lost the USB serial
+ * connection.
+ */
flags = irqsave();
+#ifdef CONFIG_SERIAL_REMOVABLE
+ uart_connected(&priv->serdev, false);
+#endif
+
+ /* Reset the configuration */
+
usbclass_resetconfig(priv);
- /* Clear out all data in the circular buffer */
+ /* Clear out all outgoing data in the circular buffer */
priv->serdev.xmit.head = 0;
priv->serdev.xmit.tail = 0;
@@ -1863,6 +1900,79 @@ static void usbclass_disconnect(FAR struct usbdevclass_driver_s *driver,
}
/****************************************************************************
+ * Name: usbclass_suspend
+ *
+ * Description:
+ * Handle the USB suspend event.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SERIAL_REMOVABLE
+static void usbclass_suspend(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev)
+{
+ FAR struct cdcacm_dev_s *priv;
+
+ usbtrace(TRACE_CLASSSUSPEND, 0);
+
+#ifdef CONFIG_DEBUG
+ if (!driver || !dev)
+ {
+ usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0);
+ return;
+ }
+#endif
+
+ /* Extract reference to private data */
+
+ priv = ((FAR struct cdcacm_driver_s*)driver)->dev;
+
+ /* And let the "upper half" driver now that we are suspended */
+
+ uart_connected(&priv->serdev, false);
+}
+#endif
+
+/****************************************************************************
+ * Name: usbclass_resume
+ *
+ * Description:
+ * Handle the USB resume event.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SERIAL_REMOVABLE
+static void usbclass_resume(FAR struct usbdevclass_driver_s *driver,
+ FAR struct usbdev_s *dev)
+{
+ FAR struct cdcacm_dev_s *priv;
+
+ usbtrace(TRACE_CLASSRESUME, 0);
+
+#ifdef CONFIG_DEBUG
+ if (!driver || !dev)
+ {
+ usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0);
+ return;
+ }
+#endif
+
+ /* Extract reference to private data */
+
+ priv = ((FAR struct cdcacm_driver_s*)driver)->dev;
+
+ /* Are we still configured? */
+
+ if (priv->config != PL2303_CONFIGIDNONE)
+ {
+ /* Yes.. let the "upper half" know that have resumed */
+
+ uart_connected(&priv->serdev, true);
+ }
+}
+#endif
+
+/****************************************************************************
* Serial Device Methods
****************************************************************************/
@@ -2185,12 +2295,15 @@ int usbdev_serialinitialize(int minor)
/* Initialize the serial driver sub-structure */
- priv->serdev.recv.size = CONFIG_PL2303_RXBUFSIZE;
- priv->serdev.recv.buffer = priv->rxbuffer;
- priv->serdev.xmit.size = CONFIG_PL2303_TXBUFSIZE;
- priv->serdev.xmit.buffer = priv->txbuffer;
- priv->serdev.ops = &g_uartops;
- priv->serdev.priv = priv;
+#ifdef CONFIG_SERIAL_REMOVABLE
+ priv->serdev.disconnected = true;
+#endif
+ priv->serdev.recv.size = CONFIG_PL2303_RXBUFSIZE;
+ priv->serdev.recv.buffer = priv->rxbuffer;
+ priv->serdev.xmit.size = CONFIG_PL2303_TXBUFSIZE;
+ priv->serdev.xmit.buffer = priv->txbuffer;
+ priv->serdev.ops = &g_uartops;
+ priv->serdev.priv = priv;
/* Initialize the USB class driver structure */
diff --git a/nuttx/drivers/usbdev/usbdev_trace.c b/nuttx/drivers/usbdev/usbdev_trace.c
index c8cc09292..c332c1358 100644
--- a/nuttx/drivers/usbdev/usbdev_trace.c
+++ b/nuttx/drivers/usbdev/usbdev_trace.c
@@ -168,9 +168,9 @@ void usbtrace(uint16_t event, uint16_t value)
}
}
#else
- /* Just print the data using lib_lowprintf */
+ /* Just print the data using lowsyslog */
- usbtrace_trprintf((trprintf_t)lib_lowprintf, event, value);
+ usbtrace_trprintf((trprintf_t)lowsyslog, event, value);
#endif
}
irqrestore(flags);
diff --git a/nuttx/drivers/usbdev/usbmsc.h b/nuttx/drivers/usbdev/usbmsc.h
index 883a49951..da35ae923 100644
--- a/nuttx/drivers/usbdev/usbmsc.h
+++ b/nuttx/drivers/usbdev/usbmsc.h
@@ -199,9 +199,9 @@
#ifdef CONFIG_CPP_HAVE_VARARGS
# ifdef CONFIG_DEBUG
# ifdef CONFIG_ARCH_LOWPUTC
-# define dbgprintf(format, arg...) lib_lowprintf(format, ##arg)
+# define dbgprintf(format, arg...) lowsyslog(format, ##arg)
# else
-# define dbgprintf(format, arg...) lib_rawprintf(format, ##arg)
+# define dbgprintf(format, arg...) syslog(format, ##arg)
# endif
# else
# define dbgprintf(x...)
@@ -209,9 +209,9 @@
#else
# ifdef CONFIG_DEBUG
# ifdef CONFIG_ARCH_LOWPUTC
-# define dbgprintf lib_lowprintf
+# define dbgprintf lowsyslog
# else
-# define dbgprintf lib_rawprintf
+# define dbgprintf syslog
# endif
# else
# define dbgprintf (void)
diff --git a/nuttx/fs/Kconfig b/nuttx/fs/Kconfig
index dfbfda3fa..6aac7a3f7 100644
--- a/nuttx/fs/Kconfig
+++ b/nuttx/fs/Kconfig
@@ -5,6 +5,10 @@
comment "File system configuration"
+config DISABLE_MOUNTPOINT
+ bool "Disable support for mount points"
+ default n
+
source fs/mmap/Kconfig
source fs/fat/Kconfig
source fs/nfs/Kconfig
@@ -14,29 +18,43 @@ source fs/binfs/Kconfig
comment "System Logging"
-config SYSLOG
- bool "System logging"
+config SYSLOG_ENABLE
+ bool "Enable SYSLOG Controls"
default n
---help---
- Enables generic system logging features.
+ Support an interface called syslog_enable to dynamically enable or
+ disable SYSLOG output. Default: SYSLOG output is always enabled.
-config SYSLOG_DEVPATH
- string "System log device"
- default "/dev/syslog"
- depends on SYSLOG
+config SYSLOG
+ bool "Advanced SYSLOG features"
+ default n
---help---
- The full path to the system logging device. For the RAMLOG SYSLOG device,
- this is normally "/dev/ramlog". For character SYSLOG devices, it should be
- some other existing character device (or file) supported by the configuration
- (such as "/dev/ttyS1")/
+ Enables generic system logging features. NOTE: This setting is not
+ required to enable system logging. If this feature is not enable
+ system logging will still be available and will log to the system
+ console (like printf()). This setting is required to enable
+ customization of the basic system loggin capability.
+
+if SYSLOG
config SYSLOG_CHAR
bool "System log character device support"
default y
- depends on SYSLOG
---help---
Enable the generic character device for the SYSLOG. The full path to the
SYSLOG device is provided by SYSLOG_DEVPATH. A valid character device (or
file) must exist at this path. It will by opened by syslog_initialize.
Do not enable more than one SYSLOG device.
+
+config SYSLOG_DEVPATH
+ string "System log device"
+ default "/dev/syslog"
+ depends on SYSLOG_CHAR
+ ---help---
+ The full path to the system logging device. For the RAMLOG SYSLOG device,
+ this is normally "/dev/ramlog". For character SYSLOG devices, it should be
+ some other existing character device (or file) supported by the configuration
+ (such as "/dev/ttyS1")/
+
+endif
diff --git a/nuttx/fs/fat/fs_configfat.c b/nuttx/fs/fat/fs_configfat.c
index 2075caa9f..04141ee2b 100644
--- a/nuttx/fs/fat/fs_configfat.c
+++ b/nuttx/fs/fat/fs_configfat.c
@@ -406,7 +406,7 @@ mkfatfs_clustersearchlimits(FAR struct fat_format_s *fmt, FAR struct fat_var_s *
}
/****************************************************************************
- * Name: mkfatfs_try12
+ * Name: mkfatfs_tryfat12
*
* Description:
* Try to define a FAT12 filesystem on the device using the candidate
@@ -462,7 +462,7 @@ mkfatfs_tryfat12(FAR struct fat_format_s *fmt, FAR struct fat_var_s *var,
* FAT12 (remembering that two FAT cluster slots are reserved).
*/
- if (config->fc_nclusters > maxnclusters - 2)
+ if (config->fc_nclusters + 2 > maxnclusters)
{
fvdbg("Too many clusters for FAT12\n");
return -ENFILE;
@@ -472,7 +472,7 @@ mkfatfs_tryfat12(FAR struct fat_format_s *fmt, FAR struct fat_var_s *var,
}
/****************************************************************************
- * Name: mkfatfs_try16
+ * Name: mkfatfs_tryfat16
*
* Description:
* Try to define a FAT16 filesystem on the device using the candidate
@@ -532,7 +532,7 @@ mkfatfs_tryfat16(FAR struct fat_format_s *fmt, FAR struct fat_var_s *var,
* be confused as a FAT12 at mount time.
*/
- if ((config->fc_nclusters > maxnclusters - 2) ||
+ if ((config->fc_nclusters + 2 > maxnclusters) ||
(config->fc_nclusters < FAT_MINCLUST16))
{
fvdbg("Too few or too many clusters for FAT16\n");
@@ -543,7 +543,7 @@ mkfatfs_tryfat16(FAR struct fat_format_s *fmt, FAR struct fat_var_s *var,
}
/****************************************************************************
- * Name: mkfatfs_try32
+ * Name: mkfatfs_tryfat32
*
* Description:
* Try to define a FAT32 filesystem on the device using the candidate
@@ -587,7 +587,7 @@ mkfatfs_tryfat32(FAR struct fat_format_s *fmt, FAR struct fat_var_s *var,
* maxnclusters = nfatsects * sectorsize / 4 - 2
*/
- maxnclusters = (config->fc_nfatsects >> (var->fv_sectshift - 2));
+ maxnclusters = (config->fc_nfatsects << (var->fv_sectshift - 2));
if (maxnclusters > FAT_MAXCLUST32)
{
maxnclusters = FAT_MAXCLUST32;
@@ -599,7 +599,7 @@ mkfatfs_tryfat32(FAR struct fat_format_s *fmt, FAR struct fat_var_s *var,
* FAT32 (remembering that two FAT cluster slots are reserved).
*/
- if ((config->fc_nclusters > maxnclusters - 3) ||
+ if ((config->fc_nclusters + 3 > maxnclusters) ||
(config->fc_nclusters < FAT_MINCLUST32 && fmt->ff_fattype != 32))
{
fvdbg("Too few or too many clusters for FAT32\n");
diff --git a/nuttx/fs/fat/fs_fat32.c b/nuttx/fs/fat/fs_fat32.c
index c10c28a5c..df8962b51 100644
--- a/nuttx/fs/fat/fs_fat32.c
+++ b/nuttx/fs/fat/fs_fat32.c
@@ -381,6 +381,7 @@ static int fat_close(FAR struct file *filep)
{
struct inode *inode;
struct fat_file_s *ff;
+ struct fat_mountpt_s *fs;
int ret = OK;
/* Sanity checks */
@@ -391,6 +392,7 @@ static int fat_close(FAR struct file *filep)
ff = filep->f_priv;
inode = filep->f_inode;
+ fs = inode->i_private;
/* Do not check if the mount is healthy. We must support closing of
* the file even when there is healthy mount.
@@ -408,6 +410,7 @@ static int fat_close(FAR struct file *filep)
if (ff->ff_buffer)
{
+ (void)fs; /* Unused if fat_io_free == free(). */
fat_io_free(ff->ff_buffer, fs->fs_hwsectorsize);
}
diff --git a/nuttx/fs/fat/fs_fat32util.c b/nuttx/fs/fat/fs_fat32util.c
index 9aa1d3992..8edef7735 100644
--- a/nuttx/fs/fat/fs_fat32util.c
+++ b/nuttx/fs/fat/fs_fat32util.c
@@ -106,8 +106,8 @@ static int fat_checkfsinfo(struct fat_mountpt_s *fs)
FSI_GETSTRUCTSIG(fs->fs_buffer) == 0x61417272 &&
FSI_GETTRAILSIG(fs->fs_buffer) == BOOT_SIGNATURE32)
{
- fs->fs_fsinextfree = FSI_GETFREECOUNT(fs->fs_buffer);
- fs->fs_fsifreecount = FSI_GETNXTFREE(fs->fs_buffer);
+ fs->fs_fsifreecount = FSI_GETFREECOUNT(fs->fs_buffer);
+ fs->fs_fsinextfree = FSI_GETNXTFREE(fs->fs_buffer);
return OK;
}
}
diff --git a/nuttx/fs/fs_fdopen.c b/nuttx/fs/fs_fdopen.c
index fd6aa88a8..d8a370482 100644
--- a/nuttx/fs/fs_fdopen.c
+++ b/nuttx/fs/fs_fdopen.c
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/fs_fdopen.c
*
- * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -68,9 +68,11 @@ static inline int fs_checkfd(FAR _TCB *tcb, int fd, int oflags)
FAR struct filelist *flist;
FAR struct inode *inode;
- /* Get the file list from the TCB */
+ DEBUGASSERT(tcb && tcb->group);
- flist = tcb->filelist;
+ /* Get the file list from the task group */
+
+ flist = &tcb->group->tg_filelist;
/* Get the inode associated with the file descriptor. This should
* normally be the case if fd >= 0. But not in the case where the
@@ -142,6 +144,7 @@ FAR struct file_struct *fs_fdopen(int fd, int oflags, FAR _TCB *tcb)
{
tcb = sched_self();
}
+ DEBUGASSERT(tcb && tcb->group);
/* Verify that this is a valid file/socket descriptor and that the
* requested access can be support.
@@ -189,9 +192,9 @@ FAR struct file_struct *fs_fdopen(int fd, int oflags, FAR _TCB *tcb)
/* Get the stream list from the TCB */
- slist = tcb->streams;
+ slist = &tcb->group->tg_streamlist;
- /* Find an unallocated FILE structure in the stream list */
+ /* Find an unallocated FILE structure in the stream list */
ret = sem_wait(&slist->sl_sem);
if (ret != OK)
diff --git a/nuttx/fs/fs_files.c b/nuttx/fs/fs_files.c
index 06addb1ef..c68ec7e73 100644
--- a/nuttx/fs/fs_files.c
+++ b/nuttx/fs/fs_files.c
@@ -155,56 +155,19 @@ void files_initialize(void)
}
/****************************************************************************
- * Name: files_alloclist
+ * Name: files_initlist
*
- * Description: Allocate a list of files for a new task
+ * Description: Initializes the list of files for a new task
*
****************************************************************************/
-FAR struct filelist *files_alloclist(void)
+void files_initlist(FAR struct filelist *list)
{
- FAR struct filelist *list;
- list = (FAR struct filelist*)kzalloc(sizeof(struct filelist));
- if (list)
- {
- /* Start with a reference count of one */
-
- list->fl_crefs = 1;
-
- /* Initialize the list access mutex */
+ DEBUGASSERT(list);
- (void)sem_init(&list->fl_sem, 0, 1);
- }
+ /* Initialize the list access mutex */
- return list;
-}
-
-/****************************************************************************
- * Name: files_addreflist
- *
- * Description:
- * Increase the reference count on a file list
- *
- ****************************************************************************/
-
-int files_addreflist(FAR struct filelist *list)
-{
- if (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.
- */
-
- register irqstate_t flags = irqsave();
- list->fl_crefs++;
- irqrestore(flags);
- }
-
- return OK;
+ (void)sem_init(&list->fl_sem, 0, 1);
}
/****************************************************************************
@@ -215,51 +178,25 @@ int files_addreflist(FAR struct filelist *list)
*
****************************************************************************/
-int files_releaselist(FAR struct filelist *list)
+void files_releaselist(FAR struct filelist *list)
{
- int crefs;
- if (list)
- {
- /* 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.
- */
-
- register irqstate_t flags = irqsave();
- crefs = --(list->fl_crefs);
- irqrestore(flags);
-
- /* If the count decrements to zero, then there is no reference
- * 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)
- {
- int i;
+ int i;
- /* Close each file descriptor .. Normally, you would need
- * take the list semaphore, but it is safe to ignore the
- * semaphore in this context because there are no references
- */
+ DEBUGASSERT(list);
- for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++)
- {
- (void)_files_close(&list->fl_files[i]);
- }
-
- /* Destroy the semaphore and release the filelist */
+ /* Close each file descriptor .. Normally, you would need take the list
+ * semaphore, but it is safe to ignore the semaphore in this context because
+ * there should not be any references in this context.
+ */
- (void)sem_destroy(&list->fl_sem);
- sched_free(list);
- }
+ for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++)
+ {
+ (void)_files_close(&list->fl_files[i]);
}
- return OK;
+ /* Destroy the semaphore */
+
+ (void)sem_destroy(&list->fl_sem);
}
/****************************************************************************
diff --git a/nuttx/fs/fs_syslog.c b/nuttx/fs/fs_syslog.c
index 1d569082a..d9ad29e0f 100644
--- a/nuttx/fs/fs_syslog.c
+++ b/nuttx/fs/fs_syslog.c
@@ -42,6 +42,7 @@
#include <sys/types.h>
#include <stdint.h>
+#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <semaphore.h>
@@ -167,8 +168,10 @@ static inline int syslog_takesem(void)
static inline void syslog_givesem(void)
{
+#ifdef CONFIG_DEBUG
pid_t me = getpid();
DEBUGASSERT(g_sysdev.sl_holder == me);
+#endif
/* Relinquish the semaphore */
@@ -265,7 +268,7 @@ int syslog_initialize(void)
{
/* The inode was not found. In this case, we will attempt to re-open
* the device repeatedly. The assumption is that the device path is
- * value but that the driver has not yet been registered.
+ * valid but that the driver has not yet been registered.
*/
g_sysdev.sl_state = SYSLOG_REOPEN;
@@ -282,7 +285,7 @@ int syslog_initialize(void)
if (!INODE_IS_DRIVER(inode))
#endif
{
- ret = ENXIO;
+ ret = -ENXIO;
goto errout_with_inode;
}
@@ -290,7 +293,7 @@ int syslog_initialize(void)
if (!inode->u.i_ops || !inode->u.i_ops->write)
{
- return -EACCES;
+ ret = -EACCES;
goto errout_with_inode;
}
@@ -346,8 +349,8 @@ int syslog_initialize(void)
return OK;
errout_with_inode:
- g_sysdev.sl_state = SYSLOG_FAILURE;
inode_release(inode);
+ g_sysdev.sl_state = SYSLOG_FAILURE;
return ret;
}
@@ -356,16 +359,18 @@ int syslog_initialize(void)
*
* Description:
* This is the low-level system logging interface. The debugging/syslogging
- * interfaces are lib_rawprintf() and lib_lowprinf(). The difference is
- * the lib_rawprintf() writes to fd=1 (stdout) and lib_lowprintf() uses
+ * interfaces are syslog() and lowsyslog(). The difference is is that
+ * the syslog() function writes to fd=1 (stdout) whereas lowsyslog() uses
* a lower level interface that works from interrupt handlers. This
- * function is a a low-level interface used to implement lib_lowprintf().
+ * function is a a low-level interface used to implement lowsyslog().
*
****************************************************************************/
int syslog_putc(int ch)
{
ssize_t nbytes;
+ uint8_t uch;
+ int errcode;
int ret;
/* Ignore any output:
@@ -382,7 +387,10 @@ int syslog_putc(int ch)
* (4) Any debug output generated from interrupt handlers. A disadvantage
* of using the generic character device for the SYSLOG is that it
* cannot handle debug output generated from interrupt level handlers.
- * (5) If an irrecoverable failure occurred during initialization. In
+ * (5) Any debug output generated from the IDLE loop. The character
+ * driver interface is blocking and the IDLE thread is not permitted
+ * to block.
+ * (6) If an irrecoverable failure occurred during initialization. In
* this case, we won't ever bother to try again (ever).
*
* NOTE: That the third case is different. It applies only to the thread
@@ -390,11 +398,12 @@ int syslog_putc(int ch)
* that is why that case is handled in syslog_semtake().
*/
- /* Case (4) */
+ /* Cases (4) and (5) */
- if (up_interrupt_context())
+ if (up_interrupt_context() || getpid() == 0)
{
- return -ENOSYS; /* Not supported */
+ errcode = ENOSYS;
+ goto errout_with_errcode;
}
/* We can save checks in the usual case: That after the SYSLOG device
@@ -408,14 +417,16 @@ int syslog_putc(int ch)
if (g_sysdev.sl_state == SYSLOG_UNINITIALIZED ||
g_sysdev.sl_state == SYSLOG_INITIALIZING)
{
- return -EAGAIN; /* Can't access the SYSLOG now... maybe next time? */
+ errcode = EAGAIN; /* Can't access the SYSLOG now... maybe next time? */
+ goto errout_with_errcode;
}
- /* Case (5) */
+ /* Case (6) */
if (g_sysdev.sl_state == SYSLOG_FAILURE)
{
- return -ENXIO; /* There is no SYSLOG device */
+ errcode = ENXIO; /* There is no SYSLOG device */
+ goto errout_with_errcode;
}
/* syslog_initialize() is called as soon as enough of the operating
@@ -443,7 +454,8 @@ int syslog_putc(int ch)
if (ret < 0)
{
sched_unlock();
- return ret;
+ errcode = -ret;
+ goto errout_with_errcode;
}
}
@@ -471,7 +483,8 @@ int syslog_putc(int ch)
* way, we are outta here.
*/
- return ret;
+ errcode = -ret;
+ goto errout_with_errcode;
}
/* Pre-pend a newline with a carriage return. */
@@ -497,19 +510,27 @@ int syslog_putc(int ch)
{
/* Write the non-newline character (and don't flush) */
- nbytes = syslog_write(&ch, 1);
+ uch = (uint8_t)ch;
+ nbytes = syslog_write(&uch, 1);
}
syslog_givesem();
- /* Check if the write was successful */
+ /* Check if the write was successful. If not, nbytes will be
+ * a negated errno value.
+ */
if (nbytes < 0)
{
- return nbytes;
+ errcode = -ret;
+ goto errout_with_errcode;
}
return ch;
+
+errout_with_errcode:
+ set_errno(errcode);
+ return EOF;
}
#endif /* CONFIG_SYSLOG && CONFIG_SYSLOG_CHAR */
diff --git a/nuttx/fs/nxffs/nxffs_dump.c b/nuttx/fs/nxffs/nxffs_dump.c
index 6a89aaf1d..9caac4c4b 100644
--- a/nuttx/fs/nxffs/nxffs_dump.c
+++ b/nuttx/fs/nxffs/nxffs_dump.c
@@ -60,7 +60,7 @@
*/
#undef fdbg
-#define fdbg lib_rawprintf
+#define fdbg syslog
/****************************************************************************
* Private Types
diff --git a/nuttx/graphics/nxfonts/nxfonts_getfont.c b/nuttx/graphics/nxfonts/nxfonts_getfont.c
index c2af977f2..0eb48e9df 100644
--- a/nuttx/graphics/nxfonts/nxfonts_getfont.c
+++ b/nuttx/graphics/nxfonts/nxfonts_getfont.c
@@ -242,7 +242,7 @@ static FAR const struct nx_fontpackage_s *g_fontpackages[] =
* Name: nxf_getglyphset
*
* Description:
- * Return information about the font set containtined he selected
+ * Return information about the font set contained in the selected
* character encoding.
*
* Input Parameters:
diff --git a/nuttx/include/assert.h b/nuttx/include/assert.h
index 31c9edf48..62ffb3a6e 100644
--- a/nuttx/include/assert.h
+++ b/nuttx/include/assert.h
@@ -1,7 +1,7 @@
/****************************************************************************
* include/assert.h
*
- * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -100,23 +100,28 @@
****************************************************************************/
/****************************************************************************
- * Global Function Prototypes
+ * Public Data
****************************************************************************/
#ifdef __cplusplus
#define EXTERN extern "C"
-extern "C" {
+extern "C"
+{
#else
#define EXTERN extern
#endif
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
#ifdef CONFIG_HAVE_FILENAME
-EXTERN void up_assert(FAR const uint8_t *filename, int linenum);
-EXTERN void up_assert_code(FAR const uint8_t *filename, int linenum,
- int errcode);
+void up_assert(FAR const uint8_t *filename, int linenum) noreturn_function;
+void up_assert_code(FAR const uint8_t *filename, int linenum, int errcode)
+ noreturn_function;
#else
-EXTERN void up_assert(void);
-EXTERN void up_assert_code(int errcode);
+void up_assert(void) noreturn_function;
+void up_assert_code(int errcode) noreturn_function;
#endif
#undef EXTERN
diff --git a/nuttx/include/debug.h b/nuttx/include/debug.h
index aa5efd432..70ae2ee18 100644
--- a/nuttx/include/debug.h
+++ b/nuttx/include/debug.h
@@ -1,7 +1,7 @@
/****************************************************************************
* include/debug.h
*
- * Copyright (C) 2007-2011 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2011, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -43,7 +43,7 @@
#include <nuttx/config.h>
#include <nuttx/compiler.h>
-#include <stdint.h>
+#include <syslog.h>
/****************************************************************************
* Pre-processor Definitions
@@ -104,22 +104,22 @@
#ifdef CONFIG_DEBUG
# define dbg(format, arg...) \
- lib_rawprintf(EXTRA_FMT format EXTRA_ARG, ##arg)
+ syslog(EXTRA_FMT format EXTRA_ARG, ##arg)
# ifdef CONFIG_ARCH_LOWPUTC
# define lldbg(format, arg...) \
- lib_lowprintf(EXTRA_FMT format EXTRA_ARG, ##arg)
+ lowsyslog(EXTRA_FMT format EXTRA_ARG, ##arg)
# else
# define lldbg(x...)
# endif
# ifdef CONFIG_DEBUG_VERBOSE
# define vdbg(format, arg...) \
- lib_rawprintf(EXTRA_FMT format EXTRA_ARG, ##arg)
+ syslog(EXTRA_FMT format EXTRA_ARG, ##arg)
# ifdef CONFIG_ARCH_LOWPUTC
# define llvdbg(format, arg...) \
- lib_lowprintf(EXTRA_FMT format EXTRA_ARG, ##arg)
+ lowsyslog(EXTRA_FMT format EXTRA_ARG, ##arg)
# else
# define llvdbg(x...)
# endif
@@ -576,29 +576,16 @@ extern "C"
{
#endif
-/* These low-level debug APIs are provided by the NuttX library. If the
- * cross-compiler's pre-processor supports a variable number of macro
- * arguments, then the macros below will map all debug statements to one
- * or the other of the following.
- */
-
-int lib_rawprintf(FAR const char *format, ...);
-
-#ifdef CONFIG_ARCH_LOWPUTC
-int lib_lowprintf(FAR const char *format, ...);
-#endif
-
/* Dump a buffer of data */
void lib_dumpbuffer(FAR const char *msg, FAR const uint8_t *buffer, unsigned int buflen);
-/* Enable or disable debug output */
-
-#ifdef CONFIG_DEBUG_ENABLE
-void dbg_enable(bool enable);
-#endif
-
-/* If the cross-compiler's pre-processor does not support variable length
+/* The system logging interfaces are pnormally accessed via the macros
+ * provided above. If the cross-compiler's C pre-processor supports a
+ * variable number of macro arguments, then those macros below will map all
+ * debug statements to the logging interfaces declared in syslog.h.
+ *
+ * If the cross-compiler's pre-processor does not support variable length
* arguments, then these additional APIs will be built.
*/
diff --git a/nuttx/include/nuttx/fs/fs.h b/nuttx/include/nuttx/fs/fs.h
index 327bf37ca..93ca2a334 100644
--- a/nuttx/include/nuttx/fs/fs.h
+++ b/nuttx/include/nuttx/fs/fs.h
@@ -240,7 +240,6 @@ struct file
struct filelist
{
sem_t fl_sem; /* Manage access to the file list */
- int16_t fl_crefs; /* Reference count */
struct file fl_files[CONFIG_NFILE_DESCRIPTORS];
};
#endif
@@ -294,7 +293,6 @@ struct file_struct
struct streamlist
{
- int sl_crefs; /* Reference count */
sem_t sl_sem; /* For thread safety */
struct file_struct sl_streams[CONFIG_NFILE_STREAMS];
};
@@ -318,7 +316,8 @@ typedef int (*foreach_mountpoint_t)(FAR const char *mountpoint,
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
-extern "C" {
+extern "C"
+{
#else
#define EXTERN extern
#endif
@@ -333,7 +332,7 @@ extern "C" {
*
****************************************************************************/
-EXTERN void weak_function fs_initialize(void);
+void weak_function fs_initialize(void);
/* fs_foreachmountpoint.c ***************************************************/
/****************************************************************************
@@ -357,7 +356,7 @@ EXTERN void weak_function fs_initialize(void);
****************************************************************************/
#ifndef CONFIG_DISABLE_MOUNTPOUNT
-EXTERN int foreach_mountpoint(foreach_mountpoint_t handler, FAR void *arg);
+int foreach_mountpoint(foreach_mountpoint_t handler, FAR void *arg);
#endif
/* fs_registerdriver.c ******************************************************/
@@ -384,9 +383,8 @@ EXTERN int foreach_mountpoint(foreach_mountpoint_t handler, FAR void *arg);
*
****************************************************************************/
-EXTERN int register_driver(const char *path,
- const struct file_operations *fops,
- mode_t mode, void *priv);
+int register_driver(FAR const char *path, FAR const struct file_operations *fops,
+ mode_t mode, FAR void *priv);
/* fs_registerblockdriver.c *************************************************/
/****************************************************************************
@@ -412,9 +410,9 @@ EXTERN int register_driver(const char *path,
*
****************************************************************************/
-EXTERN int register_blockdriver(const char *path,
- const struct block_operations *bops,
- mode_t mode, void *priv);
+int register_blockdriver(FAR const char *path,
+ FAR const struct block_operations *bops, mode_t mode,
+ FAR void *priv);
/* fs_unregisterdriver.c ****************************************************/
/****************************************************************************
@@ -425,7 +423,7 @@ EXTERN int register_blockdriver(const char *path,
*
****************************************************************************/
-EXTERN int unregister_driver(const char *path);
+int unregister_driver(const char *path);
/* fs_unregisterblockdriver.c ***********************************************/
/****************************************************************************
@@ -436,7 +434,7 @@ EXTERN int unregister_driver(const char *path);
*
****************************************************************************/
-EXTERN int unregister_blockdriver(const char *path);
+int unregister_blockdriver(const char *path);
/* fs_open.c ****************************************************************/
/****************************************************************************
@@ -447,30 +445,19 @@ EXTERN int unregister_blockdriver(const char *path);
*
****************************************************************************/
-EXTERN int inode_checkflags(FAR struct inode *inode, int oflags);
+int inode_checkflags(FAR struct inode *inode, int oflags);
/* fs_files.c ***************************************************************/
/****************************************************************************
- * Name: files_alloclist
- *
- * Description: Allocate a list of files for a new task
- *
- ****************************************************************************/
-
-#if CONFIG_NFILE_DESCRIPTORS > 0
-EXTERN FAR struct filelist *files_alloclist(void);
-#endif
-
-/****************************************************************************
- * Name: files_addreflist
+ * Name: files_initlist
*
* Description:
- * Increase the reference count on a file list
+ * Initializes the list of files for a new task
*
****************************************************************************/
#if CONFIG_NFILE_DESCRIPTORS > 0
-EXTERN int files_addreflist(FAR struct filelist *list);
+void files_initlist(FAR struct filelist *list);
#endif
/****************************************************************************
@@ -482,7 +469,7 @@ EXTERN int files_addreflist(FAR struct filelist *list);
****************************************************************************/
#if CONFIG_NFILE_DESCRIPTORS > 0
-EXTERN int files_releaselist(FAR struct filelist *list);
+void files_releaselist(FAR struct filelist *list);
#endif
/****************************************************************************
@@ -495,7 +482,7 @@ EXTERN int files_releaselist(FAR struct filelist *list);
****************************************************************************/
#if CONFIG_NFILE_DESCRIPTORS > 0
-EXTERN int files_dup(FAR struct file *filep1, FAR struct file *filep2);
+int files_dup(FAR struct file *filep1, FAR struct file *filep2);
#endif
/* fs_filedup.c *************************************************************/
@@ -515,7 +502,7 @@ EXTERN int files_dup(FAR struct file *filep1, FAR struct file *filep2);
****************************************************************************/
#if CONFIG_NFILE_DESCRIPTORS > 0
-EXTERN int file_dup(int fd, int minfd);
+int file_dup(int fd, int minfd);
#endif
/* fs_filedup2.c ************************************************************/
@@ -535,7 +522,7 @@ EXTERN int file_dup(int fd, int minfd);
#if CONFIG_NFILE_DESCRIPTORS > 0
#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0
-EXTERN int file_dup2(int fd1, int fd2);
+int file_dup2(int fd1, int fd2);
#else
# define file_dup2(fd1, fd2) dup2(fd1, fd2)
#endif
@@ -566,8 +553,8 @@ EXTERN int file_dup2(int fd1, int fd2);
****************************************************************************/
#if CONFIG_NFILE_DESCRIPTORS > 0
-EXTERN int open_blockdriver(FAR const char *pathname, int mountflags,
- FAR struct inode **ppinode);
+int open_blockdriver(FAR const char *pathname, int mountflags,
+ FAR struct inode **ppinode);
#endif
/* fs_closeblockdriver.c ****************************************************/
@@ -589,7 +576,7 @@ EXTERN int open_blockdriver(FAR const char *pathname, int mountflags,
****************************************************************************/
#if CONFIG_NFILE_DESCRIPTORS > 0
-EXTERN int close_blockdriver(FAR struct inode *inode);
+int close_blockdriver(FAR struct inode *inode);
#endif
/* fs_fdopen.c **************************************************************/
@@ -609,7 +596,7 @@ typedef struct _TCB _TCB;
#define __TCB_DEFINED__
#endif
-EXTERN FAR struct file_struct *fs_fdopen(int fd, int oflags, FAR _TCB *tcb);
+FAR struct file_struct *fs_fdopen(int fd, int oflags, FAR _TCB *tcb);
#endif
/* lib/stdio/lib_fflush.c **************************************************/
@@ -623,7 +610,7 @@ EXTERN FAR struct file_struct *fs_fdopen(int fd, int oflags, FAR _TCB *tcb);
****************************************************************************/
#if CONFIG_NFILE_STREAMS > 0
-EXTERN int lib_flushall(FAR struct streamlist *list);
+int lib_flushall(FAR struct streamlist *list);
#endif
/* drivers/dev_null.c *******************************************************/
@@ -635,7 +622,7 @@ EXTERN int lib_flushall(FAR struct streamlist *list);
*
****************************************************************************/
-EXTERN void devnull_register(void);
+void devnull_register(void);
/* drivers/dev_zero.c *******************************************************/
/****************************************************************************
@@ -646,7 +633,7 @@ EXTERN void devnull_register(void);
*
****************************************************************************/
-EXTERN void devzero_register(void);
+void devzero_register(void);
/* drivers/loop.c ***********************************************************/
/****************************************************************************
@@ -658,8 +645,8 @@ EXTERN void devzero_register(void);
*
****************************************************************************/
-EXTERN int losetup(FAR const char *devname, FAR const char *filename,
- uint16_t sectsize, off_t offset, bool readonly);
+int losetup(FAR const char *devname, FAR const char *filename,
+ uint16_t sectsize, off_t offset, bool readonly);
/****************************************************************************
* Name: loteardown
@@ -669,7 +656,7 @@ EXTERN int losetup(FAR const char *devname, FAR const char *filename,
*
****************************************************************************/
-EXTERN int loteardown(FAR const char *devname);
+int loteardown(FAR const char *devname);
/* drivers/bch/bchdev_register.c ********************************************/
/****************************************************************************
@@ -681,8 +668,8 @@ EXTERN int loteardown(FAR const char *devname);
*
****************************************************************************/
-EXTERN int bchdev_register(FAR const char *blkdev, FAR const char *chardev,
- bool readonly);
+int bchdev_register(FAR const char *blkdev, FAR const char *chardev,
+ bool readonly);
/* drivers/bch/bchdev_unregister.c ******************************************/
/****************************************************************************
@@ -694,7 +681,7 @@ EXTERN int bchdev_register(FAR const char *blkdev, FAR const char *chardev,
*
****************************************************************************/
-EXTERN int bchdev_unregister(FAR const char *chardev);
+int bchdev_unregister(FAR const char *chardev);
/* Low level, direct access. NOTE: low-level access and character driver access
* are incompatible. One and only one access method should be implemented.
@@ -710,8 +697,7 @@ EXTERN int bchdev_unregister(FAR const char *chardev);
*
****************************************************************************/
-EXTERN int bchlib_setup(FAR const char *blkdev, bool readonly,
- FAR void **handle);
+int bchlib_setup(FAR const char *blkdev, bool readonly, FAR void **handle);
/* drivers/bch/bchlib_teardown.c ********************************************/
/****************************************************************************
@@ -723,7 +709,7 @@ EXTERN int bchlib_setup(FAR const char *blkdev, bool readonly,
*
****************************************************************************/
-EXTERN int bchlib_teardown(FAR void *handle);
+int bchlib_teardown(FAR void *handle);
/* drivers/bch/bchlib_read.c ************************************************/
/****************************************************************************
@@ -735,8 +721,8 @@ EXTERN int bchlib_teardown(FAR void *handle);
*
****************************************************************************/
-EXTERN ssize_t bchlib_read(FAR void *handle, FAR char *buffer, size_t offset,
- size_t len);
+ssize_t bchlib_read(FAR void *handle, FAR char *buffer, size_t offset,
+ size_t len);
/* drivers/bch/bchlib_write.c ***********************************************/
/****************************************************************************
@@ -748,8 +734,8 @@ EXTERN ssize_t bchlib_read(FAR void *handle, FAR char *buffer, size_t offset,
*
****************************************************************************/
-EXTERN ssize_t bchlib_write(FAR void *handle, FAR const char *buffer,
- size_t offset, size_t len);
+ssize_t bchlib_write(FAR void *handle, FAR const char *buffer, size_t offset,
+ size_t len);
#undef EXTERN
#if defined(__cplusplus)
diff --git a/nuttx/include/nuttx/lib.h b/nuttx/include/nuttx/lib.h
index 220af2030..3bc581e18 100644
--- a/nuttx/include/nuttx/lib.h
+++ b/nuttx/include/nuttx/lib.h
@@ -2,7 +2,7 @@
* include/nuttx/lib.h
* Non-standard, internal APIs available in lib/.
*
- * Copyright (C) 2007-2009, 2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2012-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -67,11 +67,10 @@ extern "C" {
/* Functions contained in lib_init.c ****************************************/
-EXTERN void weak_function lib_initialize(void);
+void weak_function lib_initialize(void);
#if CONFIG_NFILE_STREAMS > 0
-EXTERN FAR struct streamlist *lib_alloclist(void);
-EXTERN void lib_addreflist(FAR struct streamlist *list);
-EXTERN void lib_releaselist(FAR struct streamlist *list);
+void lib_streaminit(FAR struct streamlist *list);
+void lib_releaselist(FAR struct streamlist *list);
#endif
#undef EXTERN
diff --git a/nuttx/include/nuttx/net/net.h b/nuttx/include/nuttx/net/net.h
index b79dda755..d23fb8796 100644
--- a/nuttx/include/nuttx/net/net.h
+++ b/nuttx/include/nuttx/net/net.h
@@ -1,7 +1,7 @@
/****************************************************************************
* include/nuttx/net/net.h
*
- * Copyright (C) 2007, 2009-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -106,7 +106,6 @@ struct socket
struct socketlist
{
sem_t sl_sem; /* Manage access to the socket list */
- int16_t sl_crefs; /* Reference count */
struct socket sl_sockets[CONFIG_NSOCKET_DESCRIPTORS];
};
#endif
@@ -117,110 +116,114 @@ struct uip_driver_s; /* Forward reference. See nuttx/net/uip/uip-arch.h */
typedef int (*netdev_callback_t)(FAR struct uip_driver_s *dev, void *arg);
/****************************************************************************
- * Public Function Prototypes
+ * Public Data
****************************************************************************/
#ifdef __cplusplus
#define EXTERN extern "C"
-extern "C" {
+extern "C"
+{
#else
#define EXTERN extern
#endif
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
/* net_checksd.c *************************************************************/
/* Check if the socket descriptor is valid for the provided TCB and if it
* supports the requested access.
*/
-EXTERN int net_checksd(int fd, int oflags);
+int net_checksd(int fd, int oflags);
/* net_sockets.c *************************************************************/
/* There interfaces are called only from OS scheduling and iniialization logic
* under sched/
*/
-EXTERN void weak_function net_initialize(void);
-EXTERN FAR struct socketlist *net_alloclist(void);
-EXTERN int net_addreflist(FAR struct socketlist *list);
-EXTERN int net_releaselist(FAR struct socketlist *list);
+void weak_function net_initialize(void);
+void net_initlist(FAR struct socketlist *list);
+void net_releaselist(FAR struct socketlist *list);
/* Given a socket descriptor, return the underly NuttX-specific socket
* structure.
*/
-EXTERN FAR struct socket *sockfd_socket(int sockfd);
+FAR struct socket *sockfd_socket(int sockfd);
/* socket.c ******************************************************************/
/* socket using underlying socket structure */
-EXTERN int psock_socket(int domain, int type, int protocol,
- FAR struct socket *psock);
+int psock_socket(int domain, int type, int protocol, FAR struct socket *psock);
/* net_close.c ***************************************************************/
/* The standard close() operation redirects operations on socket descriptors
* to this function.
*/
-EXTERN int net_close(int sockfd);
+int net_close(int sockfd);
/* Performs the close operation on a socket instance */
-EXTERN int psock_close(FAR struct socket *psock);
+int psock_close(FAR struct socket *psock);
/* net_close.c ***************************************************************/
/* Performs the bind() operation on a socket instance */
-EXTERN int psock_bind(FAR struct socket *psock,
- FAR const struct sockaddr *addr, socklen_t addrlen);
+int psock_bind(FAR struct socket *psock, FAR const struct sockaddr *addr,
+ socklen_t addrlen);
/* connect.c *****************************************************************/
/* Performs the connect() operation on a socket instance */
-EXTERN int psock_connect(FAR struct socket *psock,
- FAR const struct sockaddr *addr, socklen_t addrlen);
+int psock_connect(FAR struct socket *psock, FAR const struct sockaddr *addr,
+ socklen_t addrlen);
/* send.c ********************************************************************/
/* Send using underlying socket structure */
-EXTERN ssize_t psock_send(FAR struct socket *psock, const void *buf,
- size_t len, int flags);
+ssize_t psock_send(FAR struct socket *psock, const void *buf, size_t len,
+ int flags);
/* sendto.c ******************************************************************/
/* Sendto using underlying socket structure */
-EXTERN ssize_t psock_sendto(FAR struct socket *psock, FAR const void *buf,
- size_t len, int flags, FAR const struct sockaddr *to,
- socklen_t tolen);
+ssize_t psock_sendto(FAR struct socket *psock, FAR const void *buf,
+ size_t len, int flags, FAR const struct sockaddr *to,
+ socklen_t tolen);
/* recvfrom.c ****************************************************************/
/* recvfrom using the underlying socket structure */
-EXTERN ssize_t psock_recvfrom(FAR struct socket *psock, FAR void *buf,
- size_t len, int flags,FAR struct sockaddr *from,
- FAR socklen_t *fromlen);
+ssize_t psock_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
+ int flags,FAR struct sockaddr *from,
+ FAR socklen_t *fromlen);
/* recv using the underlying socket structure */
-#define psock_recv(psock,buf,len,flags) psock_recvfrom(psock,buf,len,flags,NULL,0)
+#define psock_recv(psock,buf,len,flags) \
+ psock_recvfrom(psock,buf,len,flags,NULL,0)
/* getsockopt.c **************************************************************/
/* getsockopt using the underlying socket structure */
-EXTERN int psock_getsockopt(FAR struct socket *psock, int level, int option,
- FAR void *value, FAR socklen_t *value_len);
+int psock_getsockopt(FAR struct socket *psock, int level, int option,
+ FAR void *value, FAR socklen_t *value_len);
/* setsockopt.c **************************************************************/
/* setsockopt using the underlying socket structure */
-EXTERN int psock_setsockopt(FAR struct socket *psock, int level, int option,
- FAR const void *value, socklen_t value_len);
+int psock_setsockopt(FAR struct socket *psock, int level, int option,
+ FAR const void *value, socklen_t value_len);
/* net_ioctl.c ***************************************************************/
/* The standard ioctl() operation redirects operations on socket descriptors
* to this function.
*/
-EXTERN int netdev_ioctl(int sockfd, int cmd, unsigned long arg);
+int netdev_ioctl(int sockfd, int cmd, unsigned long arg);
/* net_poll.c ****************************************************************/
/* The standard poll() operation redirects operations on socket descriptors
@@ -229,7 +232,9 @@ EXTERN int netdev_ioctl(int sockfd, int cmd, unsigned long arg);
#ifndef CONFIG_DISABLE_POLL
struct pollfd; /* Forward reference -- see poll.h */
-EXTERN int net_poll(int sockfd, struct pollfd *fds, bool setup);
+
+int psock_poll(FAR struct socket *psock, struct pollfd *fds, bool setup);
+int net_poll(int sockfd, struct pollfd *fds, bool setup);
#endif
/* net_dup.c *****************************************************************/
@@ -237,7 +242,7 @@ EXTERN int net_poll(int sockfd, struct pollfd *fds, bool setup);
* this function
*/
-EXTERN int net_dup(int sockfd, int minsd);
+int net_dup(int sockfd, int minsd);
/* net_dup2.c ****************************************************************/
/* The standard dup2() operation redirects operations on socket descriptors to
@@ -245,7 +250,7 @@ EXTERN int net_dup(int sockfd, int minsd);
*/
#if CONFIG_NFILE_DESCRIPTORS > 0
-EXTERN int net_dup2(int sockfd1, int sockfd2);
+int net_dup2(int sockfd1, int sockfd2);
#else
# define net_dup2(sockfd1, sockfd2) dup2(sockfd1, sockfd2)
#endif
@@ -253,12 +258,12 @@ EXTERN int net_dup2(int sockfd1, int sockfd2);
/* net_clone.c ***************************************************************/
/* Performs the low level, common portion of net_dup() and net_dup2() */
-EXTERN int net_clone(FAR struct socket *psock1, FAR struct socket *psock2);
+int net_clone(FAR struct socket *psock1, FAR struct socket *psock2);
/* net_vfcntl.c **************************************************************/
/* Performs fcntl operations on socket */
-EXTERN int net_vfcntl(int sockfd, int cmd, va_list ap);
+int net_vfcntl(int sockfd, int cmd, va_list ap);
/* netdev-register.c *********************************************************/
/* This function is called by network interface device drivers to inform the
@@ -267,23 +272,23 @@ EXTERN int net_vfcntl(int sockfd, int cmd, va_list ap);
* addresses
*/
-EXTERN int netdev_register(FAR struct uip_driver_s *dev);
+int netdev_register(FAR struct uip_driver_s *dev);
/* netdev-unregister.c *********************************************************/
/* Unregister a network device driver. */
-EXTERN int netdev_unregister(FAR struct uip_driver_s *dev);
+int netdev_unregister(FAR struct uip_driver_s *dev);
/* net_foreach.c ************************************************************/
/* Enumerates all registered network devices */
-EXTERN int netdev_foreach(netdev_callback_t callback, void *arg);
+int netdev_foreach(netdev_callback_t callback, void *arg);
/* drivers/net/slip.c ******************************************************/
/* Instantiate a SLIP network interface. */
#ifdef CONFIG_NET_SLIP
-EXTERN int slip_initialize(int intf, const char *devname);
+int slip_initialize(int intf, const char *devname);
#endif
#undef EXTERN
diff --git a/nuttx/include/nuttx/sched.h b/nuttx/include/nuttx/sched.h
index 1e75b5020..f8b4eb0dc 100644
--- a/nuttx/include/nuttx/sched.h
+++ b/nuttx/include/nuttx/sched.h
@@ -52,19 +52,55 @@
#include <time.h>
#include <nuttx/irq.h>
+#include <nuttx/fs/fs.h>
#include <nuttx/net/net.h>
/********************************************************************************
* Pre-processor Definitions
********************************************************************************/
+/* Configuration ****************************************************************/
+/* Task groups currently only supported for retention of child status */
-/* Task Management Definitins ***************************************************/
+#undef HAVE_TASK_GROUP
+#undef HAVE_GROUP_MEMBERS
+
+/* We need a group an group members if we are supportint the parent/child
+ * relationship.
+ */
+
+#if defined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS)
+# define HAVE_TASK_GROUP 1
+# define HAVE_GROUP_MEMBERS 1
+
+/* We need a group (but not members) if any other resources are shared within
+ * a task group.
+ */
+
+#else
+# if !defined(CONFIG_DISABLE_ENVIRON)
+# define HAVE_TASK_GROUP 1
+# elif CONFIG_NFILE_DESCRIPTORS > 0
+# define HAVE_TASK_GROUP 1
+# elif CONFIG_NFILE_STREAMS > 0
+# define HAVE_TASK_GROUP 1
+# elif CONFIG_NSOCKET_DESCRIPTORS > 0
+# define HAVE_TASK_GROUP 1
+# endif
+#endif
+
+/* In any event, we don't need group members if support for pthreads is disabled */
+
+#ifdef CONFIG_DISABLE_PTHREAD
+# undef HAVE_GROUP_MEMBERS
+#endif
+
+/* Task Management Definitions **************************************************/
/* This is the maximum number of times that a lock can be set */
#define MAX_LOCK_COUNT 127
-/* Values for the _TCB flags flag bits */
+/* Values for the _TCB flags bits */
#define TCB_FLAG_TTYPE_SHIFT (0) /* Bits 0-1: thread type */
#define TCB_FLAG_TTYPE_MASK (3 << TCB_FLAG_TTYPE_SHIFT)
@@ -74,7 +110,11 @@
#define TCB_FLAG_NONCANCELABLE (1 << 2) /* Bit 2: Pthread is non-cancelable */
#define TCB_FLAG_CANCEL_PENDING (1 << 3) /* Bit 3: Pthread cancel is pending */
#define TCB_FLAG_ROUND_ROBIN (1 << 4) /* Bit 4: Round robin sched enabled */
-#define TCB_FLAG_NOCLDWAIT (1 << 5) /* Bit 5: Do not retain child exit status */
+#define TCB_FLAG_EXIT_PROCESSING (1 << 5) /* Bit 5: Exitting */
+
+/* Values for struct task_group tg_flags */
+
+#define GROUP_FLAG_NOCLDWAIT (1 << 0) /* Bit 0: Do not retain child exit status */
/* Values for struct child_status_s ch_flags */
@@ -143,7 +183,13 @@ union entry_u
};
typedef union entry_u entry_t;
-/* These is the types of the functions that are executed with exit() is called
+/* This is the type of the function called at task startup */
+
+#ifdef CONFIG_SCHED_STARTHOOK
+typedef CODE void (*starthook_t)(FAR void *arg);
+#endif
+
+/* These are the types of the functions that are executed with exit() is called
* (if registered via atexit() on on_exit()).
*/
@@ -159,20 +205,7 @@ typedef CODE void (*onexitfunc_t)(int exitcode, FAR void *arg);
typedef struct msgq_s msgq_t;
-/* The structure used to maintain environment variables */
-
-#ifndef CONFIG_DISABLE_ENVIRON
-struct environ_s
-{
- unsigned int ev_crefs; /* Reference count used when environment
- * is shared by threads */
- size_t ev_alloc; /* Number of bytes allocated in environment */
- char ev_env[1]; /* Environment strings */
-};
-typedef struct environ_s environ_t;
-# define SIZEOF_ENVIRON_T(alloc) (sizeof(environ_t) + alloc - 1)
-#endif
-
+/* struct child_status_s *********************************************************/
/* This structure is used to maintin information about child tasks.
* pthreads work differently, they have join information. This is
* only for child tasks.
@@ -189,6 +222,7 @@ struct child_status_s
};
#endif
+/* struct dspace_s ***************************************************************/
/* This structure describes a reference counted D-Space region. This must be a
* separately allocated "break-away" structure that can be owned by a task and
* any pthreads created by the task.
@@ -214,6 +248,88 @@ struct dspace_s
};
#endif
+/* struct task_group_s ***********************************************************/
+/* All threads created by pthread_create belong in the same task group (along with
+ * the thread of the original task). struct task_group_s is a shared, "breakaway"
+ * structure referenced by each TCB.
+ *
+ * This structure should contain *all* resources shared by tasks and threads that
+ * belong to the same task group:
+ *
+ * Child exit status
+ * Environment varibles
+ * PIC data space and address environments
+ * File descriptors
+ * FILE streams
+ * Sockets
+ *
+ * Currenty, however, this implementation only applies to child exit status.
+ *
+ * Each instance of struct task_group_s is reference counted. Each instance is
+ * created with a reference count of one. The reference incremeneted when each
+ * thread joins the group and decremented when each thread exits, leaving the
+ * group. When the refernce count decrements to zero, the struc task_group_s
+ * is free.
+ */
+
+#ifdef HAVE_TASK_GROUP
+struct task_group_s
+{
+#ifdef HAVE_GROUP_MEMBERS
+ struct task_group_s *flink; /* Supports a singly linked list */
+ gid_t tg_gid; /* The ID of this task group */
+ gid_t tg_pgid; /* The ID of the parent task group */
+#endif
+ uint8_t tg_flags; /* See GROUP_FLAG_* definitions */
+
+ /* Group membership ***********************************************************/
+
+ uint8_t tg_nmembers; /* Number of members in the group */
+#ifdef HAVE_GROUP_MEMBERS
+ uint8_t tg_mxmembers; /* Number of members in allocation */
+ FAR pid_t *tg_members; /* Members of the group */
+#endif
+
+ /* Child exit status **********************************************************/
+
+#if defined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS)
+ FAR struct child_status_s *tg_children; /* Head of a list of child status */
+#endif
+
+ /* Environment variables ******************************************************/
+
+#ifndef CONFIG_DISABLE_ENVIRON
+ size_t tg_envsize; /* Size of environment string allocation */
+ FAR char *tg_envp; /* Allocated environment strings */
+#endif
+
+ /* PIC data space and address environments ************************************/
+ /* Logically the PIC data space belongs here (see struct dspace_s). The
+ * current logic needs review: There are differences in the away that the
+ * life of the PIC data is managed.
+ */
+
+ /* File descriptors ***********************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0
+ struct filelist tg_filelist; /* Maps file descriptor to file */
+#endif
+
+ /* FILE streams ***************************************************************/
+
+#if CONFIG_NFILE_STREAMS > 0
+ struct streamlist tg_streamlist; /* Holds C buffered I/O info */
+#endif /* CONFIG_NFILE_STREAMS */
+
+ /* Sockets ********************************************************************/
+
+#if CONFIG_NSOCKET_DESCRIPTORS > 0
+ struct socketlist tg_socketlist; /* Maps socket descriptor to socket */
+#endif
+};
+#endif
+
+/* _TCB **************************************************************************/
/* This is the task control block (TCB). Each task or thread is represented by
* a TCB. The TCB is the heart of the NuttX task-control logic.
*/
@@ -225,20 +341,33 @@ struct _TCB
FAR struct _TCB *flink; /* Doubly linked list */
FAR struct _TCB *blink;
+ /* Task Group *****************************************************************/
+
+#ifdef HAVE_TASK_GROUP
+ FAR struct task_group_s *group; /* Pointer to shared task group data */
+#endif
+
/* Task Management Fields *****************************************************/
pid_t pid; /* This is the ID of the thread */
+
#ifdef CONFIG_SCHED_HAVE_PARENT /* Support parent-child relationship */
- pid_t parent; /* This is the ID of the parent thread */
-#ifdef CONFIG_SCHED_CHILD_STATUS /* Retain child thread status */
- FAR struct child_status_s *children; /* Head of a list of child status */
-#else
+#ifndef HAVE_GROUP_MEMBERS /* Don't know pids of group members */
+ pid_t ppid; /* This is the ID of the parent thread */
+#ifndef CONFIG_SCHED_CHILD_STATUS /* Retain child thread status */
uint16_t nchildren; /* This is the number active children */
#endif
#endif
+#endif /* CONFIG_SCHED_HAVE_PARENT */
+
start_t start; /* Thread start function */
entry_t entry; /* Entry Point into the thread */
+#ifdef CONFIG_SCHED_STARTHOOK
+ starthook_t starthook; /* Task startup function */
+ FAR void *starthookarg; /* The argument passed to the function */
+#endif
+
#if defined(CONFIG_SCHED_ATEXIT) && !defined(CONFIG_SCHED_ONEXIT)
# if defined(CONFIG_SCHED_ATEXIT_MAX) && CONFIG_SCHED_ATEXIT_MAX > 1
atexitfunc_t atexitfunc[CONFIG_SCHED_ATEXIT_MAX];
@@ -289,10 +418,6 @@ struct _TCB
uint8_t init_priority; /* Initial priority of the task */
char *argv[CONFIG_MAX_TASK_ARGS+1]; /* Name+start-up parameters */
-#ifndef CONFIG_DISABLE_ENVIRON
- FAR environ_t *envp; /* Environment variables */
-#endif
-
/* Stack-Related Fields *******************************************************/
#ifndef CONFIG_CUSTOM_STACK
@@ -344,22 +469,6 @@ struct _TCB
int pterrno; /* Current per-thread errno */
- /* File system support ********************************************************/
-
-#if CONFIG_NFILE_DESCRIPTORS > 0
- FAR struct filelist *filelist; /* Maps file descriptor to file */
-#endif
-
-#if CONFIG_NFILE_STREAMS > 0
- FAR struct streamlist *streams; /* Holds C buffered I/O info */
-#endif
-
- /* Network socket *************************************************************/
-
-#if CONFIG_NSOCKET_DESCRIPTORS > 0
- FAR struct socketlist *sockets; /* Maps file descriptor to file */
-#endif
-
/* State save areas ***********************************************************/
/* The form and content of these fields are processor-specific. */
@@ -421,6 +530,12 @@ FAR struct streamlist *sched_getstreams(void);
FAR struct socketlist *sched_getsockets(void);
#endif /* CONFIG_NSOCKET_DESCRIPTORS */
+/* Setup up a start hook */
+
+#ifdef CONFIG_SCHED_STARTHOOK
+void task_starthook(FAR _TCB *tcb, starthook_t starthook, FAR void *arg);
+#endif
+
/* Internal vfork support.The overall sequence is:
*
* 1) User code calls vfork(). vfork() is provided in architecture-specific
diff --git a/nuttx/include/nuttx/serial/serial.h b/nuttx/include/nuttx/serial/serial.h
index 49dba3795..4ee2005ef 100644
--- a/nuttx/include/nuttx/serial/serial.h
+++ b/nuttx/include/nuttx/serial/serial.h
@@ -1,7 +1,7 @@
/************************************************************************************
* include/nuttx/serial/serial.h
*
- * Copyright (C) 2007-2008, 2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2008, 2012-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -49,6 +49,7 @@
#ifdef CONFIG_SERIAL_TERMIOS
# include <termios.h>
#endif
+
#include <nuttx/fs/fs.h>
/************************************************************************************
@@ -193,20 +194,23 @@ struct uart_ops_s
struct uart_dev_s
{
- uint8_t open_count; /* Number of times the device has been opened */
- volatile bool xmitwaiting; /* true: User waiting for space in xmit.buffer */
- volatile bool recvwaiting; /* true: User waiting for data in recv.buffer */
- bool isconsole; /* true: This is the serial console */
- sem_t closesem; /* Locks out new open while close is in progress */
- sem_t xmitsem; /* Wakeup user waiting for space in xmit.buffer */
- sem_t recvsem; /* Wakeup user waiting for data in recv.buffer */
+ uint8_t open_count; /* Number of times the device has been opened */
+ volatile bool xmitwaiting; /* true: User waiting for space in xmit.buffer */
+ volatile bool recvwaiting; /* true: User waiting for data in recv.buffer */
+#ifdef CONFIG_SERIAL_REMOVABLE
+ volatile bool disconnected; /* true: Removable device is not connected */
+#endif
+ bool isconsole; /* true: This is the serial console */
+ sem_t closesem; /* Locks out new open while close is in progress */
+ sem_t xmitsem; /* Wakeup user waiting for space in xmit.buffer */
+ sem_t recvsem; /* Wakeup user waiting for data in recv.buffer */
#ifndef CONFIG_DISABLE_POLL
- sem_t pollsem; /* Manages exclusive access to fds[] */
+ sem_t pollsem; /* Manages exclusive access to fds[] */
#endif
- struct uart_buffer_s xmit; /* Describes transmit buffer */
- struct uart_buffer_s recv; /* Describes receive buffer */
- FAR const struct uart_ops_s *ops; /* Arch-specific operations */
- FAR void *priv; /* Used by the arch-specific logic */
+ struct uart_buffer_s xmit; /* Describes transmit buffer */
+ struct uart_buffer_s recv; /* Describes receive buffer */
+ FAR const struct uart_ops_s *ops; /* Arch-specific operations */
+ FAR void *priv; /* Used by the arch-specific logic */
/* The following is a list if poll structures of threads waiting for
* driver events. The 'struct pollfd' reference for each open is also
@@ -226,25 +230,27 @@ struct uart_dev_s
#endif
};
+
typedef struct uart_dev_s uart_dev_t;
/************************************************************************************
* Public Data
************************************************************************************/
-/************************************************************************************
- * Public Functions
- ************************************************************************************/
-
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
-extern "C" {
+extern "C"
+{
#else
#define EXTERN extern
#endif
/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+/************************************************************************************
* Name: uart_register
*
* Description:
@@ -252,7 +258,7 @@ extern "C" {
*
************************************************************************************/
-EXTERN int uart_register(FAR const char *path, FAR uart_dev_t *dev);
+int uart_register(FAR const char *path, FAR uart_dev_t *dev);
/************************************************************************************
* Name: uart_xmitchars
@@ -265,7 +271,7 @@ EXTERN int uart_register(FAR const char *path, FAR uart_dev_t *dev);
*
************************************************************************************/
-EXTERN void uart_xmitchars(FAR uart_dev_t *dev);
+void uart_xmitchars(FAR uart_dev_t *dev);
/************************************************************************************
* Name: uart_receivechars
@@ -278,7 +284,7 @@ EXTERN void uart_xmitchars(FAR uart_dev_t *dev);
*
************************************************************************************/
-EXTERN void uart_recvchars(FAR uart_dev_t *dev);
+void uart_recvchars(FAR uart_dev_t *dev);
/************************************************************************************
* Name: uart_datareceived
@@ -290,7 +296,7 @@ EXTERN void uart_recvchars(FAR uart_dev_t *dev);
*
************************************************************************************/
-EXTERN void uart_datareceived(FAR uart_dev_t *dev);
+void uart_datareceived(FAR uart_dev_t *dev);
/************************************************************************************
* Name: uart_datasent
@@ -303,7 +309,31 @@ EXTERN void uart_datareceived(FAR uart_dev_t *dev);
*
************************************************************************************/
-EXTERN void uart_datasent(FAR uart_dev_t *dev);
+void uart_datasent(FAR uart_dev_t *dev);
+
+/************************************************************************************
+ * Name: uart_connected
+ *
+ * Description:
+ * Serial devices (like USB serial) can be removed. In that case, the "upper
+ * half" serial driver must be informed that there is no longer a valid serial
+ * channel associated with the driver.
+ *
+ * In this case, the driver will terminate all pending transfers wint ENOTCONN and
+ * will refuse all further transactions while the "lower half" is disconnected.
+ * The driver will continue to be registered, but will be in an unusable state.
+ *
+ * Conversely, the "upper half" serial driver needs to know when the serial
+ * device is reconnected so that it can resume normal operations.
+ *
+ * Assumptions/Limitations:
+ * This function may be called from an interrupt handler.
+ *
+ ************************************************************************************/
+
+#ifdef CONFIG_SERIAL_REMOVABLE
+void uart_connected(FAR uart_dev_t *dev, bool connected);
+#endif
#undef EXTERN
#if defined(__cplusplus)
diff --git a/nuttx/include/nuttx/syslog.h b/nuttx/include/nuttx/syslog.h
index 3c340d23a..bb3c8f493 100644
--- a/nuttx/include/nuttx/syslog.h
+++ b/nuttx/include/nuttx/syslog.h
@@ -116,10 +116,10 @@ EXTERN int syslog_initialize(void);
*
* Description:
* This is the low-level system logging interface. The debugging/syslogging
- * interfaces are lib_rawprintf() and lib_lowprinf(). The difference is
- * the lib_rawprintf() writes to fd=1 (stdout) and lib_lowprintf() uses
+ * interfaces are syslog() and lowsyslog(). The difference is that
+ * the syslog() internface writes to fd=1 (stdout) whereas lowsyslog() uses
* a lower level interface that works from interrupt handlers. This
- * function is a a low-level interface used to implement lib_lowprintf().
+ * function is a a low-level interface used to implement lowsyslog().
*
****************************************************************************/
diff --git a/nuttx/include/nuttx/usb/cdcacm.h b/nuttx/include/nuttx/usb/cdcacm.h
index 1dca050c4..49dc4ee12 100644
--- a/nuttx/include/nuttx/usb/cdcacm.h
+++ b/nuttx/include/nuttx/usb/cdcacm.h
@@ -54,7 +54,7 @@
* Endpoint 0 max packet size. Default 64.
* CONFIG_CDCACM_EPINTIN
* The logical 7-bit address of a hardware endpoint that supports
- * interrupt IN operation. Default 2.
+ * interrupt IN operation. Default 1.
* CONFIG_CDCACM_EPINTIN_FSSIZE
* Max package size for the interrupt IN endpoint if full speed mode.
* Default 64.
@@ -63,7 +63,7 @@
* Default 64.
* CONFIG_CDCACM_EPBULKOUT
* The logical 7-bit address of a hardware endpoint that supports
- * bulk OUT operation
+ * bulk OUT operation. Default: 3
* CONFIG_CDCACM_EPBULKOUT_FSSIZE
* Max package size for the bulk OUT endpoint if full speed mode.
* Default 64.
@@ -72,7 +72,7 @@
* Default 512.
* CONFIG_CDCACM_EPBULKIN
* The logical 7-bit address of a hardware endpoint that supports
- * bulk IN operation
+ * bulk IN operation. Default: 2
* CONFIG_CDCACM_EPBULKIN_FSSIZE
* Max package size for the bulk IN endpoint if full speed mode.
* Default 64.
@@ -107,7 +107,7 @@
*/
#ifndef CONFIG_CDCACM_EPINTIN
-# define CONFIG_CDCACM_EPINTIN 2
+# define CONFIG_CDCACM_EPINTIN 1
#endif
#ifndef CONFIG_CDCACM_EPINTIN_FSSIZE
@@ -124,7 +124,7 @@
*/
#ifndef CONFIG_CDCACM_EPBULKIN
-# define CONFIG_CDCACM_EPBULKIN 3
+# define CONFIG_CDCACM_EPBULKIN 2
#endif
#ifndef CONFIG_CDCACM_EPBULKIN_FSSIZE
@@ -141,7 +141,7 @@
*/
#ifndef CONFIG_CDCACM_EPBULKOUT
-# define CONFIG_CDCACM_EPBULKOUT 4
+# define CONFIG_CDCACM_EPBULKOUT 3
#endif
#ifndef CONFIG_CDCACM_EPBULKOUT_FSSIZE
diff --git a/nuttx/include/nuttx/usb/usbdev_trace.h b/nuttx/include/nuttx/usb/usbdev_trace.h
index ab3a5f4be..860f48983 100644
--- a/nuttx/include/nuttx/usb/usbdev_trace.h
+++ b/nuttx/include/nuttx/usb/usbdev_trace.h
@@ -104,6 +104,7 @@
#define TRACE_DEVUNINIT TRACE_EVENT(TRACE_INIT_ID, 0x0002)
#define TRACE_DEVREGISTER TRACE_EVENT(TRACE_INIT_ID, 0x0003)
#define TRACE_DEVUNREGISTER TRACE_EVENT(TRACE_INIT_ID, 0x0004)
+#define TRACE_DEVINIT_USER TRACE_EVENT(TRACE_INIT_ID, 0x0005) /* First user-defined */
/* API calls (see usbdev.h) */
@@ -117,6 +118,7 @@
#define TRACE_EPCANCEL TRACE_EVENT(TRACE_EP_ID, 0x0008)
#define TRACE_EPSTALL TRACE_EVENT(TRACE_EP_ID, 0x0009)
#define TRACE_EPRESUME TRACE_EVENT(TRACE_EP_ID, 0x000a)
+#define TRACE_EPAPI_USER TRACE_EVENT(TRACE_EP_ID, 0x000b) /* First user-defined */
#define TRACE_DEVALLOCEP TRACE_EVENT(TRACE_DEV_ID, 0x0001)
#define TRACE_DEVFREEEP TRACE_EVENT(TRACE_DEV_ID, 0x0002)
@@ -124,6 +126,7 @@
#define TRACE_DEVWAKEUP TRACE_EVENT(TRACE_DEV_ID, 0x0004)
#define TRACE_DEVSELFPOWERED TRACE_EVENT(TRACE_DEV_ID, 0x0005)
#define TRACE_DEVPULLUP TRACE_EVENT(TRACE_DEV_ID, 0x0006)
+#define TRACE_DEVAPI_USER TRACE_EVENT(TRACE_DEV_ID, 0x0007) /* First user-defined */
#define TRACE_CLASSBIND TRACE_EVENT(TRACE_CLASS_ID, 0x0001)
#define TRACE_CLASSUNBIND TRACE_EVENT(TRACE_CLASS_ID, 0x0002)
@@ -135,6 +138,8 @@
#define TRACE_CLASSRDCOMPLETE TRACE_EVENT(TRACE_CLASS_ID, 0x0007)
#define TRACE_CLASSWRCOMPLETE TRACE_EVENT(TRACE_CLASS_ID, 0x0008)
+#define TRACE_CLASSAPI_USER TRACE_EVENT(TRACE_CLASS_ID, 0x0009) /* First user-defined */
+
#define TRACE_CLASSAPI(id) TRACE_EVENT(TRACE_CLASSAPI_ID, id)
#define TRACE_CLASSSTATE(id) TRACE_EVENT(TRACE_CLASSSTATE_ID, id)
diff --git a/nuttx/sched/env_dupenv.c b/nuttx/include/syslog.h
index 32bf6a433..cfb2db97b 100644
--- a/nuttx/sched/env_dupenv.c
+++ b/nuttx/include/syslog.h
@@ -1,7 +1,7 @@
/****************************************************************************
- * eched/env_dupenv.c
+ * include/syslog.h
*
- * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -33,80 +33,62 @@
*
****************************************************************************/
+#ifndef __INCLUDE_SYSLOG_H
+#define __INCLUDE_SYSLOG_H
+
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
-#ifndef CONFIG_DISABLE_ENVIRON
-
-#include <sys/types.h>
-#include <sched.h>
+#include <stdint.h>
+#include <stdarg.h>
-#include <nuttx/kmalloc.h>
-
-#include "os_internal.h"
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
/****************************************************************************
- * Private Data
+ * Public Type Declarations
****************************************************************************/
/****************************************************************************
- * Public Functions
+ * Public Variables
****************************************************************************/
/****************************************************************************
- * Name: dupenv
- *
- * Description:
- * Copy the internal environment structure of a task. This is the action
- * that is performed when a new task is created: The new task has a private,
- * exact duplicate of the parent task's environment.
- *
- * Parameters:
- * None
- *
- * Return Value:
- * A pointer to a newly allocated copy of the specified TCB's environment
- * structure with reference count equal to one.
- *
- * Assumptions:
- * Not called from an interrupt handler.
- *
+ * Public Function Prototypes
****************************************************************************/
-FAR environ_t *dupenv(FAR _TCB *ptcb)
+#if defined(__cplusplus)
+extern "C"
{
- environ_t *envp = NULL;
+#endif
- /* Pre-emption must be disabled throughout the following because the
- * environment may be shared.
- */
+/* These low-level debug APIs are provided by the NuttX library. These are
+ * normally accessed via the macros in debug.h. If the cross-compiler's
+ * C pre-processor supports a variable number of macro arguments, then those
+ * macros below will map all debug statements to one or the other of the
+ * following.
+ */
- sched_lock();
+int syslog(FAR const char *format, ...);
+int vsyslog(const char *src, va_list ap);
- /* Does the parent task have an environment? */
+#ifdef CONFIG_ARCH_LOWPUTC
+int lowsyslog(FAR const char *format, ...);
+int lowvsyslog(const char *src, va_list ap);
+#endif
- if (ptcb->envp)
- {
- /* Yes..The parent task has an environment, duplicate it */
+/* Enable or disable syslog output */
- size_t envlen = ptcb->envp->ev_alloc
- envp = (environ_t*)kmalloc(SIZEOF_ENVIRON_T( envlen ));
- if (envp)
- {
- envp->ev_crefs = 1;
- envp->ev_alloc = envlen;
- memcmp( envp->ev_env, ptcb->envp->ev_env, envlen );
- }
- }
+#ifdef CONFIG_SYSLOG_ENABLE
+void syslog_enable(bool enable);
+#endif
- sched_unlock();
- return envp;
+#if defined(__cplusplus)
}
+#endif
-#endif /* CONFIG_DISABLE_ENVIRON */
-
-
-
+#endif /* __INCLUDE_SYSLOG_H */
diff --git a/nuttx/libc/lib.csv b/nuttx/libc/lib.csv
index 171f64e9b..29cdf39a6 100644
--- a/nuttx/libc/lib.csv
+++ b/nuttx/libc/lib.csv
@@ -16,7 +16,6 @@
"crc32","crc32.h","","uint32_t","FAR const uint8_t *","size_t"
"crc32part","crc32.h","","uint32_t","FAR const uint8_t *","size_t","uint32_t"
"dbg","debug.h","!defined(CONFIG_CPP_HAVE_VARARGS) && defined(CONFIG_DEBUG)","int","const char *","..."
-"dbg_enable","debug.h","defined(CONFIG_DEBUG_ENABLE)","void","bool"
"dirname","libgen.h","","FAR char","FAR char *"
"dq_addafter","queue.h","","void","FAR dq_entry_t *","FAR dq_entry_t *","FAR dq_queue_t *"
"dq_addbefore","queue.h","","void","FAR dq_entry_t *","FAR dq_entry_t *","FAR dq_queue_t *"
@@ -59,11 +58,10 @@
"inet_pton","arpa/inet.h","","int","int","FAR const char *","FAR void *"
"labs","stdlib.h","","long int","long int"
"lib_dumpbuffer","debug.h","","void","FAR const char *","FAR const uint8_t *","unsigned int"
-"lib_lowprintf","debug.h","","int","FAR const char *","..."
-"lib_rawprintf","debug.h","","int","FAR const char *","..."
"llabs","stdlib.h","defined(CONFIG_HAVE_LONG_LONG)","long long int","long long int"
"lldbg","debug.h","!defined(CONFIG_CPP_HAVE_VARARGS) && defined(CONFIG_DEBUG) && defined(CONFIG_ARCH_LOWPUTC)","int","const char *","..."
"llvdbg","debug.h","!defined(CONFIG_CPP_HAVE_VARARGS) && defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_VERBOSE) && defined(CONFIG_ARCH_LOWPUTC)","int","const char *","..."
+"lowsyslog","syslog.h","","int","FAR const char *","..."
"match","","","int","const char *","const char *"
"memccpy","string.h","","FAR void","FAR void *","FAR const void *","int c","size_t"
"memchr","string.h","","FAR void","FAR const void *","int c","size_t"
@@ -154,6 +152,8 @@
"strtoll","stdlib.h","defined(CONFIG_HAVE_LONG_LONG)","long long","const char *nptr","char **endptr","int base"
"strtoul","stdlib.h","","unsigned long","const char *","char **","int"
"strtoull","stdlib.h","defined(CONFIG_HAVE_LONG_LONG)","unsigned long long","const char *","char **","int"
+"syslog","syslog.h","","int","FAR const char *","..."
+"syslog_enable","syslog.h","defined(CONFIG_SYSLOG_ENABLE)","void","bool"
"tcflush","termios.h","CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_SERIAL_TERMIOS)","int","int","int"
"tcgetattr","termios.h","CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_SERIAL_TERMIOS)","int","int","FAR struct termios *"
"tcsetattr","termios.h","CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_SERIAL_TERMIOS)","int","int","int","FAR const struct termios *"
diff --git a/nuttx/libc/misc/lib_dbg.c b/nuttx/libc/misc/lib_dbg.c
index 5605ff828..921a4e24d 100644
--- a/nuttx/libc/misc/lib_dbg.c
+++ b/nuttx/libc/misc/lib_dbg.c
@@ -50,8 +50,8 @@
/* Debug output is initially disabled */
-#ifdef CONFIG_DEBUG_ENABLE
-bool g_dbgenable;
+#ifdef CONFIG_SYSLOG_ENABLE
+bool g_syslogenable;
#endif
/****************************************************************************
@@ -59,17 +59,17 @@ bool g_dbgenable;
****************************************************************************/
/****************************************************************************
- * Name: dbg_enable
+ * Name: syslog_enable
*
* Description:
* Enable or disable debug output.
*
****************************************************************************/
-#ifdef CONFIG_DEBUG_ENABLE
-void dbg_enable(bool enable)
+#ifdef CONFIG_SYSLOG_ENABLE
+void syslog_enable(bool enable)
{
- g_dbgenable = enable;
+ g_syslogenable = enable;
}
#endif
@@ -89,13 +89,13 @@ int dbg(const char *format, ...)
va_list ap;
int ret;
-#ifdef CONFIG_DEBUG_ENABLE
+#ifdef CONFIG_SYSLOG_ENABLE
ret = 0;
- if (g_dbgenable)
+ if (g_syslogenable)
#endif
{
va_start(ap, format);
- ret = lib_rawvprintf(format, ap);
+ ret = vsyslog(format, ap);
va_end(ap);
}
@@ -108,13 +108,13 @@ int lldbg(const char *format, ...)
va_list ap;
int ret;
-#ifdef CONFIG_DEBUG_ENABLE
+#ifdef CONFIG_SYSLOG_ENABLE
ret = 0;
- if (g_dbgenable)
+ if (g_syslogenable)
#endif
{
va_start(ap, format);
- ret = lib_lowvprintf(format, ap);
+ ret = lowvsyslog(format, ap);
va_end(ap);
}
@@ -128,13 +128,13 @@ int vdbg(const char *format, ...)
va_list ap;
int ret;
-#ifdef CONFIG_DEBUG_ENABLE
+#ifdef CONFIG_SYSLOG_ENABLE
ret = 0;
- if (g_dbgenable)
+ if (g_syslogenable)
#endif
{
va_start(ap, format);
- ret = lib_rawvprintf(format, ap);
+ ret = vsyslog(format, ap);
va_end(ap);
}
@@ -147,13 +147,13 @@ int llvdbg(const char *format, ...)
va_list ap;
int ret;
-#ifdef CONFIG_DEBUG_ENABLE
+#ifdef CONFIG_SYSLOG_ENABLE
ret = 0;
- if (g_dbgenable)
+ if (g_syslogenable)
#endif
{
va_start(ap, format);
- ret = lib_lowvprintf(format, ap);
+ ret = lowvsyslog(format, ap);
va_end(ap);
}
diff --git a/nuttx/libc/misc/lib_dumpbuffer.c b/nuttx/libc/misc/lib_dumpbuffer.c
index 52158b220..5194560fd 100644
--- a/nuttx/libc/misc/lib_dumpbuffer.c
+++ b/nuttx/libc/misc/lib_dumpbuffer.c
@@ -51,15 +51,15 @@
#ifdef CONFIG_CPP_HAVE_VARARGS
# ifdef CONFIG_ARCH_LOWPUTC
-# define message(format, arg...) lib_lowprintf(format, ##arg)
+# define message(format, arg...) lowsyslog(format, ##arg)
# else
-# define message(format, arg...) lib_rawprintf(format, ##arg)
+# define message(format, arg...) syslog(format, ##arg)
# endif
#else
# ifdef CONFIG_ARCH_LOWPUTC
-# define message lib_lowprintf
+# define message lowsyslog
# else
-# define message lib_rawprintf
+# define message syslog
# endif
#endif
diff --git a/nuttx/libc/misc/lib_init.c b/nuttx/libc/misc/lib_init.c
index 6a120f7b1..434c46505 100644
--- a/nuttx/libc/misc/lib_init.c
+++ b/nuttx/libc/misc/lib_init.c
@@ -1,7 +1,7 @@
/************************************************************
* libc/misc/lib_init.c
*
- * Copyright (C) 2007, 2011 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2011, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -76,69 +76,35 @@ void weak_const_function lib_initialize(void)
}
#if CONFIG_NFILE_STREAMS > 0
-/* The following function is called when a new TCB is allocated. It
- * creates the streamlist instance that is stored in the TCB.
+/* The following function is called when a new task is allocated. It
+ * intializes the streamlist instance that is stored in the task group.
*/
-FAR struct streamlist *lib_alloclist(void)
+void lib_streaminit(FAR struct streamlist *list)
{
- FAR struct streamlist *list;
- list = (FAR struct streamlist*)lib_zalloc(sizeof(struct streamlist));
- if (list)
- {
- int i;
-
- /* Start with a reference count of one */
-
- list->sl_crefs = 1;
+ int i;
- /* Initialize the list access mutex */
+ /* Initialize the list access mutex */
- (void)sem_init(&list->sl_sem, 0, 1);
+ (void)sem_init(&list->sl_sem, 0, 1);
- /* Initialize each FILE structure */
+ /* Initialize each FILE structure */
- for (i = 0; i < CONFIG_NFILE_STREAMS; i++)
- {
- /* Clear the IOB */
+ for (i = 0; i < CONFIG_NFILE_STREAMS; i++)
+ {
+ /* Clear the IOB */
- memset(&list->sl_streams[i], 0, sizeof(FILE));
+ memset(&list->sl_streams[i], 0, sizeof(FILE));
- /* Indicate not opened */
+ /* Indicate not opened */
- list->sl_streams[i].fs_filedes = -1;
+ list->sl_streams[i].fs_filedes = -1;
- /* Initialize the stream semaphore to one to support one-at-
- * a-time access to private data sets.
- */
-
- lib_sem_initialize(&list->sl_streams[i]);
- }
- }
- return list;
+ /* Initialize the stream semaphore to one to support one-at-
+ * a-time access to private data sets.
+ */
-}
-
-/* This function is called when a TCB is closed (such as with
- * pthread_create(). It increases the reference count on the stream
- * list.
- */
-
-void lib_addreflist(FAR struct streamlist *list)
-{
- if (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.
- */
-
- register irqstate_t flags = irqsave();
- list->sl_crefs++;
- irqrestore(flags);
+ lib_sem_initialize(&list->sl_streams[i]);
}
}
@@ -149,57 +115,33 @@ void lib_addreflist(FAR struct streamlist *list)
void lib_releaselist(FAR struct streamlist *list)
{
- int crefs;
- if (list)
- {
- /* 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.
- */
-
- register irqstate_t flags = irqsave();
- crefs = --(list->sl_crefs);
- irqrestore(flags);
-
- /* If the count decrements to zero, then there is no reference
- * 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)
- {
#if CONFIG_STDIO_BUFFER_SIZE > 0
- int i;
+ int i;
#endif
- /* Destroy the semaphore and release the filelist */
- (void)sem_destroy(&list->sl_sem);
+ DEBUGASSERT(list);
+
+ /* Destroy the semaphore and release the filelist */
- /* Release each stream in the list */
+ (void)sem_destroy(&list->sl_sem);
+
+ /* Release each stream in the list */
#if CONFIG_STDIO_BUFFER_SIZE > 0
- for (i = 0; i < CONFIG_NFILE_STREAMS; i++)
- {
- /* Destroy the semaphore that protects the IO buffer */
-
- (void)sem_destroy(&list->sl_streams[i].fs_sem);
-
- /* Release the IO buffer */
- if (list->sl_streams[i].fs_bufstart)
- {
- sched_free(list->sl_streams[i].fs_bufstart);
- }
- }
-#endif
- /* Finally, release the list itself */
+ for (i = 0; i < CONFIG_NFILE_STREAMS; i++)
+ {
+ /* Destroy the semaphore that protects the IO buffer */
- sched_free(list);
- }
- }
+ (void)sem_destroy(&list->sl_streams[i].fs_sem);
+
+ /* Release the IO buffer */
+
+ if (list->sl_streams[i].fs_bufstart)
+ {
+ sched_free(list->sl_streams[i].fs_bufstart);
+ }
+ }
+#endif
}
#endif /* CONFIG_NFILE_STREAMS */
diff --git a/nuttx/libc/stdio/Make.defs b/nuttx/libc/stdio/Make.defs
index 0670724da..32502f32c 100644
--- a/nuttx/libc/stdio/Make.defs
+++ b/nuttx/libc/stdio/Make.defs
@@ -37,7 +37,7 @@
# This first group of C files do not depend on having file descriptors or
# C streams.
-CSRCS += lib_fileno.c lib_printf.c lib_rawprintf.c lib_lowprintf.c \
+CSRCS += lib_fileno.c lib_printf.c lib_syslog.c lib_lowsyslog.c\
lib_sprintf.c lib_asprintf.c lib_snprintf.c lib_libsprintf.c \
lib_vsprintf.c lib_avsprintf.c lib_vsnprintf.c lib_libvsprintf.c \
lib_meminstream.c lib_memoutstream.c lib_lowinstream.c \
diff --git a/nuttx/libc/stdio/lib_fgets.c b/nuttx/libc/stdio/lib_fgets.c
index 35d024ebb..87eed285d 100644
--- a/nuttx/libc/stdio/lib_fgets.c
+++ b/nuttx/libc/stdio/lib_fgets.c
@@ -150,7 +150,7 @@ char *fgets(FAR char *buf, int buflen, FILE *stream)
if (ch == '\n')
#elif defined(CONFIG_EOL_IS_CR)
if (ch == '\r')
-#else /* elif CONFIG_EOL_IS_EITHER_CRLF */
+#else /* elif defined(CONFIG_EOL_IS_EITHER_CRLF) */
if (ch == '\n' || ch == '\r')
#endif
{
diff --git a/nuttx/libc/stdio/lib_libflushall.c b/nuttx/libc/stdio/lib_libflushall.c
index 7ac3da7e0..22baed968 100644
--- a/nuttx/libc/stdio/lib_libflushall.c
+++ b/nuttx/libc/stdio/lib_libflushall.c
@@ -1,7 +1,7 @@
/****************************************************************************
* libc/stdio/lib_libflushall.c
*
- * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
diff --git a/nuttx/libc/stdio/lib_libfread.c b/nuttx/libc/stdio/lib_libfread.c
index 3e851bf17..f8cf0f40a 100644
--- a/nuttx/libc/stdio/lib_libfread.c
+++ b/nuttx/libc/stdio/lib_libfread.c
@@ -1,7 +1,7 @@
/****************************************************************************
* libc/stdio/lib_libfread.c
*
- * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -88,7 +88,9 @@ ssize_t lib_fread(FAR void *ptr, size_t count, FAR FILE *stream)
{
unsigned char *dest = (unsigned char*)ptr;
ssize_t bytes_read;
+#if CONFIG_STDIO_BUFFER_SIZE > 0
int ret;
+#endif
/* Make sure that reading from this stream is allowed */
diff --git a/nuttx/libc/stdio/lib_lowprintf.c b/nuttx/libc/stdio/lib_lowsyslog.c
index f7d4ffe2f..bfe6a2cce 100644
--- a/nuttx/libc/stdio/lib_lowprintf.c
+++ b/nuttx/libc/stdio/lib_lowsyslog.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * libc/stdio/lib_lowprintf.c
+ * libc/stdio/lib_lowsyslog.c
*
* Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
@@ -38,8 +38,10 @@
****************************************************************************/
#include <nuttx/config.h>
+
#include <stdio.h>
#include <debug.h>
+
#include "lib_internal.h"
/* This interface can only be used from within the kernel */
@@ -83,12 +85,12 @@
****************************************************************************/
/****************************************************************************
- * Name: lib_lowvprintf
+ * Name: lowvsyslog
****************************************************************************/
#if defined(CONFIG_ARCH_LOWPUTC) || defined(CONFIG_SYSLOG)
-int lib_lowvprintf(const char *fmt, va_list ap)
+int lowvsyslog(const char *fmt, va_list ap)
{
struct lib_outstream_s stream;
@@ -103,21 +105,21 @@ int lib_lowvprintf(const char *fmt, va_list ap)
}
/****************************************************************************
- * Name: lib_lowprintf
+ * Name: lowsyslog
****************************************************************************/
-int lib_lowprintf(const char *fmt, ...)
+int lowsyslog(const char *fmt, ...)
{
va_list ap;
int ret;
-#ifdef CONFIG_DEBUG_ENABLE
+#ifdef CONFIG_SYSLOG_ENABLE
ret = 0;
- if (g_dbgenable)
+ if (g_syslogenable)
#endif
{
va_start(ap, fmt);
- ret = lib_lowvprintf(fmt, ap);
+ ret = lowvsyslog(fmt, ap);
va_end(ap);
}
diff --git a/nuttx/libc/stdio/lib_printf.c b/nuttx/libc/stdio/lib_printf.c
index 0e90c7ca5..b035aa14f 100644
--- a/nuttx/libc/stdio/lib_printf.c
+++ b/nuttx/libc/stdio/lib_printf.c
@@ -93,9 +93,9 @@ int printf(const char *fmt, ...)
#if CONFIG_NFILE_STREAMS > 0
ret = vfprintf(stdout, fmt, ap);
#elif CONFIG_NFILE_DESCRIPTORS > 0
- ret = lib_rawvprintf(fmt, ap);
+ ret = vsyslog(fmt, ap);
#elif defined(CONFIG_ARCH_LOWPUTC)
- ret = lib_lowvprintf(fmt, ap);
+ ret = lowvsyslog(fmt, ap);
#else
# ifdef CONFIG_CPP_HAVE_WARNING
# warning "printf has no data sink"
diff --git a/nuttx/libc/stdio/lib_rawprintf.c b/nuttx/libc/stdio/lib_syslog.c
index ddbb84f94..661c3b61e 100644
--- a/nuttx/libc/stdio/lib_rawprintf.c
+++ b/nuttx/libc/stdio/lib_syslog.c
@@ -1,7 +1,7 @@
/****************************************************************************
- * libc/stdio/lib_rawprintf.c
+ * libc/stdio/lib_syslog.c
*
- * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -37,8 +37,11 @@
* Included Files
****************************************************************************/
+#include <nuttx/config.h>
+
#include <stdio.h>
-#include <debug.h>
+#include <syslog.h>
+
#include "lib_internal.h"
/****************************************************************************
@@ -85,10 +88,10 @@
****************************************************************************/
/****************************************************************************
- * Name: lib_rawvprintf
+ * Name: vsyslog
****************************************************************************/
-int lib_rawvprintf(const char *fmt, va_list ap)
+int vsyslog(const char *fmt, va_list ap)
{
#if defined(CONFIG_SYSLOG)
@@ -129,21 +132,21 @@ int lib_rawvprintf(const char *fmt, va_list ap)
}
/****************************************************************************
- * Name: lib_rawprintf
+ * Name: syslog
****************************************************************************/
-int lib_rawprintf(const char *fmt, ...)
+int syslog(const char *fmt, ...)
{
va_list ap;
int ret;
-#ifdef CONFIG_DEBUG_ENABLE
+#ifdef CONFIG_SYSLOG_ENABLE
ret = 0;
- if (g_dbgenable)
+ if (g_syslogenable)
#endif
{
va_start(ap, fmt);
- ret = lib_rawvprintf(fmt, ap);
+ ret = vsyslog(fmt, ap);
va_end(ap);
}
diff --git a/nuttx/libc/stdio/lib_syslogstream.c b/nuttx/libc/stdio/lib_syslogstream.c
index 5529c5de8..e29c5ca3d 100644
--- a/nuttx/libc/stdio/lib_syslogstream.c
+++ b/nuttx/libc/stdio/lib_syslogstream.c
@@ -71,22 +71,23 @@ static void syslogstream_putc(FAR struct lib_outstream_s *this, int ch)
do
{
- /* Write the character to the supported logging device */
+ /* Write the character to the supported logging device. On failure,
+ * syslog_putc returns EOF with the errno value set;
+ */
ret = syslog_putc(ch);
- if (ret == OK)
+ if (ret != EOF)
{
this->nput++;
return;
}
- /* On failure syslog_putc will return a negated errno value. The
- * errno variable will not be set. The special value -EINTR means that
- * syslog_putc() was awakened by a signal. This is not a real error and
- * must be ignored in this context.
+ /* The special errno value -EINTR means that syslog_putc() was
+ * awakened by a signal. This is not a real error and must be
+ * ignored in this context.
*/
}
- while (ret == -EINTR);
+ while (errno == -EINTR);
}
/****************************************************************************
diff --git a/nuttx/net/net_poll.c b/nuttx/net/net_poll.c
index 2e73bd73c..1838f541e 100644
--- a/nuttx/net/net_poll.c
+++ b/nuttx/net/net_poll.c
@@ -1,7 +1,7 @@
/****************************************************************************
* net/net_poll.c
*
- * Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2008-2009, 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -46,11 +46,13 @@
#include <stdlib.h>
#include <poll.h>
#include <errno.h>
+#include <assert.h>
#include <debug.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/arch.h>
#include <nuttx/net/uip/uip.h>
#include <nuttx/net/net.h>
-#include <nuttx/arch.h>
#include <uip/uip_internal.h>
@@ -75,6 +77,14 @@
/****************************************************************************
* Private Types
****************************************************************************/
+/* This is an allocated container that holds the poll-related information */
+
+struct net_poll_s
+{
+ FAR struct socket *psock; /* Needed to handle loss of connection */
+ struct pollfd *fds; /* Needed to handle poll events */
+ FAR struct uip_callback_s *cb; /* Needed to teardown the poll */
+};
/****************************************************************************
* Private Functions
@@ -101,16 +111,18 @@
****************************************************************************/
#ifdef HAVE_NETPOLL
-static uint16_t poll_interrupt(struct uip_driver_s *dev, FAR void *conn,
+static uint16_t poll_interrupt(FAR struct uip_driver_s *dev, FAR void *conn,
FAR void *pvpriv, uint16_t flags)
{
- FAR struct pollfd *fds = (FAR struct pollfd *)pvpriv;
+ FAR struct net_poll_s *info = (FAR struct net_poll_s *)pvpriv;
nllvdbg("flags: %04x\n", flags);
+ DEBUGASSERT(!info || (info->psock && info->fds));
+
/* 'priv' might be null in some race conditions (?) */
- if (fds)
+ if (info)
{
pollevent_t eventset = 0;
@@ -118,24 +130,23 @@ static uint16_t poll_interrupt(struct uip_driver_s *dev, FAR void *conn,
if ((flags & (UIP_NEWDATA|UIP_BACKLOG)) != 0)
{
- eventset |= POLLIN & fds->events;
+ eventset |= POLLIN & info->fds->events;
}
/* A poll is a sign that we are free to send data. */
if ((flags & UIP_POLL) != 0)
{
- eventset |= (POLLOUT & fds->events);
+ eventset |= (POLLOUT & info->fds->events);
}
- /* Check for a loss of connection events.
- *
- * REVISIT: Need to call net_lostconnection() here, but don't have
- * the psock instance. What should we do?
- */
+ /* Check for a loss of connection events. */
if ((flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0)
{
+ /* Make the the connection has been lost */
+
+ net_lostconnection(info->psock, flags);
eventset |= (POLLERR | POLLHUP);
}
@@ -143,8 +154,8 @@ static uint16_t poll_interrupt(struct uip_driver_s *dev, FAR void *conn,
if (eventset)
{
- fds->revents |= eventset;
- sem_post(fds->sem);
+ info->fds->revents |= eventset;
+ sem_post(info->fds->sem);
}
}
@@ -169,9 +180,11 @@ static uint16_t poll_interrupt(struct uip_driver_s *dev, FAR void *conn,
****************************************************************************/
#ifdef HAVE_NETPOLL
-static inline int net_pollsetup(FAR struct socket *psock, struct pollfd *fds)
+static inline int net_pollsetup(FAR struct socket *psock,
+ FAR struct pollfd *fds)
{
FAR struct uip_conn *conn = psock->s_conn;
+ FAR struct net_poll_s *info;
FAR struct uip_callback_s *cb;
uip_lock_t flags;
int ret;
@@ -185,6 +198,14 @@ static inline int net_pollsetup(FAR struct socket *psock, struct pollfd *fds)
}
#endif
+ /* Allocate a container to hold the poll information */
+
+ info = (FAR struct net_poll_s *)kmalloc(sizeof(struct net_poll_s));
+ if (!info)
+ {
+ return -ENOMEM;
+ }
+
/* Some of the following must be atomic */
flags = uip_lock();
@@ -195,18 +216,29 @@ static inline int net_pollsetup(FAR struct socket *psock, struct pollfd *fds)
if (!cb)
{
ret = -EBUSY;
- goto errout_with_irq;
+ goto errout_with_lock;
}
- /* Initialize the callback structure */
+ /* Initialize the poll info container */
+
+ info->psock = psock;
+ info->fds = fds;
+ info->cb = cb;
+
+ /* Initialize the callback structure. Save the reference to the info
+ * structure as callback private data so that it will be available during
+ * callback processing.
+ */
cb->flags = (UIP_NEWDATA|UIP_BACKLOG|UIP_POLL|UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT);
- cb->priv = (FAR void *)fds;
+ cb->priv = (FAR void *)info;
cb->event = poll_interrupt;
- /* Save the nps reference in the poll structure for use at teardown as well */
+ /* Save the reference in the poll info structure as fds private as well
+ * for use durring poll teardown as well.
+ */
- fds->priv = (FAR void *)cb;
+ fds->priv = (FAR void *)info;
#ifdef CONFIG_NET_TCPBACKLOG
/* Check for read data or backlogged connection availability now */
@@ -240,7 +272,8 @@ static inline int net_pollsetup(FAR struct socket *psock, struct pollfd *fds)
uip_unlock(flags);
return OK;
-errout_with_irq:
+errout_with_lock:
+ kfree(info);
uip_unlock(flags);
return ret;
}
@@ -261,10 +294,11 @@ errout_with_irq:
****************************************************************************/
#ifdef HAVE_NETPOLL
-static inline int net_pollteardown(FAR struct socket *psock, struct pollfd *fds)
+static inline int net_pollteardown(FAR struct socket *psock,
+ FAR struct pollfd *fds)
{
FAR struct uip_conn *conn = psock->s_conn;
- FAR struct uip_callback_s *cb;
+ FAR struct net_poll_s *info;
uip_lock_t flags;
/* Sanity check */
@@ -278,18 +312,23 @@ static inline int net_pollteardown(FAR struct socket *psock, struct pollfd *fds)
/* Recover the socket descriptor poll state info from the poll structure */
- cb = (FAR struct uip_callback_s *)fds->priv;
- if (cb)
+ info = (FAR struct net_poll_s *)fds->priv;
+ DEBUGASSERT(info && info->fds && info->cb);
+ if (info)
{
/* Release the callback */
flags = uip_lock();
- uip_tcpcallbackfree(conn, cb);
+ uip_tcpcallbackfree(conn, info->cb);
uip_unlock(flags);
/* Release the poll/select data slot */
- fds->priv = NULL;
+ info->fds->priv = NULL;
+
+ /* Then free the poll info container */
+
+ kfree(info);
}
return OK;
@@ -308,7 +347,7 @@ static inline int net_pollteardown(FAR struct socket *psock, struct pollfd *fds)
* to this function.
*
* Input Parameters:
- * fd - The socket descriptor of interest
+ * psock - An instance of the internal socket structure.
* fds - The structure describing the events to be monitored, OR NULL if
* this is a request to stop monitoring events.
* setup - true: Setup up the poll; false: Teardown the poll
@@ -318,33 +357,17 @@ static inline int net_pollteardown(FAR struct socket *psock, struct pollfd *fds)
*
****************************************************************************/
-#ifndef CONFIG_DISABLE_POLL
-int net_poll(int sockfd, struct pollfd *fds, bool setup)
+#if !defined(CONFIG_DISABLE_POLL) && defined(HAVE_NETPOLL)
+int psock_poll(FAR struct socket *psock, FAR struct pollfd *fds, bool setup)
{
-#ifndef HAVE_NETPOLL
- return -ENOSYS;
-#else
- FAR struct socket *psock;
int ret;
- /* Get the underlying socket structure and verify that the sockfd
- * corresponds to valid, allocated socket
- */
-
- psock = sockfd_socket(sockfd);
- if (!psock || psock->s_crefs <= 0)
- {
- ret = -EBADF;
- goto errout;
- }
-
#ifdef CONFIG_NET_UDP
/* poll() not supported for UDP */
if (psock->s_type != SOCK_STREAM)
{
- ret = -ENOSYS;
- goto errout;
+ return -ENOSYS;
}
#endif
@@ -363,8 +386,49 @@ int net_poll(int sockfd, struct pollfd *fds, bool setup)
ret = net_pollteardown(psock, fds);
}
-errout:
return ret;
+}
+#endif
+
+/****************************************************************************
+ * Function: net_poll
+ *
+ * Description:
+ * The standard poll() operation redirects operations on socket descriptors
+ * to this function.
+ *
+ * Input Parameters:
+ * fd - The socket descriptor of interest
+ * fds - The structure describing the events to be monitored, OR NULL if
+ * this is a request to stop monitoring events.
+ * setup - true: Setup up the poll; false: Teardown the poll
+ *
+ * Returned Value:
+ * 0: Success; Negated errno on failure
+ *
+ ****************************************************************************/
+
+#ifndef CONFIG_DISABLE_POLL
+int net_poll(int sockfd, struct pollfd *fds, bool setup)
+{
+#ifndef HAVE_NETPOLL
+ return -ENOSYS;
+#else
+ FAR struct socket *psock;
+
+ /* Get the underlying socket structure and verify that the sockfd
+ * corresponds to valid, allocated socket
+ */
+
+ psock = sockfd_socket(sockfd);
+ if (!psock || psock->s_crefs <= 0)
+ {
+ return -EBADF;
+ }
+
+ /* Then let psock_poll() do the heavy lifting */
+
+ return psock_poll(psock, fds, setup);
#endif /* HAVE_NETPOLL */
}
#endif /* !CONFIG_DISABLE_POLL */
diff --git a/nuttx/net/net_sockets.c b/nuttx/net/net_sockets.c
index 81e48c121..ddb54c98c 100644
--- a/nuttx/net/net_sockets.c
+++ b/nuttx/net/net_sockets.c
@@ -116,99 +116,37 @@ void net_initialize(void)
#if CONFIG_NSOCKET_DESCRIPTORS > 0
-/* Allocate a list of files for a new task */
+/* Initialize a list of sockets for a new task */
-FAR struct socketlist *net_alloclist(void)
+void net_initlist(FAR struct socketlist *list)
{
- FAR struct socketlist *list;
- list = (FAR struct socketlist*)kzalloc(sizeof(struct socketlist));
- if (list)
- {
- /* Start with a reference count of one */
-
- list->sl_crefs = 1;
-
- /* Initialize the list access mutex */
+ /* Initialize the list access mutex */
- (void)sem_init(&list->sl_sem, 0, 1);
- }
- return list;
+ (void)sem_init(&list->sl_sem, 0, 1);
}
-/* Increase the reference count on a file list */
+/* Release release resources held by the socket list */
-int net_addreflist(FAR struct socketlist *list)
+void net_releaselist(FAR struct socketlist *list)
{
- if (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.
- */
-
- register uip_lock_t flags = uip_lock();
- list->sl_crefs++;
- uip_unlock(flags);
- }
- return OK;
-}
+ int ndx;
-/* Release a reference to the file list */
+ DEBUGASSERT(list);
-int net_releaselist(FAR struct socketlist *list)
-{
- int crefs;
- int ndx;
+ /* Close each open socket in the list. */
- if (list)
+ for (ndx = 0; ndx < CONFIG_NSOCKET_DESCRIPTORS; ndx++)
{
- /* 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.
- */
-
- uip_lock_t flags = uip_lock();
- crefs = --(list->sl_crefs);
- uip_unlock(flags);
-
- /* If the count decrements to zero, then there is no reference
- * 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)
- {
- /* Close each open socket in the list
- * REVISIT: psock_close() will attempt to use semaphores.
- * If we actually are in the IDLE thread, then could this cause
- * problems? Probably not, if the task has exited and crefs is
- * zero, then there probably could not be a contender for the
- * semaphore.
- */
-
- for (ndx = 0; ndx < CONFIG_NSOCKET_DESCRIPTORS; ndx++)
- {
- FAR struct socket *psock = &list->sl_sockets[ndx];
- if (psock->s_crefs > 0)
- {
- (void)psock_close(psock);
- }
- }
-
- /* Destroy the semaphore and release the filelist */
-
- (void)sem_destroy(&list->sl_sem);
- sched_free(list);
- }
+ FAR struct socket *psock = &list->sl_sockets[ndx];
+ if (psock->s_crefs > 0)
+ {
+ (void)psock_close(psock);
+ }
}
- return OK;
+
+ /* Destroy the semaphore */
+
+ (void)sem_destroy(&list->sl_sem);
}
int sockfd_allocate(int minsd)
diff --git a/nuttx/net/send.c b/nuttx/net/send.c
index 79dfef4ec..b26a0e5bb 100644
--- a/nuttx/net/send.c
+++ b/nuttx/net/send.c
@@ -448,7 +448,7 @@ end_wait:
* equivalent to sendto(sockfd,buf,len,flags,NULL,0).
*
* Parameters:
- * psock And instance of the internal socket structure.
+ * psock An instance of the internal socket structure.
* buf Data to send
* len Length of data to send
* flags Send flags
diff --git a/nuttx/sched/Kconfig b/nuttx/sched/Kconfig
index fe9a88085..097dd1993 100644
--- a/nuttx/sched/Kconfig
+++ b/nuttx/sched/Kconfig
@@ -124,6 +124,13 @@ config PREALLOC_CHILDSTATUS
sa.sa_flags = SA_NOCLDWAIT;
int ret = sigaction(SIGCHLD, &sa, NULL);
+config DEBUG_CHILDSTATUS
+ bool "Enable Child Status Debug Output"
+ default n
+ depends on SCHED_CHILD_STATUS && DEBUG
+ ---help---
+ Very detailed... I am sure that you do not want this.
+
config JULIAN_TIME
bool "Enables Julian time conversions"
default n
@@ -289,6 +296,16 @@ config SCHED_WAITPID
compliant) and will enable the waitid() and wait() interfaces as
well.
+config SCHED_STARTHOOK
+ bool "Enable startup hook"
+ default n
+ ---help---
+ Enable a non-standard, internal OS API call task_starthook().
+ task_starthook() registers a function that will be called on task
+ startup before that actual task entry point is called. The
+ starthook is useful, for example, for setting up automatic
+ configuration of C++ constructors.
+
config SCHED_ATEXIT
bool "Enable atexit() API"
default n
@@ -379,21 +396,11 @@ config DISABLE_MQUEUE
depends on DISABLE_OS_API
default n
-config DISABLE_MOUNTPOINT
- bool "Disable support for mount points"
- depends on DISABLE_OS_API
- default n
-
config DISABLE_ENVIRON
bool "Disable environment variable support"
depends on DISABLE_OS_API
default n
-config DISABLE_POLL
- bool "Disable driver poll interfaces"
- depends on DISABLE_OS_API
- default n
-
if !DISABLE_SIGNALS
comment "Signal Numbers"
diff --git a/nuttx/sched/Makefile b/nuttx/sched/Makefile
index 1ad244450..961560176 100644
--- a/nuttx/sched/Makefile
+++ b/nuttx/sched/Makefile
@@ -39,9 +39,7 @@ ASRCS =
AOBJS = $(ASRCS:.S=$(OBJEXT))
MISC_SRCS = os_start.c os_bringup.c errno_getptr.c errno_get.c errno_set.c
-MISC_SRCS += sched_garbage.c sched_setupstreams.c sched_getfiles.c sched_getsockets.c
-MISC_SRCS += sched_getstreams.c sched_setupidlefiles.c sched_setuptaskfiles.c
-MISC_SRCS += sched_setuppthreadfiles.c sched_releasefiles.c
+MISC_SRCS += sched_garbage.c sched_getfiles.c sched_getsockets.c sched_getstreams.c
TSK_SRCS = prctl.c task_create.c task_init.c task_setup.c task_activate.c
TSK_SRCS += task_start.c task_delete.c task_deletecurrent.c task_exithook.c
@@ -56,6 +54,10 @@ TSK_SRCS += task_posixspawn.c
endif
endif
+ifeq ($(CONFIG_SCHED_STARTHOOK),y)
+TSK_SRCS += task_starthook.c
+endif
+
SCHED_SRCS = sched_setparam.c sched_setpriority.c sched_getparam.c
SCHED_SRCS += sched_setscheduler.c sched_getscheduler.c
SCHED_SRCS += sched_yield.c sched_rrgetinterval.c sched_foreach.c
@@ -73,21 +75,28 @@ ifeq ($(CONFIG_PRIORITY_INHERITANCE),y)
SCHED_SRCS += sched_reprioritize.c
endif
+ifeq ($(CONFIG_SCHED_WAITPID),y)
+SCHED_SRCS += sched_waitpid.c
ifeq ($(CONFIG_SCHED_HAVE_PARENT),y)
-SCHED_SRCS += task_reparent.c
-ifeq ($(CONFIG_SCHED_CHILD_STATUS),y)
-SCHED_SRCS += task_childstatus.c
+SCHED_SRCS += sched_waitid.c sched_wait.c
endif
endif
-ifeq ($(CONFIG_SCHED_WAITPID),y)
-SCHED_SRCS += sched_waitpid.c
+GRP_SRCS = group_create.c group_join.c group_leave.c group_find.c
+GRP_SRCS += group_setupstreams.c group_setupidlefiles.c group_setuptaskfiles.c
+
ifeq ($(CONFIG_SCHED_HAVE_PARENT),y)
-SCHED_SRCS += sched_waitid.c sched_wait.c
+GRP_SRCS += task_reparent.c
+ifeq ($(CONFIG_SCHED_CHILD_STATUS),y)
+GRP_SRCS += group_childstatus.c
endif
endif
-ENV_SRCS = env_getenvironptr.c env_dup.c env_share.c env_release.c
+ifneq ($(CONFIG_DISABLE_SIGNALS),y)
+GRP_SRCS += group_signal.c
+endif
+
+ENV_SRCS = env_getenvironptr.c env_dup.c env_release.c
ENV_SRCS += env_findvar.c env_removevar.c
ENV_SRCS += env_clearenv.c env_getenv.c env_putenv.c env_setenv.c env_unsetenv.c
@@ -169,8 +178,9 @@ IRQ_SRCS = irq_initialize.c irq_attach.c irq_dispatch.c irq_unexpectedisr.c
KMM_SRCS = kmm_initialize.c kmm_addregion.c kmm_semaphore.c
KMM_SRCS = kmm_kmalloc.c kmm_kzalloc.c kmm_krealloc.c kmm_kfree.c
-CSRCS = $(MISC_SRCS) $(TSK_SRCS) $(SCHED_SRCS) $(WDOG_SRCS) $(TIME_SRCS) \
- $(SEM_SRCS) $(TIMER_SRCS) $(WORK_SRCS) $(PGFILL_SRCS) $(IRQ_SRCS)
+CSRCS = $(MISC_SRCS) $(TSK_SRCS) $(GRP_SRCS) $(SCHED_SRCS) $(WDOG_SRCS)
+CSRCS += $(TIME_SRCS) $(SEM_SRCS) $(TIMER_SRCS) $(WORK_SRCS) $(PGFILL_SRCS)
+CSRCS += $(IRQ_SRCS)
ifneq ($(CONFIG_DISABLE_CLOCK),y)
CSRCS += $(CLOCK_SRCS)
diff --git a/nuttx/sched/env_clearenv.c b/nuttx/sched/env_clearenv.c
index 75890f3bc..062fd60ed 100644
--- a/nuttx/sched/env_clearenv.c
+++ b/nuttx/sched/env_clearenv.c
@@ -1,7 +1,7 @@
/****************************************************************************
* sched/env_clearenv.c
*
- * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -74,7 +74,11 @@
int clearenv(void)
{
- return env_release((FAR _TCB*)g_readytorun.head);
+ FAR _TCB *tcb = (FAR _TCB*)g_readytorun.head;
+ DEBUGASSERT(tcb->group);
+
+ env_release(tcb->group);
+ return OK;
}
#endif /* CONFIG_DISABLE_ENVIRON */
diff --git a/nuttx/sched/env_dup.c b/nuttx/sched/env_dup.c
index 033348411..3b653b010 100644
--- a/nuttx/sched/env_dup.c
+++ b/nuttx/sched/env_dup.c
@@ -1,7 +1,7 @@
/****************************************************************************
* sched/env_dup.c
*
- * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2011, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -68,8 +68,8 @@
* exact duplicate of the parent task's environment.
*
* Parameters:
- * ptcb The tcb to receive the newly allocated copy of the parspecifiedent
- * TCB's environment structure with reference count equal to one
+ * group The child task group to receive the newly allocated copy of the
+ * parent task groups environment structure.
*
* Return Value:
* zero on success
@@ -79,50 +79,42 @@
*
****************************************************************************/
-int env_dup(FAR _TCB *ptcb)
+int env_dup(FAR struct task_group_s *group)
{
+ FAR _TCB *ptcb = (FAR _TCB*)g_readytorun.head;
+ FAR char *envp = NULL;
+ size_t envlen;
int ret = OK;
- if (!ptcb )
- {
- ret = -EINVAL;
- }
- else
- {
- FAR _TCB *parent = (FAR _TCB*)g_readytorun.head;
- environ_t *envp = NULL;
- /* Pre-emption must be disabled throughout the following because the
- * environment may be shared.
- */
+ DEBUGASSERT(group && ptcb && ptcb->group);
- sched_lock();
+ /* Pre-emption must be disabled throughout the following because the
+ * environment may be shared.
+ */
- /* Does the parent task have an environment? */
+ sched_lock();
- if (parent->envp)
- {
- /* Yes..The parent task has an environment, duplicate it */
-
- size_t envlen = parent->envp->ev_alloc;
- envp = (environ_t*)kmalloc(SIZEOF_ENVIRON_T( envlen ));
- if (!envp)
- {
- ret = -ENOMEM;
- }
- else
- {
- envp->ev_crefs = 1;
- envp->ev_alloc = envlen;
- memcpy( envp->ev_env, parent->envp->ev_env, envlen );
- }
- }
+ /* Does the parent task have an environment? */
- /* Save the cloned environment in the new TCB */
+ if (ptcb->group && ptcb->group->tg_envp)
+ {
+ /* Yes..The parent task has an environment, duplicate it */
- ptcb->envp = envp;
- sched_unlock();
- }
+ envlen = ptcb->group->tg_envsize;
+ envp = (FAR char *)kmalloc(envlen);
+ if (!envp)
+ {
+ ret = -ENOMEM;
+ }
+ else
+ {
+ group->tg_envsize = envlen;
+ group->tg_envp = envp;
+ memcpy(envp, ptcb->group->tg_envp, envlen);
+ }
+ }
+ sched_unlock();
return ret;
}
diff --git a/nuttx/sched/env_findvar.c b/nuttx/sched/env_findvar.c
index a8e94180c..a744c6c3a 100644
--- a/nuttx/sched/env_findvar.c
+++ b/nuttx/sched/env_findvar.c
@@ -1,7 +1,7 @@
/****************************************************************************
* sched/env_findvar.c
*
- * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -85,7 +85,7 @@ static bool env_cmpname(const char *pszname, const char *peqname)
* specified name.
*
* Parameters:
- * envp The environment structre to be searched.
+ * group The task group containging environment array to be searched.
* pname The variable name to find
*
* Return Value:
@@ -97,32 +97,25 @@ static bool env_cmpname(const char *pszname, const char *peqname)
*
****************************************************************************/
-FAR char *env_findvar(environ_t *envp, const char *pname)
+FAR char *env_findvar(FAR struct task_group_s *group, const char *pname)
{
- char *ret = NULL;
+ char *ptr;
+ char *end;
/* Verify input parameters */
- if (envp && pname)
- {
- char *ptr;
- char *end = &envp->ev_env[envp->ev_alloc];
-
- /* Search for a name=value string with matching name */
+ DEBUGASSERT(group && pname);
- for (ptr = envp->ev_env;
- ptr < end && !env_cmpname( pname, ptr);
- ptr += (strlen(ptr) + 1));
+ /* Search for a name=value string with matching name */
- /* Check for success */
+ end = &group->tg_envp[group->tg_envsize];
+ for (ptr = group->tg_envp;
+ ptr < end && !env_cmpname(pname, ptr);
+ ptr += (strlen(ptr) + 1));
- if (ptr < end)
- {
- ret = ptr;
- }
- }
+ /* Check for success */
- return ret;
+ return (ptr < end) ? ptr : NULL;
}
#endif /* CONFIG_DISABLE_ENVIRON */
diff --git a/nuttx/sched/env_getenv.c b/nuttx/sched/env_getenv.c
index ee8d798b1..4709bc380 100644
--- a/nuttx/sched/env_getenv.c
+++ b/nuttx/sched/env_getenv.c
@@ -1,7 +1,7 @@
/****************************************************************************
* env_getenv.c
*
- * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2008, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -77,10 +77,10 @@
FAR char *getenv(const char *name)
{
- FAR _TCB *rtcb;
- FAR environ_t *envp;
- FAR char *pvar;
- FAR char *pvalue = NULL;
+ FAR _TCB *rtcb;
+ FAR struct task_group_s *group;
+ FAR char *pvar;
+ FAR char *pvalue = NULL;
int ret = OK;
/* Verify that a string was passed */
@@ -95,11 +95,11 @@ FAR char *getenv(const char *name)
sched_lock();
rtcb = (FAR _TCB*)g_readytorun.head;
- envp = rtcb->envp;
+ group = rtcb->group;
/* Check if the variable exists */
- if ( !envp || (pvar = env_findvar(envp, name)) == NULL)
+ if ( !group || (pvar = env_findvar(group, name)) == NULL)
{
ret = ENOENT;
goto errout_with_lock;
diff --git a/nuttx/sched/env_internal.h b/nuttx/sched/env_internal.h
index 5370da059..e02bf289d 100644
--- a/nuttx/sched/env_internal.h
+++ b/nuttx/sched/env_internal.h
@@ -1,7 +1,7 @@
/****************************************************************************
* sched/env_internal.h
*
- * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -49,10 +49,9 @@
****************************************************************************/
#ifdef CONFIG_DISABLE_ENVIRON
-# define env_dup(ptcb) (0)
-# define env_share(ptcb) (0)
-# define env_release(ptcb) (0)
-#endif
+# define env_dup(group) (0)
+# define env_release(group) (0)
+#else
/****************************************************************************
* Public Type Declarations
@@ -62,34 +61,33 @@
* Public Variables
****************************************************************************/
-/****************************************************************************
- * Public Function Prototypes
- ****************************************************************************/
-
#ifdef __cplusplus
#define EXTERN extern "C"
-extern "C" {
+extern "C"
+{
#else
#define EXTERN extern
#endif
-#ifndef CONFIG_DISABLE_ENVIRON
-/* functions used by the task/pthread creation and destruction logic */
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
-EXTERN int env_dup(FAR _TCB *ptcb);
-EXTERN int env_share(FAR _TCB *ptcb);
-EXTERN int env_release(FAR _TCB *ptcb);
+/* Functions used by the task/pthread creation and destruction logic */
-/* functions used internally by the environment handling logic */
+int env_dup(FAR struct task_group_s *group);
+void env_release(FAR struct task_group_s *group);
-EXTERN FAR char *env_findvar(environ_t *envp, const char *pname);
-EXTERN int env_removevar(environ_t *envp, char *pvar);
-#endif
+/* Functions used internally by the environment handling logic */
+
+FAR char *env_findvar(FAR struct task_group_s *group, FAR const char *pname);
+int env_removevar(FAR struct task_group_s *group, FAR char *pvar);
#undef EXTERN
#ifdef __cplusplus
}
#endif
+#endif /* !CONFIG_DISABLE_ENVIRON */
#endif /* __SCHED_ENV_INTERNAL_H */
diff --git a/nuttx/sched/env_release.c b/nuttx/sched/env_release.c
index 8bc8d2205..aebb1f7e8 100644
--- a/nuttx/sched/env_release.c
+++ b/nuttx/sched/env_release.c
@@ -1,7 +1,7 @@
/****************************************************************************
- * sched/env_clearenv.c
+ * sched/env_release.c
*
- * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -58,65 +58,42 @@
* Name: env_release
*
* Description:
- * The env_release() function clears the environment of all name-value
- * pairs and sets the value of the external variable environ to NULL.
+ * env_release() is called only from group_leave() when the last member of
+ * a task group exits. The env_release() function clears the environment
+ * of all name-value pairs and sets the value of the external variable
+ * environ to NULL.
*
* Parameters:
- * ptcb Identifies the TCB containing the environment structure
+ * group Identifies the task group containing the environment structure
+ * to be released.
*
* Return Value:
- * zero on success
+ * None
*
* Assumptions:
* Not called from an interrupt handler
*
****************************************************************************/
-int env_release(FAR _TCB *ptcb)
+void env_release(FAR struct task_group_s *group)
{
- int ret = OK;
+ DEBUGASSERT(group);
- if (!ptcb)
- {
- ret = -EINVAL;
- }
- else
- {
- FAR environ_t *envp;
-
- /* Examine the environ data in the TCB. Preemption is disabled because the
- * the environment could be shared among threads.
- */
-
- sched_lock();
- envp = ptcb->envp;
- if (ptcb->envp)
- {
- /* Check the reference count on the environment structure */
-
- if (envp->ev_crefs <= 1)
- {
- /* Decrementing the reference count will destroy the environment */
+ /* Free any allocate environment strings */
- sched_free(envp);
- }
- else
- {
- /* The environment will persist after decrementing the reference
- * count */
-
- envp->ev_crefs--;
- }
-
- /* In any case, the environment is no longer accessible on this thread */
-
- ptcb->envp = NULL;
- }
+ if (group->tg_envp)
+ {
+ /* Free the environment */
- sched_unlock();
+ sched_free(group->tg_envp);
}
- return ret;
+ /* In any event, make sure that all environment-related varialbles in the
+ * task group structure are reset to initial values.
+ */
+
+ group->tg_envsize = 0;
+ group->tg_envp = NULL;
}
#endif /* CONFIG_DISABLE_ENVIRON */
diff --git a/nuttx/sched/env_removevar.c b/nuttx/sched/env_removevar.c
index e96aa7a37..811e6079e 100644
--- a/nuttx/sched/env_removevar.c
+++ b/nuttx/sched/env_removevar.c
@@ -59,7 +59,7 @@
* Remove the referenced name=value pair from the environment
*
* Parameters:
- * envp The environment containing the name=value pair
+ * group The task group with the environment containing the name=value pair
* pvar A pointer to the name=value pair in the restroom
*
* Return Value:
@@ -72,42 +72,44 @@
*
****************************************************************************/
-int env_removevar(environ_t *envp, char *pvar)
+int env_removevar(FAR struct task_group_s *group, FAR char *pvar)
{
+ FAR char *end; /* Pointer to the end+1 of the environment */
+ int alloc; /* Size of the allocated environment */
int ret = ERROR;
- if (envp && pvar)
- {
- /* Verify that the pointer lies within the environment region */
- int alloc = envp->ev_alloc; /* Size of the allocated environment */
- char *end = &envp->ev_env[alloc]; /* Pointer to the end+1 of the environment */
+ DEBUGASSERT(group && pvar);
- if (pvar >= envp->ev_env && pvar < end)
- {
- /* Set up for the removal */
+ /* Verify that the pointer lies within the environment region */
- int len = strlen(pvar) + 1; /* Length of name=value string to remove */
- char *src = &pvar[len]; /* Address of name=value string after */
- char *dest = pvar; /* Location to move the next string */
- int count = end - src; /* Number of bytes to move (might be zero) */
+ alloc = group->tg_envsize; /* Size of the allocated environment */
+ end = &group->tg_envp[alloc]; /* Pointer to the end+1 of the environment */
- /* Move all of the environment strings after the removed one 'down.'
- * this is inefficient, but robably not high duty.
- */
+ if (pvar >= group->tg_envp && pvar < end)
+ {
+ /* Set up for the removal */
- while (count-- > 0)
- {
- *dest++ = *src++;
- }
+ int len = strlen(pvar) + 1; /* Length of name=value string to remove */
+ char *src = &pvar[len]; /* Address of name=value string after */
+ char *dest = pvar; /* Location to move the next string */
+ int count = end - src; /* Number of bytes to move (might be zero) */
- /* Then set to the new allocation size. The caller is expected to
- * call realloc at some point but we don't do that here because the
- * caller may add more stuff to the environment.
- */
+ /* Move all of the environment strings after the removed one 'down.'
+ * this is inefficient, but robably not high duty.
+ */
- envp->ev_alloc -= len;
- ret = OK;
+ while (count-- > 0)
+ {
+ *dest++ = *src++;
}
+
+ /* Then set to the new allocation size. The caller is expected to
+ * call realloc at some point but we don't do that here because the
+ * caller may add more stuff to the environment.
+ */
+
+ group->tg_envsize -= len;
+ ret = OK;
}
return ret;
diff --git a/nuttx/sched/env_setenv.c b/nuttx/sched/env_setenv.c
index c186241ef..cfde71604 100644
--- a/nuttx/sched/env_setenv.c
+++ b/nuttx/sched/env_setenv.c
@@ -1,7 +1,7 @@
/****************************************************************************
* sched/env_setenv.c
*
- * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2011, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -83,12 +83,14 @@
*
****************************************************************************/
-int setenv(const char *name, const char *value, int overwrite)
+int setenv(FAR const char *name, FAR const char *value, int overwrite)
{
- FAR _TCB *rtcb;
- FAR environ_t *envp;
- FAR char *pvar;
- int varlen;
+ FAR _TCB *rtcb;
+ FAR struct task_group_s *group;
+ FAR char *pvar;
+ FAR char *newenvp;
+ int newsize;
+ int varlen;
int ret = OK;
/* Verify input parameter */
@@ -122,14 +124,15 @@ int setenv(const char *name, const char *value, int overwrite)
/* Get a reference to the thread-private environ in the TCB.*/
sched_lock();
- rtcb = (FAR _TCB*)g_readytorun.head;
- envp = rtcb->envp;
+ rtcb = (FAR _TCB*)g_readytorun.head;
+ group = rtcb->group;
+ DEBUGASSERT(group);
- /* Check if the variable alreay exists */
+ /* Check if the variable already exists */
- if ( envp && (pvar = env_findvar(envp, name)) != NULL)
+ if (group->tg_envp && (pvar = env_findvar(group, name)) != NULL)
{
- /* It does! Do we have permission to overwrite the existing value? */
+ /* It does! Do we have permission to overwrite the existing value? */
if (!overwrite)
{
@@ -144,7 +147,7 @@ int setenv(const char *name, const char *value, int overwrite)
* the environment buffer; this will happen below.
*/
- (void)env_removevar(envp, pvar);
+ (void)env_removevar(group, pvar);
}
/* Get the size of the new name=value string. The +2 is for the '=' and for
@@ -155,43 +158,39 @@ int setenv(const char *name, const char *value, int overwrite)
/* Then allocate or reallocate the environment buffer */
- if (envp)
+ if (group->tg_envp)
{
- int alloc = envp->ev_alloc;
- environ_t *tmp = (environ_t*)krealloc(envp, SIZEOF_ENVIRON_T(alloc + varlen));
- if (!tmp)
+ newsize = group->tg_envsize + varlen;
+ newenvp = (FAR char *)krealloc(group->tg_envp, newsize);
+ if (!newenvp)
{
ret = ENOMEM;
goto errout_with_lock;
}
- envp = tmp;
- envp->ev_alloc = alloc + varlen;
- pvar = &envp->ev_env[alloc];
+ pvar = &newenvp[group->tg_envsize];
}
else
{
- envp = (environ_t*)kmalloc(SIZEOF_ENVIRON_T(varlen));
- if (!envp)
+ newsize = varlen;
+ newenvp = (FAR char *)kmalloc(varlen);
+ if (!newenvp)
{
ret = ENOMEM;
goto errout_with_lock;
}
- envp->ev_crefs = 1;
- envp->ev_alloc = varlen;
- pvar = envp->ev_env;
+ pvar = newenvp;
}
- /* Now, put the new name=value string into the environment buffer */
+ /* Save the new buffer and size */
- sprintf(pvar, "%s=%s", name, value);
+ group->tg_envp = newenvp;
+ group->tg_envsize = newsize;
- /* Save the new environment pointer (it might have changed due to allocation or
- * reallocation.
- */
+ /* Now, put the new name=value string into the environment buffer */
- rtcb->envp = envp;
+ sprintf(pvar, "%s=%s", name, value);
sched_unlock();
return OK;
diff --git a/nuttx/sched/env_unsetenv.c b/nuttx/sched/env_unsetenv.c
index 52469fac9..8206a4ece 100644
--- a/nuttx/sched/env_unsetenv.c
+++ b/nuttx/sched/env_unsetenv.c
@@ -1,7 +1,7 @@
/****************************************************************************
* sched/env_unsetenv.c
*
- * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2011, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -75,61 +75,47 @@
*
****************************************************************************/
-int unsetenv(const char *name)
+int unsetenv(FAR const char *name)
{
- FAR _TCB *rtcb;
- FAR environ_t *envp;
- FAR char *pvar;
+ FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head;
+ FAR struct task_group_s *group = rtcb->group;
+ FAR char *pvar;
+ FAR char *newenvp;
+ int newsize;
int ret = OK;
- /* Verify input parameter */
-
- if (!name)
- {
- ret = EINVAL;
- goto errout;
- }
-
- /* Get a reference to the thread-private environ in the TCB.*/
-
- sched_lock();
- rtcb = (FAR _TCB*)g_readytorun.head;
- envp = rtcb->envp;
+ DEBUGASSERT(name && group);
/* Check if the variable exists */
- if ( envp && (pvar = env_findvar(envp, name)) != NULL)
+ sched_lock();
+ if (group && (pvar = env_findvar(group, name)) != NULL)
{
- int alloc;
- environ_t *tmp;
-
/* It does! Remove the name=value pair from the environment. */
- (void)env_removevar(envp, pvar);
+ (void)env_removevar(group, pvar);
/* Reallocate the new environment buffer */
- alloc = envp->ev_alloc;
- tmp = (environ_t*)krealloc(envp, SIZEOF_ENVIRON_T(alloc));
- if (!tmp)
+ newsize = group->tg_envsize;
+ newenvp = (FAR char *)krealloc(group->tg_envp, newsize);
+ if (!newenvp)
{
- ret = ENOMEM;
- goto errout_with_lock;
+ set_errno(ENOMEM);
+ ret = ERROR;
}
+ else
+ {
+ /* Save the new environment pointer (it might have changed due to
+ * reallocation.
+ */
- /* Save the new environment pointer (it might have changed due to reallocation. */
-
- rtcb->envp = tmp;
+ group->tg_envp = newenvp;
+ }
}
sched_unlock();
- return OK;
-
-errout_with_lock:
- sched_unlock();
-errout:
- errno = ret;
- return ERROR;
+ return ret;
}
#endif /* CONFIG_DISABLE_ENVIRON */
diff --git a/nuttx/sched/task_childstatus.c b/nuttx/sched/group_childstatus.c
index 0f6d36c29..ef42b6c34 100644
--- a/nuttx/sched/task_childstatus.c
+++ b/nuttx/sched/group_childstatus.c
@@ -1,5 +1,5 @@
/*****************************************************************************
- * sched/task_childstatus.c
+ * sched/group_childstatus.c
*
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
@@ -44,6 +44,7 @@
#include <debug.h>
#include "os_internal.h"
+#include "group_internal.h"
#if defined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS)
@@ -91,13 +92,13 @@ static struct child_pool_s g_child_pool;
*****************************************************************************/
/*****************************************************************************
- * Name: task_dumpchildren
+ * Name: group_dumpchildren
*
* Description:
* Dump all of the children when the part TCB list is modified.
*
* Parameters:
- * tcb - The parent TCB.
+ * group - The task group containing the child status.
*
* Return Value:
* None.
@@ -108,20 +109,21 @@ static struct child_pool_s g_child_pool;
*****************************************************************************/
#ifdef CONFIG_DEBUG_CHILDSTATUS
-static void task_dumpchildren(FAR _TCB *tcb, FAR const char *msg)
+static void group_dumpchildren(FAR struct task_group_s *group,
+ FAR const char *msg)
{
FAR struct child_status_s *child;
int i;
- dbg("Parent TCB=%p: %s\n", tcb, msg);
- for (i = 0, child = tcb->children; child; i++, child = child->flink)
+ dbg("Task group=%p: %s\n", group, msg);
+ for (i = 0, child = group->tg_children; child; i++, child = child->flink)
{
dbg(" %d. ch_flags=%02x ch_pid=%d ch_status=%d\n",
i, child->ch_flags, child->ch_pid, child->ch_status);
}
}
#else
-# task_dumpchildren(t,m)
+# define group_dumpchildren(t,m)
#endif
/*****************************************************************************
@@ -165,7 +167,7 @@ void task_initialize(void)
}
/*****************************************************************************
- * Name: task_allocchild
+ * Name: group_allocchild
*
* Description:
* Allocate a child status structure by removing the next entry from a
@@ -184,7 +186,7 @@ void task_initialize(void)
*
*****************************************************************************/
-FAR struct child_status_s *task_allocchild(void)
+FAR struct child_status_s *group_allocchild(void)
{
FAR struct child_status_s *ret;
@@ -201,7 +203,7 @@ FAR struct child_status_s *task_allocchild(void)
}
/*****************************************************************************
- * Name: task_freechild
+ * Name: group_freechild
*
* Description:
* Release a child status structure by returning it to a free list.
@@ -218,7 +220,7 @@ FAR struct child_status_s *task_allocchild(void)
*
*****************************************************************************/
-void task_freechild(FAR struct child_status_s *child)
+void group_freechild(FAR struct child_status_s *child)
{
/* Return the child status structure to the free list */
@@ -230,13 +232,13 @@ void task_freechild(FAR struct child_status_s *child)
}
/*****************************************************************************
- * Name: task_addchild
+ * Name: group_addchild
*
* Description:
* Add a child status structure in the given TCB.
*
* Parameters:
- * tcb - The TCB of the parent task to containing the child status.
+ * group - The task group for the child status.
* child - The structure to be added
*
* Return Value:
@@ -248,26 +250,27 @@ void task_freechild(FAR struct child_status_s *child)
*
*****************************************************************************/
-void task_addchild(FAR _TCB *tcb, FAR struct child_status_s *child)
+void group_addchild(FAR struct task_group_s *group,
+ FAR struct child_status_s *child)
{
/* Add the entry into the TCB list of children */
- child->flink = tcb->children;
- tcb->children = child;
+ child->flink = group->tg_children;
+ group->tg_children = child;
- task_dumpchildren(tcb, "task_addchild");
+ group_dumpchildren(group, "group_addchild");
}
/*****************************************************************************
- * Name: task_findchild
+ * Name: group_findchild
*
* Description:
- * Find a child status structure in the given TCB. A reference to the
- * child structure is returned, but the child remains the the TCB's list
- * of children.
+ * Find a child status structure in the given task group. A reference to
+ * the child structure is returned, but the child remains the the group's
+ * list of children.
*
* Parameters:
- * tcb - The TCB of the parent task to containing the child status.
+ * group - The ID of the parent task group to containing the child status.
* pid - The ID of the child to find.
*
* Return Value:
@@ -280,13 +283,16 @@ void task_addchild(FAR _TCB *tcb, FAR struct child_status_s *child)
*
*****************************************************************************/
-FAR struct child_status_s *task_findchild(FAR _TCB *tcb, pid_t pid)
+FAR struct child_status_s *group_findchild(FAR struct task_group_s *group,
+ pid_t pid)
{
FAR struct child_status_s *child;
+ DEBUGASSERT(group);
+
/* Find the status structure with the matching PID */
- for (child = tcb->children; child; child = child->flink)
+ for (child = group->tg_children; child; child = child->flink)
{
if (child->ch_pid == pid)
{
@@ -298,15 +304,51 @@ FAR struct child_status_s *task_findchild(FAR _TCB *tcb, pid_t pid)
}
/*****************************************************************************
- * Name: task_removechild
+ * Name: group_exitchild
*
* Description:
- * Remove one child structure from the TCB. The child is removed, but is
- * not yet freed. task_freechild must be called in order to free the child
- * status structure.
+ * Search for any child that has exitted.
*
* Parameters:
* tcb - The TCB of the parent task to containing the child status.
+ *
+ * Return Value:
+ * On success, a non-NULL pointer to a child status structure for the
+ * exited child. NULL is returned if not child has exited.
+ *
+ * Assumptions:
+ * Called during SIGCHLD processing in a safe context. No special precautions
+ * are required here.
+ *
+ *****************************************************************************/
+
+FAR struct child_status_s *group_exitchild(FAR struct task_group_s *group)
+{
+ FAR struct child_status_s *child;
+
+ /* Find the status structure of any child task that has exitted. */
+
+ for (child = group->tg_children; child; child = child->flink)
+ {
+ if ((child->ch_flags & CHILD_FLAG_EXITED) != 0)
+ {
+ return child;
+ }
+ }
+
+ return NULL;
+}
+
+/*****************************************************************************
+ * Name: group_removechild
+ *
+ * Description:
+ * Remove one child structure from a task group. The child is removed, but
+ * is not yet freed. group_freechild must be called in order to free the
+ * child status structure.
+ *
+ * Parameters:
+ * group - The task group containing the child status.
* pid - The ID of the child to find.
*
* Return Value:
@@ -319,14 +361,17 @@ FAR struct child_status_s *task_findchild(FAR _TCB *tcb, pid_t pid)
*
*****************************************************************************/
-FAR struct child_status_s *task_removechild(FAR _TCB *tcb, pid_t pid)
+FAR struct child_status_s *group_removechild(FAR struct task_group_s *group,
+ pid_t pid)
{
FAR struct child_status_s *curr;
FAR struct child_status_s *prev;
- /* Find the status structure with the matching PID */
+ DEBUGASSERT(group);
- for (prev = NULL, curr = tcb->children;
+ /* Find the status structure with the matching PID */
+
+ for (prev = NULL, curr = group->tg_children;
curr;
prev = curr, curr = curr->flink)
{
@@ -336,7 +381,7 @@ FAR struct child_status_s *task_removechild(FAR _TCB *tcb, pid_t pid)
}
}
- /* Did we find it? If so, remove it from the TCB. */
+ /* Did we find it? If so, remove it from the group. */
if (curr)
{
@@ -348,24 +393,24 @@ FAR struct child_status_s *task_removechild(FAR _TCB *tcb, pid_t pid)
}
else
{
- tcb->children = curr->flink;
+ group->tg_children = curr->flink;
}
curr->flink = NULL;
- task_dumpchildren(tcb, "task_removechild");
+ group_dumpchildren(group, "group_removechild");
}
return curr;
}
/*****************************************************************************
- * Name: task_removechildren
+ * Name: group_removechildren
*
* Description:
- * Remove and free all child structure from the TCB.
+ * Remove and free all child structure from the task group.
*
* Parameters:
- * tcb - The TCB of the parent task to containing the child status.
+ * group - The task group containing the child status.
*
* Return Value:
* None.
@@ -376,21 +421,21 @@ FAR struct child_status_s *task_removechild(FAR _TCB *tcb, pid_t pid)
*
*****************************************************************************/
-void task_removechildren(FAR _TCB *tcb)
+void group_removechildren(FAR struct task_group_s *group)
{
FAR struct child_status_s *curr;
FAR struct child_status_s *next;
/* Remove all child structures for the TCB and return them to the freelist */
- for (curr = tcb->children; curr; curr = next)
+ for (curr = group->tg_children; curr; curr = next)
{
next = curr->flink;
- task_freechild(curr);
+ group_freechild(curr);
}
- tcb->children = NULL;
- task_dumpchildren(tcb, "task_removechildren");
+ group->tg_children = NULL;
+ group_dumpchildren(group, "group_removechildren");
}
#endif /* CONFIG_SCHED_HAVE_PARENT && CONFIG_SCHED_CHILD_STATUS */
diff --git a/nuttx/sched/group_create.c b/nuttx/sched/group_create.c
new file mode 100644
index 000000000..24f6923aa
--- /dev/null
+++ b/nuttx/sched/group_create.c
@@ -0,0 +1,276 @@
+/*****************************************************************************
+ * sched/group_create.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * 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 <sched.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
+
+#include "group_internal.h"
+#include "env_internal.h"
+
+#ifdef HAVE_TASK_GROUP
+
+/*****************************************************************************
+ * Pre-processor Definitions
+ *****************************************************************************/
+/* Is this worth making a configuration option? */
+
+#define GROUP_INITIAL_MEMBERS 4
+
+/*****************************************************************************
+ * Private Types
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Private Data
+ *****************************************************************************/
+/* This is counter that is used to generate unique task group IDs */
+
+#ifdef HAVE_GROUP_MEMBERS
+static gid_t g_gidcounter;
+#endif
+
+/*****************************************************************************
+ * Public Data
+ *****************************************************************************/
+/* This is the head of a list of all group members */
+
+#ifdef HAVE_GROUP_MEMBERS
+FAR struct task_group_s *g_grouphead;
+#endif
+
+/*****************************************************************************
+ * Private Functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Name: group_assigngid
+ *
+ * Description:
+ * Create a unique group ID.
+ *
+ * Parameters:
+ * tcb - The tcb in need of the task group.
+ *
+ * Return Value:
+ * None
+ *
+ * Assumptions:
+ * Called during task creation in a safe context. No special precautions
+ * are required here.
+ *
+ *****************************************************************************/
+
+#ifdef HAVE_GROUP_MEMBERS
+void group_assigngid(FAR struct task_group_s *group)
+{
+ irqstate_t flags;
+ gid_t gid;
+
+ /* Pre-emption should already be enabled, but lets be paranoid careful */
+
+ sched_lock();
+
+ /* Loop until we create a unique ID */
+
+ for (;;)
+ {
+ /* Increment the ID counter. This is global data so be extra paraoid. */
+
+ flags = irqsave();
+ gid = ++g_gidcounter;
+
+ /* Check for overflow */
+
+ if (gid <= 0)
+ {
+ g_gidcounter = 1;
+ irqrestore(flags);
+ }
+ else
+ {
+ /* Does a task group with this ID already exist? */
+
+ irqrestore(flags);
+ if (group_find(gid) == NULL)
+ {
+ /* Now assign this ID to the group and return */
+
+ group->tg_gid = gid;
+ sched_unlock();
+ return;
+ }
+ }
+ }
+}
+#endif /* HAVE_GROUP_MEMBERS */
+
+/*****************************************************************************
+ * Public Functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Name: group_allocate
+ *
+ * Description:
+ * Create and a new task group structure for the specified TCB. This
+ * function is called as part of the task creation sequence. The structure
+ * allocated and zered, but otherwise uninitialized. The full creation
+ * of the group of a two step process: (1) First, this function allocates
+ * group structure early in the task creation sequence in order to provide a
+ * group container, then (2) group_initialize() is called to set up the
+ * group membership.
+ *
+ * Parameters:
+ * tcb - The tcb in need of the task group.
+ *
+ * Return Value:
+ * 0 (OK) on success; a negated errno value on failure.
+ *
+ * Assumptions:
+ * Called during task creation in a safe context. No special precautions
+ * are required here.
+ *
+ *****************************************************************************/
+
+int group_allocate(FAR _TCB *tcb)
+{
+ int ret;
+
+ DEBUGASSERT(tcb && !tcb->group);
+
+ /* Allocate the group structure and assign it to the TCB */
+
+ tcb->group = (FAR struct task_group_s *)kzalloc(sizeof(struct task_group_s));
+ if (!tcb->group)
+ {
+ return -ENOMEM;
+ }
+
+ /* Assign the group a unique ID. If g_gidcounter were to wrap before we
+ * finish with task creation, that would be a problem.
+ */
+
+#ifdef HAVE_GROUP_MEMBERS
+ group_assigngid(tcb->group);
+#endif
+
+ /* Duplicate the parent tasks envionment */
+
+ ret = env_dup(tcb->group);
+ if (ret < 0)
+ {
+ kfree(tcb->group);
+ tcb->group = NULL;
+ return ret;
+ }
+
+ return OK;
+}
+
+/*****************************************************************************
+ * Name: group_initialize
+ *
+ * Description:
+ * Add the task as the initial member of the group. The full creation of
+ * the group of a two step process: (1) First, this group structure is
+ * allocated by group_allocate() early in the task creation sequence, then
+ * (2) this function is called to set up the initial group membership.
+ *
+ * Parameters:
+ * tcb - The tcb in need of the task group.
+ *
+ * Return Value:
+ * 0 (OK) on success; a negated errno value on failure.
+ *
+ * Assumptions:
+ * Called during task creation in a safe context. No special precautions
+ * are required here.
+ *
+ *****************************************************************************/
+
+int group_initialize(FAR _TCB *tcb)
+{
+ FAR struct task_group_s *group;
+#ifdef HAVE_GROUP_MEMBERS
+ irqstate_t flags;
+#endif
+
+ DEBUGASSERT(tcb && tcb->group);
+ group = tcb->group;
+
+#ifdef HAVE_GROUP_MEMBERS
+ /* Allocate space to hold GROUP_INITIAL_MEMBERS members of the group */
+
+ group->tg_members = (FAR pid_t *)kmalloc(GROUP_INITIAL_MEMBERS*sizeof(pid_t));
+ if (!group->tg_members)
+ {
+ free(group);
+ return -ENOMEM;
+ }
+
+ /* Assign the PID of this new task as a member of the group*/
+
+ group->tg_members[0] = tcb->pid;
+
+ /* Initialize the non-zero elements of group structure and assign it to
+ * the tcb.
+ */
+
+ group->tg_mxmembers = GROUP_INITIAL_MEMBERS; /* Number of members in allocation */
+
+ /* Add the initialized entry to the list of groups */
+
+ flags = irqsave();
+ group->flink = g_grouphead;
+ g_grouphead = group;
+ irqrestore(flags);
+
+#endif
+
+ group->tg_nmembers = 1; /* Number of members in the group */
+ return OK;
+}
+
+#endif /* HAVE_TASK_GROUP */
diff --git a/nuttx/sched/env_share.c b/nuttx/sched/group_find.c
index 5f37a0219..eb3989223 100644
--- a/nuttx/sched/env_share.c
+++ b/nuttx/sched/group_find.c
@@ -1,7 +1,7 @@
-/****************************************************************************
- * sched/env_share.c
+/*****************************************************************************
+ * sched/group_find.c
*
- * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -31,87 +31,95 @@
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
- ****************************************************************************/
+ *****************************************************************************/
-/****************************************************************************
+/*****************************************************************************
* Included Files
- ****************************************************************************/
+ *****************************************************************************/
#include <nuttx/config.h>
-#ifndef CONFIG_DISABLE_ENVIRON
-
#include <sched.h>
+#include <assert.h>
#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
-#include "os_internal.h"
+#include "group_internal.h"
#include "env_internal.h"
-/****************************************************************************
+#ifdef HAVE_TASK_GROUP
+
+/*****************************************************************************
+ * Pre-processor Definitions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Private Types
+ *****************************************************************************/
+
+/*****************************************************************************
* Private Data
- ****************************************************************************/
+ *****************************************************************************/
-/****************************************************************************
+/*****************************************************************************
+ * Public Data
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Private Functions
+ *****************************************************************************/
+
+/*****************************************************************************
* Public Functions
- ****************************************************************************/
+ *****************************************************************************/
-/****************************************************************************
- * Name: env_share
+/*****************************************************************************
+ * Name: group_find
*
* Description:
- * Increment the reference count on the internal environment structure of
- * a task. This is the action that is performed when a new pthread is
- * created: The new pthread shares the environment with its parent.
+ * Given a group ID, find the group task structure with that ID. IDs are
+ * used instead of pointers to group structures. This is done because a
+ * group can disappear at any time leaving a stale pointer; an ID is cleaner
+ * because if the group disappears, this function will fail gracefully.
*
* Parameters:
- * ptcb The new TCB to receive the shared environment.
+ * gid - The group ID to find.
*
* Return Value:
- * A pointer to a specified TCB's environment structure with an incremented
- * reference count.
+ * On success, a pointer to the group task structure is returned. This
+ * function can fail only if there is no group that corresponds to the
+ * groupd ID.
*
* Assumptions:
- * Not called from an interrupt handler.
+ * Called during when signally tasks in a safe context. No special
+ * precautions should be required here. However, extra care is taken when
+ * accessing the global g_grouphead list.
*
- ****************************************************************************/
+ *****************************************************************************/
-int env_share(FAR _TCB *ptcb)
+#ifdef HAVE_GROUP_MEMBERS
+FAR struct task_group_s *group_find(gid_t gid)
{
- int ret = OK;
- if (!ptcb)
- {
- ret = -EINVAL;
- }
- else
- {
- FAR _TCB *parent = (FAR _TCB*)g_readytorun.head;
- environ_t *envp = parent->envp;
+ FAR struct task_group_s *group;
+ irqstate_t flags;
- /* Pre-emption must be disabled throughout the following because the
- * environment is shared.
- */
+ /* Find the status structure with the matching PID */
- sched_lock();
-
- /* Does the parent task have an environment? */
-
- if (envp)
+ flags = irqsave();
+ for (group = g_grouphead; group; group = group->flink)
+ {
+ if (group->tg_gid == gid)
{
- /* Yes.. increment the reference count on the environment */
-
- envp->ev_crefs++;
+ irqrestore(flags);
+ return group;
}
-
- /* Then share the environment */
-
- ptcb->envp = envp;
- sched_unlock();
}
- return ret;
+ irqrestore(flags);
+ return NULL;
}
+#endif
-#endif /* CONFIG_DISABLE_ENVIRON */
-
-
-
+#endif /* HAVE_TASK_GROUP */
diff --git a/nuttx/sched/sched_setuppthreadfiles.c b/nuttx/sched/group_internal.h
index 648d9273e..ca6aacff7 100644
--- a/nuttx/sched/sched_setuppthreadfiles.c
+++ b/nuttx/sched/group_internal.h
@@ -1,7 +1,7 @@
/****************************************************************************
- * sched_setuppthreadfiles.c
+ * sched/group_internal.h
*
- * Copyright (C) 2007, 2009, 2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -33,76 +33,94 @@
*
****************************************************************************/
+#ifndef __SCHED_GROUP_INERNAL_H
+#define __SCHED_GROUP_INERNAL_H
+
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
+#include <sys/types.h>
+#include <stdbool.h>
+#include <queue.h>
#include <sched.h>
-#include <nuttx/fs/fs.h>
-#include <nuttx/net/net.h>
-#include <nuttx/lib.h>
-
-#include "os_internal.h"
-
-#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0
+#include <nuttx/kmalloc.h>
/****************************************************************************
- * Private Functions
+ * Pre-processor Definitions
****************************************************************************/
+/* Any negative GID is invalid. */
+
+#define INVALID_GROUP_ID (pid_t)-1
+#define IS_INVALID_GID(gid) ((int)(gid) < 0)
/****************************************************************************
- * Public Functions
+ * Public Type Definitions
****************************************************************************/
/****************************************************************************
- * Name: sched_setuppthreadfiles
- *
- * Description:
- * Configure a newly allocated TCB so that it will inherit file
- * descriptors and streams from the parent pthread.
- *
- * Parameters:
- * tcb - tcb of the new task.
- *
- * Return Value:
- * OK (if an error were returned, it would need to be a non-negated
- * errno value).
- *
- * Assumptions:
- *
+ * Public Data
****************************************************************************/
+/* This is the head of a list of all group members */
-int sched_setuppthreadfiles(FAR _TCB *tcb)
-{
- FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head;
+#ifdef HAVE_GROUP_MEMBERS
+extern FAR struct task_group_s *g_grouphead;
+#endif
-#if CONFIG_NFILE_DESCRIPTORS > 0
- /* The child thread inherits the parent file descriptors */
-
- tcb->filelist = rtcb->filelist;
- files_addreflist(tcb->filelist);
-
-#endif /* CONFIG_NFILE_DESCRIPTORS */
-
-#if CONFIG_NSOCKET_DESCRIPTORS > 0
- /* The child thread inherits the parent socket descriptors */
-
- tcb->sockets = rtcb->sockets;
- net_addreflist(tcb->sockets);
-
-#endif /* CONFIG_NSOCKET_DESCRIPTORS */
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+/* Task group data structure management */
+
+#ifdef HAVE_TASK_GROUP
+int group_allocate(FAR _TCB *tcb);
+int group_initialize(FAR _TCB *tcb);
+int group_bind(FAR _TCB *tcb);
+int group_join(FAR _TCB *tcb);
+void group_leave(FAR _TCB *tcb);
+
+#ifdef HAVE_GROUP_MEMBERS
+FAR struct task_group_s *group_find(gid_t gid);
+int group_addmember(FAR struct task_group_s *group, pid_t pid);
+int group_removemember(FAR struct task_group_s *group, pid_t pid);
+#endif
+
+#ifndef CONFIG_DISABLE_SIGNALS
+int group_signal(FAR struct task_group_s *group, FAR siginfo_t *info);
+#endif
+#endif /* HAVE_TASK_GROUP */
+
+/* Parent/child data management */
+
+#ifdef CONFIG_SCHED_HAVE_PARENT
+int task_reparent(pid_t ppid, pid_t chpid);
+
+#ifdef CONFIG_SCHED_CHILD_STATUS
+FAR struct child_status_s *group_allocchild(void);
+void group_freechild(FAR struct child_status_s *status);
+void group_addchild(FAR struct task_group_s *group,
+ FAR struct child_status_s *child);
+FAR struct child_status_s *group_exitchild(FAR struct task_group_s *group);
+FAR struct child_status_s *group_findchild(FAR struct task_group_s *group,
+ pid_t pid);
+FAR struct child_status_s *group_removechild(FAR struct task_group_s *group,
+ pid_t pid);
+void group_removechildren(FAR struct task_group_s *group);
+
+#endif /* CONFIG_SCHED_CHILD_STATUS */
+#endif /* CONFIG_SCHED_HAVE_PARENT */
+
+/* Group data resource configuration */
+#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0
+int group_setupidlefiles(FAR _TCB *tcb);
+int group_setuptaskfiles(FAR _TCB *tcb);
#if CONFIG_NFILE_STREAMS > 0
- /* The child thread inherits the parent streams */
-
- tcb->streams = rtcb->streams;
- lib_addreflist(tcb->streams);
-
-#endif /* CONFIG_NFILE_STREAMS */
- return OK;
-}
+int group_setupstreams(FAR _TCB *tcb);
+#endif
+#endif
-#endif /* CONFIG_NFILE_DESCRIPTORS || CONFIG_NSOCKET_DESCRIPTORS */
+#endif /* __SCHED_GROUP_INERNAL_H */
diff --git a/nuttx/sched/group_join.c b/nuttx/sched/group_join.c
new file mode 100644
index 000000000..70319b3a1
--- /dev/null
+++ b/nuttx/sched/group_join.c
@@ -0,0 +1,227 @@
+/*****************************************************************************
+ * sched/group_join.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * 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 <sched.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
+
+#include "group_internal.h"
+#include "env_internal.h"
+
+#ifdef HAVE_TASK_GROUP
+
+/*****************************************************************************
+ * Pre-processor Definitions
+ *****************************************************************************/
+/* Is this worth making a configuration option? */
+
+#define GROUP_REALLOC_MEMBERS 4
+
+/*****************************************************************************
+ * Private Types
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Private Data
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Private Functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Public Functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Name: group_bind
+ *
+ * Description:
+ * A thread joins the group when it is created. This is a two step process,
+ * first, the group must bound to the new threads TCB. group_bind() does
+ * this (at the return from group_join, things are a little unstable: The
+ * group has been bound, but tg_nmembers hs not yet been incremented).
+ * Then, after the new thread is initialized and has a PID assigned to it,
+ * group_join() is called, incrementing the tg_nmembers count on the group.
+ *
+ * Parameters:
+ * tcb - The TCB of the new "child" task that need to join the group.
+ *
+ * Return Value:
+ * 0 (OK) on success; a negated errno value on failure.
+ *
+ * Assumptions:
+ * - The parent task from which the group will be inherited is the task at
+ * the thead of the ready to run list.
+ * - Called during thread creation in a safe context. No special precautions
+ * are required here.
+ *
+ *****************************************************************************/
+
+int group_bind(FAR _TCB *tcb)
+{
+ FAR _TCB *ptcb = (FAR _TCB *)g_readytorun.head;
+
+ DEBUGASSERT(ptcb && tcb && ptcb->group && !tcb->group);
+
+ /* Copy the group reference from the parent to the child */
+
+ tcb->group = ptcb->group;
+ return OK;
+}
+
+/*****************************************************************************
+ * Name: group_join
+ *
+ * Description:
+ * A thread joins the group when it is created. This is a two step process,
+ * first, the group must bound to the new threads TCB. group_bind() does
+ * this (at the return from group_join, things are a little unstable: The
+ * group has been bound, but tg_nmembers hs not yet been incremented).
+ * Then, after the new thread is initialized and has a PID assigned to it,
+ * group_join() is called, incrementing the tg_nmembers count on the group.
+ *
+ * Parameters:
+ * tcb - The TCB of the new "child" task that need to join the group.
+ *
+ * Return Value:
+ * 0 (OK) on success; a negated errno value on failure.
+ *
+ * Assumptions:
+ * - The parent task from which the group will be inherited is the task at
+ * the thead of the ready to run list.
+ * - Called during thread creation in a safe context. No special precautions
+ * are required here.
+ *
+ *****************************************************************************/
+
+int group_join(FAR _TCB *tcb)
+{
+ FAR struct task_group_s *group;
+#ifdef HAVE_GROUP_MEMBERS
+ int ret;
+#endif
+
+ DEBUGASSERT(tcb && tcb->group &&
+ tcb->group->tg_nmembers < UINT8_MAX);
+
+ /* Get the group from the TCB */
+
+ group = tcb->group;
+
+#ifdef HAVE_GROUP_MEMBERS
+ /* Add the member to the group */
+
+ ret = group_addmember(group, tcb->pid);
+ if (ret < 0)
+ {
+ return ret;
+ }
+#endif
+
+ group->tg_nmembers++;
+ return OK;
+}
+
+/*****************************************************************************
+ * Name: group_addmember
+ *
+ * Description:
+ * Add a new member to a group.
+ *
+ * Parameters:
+ * group - The task group to add the new member
+ * pid - The new member
+ *
+ * Return Value:
+ * 0 (OK) on success; a negated errno value on failure.
+ *
+ * Assumptions:
+ * Called during thread creation and during reparenting in a safe context.
+ * No special precautions are required here.
+ *
+ *****************************************************************************/
+
+#ifdef HAVE_GROUP_MEMBERS
+int group_addmember(FAR struct task_group_s *group, pid_t pid)
+{
+ DEBUGASSERT(group && group->tg_nmembers < UINT8_MAX);
+
+ /* Will we need to extend the size of the array of groups? */
+
+ if (group->tg_nmembers >= group->tg_mxmembers)
+ {
+ FAR pid_t *newmembers;
+ unsigned int newmax;
+
+ /* Yes... reallocate the array of members */
+
+ newmax = group->tg_mxmembers + GROUP_REALLOC_MEMBERS;
+ if (newmax > UINT8_MAX)
+ {
+ newmax = UINT8_MAX;
+ }
+
+ newmembers = (FAR pid_t *)
+ krealloc(group->tg_members, sizeof(pid_t) * newmax);
+
+ if (!newmembers)
+ {
+ return -ENOMEM;
+ }
+
+ /* Save the new number of members in the reallocated members array */
+
+ group->tg_members = newmembers;
+ group->tg_mxmembers = newmax;
+ }
+
+ /* Assign this new pid to the group. */
+
+ group->tg_members[group->tg_nmembers] = pid;
+ return OK;
+}
+#endif /* HAVE_GROUP_MEMBERS */
+
+#endif /* HAVE_TASK_GROUP */
diff --git a/nuttx/sched/group_leave.c b/nuttx/sched/group_leave.c
new file mode 100644
index 000000000..4dec30633
--- /dev/null
+++ b/nuttx/sched/group_leave.c
@@ -0,0 +1,366 @@
+/*****************************************************************************
+ * sched/group_leave.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * 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 <sched.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/fs/fs.h>
+#include <nuttx/net/net.h>
+#include <nuttx/lib.h>
+
+#include "group_internal.h"
+#include "env_internal.h"
+
+#ifdef HAVE_TASK_GROUP
+
+/*****************************************************************************
+ * Pre-processor Definitions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Private Types
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Private Data
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Private Functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Name: group_remove
+ *
+ * Description:
+ * Remove a group from the list of groups.
+ *
+ * Parameters:
+ * group - The group to be removed.
+ *
+ * Return Value:
+ * None.
+ *
+ * Assumptions:
+ * Called during task deletion in a safe context. No special precautions
+ * are required here.
+ *
+ *****************************************************************************/
+
+#ifdef HAVE_GROUP_MEMBERS
+void group_remove(FAR struct task_group_s *group)
+{
+ FAR struct task_group_s *curr;
+ FAR struct task_group_s *prev;
+ irqstate_t flags;
+
+ /* Let's be especially careful while access the global task group list.
+ * This is probably un-necessary.
+ */
+
+ flags = irqsave();
+
+ /* Find the task group structure */
+
+ for (prev = NULL, curr = g_grouphead;
+ curr && curr != group;
+ prev = curr, curr = curr->flink);
+
+ /* Did we find it? If so, remove it from the list. */
+
+ if (curr)
+ {
+ /* Do we remove it from mid-list? Or from the head of the list? */
+
+ if (prev)
+ {
+ prev->flink = curr->flink;
+ }
+ else
+ {
+ g_grouphead = curr->flink;
+ }
+
+ curr->flink = NULL;
+ }
+
+ irqrestore(flags);
+}
+#endif
+
+/*****************************************************************************
+ * Name: group_release
+ *
+ * Description:
+ * Release group resources after the last member has left the group.
+ *
+ * Parameters:
+ * group - The group to be removed.
+ *
+ * Return Value:
+ * None.
+ *
+ * Assumptions:
+ * Called during task deletion in a safe context. No special precautions
+ * are required here.
+ *
+ *****************************************************************************/
+
+static inline void group_release(FAR struct task_group_s *group)
+{
+ /* Free all un-reaped child exit status */
+
+#if defined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS)
+ group_removechildren(group);
+#endif
+
+ /* Free all file-related resources now. We really need to close files as
+ * soon as possible while we still have a functioning task.
+ */
+
+#if CONFIG_NFILE_DESCRIPTORS > 0
+ /* Free resources held by the file descriptor list */
+
+ files_releaselist(&group->tg_filelist);
+
+#if CONFIG_NFILE_STREAMS > 0
+ /* Free resource held by the stream list */
+
+ lib_releaselist(&group->tg_streamlist);
+
+#endif /* CONFIG_NFILE_STREAMS */
+#endif /* CONFIG_NFILE_DESCRIPTORS */
+
+#if CONFIG_NSOCKET_DESCRIPTORS > 0
+ /* Free resource held by the socket list */
+
+ net_releaselist(&group->tg_socketlist);
+#endif /* CONFIG_NSOCKET_DESCRIPTORS */
+
+ /* Release all shared environment variables */
+
+#ifndef CONFIG_DISABLE_ENVIRON
+ env_release(group);
+#endif
+
+#ifdef HAVE_GROUP_MEMBERS
+ /* Remove the group from the list of groups */
+
+ group_remove(group);
+
+ /* Release the members array */
+
+ if (group->tg_members)
+ {
+ sched_free(group->tg_members);
+ group->tg_members = NULL;
+ }
+#endif
+
+ /* Release the group container itself */
+
+ sched_free(group);
+}
+
+/*****************************************************************************
+ * Public Functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Name: group_leave
+ *
+ * Description:
+ * Release a reference on a group. This function is called when a task or
+ * thread exits. It decrements the reference count on the group. If the
+ * reference count decrements to zero, then it frees the group and all of
+ * resources contained in the group.
+ *
+ * Parameters:
+ * tcb - The TCB of the task that is exiting.
+ *
+ * Return Value:
+ * None.
+ *
+ * Assumptions:
+ * Called during task deletion in a safe context. No special precautions
+ * are required here.
+ *
+ *****************************************************************************/
+
+#ifdef HAVE_GROUP_MEMBERS
+void group_leave(FAR _TCB *tcb)
+{
+ FAR struct task_group_s *group;
+
+ DEBUGASSERT(tcb);
+
+ /* Make sure that we have a group */
+
+ group = tcb->group;
+ if (group)
+ {
+ /* Remove the member from group */
+
+ int ret = group_removemember(group, tcb->pid);
+ DEBUGASSERT(ret >= 0);
+
+ /* Is the group now empty? */
+
+ if (ret == 0)
+ {
+ /* Release all of the resource held by the task group */
+
+ group_release(group);
+ }
+
+ /* In any event, we can detach the group from the TCB so that we won't
+ * do this again.
+ */
+
+ tcb->group = NULL;
+ }
+}
+
+#else /* HAVE_GROUP_MEMBERS */
+
+void group_leave(FAR _TCB *tcb)
+{
+ FAR struct task_group_s *group;
+
+ DEBUGASSERT(tcb);
+
+ /* Make sure that we have a group */
+
+ group = tcb->group;
+ if (group)
+ {
+ /* Yes, we have a group.. Is this the last member of the group? */
+
+ if (group->tg_nmembers > 1)
+ {
+ /* No.. just decrement the number of members in the group */
+
+ group->tg_nmembers--;
+ }
+
+ /* Yes.. that was the last member remaining in the group */
+
+ else
+ {
+ /* Release all of the resource held by the task group */
+
+ group_release(group);
+ }
+
+ /* In any event, we can detach the group from the TCB so we won't do
+ * this again.
+ */
+
+ tcb->group = NULL;
+ }
+}
+
+#endif /* HAVE_GROUP_MEMBERS */
+
+/*****************************************************************************
+ * Name: group_removemember
+ *
+ * Description:
+ * Remove a member from a group.
+ *
+ * Parameters:
+ * group - The group from which to remove the member.
+ * pid - The member to be removed.
+ *
+ * Return Value:
+ * On success, returns the number of members remaining in the group (>=0).
+ * Can fail only if the member is not found in the group. On failure,
+ * returns -ENOENT
+ *
+ * Assumptions:
+ * Called during task deletion and also from the reparenting logic, both
+ * in a safe context. No special precautions are required here.
+ *
+ *****************************************************************************/
+
+#ifdef HAVE_GROUP_MEMBERS
+int group_removemember(FAR struct task_group_s *group, pid_t pid)
+{
+ int i;
+
+ DEBUGASSERT(group);
+
+ /* Find the member in the array of members and remove it */
+
+ for (i = 0; i < group->tg_nmembers; i++)
+ {
+ /* Does this member have the matching pid */
+
+ if (group->tg_members[i] == pid)
+ {
+ /* Yes.. break out of the loop. We don't do the actual
+ * removal here, instead we re-test i and do the adjustments
+ * outside of the loop. We do this because we want the
+ * DEBUGASSERT to work properly.
+ */
+
+ break;
+ }
+ }
+
+ /* Now, test if we found the task in the array of members. */
+
+ if (i < group->tg_nmembers)
+ {
+ /* Remove the member from the array of members */
+
+ group->tg_members[i] = group->tg_members[group->tg_nmembers - 1];
+ group->tg_nmembers--;
+ return group->tg_nmembers;
+ }
+
+ return -ENOENT;
+}
+#endif /* HAVE_GROUP_MEMBERS */
+
+#endif /* HAVE_TASK_GROUP */
diff --git a/nuttx/sched/sched_setupidlefiles.c b/nuttx/sched/group_setupidlefiles.c
index ae814e1a6..ceb9f3e2c 100644
--- a/nuttx/sched/sched_setupidlefiles.c
+++ b/nuttx/sched/group_setupidlefiles.c
@@ -1,7 +1,7 @@
/****************************************************************************
- * sched/sched_setupidlefiles.c
+ * sched/group_setupidlefiles.c
*
- * Copyright (C) 2007-2010, 2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2010, 2012-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -50,6 +50,7 @@
#include <nuttx/net/net.h>
#include "os_internal.h"
+#include "group_internal.h"
#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0
@@ -62,7 +63,7 @@
****************************************************************************/
/****************************************************************************
- * Name: sched_setupidlefiles
+ * Name: group_setupidlefiles
*
* Description:
* Configure the idle thread's TCB.
@@ -77,30 +78,29 @@
*
****************************************************************************/
-int sched_setupidlefiles(FAR _TCB *tcb)
+int group_setupidlefiles(FAR _TCB *tcb)
{
+#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NFILE_DESCRIPTORS > 0
+ FAR struct task_group_s *group = tcb->group;
+#endif
#if CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_DEV_CONSOLE)
int fd;
#endif
- /* Allocate file descriptors for the TCB */
+#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NFILE_DESCRIPTORS > 0
+ DEBUGASSERT(group);
+#endif
#if CONFIG_NFILE_DESCRIPTORS > 0
- tcb->filelist = files_alloclist();
- if (!tcb->filelist)
- {
- return -ENOMEM;
- }
+ /* Initialize file descriptors for the TCB */
+
+ files_initlist(&group->tg_filelist);
#endif
+#if CONFIG_NSOCKET_DESCRIPTORS > 0
/* Allocate socket descriptors for the TCB */
-#if CONFIG_NSOCKET_DESCRIPTORS > 0
- tcb->sockets = net_alloclist();
- if (!tcb->sockets)
- {
- return -ENOMEM;
- }
+ net_initlist(&group->tg_socketlist);
#endif
/* Open stdin, dup to get stdout and stderr. This should always
@@ -139,7 +139,7 @@ int sched_setupidlefiles(FAR _TCB *tcb)
/* Allocate file/socket streams for the TCB */
#if CONFIG_NFILE_STREAMS > 0
- return sched_setupstreams(tcb);
+ return group_setupstreams(tcb);
#else
return OK;
#endif
diff --git a/nuttx/sched/sched_setupstreams.c b/nuttx/sched/group_setupstreams.c
index 22895b047..08399ae41 100644
--- a/nuttx/sched/sched_setupstreams.c
+++ b/nuttx/sched/group_setupstreams.c
@@ -1,7 +1,7 @@
/****************************************************************************
- * sched_setupstreams.c
+ * group_setupstreams.c
*
- * Copyright (C) 2007-2008, 2010-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2008, 2010-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -46,6 +46,8 @@
#include <nuttx/net/net.h>
#include <nuttx/lib.h>
+#include "group_internal.h"
+
/* Make sure that there are file or socket descriptors in the system and
* that some number of streams have been configured.
*/
@@ -62,7 +64,7 @@
****************************************************************************/
/****************************************************************************
- * Name: sched_setupstreams
+ * Name: group_setupstreams
*
* Description:
* Setup streams data structures that may be used for standard C buffered
@@ -70,26 +72,25 @@
*
****************************************************************************/
-int sched_setupstreams(FAR _TCB *tcb)
+int group_setupstreams(FAR _TCB *tcb)
{
- /* Allocate file streams for the TCB */
-
- tcb->streams = lib_alloclist();
- if (tcb->streams)
- {
- /* fdopen to get the stdin, stdout and stderr streams.
- * The following logic depends on the fact that the library
- * layer will allocate FILEs in order.
- *
- * fd = 0 is stdin (read-only)
- * fd = 1 is stdout (write-only, append)
- * fd = 2 is stderr (write-only, append)
- */
-
- (void)fs_fdopen(0, O_RDONLY, tcb);
- (void)fs_fdopen(1, O_WROK|O_CREAT, tcb);
- (void)fs_fdopen(2, O_WROK|O_CREAT, tcb);
- }
+ DEBUGASSERT(tcb && tcb->group);
+
+ /* Initialize file streams for the task group */
+
+ lib_streaminit(&tcb->group->tg_streamlist);
+
+ /* fdopen to get the stdin, stdout and stderr streams. The following logic
+ * depends on the fact that the library layer will allocate FILEs in order.
+ *
+ * fd = 0 is stdin (read-only)
+ * fd = 1 is stdout (write-only, append)
+ * fd = 2 is stderr (write-only, append)
+ */
+
+ (void)fs_fdopen(0, O_RDONLY, tcb);
+ (void)fs_fdopen(1, O_WROK|O_CREAT, tcb);
+ (void)fs_fdopen(2, O_WROK|O_CREAT, tcb);
return OK;
}
diff --git a/nuttx/sched/sched_setuptaskfiles.c b/nuttx/sched/group_setuptaskfiles.c
index d01b8d4cd..e2e7d4634 100644
--- a/nuttx/sched/sched_setuptaskfiles.c
+++ b/nuttx/sched/group_setuptaskfiles.c
@@ -1,7 +1,7 @@
/****************************************************************************
- * sched/sched_setuptaskfiles.c
+ * sched/group_setuptaskfiles.c
*
- * Copyright (C) 2007-2008, 2010, 2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2008, 2010, 2012-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -46,6 +46,7 @@
#include <nuttx/net/net.h>
#include "os_internal.h"
+#include "group_internal.h"
#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0
@@ -93,34 +94,33 @@ static inline void sched_dupfiles(FAR _TCB *tcb)
FAR struct file *child;
int i;
+ DEBUGASSERT(tcb && tcb->group && rtcb->group);
+
/* Duplicate the file descriptors. This will be either all of the
* file descriptors or just the first three (stdin, stdout, and stderr)
* if CONFIG_FDCLONE_STDIO is defined. NFSDS_TOCLONE is set
* accordingly above.
*/
- if (rtcb->filelist)
- {
- /* Get pointers to the parent and child task file lists */
+ /* Get pointers to the parent and child task file lists */
- parent = rtcb->filelist->fl_files;
- child = tcb->filelist->fl_files;
+ parent = rtcb->group->tg_filelist.fl_files;
+ child = tcb->group->tg_filelist.fl_files;
- /* Check each file in the parent file list */
+ /* Check each file in the parent file list */
- for (i = 0; i < NFDS_TOCLONE; i++)
- {
- /* Check if this file is opened by the parent. We can tell if
- * if the file is open because it contain a reference to a non-NULL
- * i-node structure.
- */
+ for (i = 0; i < NFDS_TOCLONE; i++)
+ {
+ /* Check if this file is opened by the parent. We can tell if
+ * if the file is open because it contain a reference to a non-NULL
+ * i-node structure.
+ */
- if (parent[i].f_inode)
- {
- /* Yes... duplicate it for the child */
+ if (parent[i].f_inode)
+ {
+ /* Yes... duplicate it for the child */
- (void)files_dup(&parent[i], &child[i]);
- }
+ (void)files_dup(&parent[i], &child[i]);
}
}
}
@@ -152,32 +152,31 @@ static inline void sched_dupsockets(FAR _TCB *tcb)
FAR struct socket *child;
int i;
- /* Duplicate the socket descriptors of all sockets opened by the parent
- * task.
- */
+ /* Duplicate the socket descriptors of all sockets opened by the parent
+ * task.
+ */
- if (rtcb->sockets)
- {
- /* Get pointers to the parent and child task socket lists */
+ DEBUGASSERT(tcb && tcb->group && rtcb->group);
- parent = rtcb->sockets->sl_sockets;
- child = tcb->sockets->sl_sockets;
+ /* Get pointers to the parent and child task socket lists */
- /* Check each socket in the parent socket list */
+ parent = rtcb->group->tg_socketlist.sl_sockets;
+ child = tcb->group->tg_socketlist.sl_sockets;
- for (i = 0; i < CONFIG_NSOCKET_DESCRIPTORS; i++)
- {
- /* Check if this parent socket is allocated. We can tell if the
- * socket is allocated because it will have a positive, non-zero
- * reference count.
- */
+ /* Check each socket in the parent socket list */
- if (parent[i].s_crefs > 0)
- {
- /* Yes... duplicate it for the child */
+ for (i = 0; i < CONFIG_NSOCKET_DESCRIPTORS; i++)
+ {
+ /* Check if this parent socket is allocated. We can tell if the
+ * socket is allocated because it will have a positive, non-zero
+ * reference count.
+ */
+
+ if (parent[i].s_crefs > 0)
+ {
+ /* Yes... duplicate it for the child */
- (void)net_clone(&parent[i], &child[i]);
- }
+ (void)net_clone(&parent[i], &child[i]);
}
}
}
@@ -190,7 +189,7 @@ static inline void sched_dupsockets(FAR _TCB *tcb)
****************************************************************************/
/****************************************************************************
- * Name: sched_setuptaskfiles
+ * Name: group_setuptaskfiles
*
* Description:
* Configure a newly allocated TCB so that it will inherit
@@ -207,26 +206,24 @@ static inline void sched_dupsockets(FAR _TCB *tcb)
*
****************************************************************************/
-int sched_setuptaskfiles(FAR _TCB *tcb)
+int group_setuptaskfiles(FAR _TCB *tcb)
{
- /* Allocate file descriptors for the TCB */
+#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0
+ FAR struct task_group_s *group = tcb->group;
+
+ DEBUGASSERT(group);
+#endif
#if CONFIG_NFILE_DESCRIPTORS > 0
- tcb->filelist = files_alloclist();
- if (!tcb->filelist)
- {
- return -ENOMEM;
- }
+ /* Initialize file descriptors for the TCB */
+
+ files_initlist(&group->tg_filelist);
#endif
+#if CONFIG_NSOCKET_DESCRIPTORS > 0
/* Allocate socket descriptors for the TCB */
-#if CONFIG_NSOCKET_DESCRIPTORS > 0
- tcb->sockets = net_alloclist();
- if (!tcb->sockets)
- {
- return -ENOMEM;
- }
+ net_initlist(&group->tg_socketlist);
#endif
/* Duplicate the parent task's file descriptors */
@@ -240,7 +237,7 @@ int sched_setuptaskfiles(FAR _TCB *tcb)
/* Allocate file/socket streams for the new TCB */
#if CONFIG_NFILE_STREAMS > 0
- return sched_setupstreams(tcb);
+ return group_setupstreams(tcb);
#else
return OK;
#endif
diff --git a/nuttx/sched/group_signal.c b/nuttx/sched/group_signal.c
new file mode 100644
index 000000000..009ab7a55
--- /dev/null
+++ b/nuttx/sched/group_signal.c
@@ -0,0 +1,163 @@
+/*****************************************************************************
+ * sched/group_signal.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * 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 <sched.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <debug.h>
+
+#include "os_internal.h"
+#include "group_internal.h"
+#include "sig_internal.h"
+
+#if defined(HAVE_TASK_GROUP) && !defined(CONFIG_DISABLE_SIGNALS)
+
+/*****************************************************************************
+ * Pre-processor Definitions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Private Types
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Private Data
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Private Functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Public Functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Name: group_signal
+ *
+ * Description:
+ * Send a signal to every member of the group.
+ *
+ * Parameters:
+ * group - The task group that needs to be signalled.
+ *
+ * Return Value:
+ * 0 (OK) on success; a negated errno value on failure.
+ *
+ * Assumptions:
+ * Called during task terminatino in a safe context. No special precautions
+ * are required here.
+ *
+ *****************************************************************************/
+
+int group_signal(FAR struct task_group_s *group, FAR siginfo_t *info)
+{
+#ifdef HAVE_GROUP_MEMBERS
+ FAR _TCB *gtcb;
+ int i;
+
+ DEBUGASSERT(group && info);
+
+ /* Make sure that pre-emption is disabled to that we signal all of teh
+ * members of the group before any of them actually run.
+ */
+
+ sched_lock();
+
+ /* Send the signal to each member of the group */
+
+ for (i = 0; i < group->tg_nmembers; i++)
+ {
+ gtcb = sched_gettcb(group->tg_members[i]);
+ DEBUGASSERT(gtcb);
+ if (gtcb)
+ {
+ /* Use the sig_received interface so that it does not muck with
+ * the siginfo_t.
+ */
+
+#ifdef CONFIG_DEBUG
+ int ret = sig_received(gtcb, info);
+ DEBUGASSERT(ret == 0);
+#else
+ (void)sig_received(gtcb, info);
+#endif
+ }
+ }
+
+ /* Re-enable pre-emption an return success */
+
+ sched_unlock();
+ return OK;
+#else
+ return -ENOSYS;
+#endif
+}
+
+/*****************************************************************************
+ * Name: group_signalmember
+ *
+ * Description:
+ * Send a signal to every member of the group to which task belongs.
+ *
+ * Parameters:
+ * tcb - The tcb of one task in the task group that needs to be signalled.
+ *
+ * Return Value:
+ * 0 (OK) on success; a negated errno value on failure.
+ *
+ * Assumptions:
+ * Called during task terminatino in a safe context. No special precautions
+ * are required here.
+ *
+ *****************************************************************************/
+
+int group_signalmember(FAR _TCB *tcb, FAR siginfo_t *info)
+{
+#ifdef HAVE_GROUP_MEMBERS
+ DEBUGASSERT(tcb);
+ return group_signal(tcb->group, info);
+#else
+ return sig_received(tcb, info);
+#endif
+}
+#endif /* HAVE_TASK_GROUP && !CONFIG_DISABLE_SIGNALS */
diff --git a/nuttx/sched/mq_sndinternal.c b/nuttx/sched/mq_sndinternal.c
index 51f898875..f16f7de1a 100644
--- a/nuttx/sched/mq_sndinternal.c
+++ b/nuttx/sched/mq_sndinternal.c
@@ -124,7 +124,7 @@ int mq_verifysend(mqd_t mqdes, const void *msg, size_t msglen, int prio)
return ERROR;
}
- if (msglen < 0 || msglen > (size_t)mqdes->msgq->maxmsgsize)
+ if (msglen > (size_t)mqdes->msgq->maxmsgsize)
{
set_errno(EMSGSIZE);
return ERROR;
diff --git a/nuttx/sched/os_internal.h b/nuttx/sched/os_internal.h
index 7d5095bad..262a40ccc 100644
--- a/nuttx/sched/os_internal.h
+++ b/nuttx/sched/os_internal.h
@@ -99,15 +99,6 @@ enum os_crash_codes_e
#define MAX_TASKS_MASK (CONFIG_MAX_TASKS-1)
#define PIDHASH(pid) ((pid) & MAX_TASKS_MASK)
-/* Stubs used when there are no file descriptors */
-
-#if CONFIG_NFILE_DESCRIPTORS <= 0 && CONFIG_NSOCKET_DESCRIPTORS <= 0
-# define sched_setupidlefiles(t) (OK)
-# define sched_setuptaskfiles(t) (OK)
-# define sched_setuppthreadfiles(t) (OK)
-# define sched_releasefiles(t) (OK)
-#endif
-
/* One processor family supported by NuttX has a single, fixed hardware stack.
* That is the 8051 family. So for that family only, there is a variant form
* of kernel_thread() that does not take a stack size parameter. The following
@@ -262,24 +253,16 @@ extern const tasklist_t g_tasklisttable[NUM_TASK_STATES];
****************************************************************************/
int os_bringup(void);
+#ifdef CONFIG_SCHED_CHILD_STATUS
+void weak_function task_initialize(void);
+#endif
void task_start(void);
int task_schedsetup(FAR _TCB *tcb, int priority, start_t start,
main_t main, uint8_t ttype);
int task_argsetup(FAR _TCB *tcb, FAR const char *name, FAR const char *argv[]);
void task_exithook(FAR _TCB *tcb, int status);
int task_deletecurrent(void);
-#ifdef CONFIG_SCHED_HAVE_PARENT
-#ifdef CONFIG_SCHED_CHILD_STATUS
-void weak_function task_initialize(void);
-FAR struct child_status_s *task_allocchild(void);
-void task_freechild(FAR struct child_status_s *status);
-void task_addchild(FAR _TCB *tcb, FAR struct child_status_s *child);
-FAR struct child_status_s *task_findchild(FAR _TCB *tcb, pid_t pid);
-FAR struct child_status_s *task_removechild(FAR _TCB *tcb, pid_t pid);
-void task_removechildren(FAR _TCB *tcb);
-#endif
-int task_reparent(pid_t ppid, pid_t chpid);
-#endif
+
#ifndef CONFIG_CUSTOM_STACK
int kernel_thread(FAR const char *name, int priority, int stack_size,
main_t entry, FAR const char *argv[]);
@@ -302,16 +285,6 @@ int sched_reprioritize(FAR _TCB *tcb, int sched_priority);
FAR _TCB *sched_gettcb(pid_t pid);
bool sched_verifytcb(FAR _TCB *tcb);
-#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0
-int sched_setupidlefiles(FAR _TCB *tcb);
-int sched_setuptaskfiles(FAR _TCB *tcb);
-int sched_setuppthreadfiles(FAR _TCB *tcb);
-#if CONFIG_NFILE_STREAMS > 0
-int sched_setupstreams(FAR _TCB *tcb);
-#endif
-int sched_releasefiles(FAR _TCB *tcb);
-#endif
-
int sched_releasetcb(FAR _TCB *tcb);
void sched_garbagecollection(void);
diff --git a/nuttx/sched/os_start.c b/nuttx/sched/os_start.c
index a6d4e83b9..c60edc495 100644
--- a/nuttx/sched/os_start.c
+++ b/nuttx/sched/os_start.c
@@ -1,7 +1,7 @@
/****************************************************************************
* sched/os_start.c
*
- * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -63,6 +63,9 @@
#include "clock_internal.h"
#include "timer_internal.h"
#include "irq_internal.h"
+#ifdef HAVE_TASK_GROUP
+#include "group_internal.h"
+#endif
/****************************************************************************
* Pre-processor Definitions
@@ -286,7 +289,6 @@ void os_start(void)
/* Initialize the processor-specific portion of the TCB */
- g_idletcb.flags = (TCB_FLAG_TTYPE_KERNEL | TCB_FLAG_NOCLDWAIT);
up_initial_state(&g_idletcb);
/* Initialize the semaphore facility(if in link). This has to be done
@@ -325,6 +327,12 @@ void os_start(void)
}
#endif
+ /* Allocate the IDLE group and suppress child status. */
+
+#ifdef HAVE_TASK_GROUP
+ (void)group_allocate(&g_idletcb);
+#endif
+
/* Initialize the interrupt handling subsystem (if included) */
#ifdef CONFIG_HAVE_WEAKFUNCTIONS
@@ -441,7 +449,16 @@ void os_start(void)
* inherited by all of the threads created by the IDLE task.
*/
- (void)sched_setupidlefiles(&g_idletcb);
+ (void)group_setupidlefiles(&g_idletcb);
+
+ /* Complete initialization of the IDLE group. Suppress retention
+ * of child status in the IDLE group.
+ */
+
+#ifdef HAVE_TASK_GROUP
+ (void)group_initialize(&g_idletcb);
+ g_idletcb.group->tg_flags = GROUP_FLAG_NOCLDWAIT;
+#endif
/* Create initial tasks and bring-up the system */
diff --git a/nuttx/sched/pthread_create.c b/nuttx/sched/pthread_create.c
index f4d0d8fdf..48a0788a6 100644
--- a/nuttx/sched/pthread_create.c
+++ b/nuttx/sched/pthread_create.c
@@ -53,8 +53,8 @@
#include <nuttx/arch.h>
#include "os_internal.h"
+#include "group_internal.h"
#include "clock_internal.h"
-#include "env_internal.h"
#include "pthread_internal.h"
/****************************************************************************
@@ -246,12 +246,13 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
{
FAR _TCB *ptcb;
FAR join_t *pjoin;
- int ret;
int priority;
#if CONFIG_RR_INTERVAL > 0
int policy;
#endif
+ int errcode;
pid_t pid;
+ int ret;
/* If attributes were not supplied, use the default attributes */
@@ -268,6 +269,19 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
return ENOMEM;
}
+ /* Bind the parent's group to the new TCB (we have not yet joined the
+ * group).
+ */
+
+#ifdef HAVE_TASK_GROUP
+ ret = group_bind(ptcb);
+ if (ret < 0)
+ {
+ errcode = ENOMEM;
+ goto errout_with_tcb;
+ }
+#endif
+
/* Share the address environment of the parent task. NOTE: Only tasks
* created throught the nuttx/binfmt loaders may have an address
* environment.
@@ -277,31 +291,18 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
ret = up_addrenv_share((FAR const _TCB *)g_readytorun.head, ptcb);
if (ret < 0)
{
- sched_releasetcb(ptcb);
- return -ret;
+ errcode = -ret;
+ goto errout_with_tcb;
}
#endif
- /* Associate file descriptors with the new task */
-
- ret = sched_setuppthreadfiles(ptcb);
- if (ret != OK)
- {
- sched_releasetcb(ptcb);
- return ret;
- }
-
- /* Share the parent's envionment */
-
- (void)env_share(ptcb);
-
/* Allocate a detachable structure to support pthread_join logic */
pjoin = (FAR join_t*)kzalloc(sizeof(join_t));
if (!pjoin)
{
- sched_releasetcb(ptcb);
- return ENOMEM;
+ errcode = ENOMEM;
+ goto errout_with_tcb;
}
/* Allocate the stack for the TCB */
@@ -309,9 +310,8 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
ret = up_create_stack(ptcb, attr->stacksize);
if (ret != OK)
{
- sched_releasetcb(ptcb);
- sched_free(pjoin);
- return ENOMEM;
+ errcode = ENOMEM;
+ goto errout_with_join;
}
/* Should we use the priority and scheduler specified in the
@@ -360,9 +360,8 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
TCB_FLAG_TTYPE_PTHREAD);
if (ret != OK)
{
- sched_releasetcb(ptcb);
- sched_free(pjoin);
- return EBUSY;
+ errcode = EBUSY;
+ goto errout_with_join;
}
/* Configure the TCB for a pthread receiving on parameter
@@ -371,6 +370,17 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
pthread_argsetup(ptcb, arg);
+ /* Join the parent's task group */
+
+#ifdef HAVE_TASK_GROUP
+ ret = group_join(ptcb);
+ if (ret < 0)
+ {
+ errcode = ENOMEM;
+ goto errout_with_join;
+ }
+#endif
+
/* Attach the join info to the TCB. */
ptcb->joininfo = (void*)pjoin;
@@ -440,10 +450,18 @@ int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr,
dq_rem((FAR dq_entry_t*)ptcb, (dq_queue_t*)&g_inactivetasks);
(void)sem_destroy(&pjoin->data_sem);
(void)sem_destroy(&pjoin->exit_sem);
- sched_releasetcb(ptcb);
- sched_free(pjoin);
- ret = EIO;
+
+ errcode = EIO;
+ goto errout_with_join;
}
return ret;
+
+errout_with_join:
+ sched_free(pjoin);
+ ptcb->joininfo = NULL;
+
+errout_with_tcb:
+ sched_releasetcb(ptcb);
+ return errcode;
}
diff --git a/nuttx/sched/pthread_join.c b/nuttx/sched/pthread_join.c
index 6a02af352..d3f648dc7 100644
--- a/nuttx/sched/pthread_join.c
+++ b/nuttx/sched/pthread_join.c
@@ -123,7 +123,7 @@ int pthread_join(pthread_t thread, FAR pthread_addr_t *pexit_value)
* This can fail for one of three reasons: (1) There is no
* thread associated with 'thread,' (2) the thread is a task
* and does not have join information, or (3) the thread
- * was detached and has exitted.
+ * was detached and has exited.
*/
pjoin = pthread_findjoininfo((pid_t)thread);
diff --git a/nuttx/sched/sched_getfiles.c b/nuttx/sched/sched_getfiles.c
index 256b4cb6b..17ca2bbf6 100644
--- a/nuttx/sched/sched_getfiles.c
+++ b/nuttx/sched/sched_getfiles.c
@@ -1,7 +1,7 @@
/************************************************************************
* sched/sched_getfiles.c
*
- * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -70,7 +70,10 @@
FAR struct filelist *sched_getfiles(void)
{
FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head;
- return rtcb->filelist;
+ FAR struct task_group_s *group = rtcb->group;
+
+ DEBUGASSERT(group);
+ return &group->tg_filelist;
}
#endif /* CONFIG_NFILE_DESCRIPTORS */
diff --git a/nuttx/sched/sched_getsockets.c b/nuttx/sched/sched_getsockets.c
index cd499420f..ea988d6ff 100644
--- a/nuttx/sched/sched_getsockets.c
+++ b/nuttx/sched/sched_getsockets.c
@@ -1,7 +1,7 @@
/************************************************************************
* sched/sched_getsockets.c
*
- * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -71,7 +71,10 @@
FAR struct socketlist *sched_getsockets(void)
{
FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head;
- return rtcb->sockets;
+ FAR struct task_group_s *group = rtcb->group;
+
+ DEBUGASSERT(group);
+ return &group->tg_socketlist;
}
#endif /* CONFIG_NSOCKET_DESCRIPTORS */
diff --git a/nuttx/sched/sched_getstreams.c b/nuttx/sched/sched_getstreams.c
index f7c21ab4c..dab406e66 100644
--- a/nuttx/sched/sched_getstreams.c
+++ b/nuttx/sched/sched_getstreams.c
@@ -1,7 +1,7 @@
/****************************************************************************
* sched/sched_getstreams.c
*
- * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2008, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -70,7 +70,10 @@
FAR struct streamlist *sched_getstreams(void)
{
FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head;
- return rtcb->streams;
+ FAR struct task_group_s *group = rtcb->group;
+
+ DEBUGASSERT(group);
+ return &group->tg_streamlist;
}
#endif /* CONFIG_NFILE_DESCRIPTORS && CONFIG_NFILE_STREAMS */
diff --git a/nuttx/sched/sched_releasetcb.c b/nuttx/sched/sched_releasetcb.c
index 0557c829b..02f7170c2 100644
--- a/nuttx/sched/sched_releasetcb.c
+++ b/nuttx/sched/sched_releasetcb.c
@@ -1,7 +1,7 @@
/************************************************************************
* sched/sched_releasetcb.c
*
- * Copyright (C) 2007, 2009, 2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2012-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -45,8 +45,8 @@
#include <nuttx/arch.h>
#include "os_internal.h"
+#include "group_internal.h"
#include "timer_internal.h"
-#include "env_internal.h"
/************************************************************************
* Private Functions
@@ -163,20 +163,17 @@ int sched_releasetcb(FAR _TCB *tcb)
}
}
- /* Release any allocated file structures */
-
- ret = sched_releasefiles(tcb);
-
- /* Release environment variables */
-
- (void)env_release(tcb);
-
/* Release this thread's reference to the address environment */
#ifdef CONFIG_ADDRENV
ret = up_addrenv_release(tcb);
#endif
+ /* Leave the group (if we did not already leady in task_exithook.c) */
+
+#ifdef HAVE_TASK_GROUP
+ group_leave(tcb);
+#endif
/* And, finally, release the TCB itself */
sched_free(tcb);
diff --git a/nuttx/sched/sched_waitid.c b/nuttx/sched/sched_waitid.c
index 37ee26ce0..9c24189c4 100644
--- a/nuttx/sched/sched_waitid.c
+++ b/nuttx/sched/sched_waitid.c
@@ -46,6 +46,7 @@
#include <nuttx/sched.h>
#include "os_internal.h"
+#include "group_internal.h"
#if defined(CONFIG_SCHED_WAITPID) && defined(CONFIG_SCHED_HAVE_PARENT)
@@ -54,6 +55,36 @@
*****************************************************************************/
/*****************************************************************************
+ * Name: exited_child
+ *
+ * Description:
+ * Handle the case where a child exited properlay was we (apparently) lost
+ * the detch of child signal.
+ *
+ *****************************************************************************/
+
+#ifdef CONFIG_SCHED_CHILD_STATUS
+static void exited_child(FAR _TCB *rtcb, FAR struct child_status_s *child,
+ FAR siginfo_t *info)
+{
+ /* The child has exited. Return the saved exit status (and some fudged
+ * information.
+ */
+
+ info->si_signo = SIGCHLD;
+ info->si_code = CLD_EXITED;
+ info->si_value.sival_ptr = NULL;
+ info->si_pid = child->ch_pid;
+ info->si_status = child->ch_status;
+
+ /* Discard the child entry */
+
+ (void)group_removechild(rtcb->group, child->ch_pid);
+ group_freechild(child);
+}
+#endif
+
+/*****************************************************************************
* Public Functions
*****************************************************************************/
@@ -120,9 +151,14 @@
*
*****************************************************************************/
-int waitid(idtype_t idtype, id_t id, siginfo_t *info, int options)
+int waitid(idtype_t idtype, id_t id, FAR siginfo_t *info, int options)
{
FAR _TCB *rtcb = (FAR _TCB *)g_readytorun.head;
+ FAR _TCB *ctcb;
+#ifdef CONFIG_SCHED_CHILD_STATUS
+ FAR struct child_status_s *child;
+ bool retains;
+#endif
sigset_t sigset;
int err;
int ret;
@@ -160,7 +196,11 @@ int waitid(idtype_t idtype, id_t id, siginfo_t *info, int options)
*/
#ifdef CONFIG_SCHED_CHILD_STATUS
- if (rtcb->children == NULL)
+ /* Does this task retain child status? */
+
+ retains = ((rtcb->group->tg_flags && GROUP_FLAG_NOCLDWAIT) == 0);
+
+ if (rtcb->group->tg_children == NULL && retains)
{
/* There are no children */
@@ -169,13 +209,33 @@ int waitid(idtype_t idtype, id_t id, siginfo_t *info, int options)
}
else if (idtype == P_PID)
{
- if (task_findchild(rtcb, (pid_t)id) == NULL)
- {
- /* This specific pid is not a child */
+ /* Get the TCB corresponding to this PID and make sure it is our child. */
+ ctcb = sched_gettcb((pid_t)id);
+#ifdef HAVE_GROUP_MEMBERS
+ if (!ctcb || ctcb->group->tg_pgid != rtcb->group->tg_gid)
+#else
+ if (!ctcb || ctcb->ppid != rtcb->pid)
+#endif
+ {
err = ECHILD;
goto errout_with_errno;
}
+
+ /* Does this task retain child status? */
+
+ if (retains)
+ {
+ /* Check if this specific pid has allocated child status? */
+
+ if (group_findchild(rtcb->group, (pid_t)id) == NULL)
+ {
+ /* This specific pid is not a child */
+
+ err = ECHILD;
+ goto errout_with_errno;
+ }
+ }
}
#else
if (rtcb->nchildren == 0)
@@ -189,8 +249,12 @@ int waitid(idtype_t idtype, id_t id, siginfo_t *info, int options)
{
/* Get the TCB corresponding to this PID and make sure it is our child. */
- FAR _TCB *ctcb = sched_gettcb((pid_t)id);
- if (!ctcb || ctcb->parent != rtcb->pid)
+ ctcb = sched_gettcb((pid_t)id);
+#ifdef HAVE_GROUP_MEMBERS
+ if (!ctcb || ctcb->group->tg_pgid != rtcb->group->tg_gid)
+#else
+ if (!ctcb || ctcb->ppid != rtcb->pid)
+#endif
{
err = ECHILD;
goto errout_with_errno;
@@ -209,48 +273,61 @@ int waitid(idtype_t idtype, id_t id, siginfo_t *info, int options)
* instead).
*/
- DEBUGASSERT(rtcb->children);
- if (rtcb->children == NULL)
+ DEBUGASSERT(!retains || rtcb->group->tg_children);
+ if (idtype == P_ALL)
{
- /* This should not happen. I am just wasting your FLASH. */
+ /* We are waiting for any child to exit */
- err = ECHILD;
- goto errout_with_errno;
- }
- else if (idtype == P_PID)
- {
- FAR struct child_status_s *child;
-
- /* We are waiting for a specific PID. Get the current status
- * of the child task.
- */
-
- child = task_findchild(rtcb, (pid_t)id);
- DEBUGASSERT(child);
- if (!child)
+ if (retains && (child = group_exitchild(rtcb->group)) != NULL)
{
- /* Yikes! The child status entry just disappeared! */
+ /* A child has exited. Apparently we missed the signal.
+ * Return the exit status and break out of the loop.
+ */
- err = ECHILD;
- goto errout_with_errno;
+ exited_child(rtcb, child, info);
+ break;
}
+ }
+ /* We are waiting for a specific PID. Does this task retain child status? */
+
+ else if (retains)
+ {
+ /* Yes ... Get the current status of the child task. */
+
+ child = group_findchild(rtcb->group, (pid_t)id);
+ DEBUGASSERT(child);
+
/* Did the child exit? */
if ((child->ch_flags & CHILD_FLAG_EXITED) != 0)
{
- /* The child has exited. Return the saved exit status */
+ /* The child has exited. Return the exit status and break out
+ * of the loop.
+ */
- info->si_signo = SIGCHLD;
- info->si_code = CLD_EXITED;
- info->si_value.sival_ptr = NULL;
- info->si_pid = (pid_t)id;
- info->si_status = child->ch_status;
+ exited_child(rtcb, child, info);
+ break;
+ }
+ }
+ else
+ {
+ /* We can use kill() with signal number 0 to determine if that
+ * task is still alive.
+ */
- /* Discard the child entry and break out of the loop */
+ ret = kill((pid_t)id, 0);
+ if (ret < 0)
+ {
+ /* It is no longer running. We know that the child task
+ * was running okay when we started, so we must have lost
+ * the signal. In this case, we know that the task exit'ed,
+ * but we do not know its exit status. It would be better
+ * to reported ECHILD than bogus status.
+ */
- (void)task_removechild(rtcb, (pid_t)id);
- task_freechild(child);
+ err = ECHILD;
+ goto errout_with_errno;
}
}
#else
diff --git a/nuttx/sched/sched_waitpid.c b/nuttx/sched/sched_waitpid.c
index fe3f7167d..0285c2673 100644
--- a/nuttx/sched/sched_waitpid.c
+++ b/nuttx/sched/sched_waitpid.c
@@ -47,6 +47,7 @@
#include <nuttx/sched.h>
#include "os_internal.h"
+#include "group_internal.h"
#ifdef CONFIG_SCHED_WAITPID
@@ -171,21 +172,17 @@
*
* Assumptions:
*
- *****************************************************************************/
-
-/***************************************************************************
- * NOTE: This is a partially functional, experimental version of waitpid()
- *
- * If there is no SIGCHLD signal supported (CONFIG_SCHED_HAVE_PARENT not
- * defined), then waitpid() is still available, but does not obey the
- * restriction that the pid be a child of the caller.
+ * Compatibility
+ * If there is no SIGCHLD signal supported (CONFIG_SCHED_HAVE_PARENT not
+ * defined), then waitpid() is still available, but does not obey the
+ * restriction that the pid be a child of the caller.
*
- ***************************************************************************/
+ *****************************************************************************/
#ifndef CONFIG_SCHED_HAVE_PARENT
pid_t waitpid(pid_t pid, int *stat_loc, int options)
{
- _TCB *tcb;
+ _TCB *ctcb;
bool mystat;
int err;
int ret;
@@ -208,8 +205,8 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
/* Get the TCB corresponding to this PID */
- tcb = sched_gettcb(pid);
- if (!tcb)
+ ctcb = sched_gettcb(pid);
+ if (!ctcb)
{
err = ECHILD;
goto errout_with_errno;
@@ -221,15 +218,15 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
* others?
*/
- if (stat_loc != NULL && tcb->stat_loc == NULL)
+ if (stat_loc != NULL && ctcb->stat_loc == NULL)
{
- tcb->stat_loc = stat_loc;
- mystat = true;
+ ctcb->stat_loc = stat_loc;
+ mystat = true;
}
/* Then wait for the task to exit */
- ret = sem_wait(&tcb->exitsem);
+ ret = sem_wait(&ctcb->exitsem);
if (ret < 0)
{
/* Unlock pre-emption and return the ERROR (sem_wait has already set
@@ -239,7 +236,7 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
if (mystat)
{
- tcb->stat_loc = NULL;
+ ctcb->stat_loc = NULL;
}
goto errout;
@@ -274,8 +271,10 @@ errout:
pid_t waitpid(pid_t pid, int *stat_loc, int options)
{
FAR _TCB *rtcb = (FAR _TCB *)g_readytorun.head;
+ FAR _TCB *ctcb;
#ifdef CONFIG_SCHED_CHILD_STATUS
FAR struct child_status_s *child;
+ bool retains;
#endif
FAR struct siginfo info;
sigset_t sigset;
@@ -303,27 +302,47 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
sched_lock();
- /* Verify that this task actually has children and that the the request
- * TCB is actually a child of this task.
+ /* Verify that this task actually has children and that the requested PID
+ * is actually a child of this task.
*/
#ifdef CONFIG_SCHED_CHILD_STATUS
- if (rtcb->children == NULL)
- {
- /* There are no children */
+ /* Does this task retain child status? */
+ retains = ((rtcb->group->tg_flags && GROUP_FLAG_NOCLDWAIT) == 0);
+
+ if (rtcb->group->tg_children == NULL && retains)
+ {
err = ECHILD;
goto errout_with_errno;
}
else if (pid != (pid_t)-1)
{
- /* This specific pid is not a child */
+ /* Get the TCB corresponding to this PID and make sure it is our child. */
- if (task_findchild(rtcb, pid) == NULL)
+ ctcb = sched_gettcb(pid);
+#ifdef HAVE_GROUP_MEMBERS
+ if (!ctcb || ctcb->group->tg_pgid != rtcb->group->tg_gid)
+#else
+ if (!ctcb || ctcb->ppid != rtcb->pid)
+#endif
{
err = ECHILD;
goto errout_with_errno;
}
+
+ /* Does this task retain child status? */
+
+ if (retains)
+ {
+ /* Check if this specific pid has allocated child status? */
+
+ if (group_findchild(rtcb->group, pid) == NULL)
+ {
+ err = ECHILD;
+ goto errout_with_errno;
+ }
+ }
}
#else
if (rtcb->nchildren == 0)
@@ -337,8 +356,12 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
{
/* Get the TCB corresponding to this PID and make sure it is our child. */
- FAR _TCB *ctcb = sched_gettcb(pid);
- if (!ctcb || ctcb->parent != rtcb->pid)
+ ctcb = sched_gettcb(pid);
+#ifdef HAVE_GROUP_MEMBERS
+ if (!ctcb || ctcb->group->tg_pgid != rtcb->group->tg_gid)
+#else
+ if (!ctcb || ctcb->ppid != rtcb->pid)
+#endif
{
err = ECHILD;
goto errout_with_errno;
@@ -350,6 +373,7 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
for (;;)
{
+#ifdef CONFIG_SCHED_CHILD_STATUS
/* Check if the task has already died. Signals are not queued in
* NuttX. So a possibility is that the child has died and we
* missed the death of child signal (we got some other signal
@@ -362,39 +386,33 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
* chilren.
*/
-#ifdef CONFIG_SCHED_CHILD_STATUS
- DEBUGASSERT(rtcb->children);
- if (rtcb->children == NULL)
-#else
- if (rtcb->nchildren == 0)
-#endif
+ DEBUGASSERT(!retains || rtcb->group->tg_children);
+ if (retains && (child = group_exitchild(rtcb->group)) != NULL)
{
- /* There were one or more children when we started so they
- * must have exit'ed. There are just no bread crumbs left
- * behind to tell us the PID(s) of the existed children.
- * Reporting ECHLD is about all we can do in this case.
+ /* A child has exited. Apparently we missed the signal.
+ * Return the saved exit status.
*/
- err = ECHILD;
- goto errout_with_errno;
+ /* The child has exited. Return the saved exit status */
+
+ *stat_loc = child->ch_status << 8;
+
+ /* Discard the child entry and break out of the loop */
+
+ (void)group_removechild(rtcb->group, child->ch_pid);
+ group_freechild(child);
+ break;
}
}
- else
+
+ /* We are waiting for a specific PID. Does this task retain child status? */
+
+ else if (retains)
{
-#ifdef CONFIG_SCHED_CHILD_STATUS
- /* We are waiting for a specific PID. Get the current status
- * of the child task.
- */
+ /* Get the current status of the child task. */
- child = task_findchild(rtcb, pid);
+ child = group_findchild(rtcb->group, pid);
DEBUGASSERT(child);
- if (!child)
- {
- /* Yikes! The child status entry just disappeared! */
-
- err = ECHILD;
- goto errout_with_errno;
- }
/* Did the child exit? */
@@ -402,33 +420,54 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
{
/* The child has exited. Return the saved exit status */
- *stat_loc = child->ch_status;
+ *stat_loc = child->ch_status << 8;
/* Discard the child entry and break out of the loop */
- (void)task_removechild(rtcb, pid);
- task_freechild(child);
+ (void)group_removechild(rtcb->group, pid);
+ group_freechild(child);
+ break;
}
-#else
- /* We are waiting for a specific PID. We can use kill() with
- * signal number 0 to determine if that task is still alive.
+ }
+ else
+ {
+ /* We can use kill() with signal number 0 to determine if that
+ * task is still alive.
*/
ret = kill(pid, 0);
if (ret < 0)
{
- /* It is no longer running. We know that the child task was
- * running okay when we started, so we must have lost the
- * signal. In this case, we know that the task exit'ed, but
- * we do not know its exit status. It would be better to
- * reported ECHILD that bogus status.
+ /* It is no longer running. We know that the child task
+ * was running okay when we started, so we must have lost
+ * the signal. In this case, we know that the task exit'ed,
+ * but we do not know its exit status. It would be better
+ * to reported ECHILD than bogus status.
*/
err = ECHILD;
goto errout_with_errno;
}
-#endif
}
+#else
+ /* Check if the task has already died. Signals are not queued in
+ * NuttX. So a possibility is that the child has died and we
+ * missed the death of child signal (we got some other signal
+ * instead).
+ */
+
+ if (rtcb->nchildren == 0 ||
+ (pid != (pid_t)-1 && (ret = kill(pid, 0)) < 0))
+ {
+ /* We know that the child task was running okay we stared,
+ * so we must have lost the signal. What can we do?
+ * Let's claim we were interrupted by a signal.
+ */
+
+ err = EINTR;
+ goto errout_with_errno;
+ }
+#endif
/* Wait for any death-of-child signal */
@@ -447,7 +486,7 @@ pid_t waitpid(pid_t pid, int *stat_loc, int options)
{
/* Yes... return the status and PID (in the event it was -1) */
- *stat_loc = info.si_status;
+ *stat_loc = info.si_status << 8;
pid = info.si_pid;
break;
}
diff --git a/nuttx/sched/sig_action.c b/nuttx/sched/sig_action.c
index 708667993..5c00179dc 100644
--- a/nuttx/sched/sig_action.c
+++ b/nuttx/sched/sig_action.c
@@ -46,6 +46,7 @@
#include <errno.h>
#include "os_internal.h"
+#include "group_internal.h"
#include "sig_internal.h"
/****************************************************************************
@@ -169,7 +170,6 @@ int sigaction(int signo, FAR const struct sigaction *act, FAR struct sigaction *
{
FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head;
FAR sigactq_t *sigact;
- int ret;
/* Since sigactions can only be installed from the running thread of
* execution, no special precautions should be necessary.
@@ -238,11 +238,11 @@ int sigaction(int signo, FAR const struct sigaction *act, FAR struct sigaction *
/* Mark that status should be not be retained */
- rtcb->flags |= TCB_FLAG_NOCLDWAIT;
+ rtcb->group->tg_flags |= GROUP_FLAG_NOCLDWAIT;
/* Free all pending exit status */
- task_removechildren(rtcb);
+ group_removechildren(rtcb->group);
irqrestore(flags);
}
#endif
@@ -251,24 +251,31 @@ int sigaction(int signo, FAR const struct sigaction *act, FAR struct sigaction *
if (act->sa_u._sa_handler == SIG_IGN)
{
- /* If there is a old sigaction, remove it from sigactionq */
+ /* Do we still have a sigaction container from the previous setting? */
- sq_rem((FAR sq_entry_t*)sigact, &rtcb->sigactionq);
+ if (sigact)
+ {
+ /* Yes.. Remove it from sigactionq */
+
+ sq_rem((FAR sq_entry_t*)sigact, &rtcb->sigactionq);
- /* And deallocate it */
+ /* And deallocate it */
- sig_releaseaction(sigact);
+ sig_releaseaction(sigact);
+ }
}
/* A sigaction has been supplied */
else
{
- /* Check if a sigaction was found */
+ /* Do we still have a sigaction container from the previous setting?
+ * If so, then re-use for the new signal action.
+ */
if (!sigact)
{
- /* No sigaction was found, but one is needed. Allocate one. */
+ /* No.. Then we need to allocate one for the new action. */
sigact = sig_allocateaction();
@@ -294,7 +301,7 @@ int sigaction(int signo, FAR const struct sigaction *act, FAR struct sigaction *
COPY_SIGACTION(&sigact->act, act);
}
- return ret;
+ return OK;
}
/****************************************************************************
diff --git a/nuttx/sched/task_create.c b/nuttx/sched/task_create.c
index 2ed929ab0..944743200 100644
--- a/nuttx/sched/task_create.c
+++ b/nuttx/sched/task_create.c
@@ -48,7 +48,7 @@
#include <nuttx/kmalloc.h>
#include "os_internal.h"
-#include "env_internal.h"
+#include "group_internal.h"
/****************************************************************************
* Definitions
@@ -108,6 +108,7 @@ static int thread_create(const char *name, uint8_t ttype, int priority,
{
FAR _TCB *tcb;
pid_t pid;
+ int errcode;
int ret;
/* Allocate a TCB for the new task. */
@@ -115,29 +116,39 @@ static int thread_create(const char *name, uint8_t ttype, int priority,
tcb = (FAR _TCB*)kzalloc(sizeof(_TCB));
if (!tcb)
{
+ errcode = ENOMEM;
goto errout;
}
+ /* Allocate a new task group */
+
+#ifdef HAVE_TASK_GROUP
+ ret = group_allocate(tcb);
+ if (ret < 0)
+ {
+ errcode = -ret;
+ goto errout_with_tcb;
+ }
+#endif
+
/* Associate file descriptors with the new task */
#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0
- ret = sched_setuptaskfiles(tcb);
+ ret = group_setuptaskfiles(tcb);
if (ret != OK)
{
+ errcode = -ret;
goto errout_with_tcb;
}
#endif
- /* Clone the parent's task environment */
-
- (void)env_dup(tcb);
-
/* Allocate the stack for the TCB */
#ifndef CONFIG_CUSTOM_STACK
ret = up_create_stack(tcb, stack_size);
if (ret != OK)
{
+ errcode = -ret;
goto errout_with_tcb;
}
#endif
@@ -145,8 +156,9 @@ static int thread_create(const char *name, uint8_t ttype, int priority,
/* Initialize the task control block */
ret = task_schedsetup(tcb, priority, task_start, entry, ttype);
- if (ret != OK)
+ if (ret < OK)
{
+ errcode = -ret;
goto errout_with_tcb;
}
@@ -154,6 +166,17 @@ static int thread_create(const char *name, uint8_t ttype, int priority,
(void)task_argsetup(tcb, name, argv);
+ /* Now we have enough in place that we can join the group */
+
+#ifdef HAVE_TASK_GROUP
+ ret = group_initialize(tcb);
+ if (ret < 0)
+ {
+ errcode = -ret;
+ goto errout_with_tcb;
+ }
+#endif
+
/* Get the assigned pid before we start the task */
pid = (int)tcb->pid;
@@ -163,6 +186,8 @@ static int thread_create(const char *name, uint8_t ttype, int priority,
ret = task_activate(tcb);
if (ret != OK)
{
+ errcode = get_errno();
+
/* The TCB was added to the active task list by task_schedsetup() */
dq_rem((FAR dq_entry_t*)tcb, (dq_queue_t*)&g_inactivetasks);
@@ -175,7 +200,7 @@ errout_with_tcb:
sched_releasetcb(tcb);
errout:
- errno = ENOMEM;
+ set_errno(errcode);
return ERROR;
}
diff --git a/nuttx/sched/task_exithook.c b/nuttx/sched/task_exithook.c
index 1813c12ed..889df25e0 100644
--- a/nuttx/sched/task_exithook.c
+++ b/nuttx/sched/task_exithook.c
@@ -49,6 +49,7 @@
#include <nuttx/fs/fs.h>
#include "os_internal.h"
+#include "group_internal.h"
#include "sig_internal.h"
/****************************************************************************
@@ -103,10 +104,7 @@ static inline void task_atexit(FAR _TCB *tcb)
(*tcb->atexitfunc[index])();
- /* Nullify the atexit function. task_exithook may be called more then
- * once in most task exit scenarios. Nullifying the atext function
- * pointer will assure that the callback is performed only once.
- */
+ /* Nullify the atexit function to prevent its reuse. */
tcb->atexitfunc[index] = NULL;
}
@@ -119,10 +117,7 @@ static inline void task_atexit(FAR _TCB *tcb)
(*tcb->atexitfunc)();
- /* Nullify the atexit function. task_exithook may be called more then
- * once in most task exit scenarios. Nullifying the atext function
- * pointer will assure that the callback is performed only once.
- */
+ /* Nullify the atexit function to prevent its reuse. */
tcb->atexitfunc = NULL;
}
@@ -160,10 +155,7 @@ static inline void task_onexit(FAR _TCB *tcb, int status)
(*tcb->onexitfunc[index])(status, tcb->onexitarg[index]);
- /* Nullify the on_exit function. task_exithook may be called more then
- * once in most task exit scenarios. Nullifying the atext function
- * pointer will assure that the callback is performed only once.
- */
+ /* Nullify the on_exit function to prevent its reuse. */
tcb->onexitfunc[index] = NULL;
}
@@ -175,10 +167,7 @@ static inline void task_onexit(FAR _TCB *tcb, int status)
(*tcb->onexitfunc)(status, tcb->onexitarg);
- /* Nullify the on_exit function. task_exithook may be called more then
- * once in most task exit scenarios. Nullifying the on_exit function
- * pointer will assure that the callback is performed only once.
- */
+ /* Nullify the on_exit function to prevent its reuse. */
tcb->onexitfunc = NULL;
}
@@ -189,6 +178,89 @@ static inline void task_onexit(FAR _TCB *tcb, int status)
#endif
/****************************************************************************
+ * Name: task_exitstatus
+ *
+ * Description:
+ * Report exit status when main task of a task group exits
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SCHED_CHILD_STATUS
+static inline void task_exitstatus(FAR struct task_group_s *group, int status)
+{
+ FAR struct child_status_s *child;
+
+ /* Check if the parent task group has suppressed retention of
+ * child exit status information.
+ */
+
+ if ((group->tg_flags & GROUP_FLAG_NOCLDWAIT) == 0)
+ {
+ /* No.. Find the exit status entry for this task in the parent TCB */
+
+ child = group_findchild(group, getpid());
+ DEBUGASSERT(child);
+ if (child)
+ {
+#ifndef HAVE_GROUP_MEMBERS
+ /* No group members? Save the exit status */
+
+ child->ch_status = status;
+#endif
+ /* Save the exit status.. For the case of HAVE_GROUP_MEMBERS,
+ * the child status will be as exited until the last member
+ * of the task group exits.
+ */
+
+ child->ch_status = status;
+ }
+ }
+}
+#else
+
+# define task_exitstatus(group,status)
+
+#endif /* CONFIG_SCHED_CHILD_STATUS */
+
+/****************************************************************************
+ * Name: task_groupexit
+ *
+ * Description:
+ * Mark that the final thread of a child task group as exited.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SCHED_CHILD_STATUS
+static inline void task_groupexit(FAR struct task_group_s *group)
+{
+ FAR struct child_status_s *child;
+
+ /* Check if the parent task group has suppressed retention of child exit
+ * status information.
+ */
+
+ if ((group->tg_flags & GROUP_FLAG_NOCLDWAIT) == 0)
+ {
+ /* No.. Find the exit status entry for this task in the parent TCB */
+
+ child = group_findchild(group, getpid());
+ DEBUGASSERT(child);
+ if (child)
+ {
+ /* Mark that all members of the child task group has exit'ed */
+
+ child->ch_flags |= CHILD_FLAG_EXITED;
+ }
+ }
+}
+
+#else
+
+# define task_groupexit(group)
+
+#endif /* CONFIG_SCHED_CHILD_STATUS */
+
+/****************************************************************************
* Name: task_sigchild
*
* Description:
@@ -197,72 +269,96 @@ static inline void task_onexit(FAR _TCB *tcb, int status)
****************************************************************************/
#ifdef CONFIG_SCHED_HAVE_PARENT
-static inline void task_sigchild(FAR _TCB *tcb, int status)
+#ifdef HAVE_GROUP_MEMBERS
+static inline void task_sigchild(gid_t pgid, FAR _TCB *ctcb, int status)
{
- FAR _TCB *ptcb;
+ FAR struct task_group_s *chgrp = ctcb->group;
+ FAR struct task_group_s *pgrp;
siginfo_t info;
- /* Only exiting tasks should generate SIGCHLD. pthreads use other
- * mechansims.
+ DEBUGASSERT(chgrp);
+
+ /* Get the parent task group. It is possible that all of the members of
+ * the parent task group have exited. This would not be an error. In
+ * this case, the child task group has been orphaned.
*/
- if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_TASK)
+ pgrp = group_find(chgrp->tg_pgid);
+ if (!pgrp)
{
- /* Keep things stationary through the following */
+ /* Set the task group ID to an invalid group ID. The dead parent
+ * task group ID could get reused some time in the future.
+ */
- sched_lock();
+ chgrp->tg_pgid = INVALID_GROUP_ID;
+ return;
+ }
- /* Get the TCB of the receiving task */
+ /* Save the exit status now if this is the main thread of the task group
+ * that is exiting. Only the exiting main task of a task group carries
+ * interpretable exit Check if this is the main task that is exiting.
+ */
- ptcb = sched_gettcb(tcb->parent);
- if (!ptcb)
- {
- /* The parent no longer exists... bail */
+ if ((ctcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_TASK)
+ {
+ task_exitstatus(pgrp, status);
+ }
- sched_unlock();
- return;
- }
+ /* But only the final exiting thread in a task group, whatever it is,
+ * should generate SIGCHLD.
+ */
-#ifdef CONFIG_SCHED_CHILD_STATUS
- /* Check if the parent task has suppressed retention of child exit
- * status information. Only 'tasks' report exit status, not pthreads.
- * pthreads have a different mechanism.
+ if (chgrp->tg_nmembers == 1)
+ {
+ /* Mark that all of the threads in the task group have exited */
+
+ task_groupexit(pgrp);
+
+ /* Create the siginfo structure. We don't actually know the cause.
+ * That is a bug. Let's just say that the child task just exit-ted
+ * for now.
*/
- if ((ptcb->flags & TCB_FLAG_NOCLDWAIT) == 0)
- {
- FAR struct child_status_s *child;
+ info.si_signo = SIGCHLD;
+ info.si_code = CLD_EXITED;
+ info.si_value.sival_ptr = NULL;
+ info.si_pid = ctcb->pid;
+ info.si_status = status;
+
+ /* Send the signal. We need to use this internal interface so that we
+ * can provide the correct si_code value with the signal.
+ */
- /* No.. Find the exit status entry for this task in the parent TCB */
+ (void)group_signal(pgrp, &info);
+ }
+}
- child = task_findchild(ptcb, getpid());
- DEBUGASSERT(child);
- if (child)
- {
- /* Mark that the child has exit'ed */
+#else /* HAVE_GROUP_MEMBERS */
- child->ch_flags |= CHILD_FLAG_EXITED;
+static inline void task_sigchild(FAR _TCB *ptcb, FAR _TCB *ctcb, int status)
+{
+ siginfo_t info;
- /* Save the exit status */
+ /* If task groups are not supported then we will report SIGCHLD when the
+ * task exits. Unfortunately, there could still be threads in the group
+ * that are still running.
+ */
+
+ if ((ctcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_TASK)
+ {
+#ifdef CONFIG_SCHED_CHILD_STATUS
+ /* Save the exit status now of the main thread */
+
+ task_exitstatus(ptcb->group, status);
+
+#else /* CONFIG_SCHED_CHILD_STATUS */
- child->ch_status = status;
- }
- }
-#else
/* Decrement the number of children from this parent */
DEBUGASSERT(ptcb->nchildren > 0);
ptcb->nchildren--;
-#endif
- /* Set the parent to an impossible PID. We do this because under
- * certain conditions, task_exithook() can be called multiple times.
- * If this function is called again, sched_gettcb() will fail on the
- * invalid parent PID above, nchildren will be decremented once and
- * all will be well.
- */
-
- tcb->parent = INVALID_PROCESS_ID;
+#endif /* CONFIG_SCHED_CHILD_STATUS */
/* Create the siginfo structure. We don't actually know the cause.
* That is a bug. Let's just say that the child task just exit-ted
@@ -272,7 +368,7 @@ static inline void task_sigchild(FAR _TCB *tcb, int status)
info.si_signo = SIGCHLD;
info.si_code = CLD_EXITED;
info.si_value.sival_ptr = NULL;
- info.si_pid = tcb->pid;
+ info.si_pid = ctcb->pid;
info.si_status = status;
/* Send the signal. We need to use this internal interface so that we
@@ -280,11 +376,72 @@ static inline void task_sigchild(FAR _TCB *tcb, int status)
*/
(void)sig_received(ptcb, &info);
+ }
+}
+
+#endif /* HAVE_GROUP_MEMBERS */
+#else /* CONFIG_SCHED_HAVE_PARENT */
+
+# define task_sigchild(x,ctcb,status)
+
+#endif /* CONFIG_SCHED_HAVE_PARENT */
+
+/****************************************************************************
+ * Name: task_leavegroup
+ *
+ * Description:
+ * Send the SIGCHILD signal to the parent thread
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SCHED_HAVE_PARENT
+static inline void task_leavegroup(FAR _TCB *ctcb, int status)
+{
+#ifdef HAVE_GROUP_MEMBERS
+ DEBUGASSERT(ctcb && ctcb->group);
+
+ /* Keep things stationary throughout the following */
+
+ sched_lock();
+
+ /* Send SIGCHLD to all members of the parent's task group */
+
+ task_sigchild(ctcb->group->tg_pgid, ctcb, status);
+ sched_unlock();
+#else
+ FAR _TCB *ptcb;
+
+ /* Keep things stationary throughout the following */
+
+ sched_lock();
+
+ /* Get the TCB of the receiving, parent task. We do this early to
+ * handle multiple calls to task_leavegroup. ctcb->ppid is set to an
+ * invalid value below and the following call will fail if we are
+ * called again.
+ */
+
+ ptcb = sched_gettcb(ctcb->ppid);
+ if (!ptcb)
+ {
+ /* The parent no longer exists... bail */
+
sched_unlock();
+ return;
}
+
+ /* Send SIGCHLD to all members of the parent's task group */
+
+ task_sigchild(ptcb, ctcb, status);
+
+ /* Forget who our parent was */
+
+ ctcb->ppid = INVALID_PROCESS_ID;
+ sched_unlock();
+#endif
}
#else
-# define task_sigchild(tcb,status)
+# define task_leavegroup(ctcb,status)
#endif
/****************************************************************************
@@ -352,6 +509,16 @@ static inline void task_exitwakeup(FAR _TCB *tcb, int status)
void task_exithook(FAR _TCB *tcb, int status)
{
+ /* Under certain conditions, task_exithook() can be called multiple times.
+ * A bit in the TCB was set the first time this function was called. If
+ * that bit is set, then just ext doing nothing more..
+ */
+
+ if ((tcb->flags & TCB_FLAG_EXIT_PROCESSING) != 0)
+ {
+ return;
+ }
+
/* If exit function(s) were registered, call them now before we do any un-
* initialization. NOTE: In the case of task_delete(), the exit function
* will *not* be called on the thread execution of the task being deleted!
@@ -363,9 +530,9 @@ void task_exithook(FAR _TCB *tcb, int status)
task_onexit(tcb, status);
- /* Send SIGCHLD to the parent of the exit-ing task */
+ /* Leave the task group */
- task_sigchild(tcb, status);
+ task_leavegroup(tcb, status);
/* Wakeup any tasks waiting for this task to exit */
@@ -376,26 +543,27 @@ void task_exithook(FAR _TCB *tcb, int status)
*/
#if CONFIG_NFILE_STREAMS > 0
- (void)lib_flushall(tcb->streams);
+ (void)lib_flushall(&tcb->group->tg_streamlist);
#endif
- /* Discard any un-reaped child status (no zombies here!) */
+ /* Leave the task group. Perhaps discarding any un-reaped child
+ * status (no zombies here!)
+ */
-#if defined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS)
- task_removechildren(tcb);
+#ifdef HAVE_TASK_GROUP
+ group_leave(tcb);
#endif
- /* Free all file-related resources now. This gets called again
- * just be be certain when the TCB is delallocated. However, we
- * really need to close files as soon as possible while we still
- * have a functioning task.
- */
-
- (void)sched_releasefiles(tcb);
-
/* Deallocate anything left in the TCB's queues */
#ifndef CONFIG_DISABLE_SIGNALS
sig_cleanup(tcb); /* Deallocate Signal lists */
#endif
+
+ /* This function can be re-entered in certain cases. Set a flag
+ * bit in the TCB to not that we have already completed this exit
+ * processing.
+ */
+
+ tcb->flags |= TCB_FLAG_EXIT_PROCESSING;
}
diff --git a/nuttx/sched/task_init.c b/nuttx/sched/task_init.c
index 0f0fdc68e..78f35bc2a 100644
--- a/nuttx/sched/task_init.c
+++ b/nuttx/sched/task_init.c
@@ -1,7 +1,7 @@
/****************************************************************************
* sched/task_init.c
*
- * Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -42,10 +42,12 @@
#include <sys/types.h>
#include <stdint.h>
#include <sched.h>
+#include <errno.h>
+
#include <nuttx/arch.h>
#include "os_internal.h"
-#include "env_internal.h"
+#include "group_internal.h"
/****************************************************************************
* Definitions
@@ -102,10 +104,10 @@
* parameters are required, argv may be NULL.
*
* Return Value:
- * OK on success; ERROR on failure. (See task_schedsetup() for possible
- * failure conditions). On failure, the caller is responsible for freeing
- * the stack memory and for calling sched_releasetcb() to free the TCB
- * (which could be in most any state).
+ * OK on success; ERROR on failure with errno set appropriately. (See
+ * task_schedsetup() for possible failure conditions). On failure, the
+ * caller is responsible for freeing the stack memory and for calling
+ * sched_releasetcb() to free the TCB (which could be in most any state).
*
****************************************************************************/
@@ -118,20 +120,30 @@ int task_init(FAR _TCB *tcb, const char *name, int priority,
main_t entry, const char *argv[])
#endif
{
+ int errcode;
int ret;
- /* Associate file descriptors with the new task */
+ /* Create a new task group */
-#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0
- if (sched_setuptaskfiles(tcb) != OK)
+#ifdef HAVE_TASK_GROUP
+ ret = group_allocate(tcb);
+ if (ret < 0)
{
- return ERROR;
+ errcode = -ret;
+ goto errout;
}
#endif
- /* Clone the parent's task environment */
+ /* Associate file descriptors with the new task */
- (void)env_dup(tcb);
+#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0
+ ret = group_setuptaskfiles(tcb);
+ if (ret < 0)
+ {
+ errcode = -ret;
+ goto errout_with_group;
+ }
+#endif
/* Configure the user provided stack region */
@@ -143,13 +155,35 @@ int task_init(FAR _TCB *tcb, const char *name, int priority,
ret = task_schedsetup(tcb, priority, task_start, entry,
TCB_FLAG_TTYPE_TASK);
- if (ret == OK)
+ if (ret < OK)
{
- /* Setup to pass parameters to the new task */
+ errcode = -ret;
+ goto errout_with_group;
+ }
+
+ /* Setup to pass parameters to the new task */
+
+ (void)task_argsetup(tcb, name, argv);
+
+ /* Now we have enough in place that we can join the group */
- (void)task_argsetup(tcb, name, argv);
+#ifdef HAVE_TASK_GROUP
+ ret = group_initialize(tcb);
+ if (ret < 0)
+ {
+ errcode = -ret;
+ goto errout_with_group;
}
+#endif
+ return OK;
- return ret;
+errout_with_group:
+#ifdef HAVE_TASK_GROUP
+ group_leave(tcb);
+
+errout:
+#endif
+ set_errno(errcode);
+ return ERROR;
}
diff --git a/nuttx/sched/task_posixspawn.c b/nuttx/sched/task_posixspawn.c
index 7bb9c9a4d..e9ad1fc45 100644
--- a/nuttx/sched/task_posixspawn.c
+++ b/nuttx/sched/task_posixspawn.c
@@ -54,6 +54,7 @@
#include <nuttx/spawn.h>
#include "os_internal.h"
+#include "group_internal.h"
/****************************************************************************
* Private Types
diff --git a/nuttx/sched/task_reparent.c b/nuttx/sched/task_reparent.c
index 28d371bf1..5bb62893f 100644
--- a/nuttx/sched/task_reparent.c
+++ b/nuttx/sched/task_reparent.c
@@ -42,6 +42,7 @@
#include <errno.h>
#include "os_internal.h"
+#include "group_internal.h"
#ifdef CONFIG_SCHED_HAVE_PARENT
@@ -69,6 +70,141 @@
*
*****************************************************************************/
+#ifdef HAVE_GROUP_MEMBERS
+int task_reparent(pid_t ppid, pid_t chpid)
+{
+#ifdef CONFIG_SCHED_CHILD_STATUS
+ FAR struct child_status_s *child;
+#endif
+ FAR struct task_group_s *chgrp;
+ FAR struct task_group_s *ogrp;
+ FAR struct task_group_s *pgrp;
+ _TCB *tcb;
+ gid_t ogid;
+ gid_t pgid;
+ irqstate_t flags;
+ int ret;
+
+ /* Disable interrupts so that nothing can change in the relatinoship of
+ * the three task: Child, current parent, and new parent.
+ */
+
+ flags = irqsave();
+
+ /* Get the child tasks task group */
+
+ tcb = sched_gettcb(chpid);
+ if (!tcb)
+ {
+ ret = -ECHILD;
+ goto errout_with_ints;
+ }
+
+ DEBUGASSERT(tcb->group);
+ chgrp = tcb->group;
+
+ /* Get the GID of the old parent task's task group (ogid) */
+
+ ogid = chgrp->tg_pgid;
+
+ /* Get the old parent task's task group (ogrp) */
+
+ ogrp = group_find(ogid);
+ if (!ogrp)
+ {
+ ret = -ESRCH;
+ goto errout_with_ints;
+ }
+
+ /* If new parent task's PID (ppid) is zero, then new parent is the
+ * grandparent will be the new parent, i.e., the parent of the current
+ * parent task.
+ */
+
+ if (ppid == 0)
+ {
+ /* Get the grandparent task's task group (pgrp) */
+
+ pgid = ogrp->tg_pgid;
+ pgrp = group_find(pgid);
+ }
+ else
+ {
+ /* Get the new parent task's task group (pgrp) */
+
+ tcb = sched_gettcb(ppid);
+ if (!tcb)
+ {
+ ret = -ESRCH;
+ goto errout_with_ints;
+ }
+
+ pgrp = tcb->group;
+ pgid = pgrp->tg_gid;
+ }
+
+ if (!pgrp)
+ {
+ ret = -ESRCH;
+ goto errout_with_ints;
+ }
+
+ /* Then reparent the child. Notice that we don't actually change the
+ * parent of the task. Rather, we change the parent task group for
+ * all members of the child's task group.
+ */
+
+ chgrp->tg_pgid = pgid;
+
+#ifdef CONFIG_SCHED_CHILD_STATUS
+ /* Remove the child status entry from old parent task group */
+
+ child = group_removechild(ogrp, chpid);
+ if (child)
+ {
+ /* Has the new parent's task group supressed child exit status? */
+
+ if ((pgrp->tg_flags && GROUP_FLAG_NOCLDWAIT) == 0)
+ {
+ /* No.. Add the child status entry to the new parent's task group */
+
+ group_addchild(pgrp, child);
+ }
+ else
+ {
+ /* Yes.. Discard the child status entry */
+
+ group_freechild(child);
+ }
+
+ /* Either case is a success */
+
+ ret = OK;
+ }
+ else
+ {
+ /* This would not be an error if the original parent's task group has
+ * suppressed child exit status.
+ */
+
+ ret = ((ogrp->tg_flags && GROUP_FLAG_NOCLDWAIT) == 0) ? -ENOENT : OK;
+ }
+
+#else /* CONFIG_SCHED_CHILD_STATUS */
+
+ DEBUGASSERT(otcb->nchildren > 0);
+
+ otcb->nchildren--; /* The orignal parent now has one few children */
+ ptcb->nchildren++; /* The new parent has one additional child */
+ ret = OK;
+
+#endif /* CONFIG_SCHED_CHILD_STATUS */
+
+errout_with_ints:
+ irqrestore(flags);
+ return ret;
+}
+#else
int task_reparent(pid_t ppid, pid_t chpid)
{
#ifdef CONFIG_SCHED_CHILD_STATUS
@@ -98,7 +234,7 @@ int task_reparent(pid_t ppid, pid_t chpid)
/* Get the PID of the child task's parent (opid) */
- opid = chtcb->parent;
+ opid = chtcb->ppid;
/* Get the TCB of the child task's parent (otcb) */
@@ -116,7 +252,7 @@ int task_reparent(pid_t ppid, pid_t chpid)
if (ppid == 0)
{
- ppid = otcb->parent;
+ ppid = otcb->ppid;
}
/* Get the new parent task's TCB (ptcb) */
@@ -130,34 +266,55 @@ int task_reparent(pid_t ppid, pid_t chpid)
/* Then reparent the child */
- chtcb->parent = ppid; /* The task specified by ppid is the new parent */
+ chtcb->ppid = ppid; /* The task specified by ppid is the new parent */
#ifdef CONFIG_SCHED_CHILD_STATUS
/* Remove the child status entry from old parent TCB */
- child = task_removechild(otcb, chpid);
+ child = group_removechild(otcb->group, chpid);
if (child)
{
- /* Add the child status entry to the new parent TCB */
+ /* Has the new parent's task group supressed child exit status? */
+
+ if ((ptcb->group->tg_flags && GROUP_FLAG_NOCLDWAIT) == 0)
+ {
+ /* No.. Add the child status entry to the new parent's task group */
+
+ group_addchild(ptcb->group, child);
+ }
+ else
+ {
+ /* Yes.. Discard the child status entry */
+
+ group_freechild(child);
+ }
+
+ /* Either case is a success */
- task_addchild(ptcb, child);
ret = OK;
}
else
{
- ret = -ENOENT;
+ /* This would not be an error if the original parent's task group has
+ * suppressed child exit status.
+ */
+
+ ret = ((otcb->group->tg_flags && GROUP_FLAG_NOCLDWAIT) == 0) ? -ENOENT : OK;
}
-#else
+
+#else /* CONFIG_SCHED_CHILD_STATUS */
+
DEBUGASSERT(otcb->nchildren > 0);
otcb->nchildren--; /* The orignal parent now has one few children */
ptcb->nchildren++; /* The new parent has one additional child */
ret = OK;
-#endif
+
+#endif /* CONFIG_SCHED_CHILD_STATUS */
errout_with_ints:
irqrestore(flags);
return ret;
}
-
+#endif
#endif /* CONFIG_SCHED_HAVE_PARENT */
diff --git a/nuttx/sched/task_setup.c b/nuttx/sched/task_setup.c
index 43ed24b32..b770d46e6 100644
--- a/nuttx/sched/task_setup.c
+++ b/nuttx/sched/task_setup.c
@@ -1,7 +1,7 @@
/****************************************************************************
* sched/task_setup.c
*
- * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -49,6 +49,7 @@
#include <nuttx/arch.h>
#include "os_internal.h"
+#include "group_internal.h"
/****************************************************************************
* Definitions
@@ -150,7 +151,8 @@ static int task_assignpid(FAR _TCB *tcb)
* Name: task_saveparent
*
* Description:
- * Save the task ID of the parent task in the child task's TCB.
+ * Save the task ID of the parent task in the child task's TCB and allocate
+ * a child status structure to catch the child task's exit status.
*
* Parameters:
* tcb - The TCB of the new, child task.
@@ -170,31 +172,57 @@ static inline void task_saveparent(FAR _TCB *tcb, uint8_t ttype)
{
FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head;
+#if defined(HAVE_GROUP_MEMBERS) || defined(CONFIG_SCHED_CHILD_STATUS)
+ DEBUGASSERT(tcb && tcb->group && rtcb->group);
+#else
+#endif
+
+#ifdef HAVE_GROUP_MEMBERS
+ /* Save the ID of the parent tasks' task group in the child's task group.
+ * Do nothing for pthreads. The parent and the child are both members of
+ * the same task group.
+ */
+
+ if ((tcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_PTHREAD)
+ {
+ /* This is a new task in a new task group, we have to copy the ID from
+ * the parent's task group structure to child's task group.
+ */
+
+ tcb->group->tg_pgid = rtcb->group->tg_gid;
+ }
+
+#else
+ DEBUGASSERT(tcb);
+
/* Save the parent task's ID in the child task's TCB. I am not sure if
* this makes sense for the case of pthreads or not, but I don't think it
* is harmful in any event.
*/
- tcb->parent = rtcb->pid;
+ tcb->ppid = rtcb->pid;
+#endif
- /* Exit status only needs to be retained for the case of tasks, however */
+#ifdef CONFIG_SCHED_CHILD_STATUS
+ /* Tasks can also suppress retention of their child status by applying
+ * the SA_NOCLDWAIT flag with sigaction().
+ */
- if (ttype == TCB_FLAG_TTYPE_TASK)
+ if ((rtcb->group->tg_flags && GROUP_FLAG_NOCLDWAIT) == 0)
{
-#ifdef CONFIG_SCHED_CHILD_STATUS
FAR struct child_status_s *child;
/* Make sure that there is not already a structure for this PID in the
* parent TCB. There should not be.
*/
- child = task_findchild(rtcb, tcb->pid);
+ child = group_findchild(rtcb->group, tcb->pid);
DEBUGASSERT(!child);
if (!child)
{
/* Allocate a new status structure */
- child = task_allocchild();
+ child = group_allocchild();
}
/* Did we successfully find/allocate the child status structure? */
@@ -210,16 +238,16 @@ static inline void task_saveparent(FAR _TCB *tcb, uint8_t ttype)
/* Add the entry into the TCB list of children */
- task_addchild(rtcb, child);
+ group_addchild(rtcb->group, child);
}
+ }
#else
- DEBUGASSERT(rtcb->nchildren < UINT16_MAX);
- rtcb->nchildren++;
+ DEBUGASSERT(rtcb->nchildren < UINT16_MAX);
+ rtcb->nchildren++;
#endif
- }
}
#else
-# define task_saveparent(tcb, type)
+# define task_saveparent(tcb,ttype)
#endif
/****************************************************************************
@@ -318,7 +346,9 @@ int task_schedsetup(FAR _TCB *tcb, int priority, start_t start, main_t main,
tcb->flags &= ~TCB_FLAG_TTYPE_MASK;
tcb->flags |= ttype;
- /* Save the task ID of the parent task in the TCB */
+ /* Save the task ID of the parent task in the TCB and allocate
+ * a child status structure.
+ */
task_saveparent(tcb, ttype);
diff --git a/nuttx/sched/task_start.c b/nuttx/sched/task_start.c
index a9cc38dfc..5a32a5dd8 100644
--- a/nuttx/sched/task_start.c
+++ b/nuttx/sched/task_start.c
@@ -94,6 +94,15 @@ void task_start(void)
FAR _TCB *tcb = (FAR _TCB*)g_readytorun.head;
int argc;
+ /* Execute the start hook if one has been registered */
+
+#ifdef CONFIG_SCHED_STARTHOOK
+ if (tcb->starthook)
+ {
+ tcb->starthook(tcb->starthookarg);
+ }
+#endif
+
/* Count how many non-null arguments we are passing */
for (argc = 1; argc <= CONFIG_MAX_TASK_ARGS; argc++)
diff --git a/nuttx/sched/sched_releasefiles.c b/nuttx/sched/task_starthook.c
index a3ef71af4..1cb29349f 100644
--- a/nuttx/sched/sched_releasefiles.c
+++ b/nuttx/sched/task_starthook.c
@@ -1,7 +1,7 @@
/****************************************************************************
- * sched/sched_releasefiles.c
+ * sched/task_start.c
*
- * Copyright (C) 2007, 2008, 2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2010 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -39,12 +39,29 @@
#include <nuttx/config.h>
-#include <sched.h>
-#include <nuttx/fs/fs.h>
-#include <nuttx/net/net.h>
-#include <nuttx/lib.h>
+#include <nuttx/sched.h>
-#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0
+#ifdef CONFIG_SCHED_STARTHOOK
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Type Declarations
+ ****************************************************************************/
+
+/****************************************************************************
+ * Global Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
/****************************************************************************
* Private Functions
@@ -55,60 +72,29 @@
****************************************************************************/
/****************************************************************************
- * Name: sched_releasefiles
+ * Name: task_starthook
*
* Description:
- * Release file resources attached to a TCB. This file may be called
- * multiple times as a task exists. It will be called as early as possible
- * to support proper closing of complex drivers that may need to wait
- * on external events.
+ * Configure a start hook... a function that will be called on the thread
+ * of the new task before the new task's main entry point is called.
+ * The start hook is useful, for example, for setting up automatic
+ * configuration of C++ constructors.
*
- * Parameters:
- * tcb - tcb of the new task.
+ * Inputs:
+ * tcb - The new, unstarted task task that needs the start hook
+ * starthook - The pointer to the start hook function
+ * arg - The argument to pass to the start hook function.
*
- * Return Value:
+ * Return:
* None
*
- * Assumptions:
- *
****************************************************************************/
-int sched_releasefiles(_TCB *tcb)
+void task_starthook(FAR _TCB *tcb, starthook_t starthook, FAR void *arg)
{
- if (tcb)
- {
-#if CONFIG_NFILE_DESCRIPTORS > 0
- /* Free the file descriptor list */
-
- if (tcb->filelist)
- {
- files_releaselist(tcb->filelist);
- tcb->filelist = NULL;
- }
-
-#if CONFIG_NFILE_STREAMS > 0
- /* Free the stream list */
-
- if (tcb->streams)
- {
- lib_releaselist(tcb->streams);
- tcb->streams = NULL;
- }
-#endif /* CONFIG_NFILE_STREAMS */
-#endif /* CONFIG_NFILE_DESCRIPTORS */
-
-#if CONFIG_NSOCKET_DESCRIPTORS > 0
- /* Free the file descriptor list */
-
- if (tcb->sockets)
- {
- net_releaselist(tcb->sockets);
- tcb->sockets = NULL;
- }
-#endif /* CONFIG_NSOCKET_DESCRIPTORS */
- }
-
- return OK;
+ DEBUGASSERT(tcb);
+ tcb->starthook = starthook;
+ tcb->starthookarg = arg;
}
-#endif /* CONFIG_NFILE_DESCRIPTORS || CONFIG_NSOCKET_DESCRIPTORS */
+#endif /* CONFIG_SCHED_STARTHOOK */
diff --git a/nuttx/sched/task_vfork.c b/nuttx/sched/task_vfork.c
index fece4c596..ac86ddc56 100644
--- a/nuttx/sched/task_vfork.c
+++ b/nuttx/sched/task_vfork.c
@@ -39,6 +39,7 @@
#include <nuttx/config.h>
+#include <sys/wait.h>
#include <stdint.h>
#include <assert.h>
#include <queue.h>
@@ -48,7 +49,7 @@
#include <nuttx/sched.h>
#include "os_internal.h"
-#include "env_internal.h"
+#include "group_internal.h"
/****************************************************************************
* Pre-processor Definitions
@@ -125,17 +126,13 @@ FAR _TCB *task_vforksetup(start_t retaddr)
/* Associate file descriptors with the new task */
#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0
- ret = sched_setuptaskfiles(child);
+ ret = group_setuptaskfiles(child);
if (ret != OK)
{
goto errout_with_tcb;
}
#endif
- /* Clone the parent's task environment */
-
- (void)env_dup(child);
-
/* Get the priority of the parent task */
#ifdef CONFIG_PRIORITY_INHERITANCE
diff --git a/nuttx/sched/timer_initialize.c b/nuttx/sched/timer_initialize.c
index 05980bb1a..2651469ef 100644
--- a/nuttx/sched/timer_initialize.c
+++ b/nuttx/sched/timer_initialize.c
@@ -137,7 +137,7 @@ void weak_function timer_initialize(void)
* resources are referenced.
*
* Parameters:
- * pid - the task ID of the thread that exitted
+ * pid - the task ID of the thread that exited
*
* Return Value:
* None
diff --git a/nuttx/tools/mkconfig.c b/nuttx/tools/mkconfig.c
index d8d09df34..a622743a0 100644
--- a/nuttx/tools/mkconfig.c
+++ b/nuttx/tools/mkconfig.c
@@ -126,17 +126,23 @@ int main(int argc, char **argv, char **envp)
printf("#ifndef CONFIG_RR_INTERVAL\n");
printf("# define CONFIG_RR_INTERVAL 0\n");
printf("#endif\n\n");
- printf("/* The correct way to disable filesystem supuport is to set the\n");
- printf(" * number of file descriptors to zero.\n");
+ printf("/* The correct way to disable filesystem supuport is to set the number of\n");
+ printf(" * file descriptors to zero.\n");
printf(" */\n\n");
printf("#ifndef CONFIG_NFILE_DESCRIPTORS\n");
printf("# define CONFIG_NFILE_DESCRIPTORS 0\n");
printf("#endif\n\n");
- printf("/* If a console is selected, then make sure that there are\n");
- printf(" * resources for 3 file descriptors and, if any streams are\n");
- printf(" * selected, also for 3 file streams.\n");
+ printf("/* If a console is selected, then make sure that there are resources for\n");
+ printf(" * three file descriptors and, if any streams are selected, also for three\n");
+ printf(" * file streams.\n");
+ printf(" *\n");
+ printf(" * CONFIG_DEV_CONSOLE means that a builtin console device exists at /dev/console\n");
+ printf(" * and can be opened during boot-up. Other consoles, such as USB consoles, may\n");
+ printf(" * not exist at boot-upand have to be handled in a different way. Three file\n");
+ printf(" * descriptors and three file streams are still needed.\n");
printf(" */\n\n");
- printf("#ifdef CONFIG_DEV_CONSOLE\n");
+ printf("#if defined(CONFIG_DEV_CONSOLE) || defined(CONFIG_CDCACM_CONSOLE) || \\\n");
+ printf(" defined(CONFIG_PL2303_CONSOLE)\n");
printf("# if CONFIG_NFILE_DESCRIPTORS < 3\n");
printf("# undef CONFIG_NFILE_DESCRIPTORS\n");
printf("# define CONFIG_NFILE_DESCRIPTORS 3\n");
@@ -145,12 +151,10 @@ int main(int argc, char **argv, char **envp)
printf("# undef CONFIG_NFILE_STREAMS\n");
printf("# define CONFIG_NFILE_STREAMS 3\n");
printf("# endif\n\n");
- printf("/* If no console is selected, then disable all console devices */\n\n");
+ printf("/* If no console is selected, then disable all builtin console devices */\n\n");
printf("#else\n");
printf("# undef CONFIG_DEV_LOWCONSOLE\n");
printf("# undef CONFIG_RAMLOG_CONSOLE\n");
- printf("# undef CONFIG_CDCACM_CONSOLE\n");
- printf("# undef CONFIG_PL2303_CONSOLE\n");
printf("#endif\n\n");
printf("/* If priority inheritance is disabled, then do not allocate any\n");
printf(" * associated resources.\n");