diff --git a/arch/c5471/src/up_exit.c b/arch/c5471/src/up_exit.c index 8e211e0c2e..606ea097b5 100644 --- a/arch/c5471/src/up_exit.c +++ b/arch/c5471/src/up_exit.c @@ -45,6 +45,10 @@ #include "os_internal.h" #include "up_internal.h" +#ifdef CONFIG_DUMP_ON_EXIT +#include +#endif + /************************************************************ * Private Definitions ************************************************************/ @@ -57,6 +61,57 @@ * Private Funtions ************************************************************/ +/************************************************************ + * Name: _up_dumponexit + * + * Description: + * Dump the state of all tasks whenever on task exits. This + * is debug instrumentation that was added to check file- + * related reference counting but could be useful again + * sometime in the future. + * + ************************************************************/ + +#if defined(CONFIG_DUMP_ON_EXIT) && defined(CONFIG_DEBUG) +static void _up_dumponexit(FAR _TCB *tcb, FAR void *arg) +{ + int i; + dbg(" TCB=%p name=%s\n", tcb, tcb->name); + if (tcb->filelist) + { + dbg(" filelist refcount=%d\n", + tcb->filelist->fl_crefs); + + for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++) + { + struct inode *inode = tcb->filelist->fl_files[i].f_inode; + if (inode) + { + dbg(" fd=%d refcount=%d\n", + i, inode->i_crefs); + } + } + } + + if (tcb->streams) + { + dbg(" streamlist refcount=%d\n", + tcb->streams->sl_crefs); + + for (i = 0; i < CONFIG_NFILE_STREAMS; i++) + { + struct file_struct *filep = &tcb->streams->sl_streams[i]; + if (filep->fs_filedes >= 0) + { + dbg(" fd=%d nbytes=%d\n", + filep->fs_filedes, + filep->fs_bufpos - filep->fs_bufstart); + } + } + } +} +#endif + /************************************************************ * Public Funtions ************************************************************/ @@ -76,6 +131,11 @@ void _exit(int status) dbg("TCB=%p exitting\n", tcb); +#if defined(CONFIG_DUMP_ON_EXIT) && defined(CONFIG_DEBUG) + dbg("Other tasks:\n"); + sched_foreach(_up_dumponexit, NULL); +#endif + /* Remove the tcb task from the ready-to-run list. We can * ignore the return value because we know that a context * switch is needed. diff --git a/arch/c5471/src/up_internal.h b/arch/c5471/src/up_internal.h index ef08d36a7f..6f6f82c835 100644 --- a/arch/c5471/src/up_internal.h +++ b/arch/c5471/src/up_internal.h @@ -53,6 +53,7 @@ #undef CONFIG_SUPPRESS_TIMER_INTS /* No timer */ #define CONFIG_SUPPRESS_SERIAL_INTS 1 /* Console will poll */ #undef CONFIG_SUPPRESS_UART_CONFIG /* Do not reconfig UART */ +#undef CONFIG_DUMP_ON_EXIT /* Dumpt task state on exit */ /* LED definitions */ diff --git a/include/sched.h b/include/sched.h index 0cf8d58d55..12cc290467 100644 --- a/include/sched.h +++ b/include/sched.h @@ -254,6 +254,11 @@ struct _TCB }; typedef struct _TCB _TCB; + +/* This is the callback type used by sched_foreach() */ + +typedef void (sched_foreach_t)(FAR _TCB *tcb, FAR void *arg); + #endif /* __ASSEMBLY__ */ /************************************************************ @@ -341,6 +346,13 @@ EXTERN FAR struct streamlist *sched_getstreams(void); #endif /* CONFIG_NFILE_STREAMS */ #endif /* CONFIG_NFILE_DESCRIPTORS */ +/* sched_foreach will enumerate over each task and provide the + * TCB of each task to a user callback functions. Interrupts + * will be disabled throughout this enumeration! + */ + +EXTERN void sched_foreach(sched_foreach_t handler, FAR void *arg); + #undef EXTERN #if defined(__cplusplus) } diff --git a/include/stdio.h b/include/stdio.h index 8b9a7e28e4..f234a861c2 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -131,6 +131,7 @@ struct _dirent { FAR char *d_name; /* name of directory entry */ }; + struct dirent { FAR char *d_name; /* A pointer to d_szname */ diff --git a/lib/lib_fflush.c b/lib/lib_fflush.c index d0f74bd2b1..e7f4e69609 100644 --- a/lib/lib_fflush.c +++ b/lib/lib_fflush.c @@ -91,6 +91,7 @@ void lib_flushall(FAR struct streamlist *list) { /* Make sure that there are streams associated with this thread */ + if (list) { int i; @@ -131,6 +132,10 @@ int fflush(FILE *stream) return ERROR; } + /* Make sure that we have exclusive access to the stream */ + + lib_take_semaphore(stream); + /* How many bytes are used in the buffer now */ nbuffer = stream->fs_bufpos - stream->fs_bufstart; @@ -141,6 +146,7 @@ int fflush(FILE *stream) bytes_written = write(stream->fs_filedes, src, nbuffer); if (bytes_written < 0) { + lib_give_semaphore(stream); return bytes_written; } @@ -166,6 +172,7 @@ int fflush(FILE *stream) /* Return the number of bytes remaining in the buffer */ + lib_give_semaphore(stream); return stream->fs_bufpos - stream->fs_bufstart; #else return 0; diff --git a/lib/lib_init.c b/lib/lib_init.c index 90ccc358b8..d6eb5f0a48 100644 --- a/lib/lib_init.c +++ b/lib/lib_init.c @@ -166,7 +166,7 @@ void lib_releaselist(FAR struct streamlist *list) /* Decrement the reference count */ _lib_semtake(list); - crefs = --list->sl_crefs; + crefs = --(list->sl_crefs); _lib_semgive(list); /* If the count decrements to zero, then there is no reference diff --git a/sched/Makefile b/sched/Makefile index d110cb664a..375cb6a3d6 100644 --- a/sched/Makefile +++ b/sched/Makefile @@ -51,7 +51,7 @@ TSK_SRCS = task_create.c task_init.c task_delete.c task_restart.c \ sched_free.c sched_gettcb.c sched_releasetcb.c SCHED_SRCS = sched_setparam.c sched_getparam.c \ sched_setscheduler.c sched_getscheduler.c \ - sched_yield.c sched_rrgetinterval.c \ + sched_yield.c sched_rrgetinterval.c sched_foreach.c \ sched_getprioritymax.c sched_getprioritymin.c \ sched_lock.c sched_unlock.c sched_lockcount.c WDOG_SRCS = wd_initialize.c wd_create.c wd_start.c wd_cancel.c wd_delete.c diff --git a/sched/pthread_exit.c b/sched/pthread_exit.c index cd0833ba62..087076ac3d 100644 --- a/sched/pthread_exit.c +++ b/sched/pthread_exit.c @@ -112,7 +112,7 @@ void pthread_exit(FAR void *exit_value) } /* Then just exit, retaining all file descriptors and without - * calling atexit() funcitons. + * calling atexit() functions. */ _exit(error_code); diff --git a/sched/sched_foreach.c b/sched/sched_foreach.c new file mode 100644 index 0000000000..f1c1dc05c0 --- /dev/null +++ b/sched/sched_foreach.c @@ -0,0 +1,84 @@ +/************************************************************ + * sched_foreach.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name Gregory Nutt nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************/ + +/************************************************************ + * Included Files + ************************************************************/ + +#include +#include "os_internal.h" + +/************************************************************ + * Global Functions + ************************************************************/ + +/************************************************************ + * Function: sched_foreach + * + * Description: + * Enumerate over each task and provide the TCB of each + * task to a user callback functions. Interrupts will be + * disabled throughout this enumeration! + * + * Parameters: + * handler - The function to be called with the TCB of + * each task + * + * Return Value: + * None + * + * Assumptions: + * + ************************************************************/ + +void sched_foreach(sched_foreach_t handler, FAR void *arg) +{ + FAR _TCB *tcb; + irqstate_t flags = irqsave(); + int ndx; + + /* Verify that the PID is within range */ + + for (ndx = 0; ndx < CONFIG_MAX_TASKS; ndx++) + { + if (g_pidhash[ndx].tcb) + { + handler(g_pidhash[ndx].tcb, arg); + } + } + irqrestore(flags); +} + +