| #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); |
| } |