blob: 448f5871b6a517c253c44f8a9337ed1e1e4ed530 [file] [log] [blame]
#include <abort-instr.h>
#include <string.h>
#include <vcore.h>
#include <stdio.h>
#include <ros/syscall.h>
#include <ros/procinfo.h>
#include <unistd.h>
#include <vcore-tls.c>
__thread int __vcoreid = 0;
__thread bool __vcore_context = FALSE;
void __uthread_vcore_entry(void)
{
fputs("Define a uthread_vcore_entry() or a vcore_entry(), foo!\n", stderr);
abort();
}
weak_alias(__uthread_vcore_entry, uthread_vcore_entry)
void __vcore_entry(void)
{
uthread_vcore_entry();
}
weak_alias(__vcore_entry, vcore_entry)
void __vcore_event_init(void)
{
fputs("Build your application with -lparlib\n", stderr);
abort();
}
weak_alias(__vcore_event_init, vcore_event_init)
#define failmsg(str) write(2,str"\n",sizeof(str"\n")-1)
void __ros_libc_csu_init(int argc, char **argv, char **envp)
{
vcore_event_init();
// Note that we want the ctors to be called after vcore_event_init.
// (They are invoked by the next line.)
__libc_csu_init(argc, argv, envp);
}
void
_start(void)
{
// WARNING: __vcore_self_on_entry must be read before
// anything is register-allocated!
int id = __vcore_id_on_entry;
static int init = 0;
// For dynamically-linked programs, the first time through,
// __vcore_self_on_entry could be clobbered (on x86), because
// the linker will have overwritten eax. Happily, the first
// time through, we know we are vcore 0. Subsequent entries
// into this routine do not have this problem.
if(init == 0)
id = 0;
// vcore0 when it comes up again, and all threads besides thread 0 must
// acquire a TCB.
if(init || (id != 0))
{
/* The kernel sets the TLS desc for us, based on whatever is in VCPD.
*
* x86 32-bit TLS is pretty jacked up, so the kernel doesn't set the TLS
* desc for us. it's a little more expensive to do it here, esp for
* amd64. Can remove this when/if we overhaul 32 bit TLS.
*
* AFAIK, riscv's TLS changes are really cheap, and they don't do it in
* the kernel (yet/ever), so they can set their TLS here too. */
#ifndef __x86_64__
set_tls_desc((void*)__procdata.vcore_preempt_data[id].vcore_tls_desc,
id);
#endif
__vcoreid = id;
__vcore_context = TRUE;
vcore_entry();
failmsg("why did vcore_entry() return?");
goto diediedie;
}
init = 1;
extern int main(int,char**,char**);
extern void __libc_csu_init(int,char**,char**);
extern void __libc_csu_fini(void);
extern void __libc_start_main(typeof(&main),int,char**,
typeof(&__libc_csu_init),
typeof(&__libc_csu_fini),
void*,void*);
char** argv = (char**)alloca(sizeof(__procinfo.argp));
memcpy(argv,__procinfo.argp,sizeof(__procinfo.argp));
char* argbuf = (char*)alloca(sizeof(__procinfo.argbuf));
memcpy(argbuf,__procinfo.argbuf,sizeof(__procinfo.argbuf));
// touch up pointers, but don't mess up auxp!
for(int i = 0, zeros = 0; i < PROCINFO_MAX_ARGP; i++)
{
if(argv[i])
argv[i] += argbuf - __procinfo.argbuf;
else if(++zeros == 2)
break;
}
int argc = 0;
while(argv[argc])
argc++;
extern char** _environ;
_environ = argv+argc+1;
__libc_start_main(&main, argc, argv, &__ros_libc_csu_init, &__libc_csu_fini,
0, 0);
failmsg("why did main() return?");
diediedie:
abort();
#ifdef ABORT_INSTRUCTION
ABORT_INSTRUCTION;
#endif
while(1);
}