summaryrefslogtreecommitdiffstats
path: root/cpukit/libcsupport/src/newlibc_exit.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/libcsupport/src/newlibc_exit.c')
-rw-r--r--cpukit/libcsupport/src/newlibc_exit.c160
1 files changed, 160 insertions, 0 deletions
diff --git a/cpukit/libcsupport/src/newlibc_exit.c b/cpukit/libcsupport/src/newlibc_exit.c
new file mode 100644
index 0000000000..818ba884f4
--- /dev/null
+++ b/cpukit/libcsupport/src/newlibc_exit.c
@@ -0,0 +1,160 @@
+/*
+ * Implementation of hooks for the CYGNUS newlib libc
+ * These hooks set things up so that:
+ * + '_REENT' is switched at task switch time.
+ *
+ * COPYRIGHT (c) 1994 by Division Incorporated
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+
+#if defined(RTEMS_NEWLIB)
+#include <rtems/libcsupport.h>
+
+/* Since we compile with strict ANSI we need to undef it to get
+ * prototypes for extensions
+ */
+#undef __STRICT_ANSI__
+
+#include <stdlib.h> /* for free() */
+#include <string.h> /* for memset() */
+
+#include <sys/reent.h> /* for extern of _REENT (aka _impure_ptr) */
+#include <errno.h>
+
+#include <stdio.h>
+
+int _fwalk(struct _reent *ptr, int (*function) (FILE *) );
+
+/* do we think we are reentrant? */
+extern int libc_reentrant;
+extern struct _reent * const _global_impure_ptr __ATTRIBUTE_IMPURE_PTR__;
+
+/*
+ * CYGNUS newlib routine that does atexit() processing and flushes
+ * stdio streams
+ * undocumented
+ */
+
+extern void _wrapup_reent(struct _reent *);
+extern void _reclaim_reent(struct _reent *);
+
+void libc_wrapup(void)
+{
+ /*
+ * In case RTEMS is already down, don't do this. It could be
+ * dangerous.
+ */
+
+ if (!_System_state_Is_up(_System_state_Get()))
+ return;
+
+ /*
+ * This was already done if the user called exit() directly .
+ _wrapup_reent(0);
+ */
+
+ if (_REENT != _global_impure_ptr) {
+ _wrapup_reent(_global_impure_ptr);
+#if 0
+ /* Don't reclaim this one, just in case we do printfs
+ * on the way out to ROM.
+ */
+ _reclaim_reent(&libc_global_reent);
+#endif
+ _REENT = _global_impure_ptr;
+ }
+
+ /*
+ * Try to drain output buffers.
+ *
+ * Should this be changed to do *all* file streams?
+ * _fwalk (_REENT, fclose);
+ */
+
+ fclose (stdin);
+ fclose (stdout);
+ fclose (stderr);
+}
+
+/*
+ * Function: _exit
+ * Created: 94/12/10
+ *
+ * Description:
+ * Called from exit() after it does atexit() processing and stdio fflush's
+ *
+ * called from bottom of exit() to really delete the task.
+ * If we are using reentrant libc, then let the delete extension
+ * do all the work, otherwise if a shutdown is in progress,
+ * then just do it.
+ *
+ * Parameters:
+ * exit status
+ *
+ * Returns:
+ * does not return
+ *
+ * Side Effects:
+ *
+ * Notes:
+ *
+ *
+ * Deficiencies/ToDo:
+ *
+ *
+ */
+
+#include <unistd.h>
+
+/* FIXME: These defines are a blatant hack */
+ #define EXIT_SYMBOL _exit
+
+ #if defined(__AVR__)
+ #undef __USE_INIT_FINI__
+ #endif
+ #if defined(__USE_INIT_FINI__)
+ #if defined(__m32r__)
+ #define FINI_SYMBOL __fini
+ #else
+ #define FINI_SYMBOL _fini
+ #endif
+
+ extern void FINI_SYMBOL( void );
+ #endif
+
+void EXIT_SYMBOL(int status)
+{
+ /*
+ * If the toolset uses init/fini sections, then we need to
+ * run the global destructors now.
+ */
+ #if defined(__USE_INIT_FINI__)
+ FINI_SYMBOL();
+ #endif
+
+ /*
+ * We need to do the exit processing on the global reentrancy structure.
+ * This has already been done on the per task reentrancy structure
+ * associated with this task.
+ */
+
+ libc_wrapup();
+ rtems_shutdown_executive(status);
+ for (;;) ; /* to avoid warnings */
+}
+
+
+#endif