In libc, execute vcore_event_init before ctors
[akaros.git] / tools / compilers / gcc-glibc / glibc-2.14.1-ros / sysdeps / ros / start.c
1 #include <abort-instr.h>
2 #include <string.h>
3 #include <vcore.h>
4 #include <stdio.h>
5 #include <ros/syscall.h>
6 #include <ros/procinfo.h>
7 #include <unistd.h>
8 #include <vcore-tls.c>
9
10 void** __vcore_thread_control_blocks = NULL;
11 weak_alias(__vcore_thread_control_blocks,vcore_thread_control_blocks)
12
13 __thread int __vcoreid = 0;
14 __thread bool __vcore_context = FALSE;
15
16 void __uthread_vcore_entry(void)
17 {
18         fputs("Define a uthread_vcore_entry() or a vcore_entry(), foo!\n", stderr);
19         abort();
20 }
21 weak_alias(__uthread_vcore_entry, uthread_vcore_entry)
22
23 void __vcore_entry(void)
24 {
25         uthread_vcore_entry();
26 }
27 weak_alias(__vcore_entry, vcore_entry)
28
29 void __vcore_event_init(void)
30 {
31         fputs("Build your application with -lparlib\n", stderr);
32         abort();
33 }
34 weak_alias(__vcore_event_init, vcore_event_init)
35
36 #define failmsg(str) write(2,str"\n",sizeof(str"\n")-1)
37
38 void __ros_libc_csu_init(int argc, char **argv, char **envp)
39 {
40         vcore_event_init();
41         // Note that we want the ctors to be called after vcore_event_init.
42         // (They are invoked by the next line.)
43         __libc_csu_init(argc, argv, envp);
44 }
45
46 void
47 _start(void)
48 {
49         // WARNING: __vcore_self_on_entry must be read before
50         // anything is register-allocated!
51         int id = __vcore_id_on_entry;
52         static int init = 0;
53         // For dynamically-linked programs, the first time through,
54         // __vcore_self_on_entry could be clobbered (on x86), because
55         // the linker will have overwritten eax.  Happily, the first
56         // time through, we know we are vcore 0.  Subsequent entries
57         // into this routine do not have this problem.
58         if(init == 0)
59                 id = 0;
60         
61         // vcore0 when it comes up again, and all threads besides thread 0 must
62         // acquire a TCB.
63         if(init || (id != 0))
64         {
65                 set_tls_desc(__vcore_thread_control_blocks[id],id);
66                 __vcoreid = id;
67                 __vcore_context = TRUE;
68                 vcore_entry();
69                 failmsg("why did vcore_entry() return?");
70                 goto diediedie;
71         }
72
73         init = 1;
74
75         extern int main(int,char**,char**);
76         extern void __libc_csu_init(int,char**,char**);
77         extern void __libc_csu_fini(void);
78         extern void __libc_start_main(typeof(&main),int,char**,
79                       typeof(&__libc_csu_init),
80                       typeof(&__libc_csu_fini),
81                       void*,void*);
82
83         char** argv = (char**)alloca(sizeof(__procinfo.argp));
84         memcpy(argv,__procinfo.argp,sizeof(__procinfo.argp));
85
86         char* argbuf = (char*)alloca(sizeof(__procinfo.argbuf));
87         memcpy(argbuf,__procinfo.argbuf,sizeof(__procinfo.argbuf));
88
89         // touch up pointers, but don't mess up auxp!
90         for(int i = 0, zeros = 0; i < PROCINFO_MAX_ARGP; i++)
91         {
92                 if(argv[i])
93                         argv[i] += argbuf - __procinfo.argbuf;
94                 else if(++zeros == 2)
95                         break;
96         }
97
98         int argc = 0;
99         while(argv[argc])
100                 argc++;
101
102         extern char** _environ;
103         _environ = argv+argc+1;
104
105         __libc_start_main(&main, argc, argv, &__ros_libc_csu_init, &__libc_csu_fini,
106                           0, 0);
107
108         failmsg("why did main() return?");
109
110 diediedie:
111         abort();
112         #ifdef ABORT_INSTRUCTION
113         ABORT_INSTRUCTION;
114         #endif
115         while(1);
116 }