Files
pspsdk/src/startup/crt0_prx.c
David Guillen Fandos 4b2982cb7d Fix init / libc_init ordering
_init might require working pthreads, due to C++ constructors using
mutexes and threads. Since libc does not require _init execution, we
simply reorder them.

This removes support for kernel-mode _init on user programs that run in
kernel mode (mostly old FW 1.5, but should not affect almost any
homebrew out there, since they don't use user-mode main thread).
2023-06-28 23:11:56 +02:00

133 lines
3.7 KiB
C

/*
* PSP Software Development Kit - https://github.com/pspdev
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* crt0_prx.c - Pure PRX startup code.
*
* Copyright (c) 2005 Marcus R. Brown <mrbrown@ocgnet.org>
*
*/
#include <pspkerneltypes.h>
#include <pspmoduleinfo.h>
#include <pspthreadman.h>
#include <stdlib.h>
#include <string.h>
/* The maximum number of arguments that can be passed to main(). */
#define ARG_MAX 19
/* Default thread parameters for the main program thread. */
#define DEFAULT_THREAD_PRIORITY 32
#define DEFAULT_THREAD_ATTRIBUTE 0
#define DEFAULT_THREAD_STACK_KB_SIZE 256
#define DEFAULT_MAIN_THREAD_NAME "user_main"
/* If these variables are defined by the program, then they override the
defaults given above. */
extern int sce_newlib_nocreate_thread_in_start __attribute__((weak));
extern unsigned int sce_newlib_priority __attribute__((weak));
extern unsigned int sce_newlib_attribute __attribute__((weak));
extern unsigned int sce_newlib_stack_kb_size __attribute__((weak));
extern const char* sce_newlib_main_thread_name __attribute__((weak));
/* This is declared weak in case someone compiles an empty program. That
program won't work on the PSP, but it could be useful for testing the
toolchain. */
extern SceModuleInfo module_info __attribute__((weak));
/* Allow to provide a libc init hook to be called before main */
extern void __libcglue_init(int argc, char *argv[]);
extern void _init(void);
extern void _fini(void);
extern int main(int argc, char *argv[]);
/**
* Main program thread
*
* Initializes runtime parameters and calls the program's main().
*
* @param args - Size (in bytes) of the argp parameter.
* @param argp - Pointer to program arguments. Each argument is a NUL-terminated string.
*/
void _main(SceSize args, void *argp)
{
char *argv[ARG_MAX + 1];
int argc = 0;
int loc = 0;
char *ptr = argp;
/* Turn our thread arguments into main()'s argc and argv[]. */
while(loc < args)
{
argv[argc] = &ptr[loc];
loc += strlen(&ptr[loc]) + 1;
argc++;
if(argc == ARG_MAX)
{
break;
}
}
argv[argc] = NULL;
/* Call libc initialization hook */
__libcglue_init(argc, argv);
/* Init can contain C++ constructors that require working threading */
_init();
/* Make sure _fini() is called when the program ends. */
atexit((void *) _fini);
/* Call main(). */
int res = main(argc, argv);
/* Return control to the operating system. */
exit(res);
}
int module_start(SceSize args, void *argp) __attribute__((alias("_start")));
/**
* Startup thread
*
* Creates the main program thread based on variables defined by the program.
*
* @param args - Size (in bytes) of arguments passed to the program by the kernel.
* @param argp - Pointer to arguments passed by the kernel.
*/
int _start(SceSize args, void *argp)
{
if (&sce_newlib_nocreate_thread_in_start != NULL) {
/* The program does not want main() to be run in a seperate thread. */
_main(args, argp);
return 1;
}
int priority = DEFAULT_THREAD_PRIORITY;
unsigned int attribute = DEFAULT_THREAD_ATTRIBUTE;
unsigned int stackSize = DEFAULT_THREAD_STACK_KB_SIZE * 1024;
const char *threadName = DEFAULT_MAIN_THREAD_NAME;
if (&sce_newlib_priority != NULL) {
priority = sce_newlib_priority;
}
if (&sce_newlib_attribute != NULL) {
attribute = sce_newlib_attribute;
}
if (&sce_newlib_stack_kb_size != NULL) {
stackSize = sce_newlib_stack_kb_size * 1024;
}
if (&sce_newlib_main_thread_name != NULL) {
threadName = sce_newlib_main_thread_name;
}
SceUID thid;
thid = sceKernelCreateThread(threadName, (void *) _main, priority, stackSize, attribute, 0);
sceKernelStartThread(thid, args, argp);
return 0;
}