1 /*
2  * modified by Nintendo, NOTE this code is built into coreinit.rpl
3  * this copy is just for reference.
4  */
5 /*
6 		    Language Independent Library
7 
8 	    Copyright 1983-2008 Green Hills Software,Inc.
9 
10  *  This program is the property of Green Hills Software, Inc,
11  *  its contents are proprietary information and no part of it
12  *  is to be disclosed to anyone except employees of Green Hills
13  *  Software, Inc., or as agreed in writing signed by the President
14  *  of Green Hills Software, Inc.
15 */
16 /* ind_exit.c: low-level startup & shutdown. Machine Independent. */
17 
18 /* please examine ind_io.c for an overview of this file's contents */
19 
20 #if defined(EMBEDDED)
21 
22 #include "indos.h"
23 #include "ind_exit.h"
24 #include "ind_thrd.h"
25 #if 1 // CAFE MOD
26 #include <ppc_ghs.h>
27 #include <cafe/os.h>
28 #endif // CAFE MOD
29 
30 #pragma weak __cpp_exception_cleanup
31 extern void __cpp_exception_cleanup(void **);
32 #pragma weak __ghs_cpp_exception_cleanup
33 extern void __ghs_cpp_exception_cleanup(void);
34 
35 /*============================================================================*/
36 /*   FUNCTIONS ALWAYS NEEDED TO RUN PROGRAMS COMPILED WITH THE DEFAULT CRT0   */
37 /*============================================================================*/
38 /*	_exit()		terminate the program				      */
39 /*	__ghs_at_exit()	arrange for a function to be invoked at exit() time   */
40 /*============================================================================*/
41 
42 static struct __GHS_AT_EXIT *exitlisthead;
43 
44 /******************************************************************************/
45 /*  void _exit (code);							      */
46 /*  Exit from the program with a status code specified by code.		      */
47 /*  DO NOT RETURN!							      */
48 /*									      */
49 /*  This function is called by exit() after the libraries have shut down,     */
50 /*  and also by ind_crt0.c in the event that the program's main() returns.    */
51 /******************************************************************************/
52 #if defined(__scllc_asm)
53 /* StarCore LLC assembler doesn't support "set __exit,__Exit" */
54 #pragma asm
55 	section .text
56 	global	__exit
57 __exit	type	func
58 	endsec
59 #pragma endasm
60 #else
61 #pragma weak _exit = _Exit
62 #endif
63 
64 #if 1 // CAFE MOD
65 typedef void (*vfpt)();
66 extern vfpt _ctors[];
67 
68 #pragma weak __cpp_exception_cleanup
69 void __cpp_exception_cleanup(void **);
70 
71 void (*__atexit_cleanup)(int);
72 void (*__stdio_cleanup)(void);
73 
74 #pragma weak __ghs_at_exit_cleanup
75 void __ghs_at_exit_cleanup(void);
76 
exit(int status)77 void exit(int status)
78 {
79     // run the explicit  atexit list here NOTE: RPX DTORS are
80     // called in this list before any other DTORS are called
81 #ifdef _DEBUG
82     OSReportVerbose("ATEXIT: RPX (calls RPX DTORs)\n");
83 #endif
84 	if (__atexit_cleanup) {
85 		__atexit_cleanup(status);
86 	}
87 
88     // don't call DTORs here coreinit.rpl is not allowed to have DTORs
89     // note does not work as __call_dtors() is a C++ function...
90 	// __call_dtors();
91 
92 	if (__stdio_cleanup) {
93 		__stdio_cleanup();
94 	}
95 
96 	_Exit(status);
97 }
98 
99 extern void __PPCExit(int result);
100 
__ghs_at_exit_cleanup(void)101 void __ghs_at_exit_cleanup(void)
102 {
103     struct __GHS_AT_EXIT *el;
104 
105     for (el = exitlisthead; el; el = el->next)
106     	el->func();
107 }
108 
_Exit(int code)109 void _Exit (int code)
110 {
111     __ghs_at_exit_cleanup();
112 
113     /* do we really need to do this?
114      * or can we just exit?
115      */
116     if (__cpp_exception_cleanup) {
117         OSThread *pThread = OSGetCurrentThread();
118         if (pThread)
119             __cpp_exception_cleanup(&pThread->crt.__eh_globals);
120     }
121 
122    __PPCExit(code);
123 
124 	/* If we get here, __PPCExit didn't do anything. Loop forever. */
125     for (;;)
126 	continue;
127 }
128 #endif // CAFE MOD
129 
130 #if 0 // CAFE GHS ORIG
131 void _Exit (int code)
132 {
133     struct __GHS_AT_EXIT *el;
134 
135     __ghsLock();
136     for (el = exitlisthead; el; el = el->next)
137 	el->func();
138 
139 /* [nikola] Mon Sep 20 15:07:55 PDT 1999 - cleanup the exception handling */
140 #ifndef __disable_thread_safe_extensions
141 /*--------------------*/
142 /* C++ Thread-safe    */
143 /* Exception handling */
144 /*--------------------*/
145     {
146 	if(__ghs_weak_sym_check(__cpp_exception_cleanup))
147 	    __ghs_cpp_exception_cleanup();
148     }
149 #endif /* !defined(__disable_thread_safe_extensions) */
150     __ghsUnlock();
151 
152 #pragma ghs nowarning 1547	/* Syscall prototype problems */
153     (void)__ghs_syscall(SYSCALL_EXIT, code);
154 #pragma ghs endnowarning 1547
155 /* If we get here, SYSCALL_EXIT didn't do anything. Loop forever. */
156     for (;;)
157 	continue;
158 }
159 #endif // CAFE GHS ORIG
160 
161 /******************************************************************************/
162 /*  void __ghs_at_exit (struct __GHS_AT_EXIT *gae);			      */
163 /*  Add gae to the list of functions to be executed when _Exit() is called.   */
164 /******************************************************************************/
__ghs_at_exit(struct __GHS_AT_EXIT * gae)165 void __ghs_at_exit (struct __GHS_AT_EXIT *gae)
166 {
167     __ghsLock();
168     gae->next = exitlisthead;
169     exitlisthead = gae;
170     __ghsUnlock();
171 }
172 #endif	/* EMBEDDED */
173