Upgrade to gcc-4.9.2
[akaros.git] / tools / compilers / gcc-glibc / glibc-2.14.1-ros / sysdeps / akaros / 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 __thread int __vcoreid = 0;
11 __thread bool __vcore_context = FALSE;
12
13 void __uthread_vcore_entry(void)
14 {
15         fputs("Define a uthread_vcore_entry() or a vcore_entry(), foo!\n", stderr);
16         abort();
17 }
18 weak_alias(__uthread_vcore_entry, uthread_vcore_entry)
19
20 void __vcore_entry(void)
21 {
22         uthread_vcore_entry();
23 }
24 weak_alias(__vcore_entry, vcore_entry)
25
26 void __vcore_event_init(void)
27 {
28         fputs("Build your application with -lparlib\n", stderr);
29         abort();
30 }
31 weak_alias(__vcore_event_init, vcore_event_init)
32
33 #define failmsg(str) write(2,str"\n",sizeof(str"\n")-1)
34
35 void __ros_libc_csu_init(int argc, char **argv, char **envp)
36 {
37         vcore_event_init();
38         // Note that we want the ctors to be called after vcore_event_init.
39         // (They are invoked by the next line.)
40         __libc_csu_init(argc, argv, envp);
41 }
42
43 void
44 _start(void)
45 {
46         // WARNING: __vcore_self_on_entry must be read before
47         // anything is register-allocated!
48         int id = __vcore_id_on_entry;
49         static int init = 0;
50         // For dynamically-linked programs, the first time through,
51         // __vcore_self_on_entry could be clobbered (on x86), because
52         // the linker will have overwritten eax.  Happily, the first
53         // time through, we know we are vcore 0.  Subsequent entries
54         // into this routine do not have this problem.
55         if(init == 0)
56                 id = 0;
57         
58         // vcore0 when it comes up again, and all threads besides thread 0 must
59         // acquire a TCB.
60         if(init || (id != 0))
61         {
62                 /* The kernel sets the TLS desc for us, based on whatever is in VCPD.
63                  *
64                  * x86 32-bit TLS is pretty jacked up, so the kernel doesn't set the TLS
65                  * desc for us.  it's a little more expensive to do it here, esp for
66                  * amd64.  Can remove this when/if we overhaul 32 bit TLS.
67                  *
68                  * AFAIK, riscv's TLS changes are really cheap, and they don't do it in
69                  * the kernel (yet/ever), so they can set their TLS here too. */
70                 #ifndef __x86_64__
71                 set_tls_desc((void*)__procdata.vcore_preempt_data[id].vcore_tls_desc,
72                              id);
73                 #endif
74                 __vcoreid = id;
75                 __vcore_context = TRUE;
76                 vcore_entry();
77                 failmsg("why did vcore_entry() return?");
78                 goto diediedie;
79         }
80
81         init = 1;
82
83         extern int main(int,char**,char**);
84         extern void __libc_csu_init(int,char**,char**);
85         extern void __libc_csu_fini(void);
86         extern void __libc_start_main(typeof(&main),int,char**,
87                       typeof(&__libc_csu_init),
88                       typeof(&__libc_csu_fini),
89                       void*,void*);
90
91         char** argv = (char**)alloca(sizeof(__procinfo.argp));
92         memcpy(argv,__procinfo.argp,sizeof(__procinfo.argp));
93
94         char* argbuf = (char*)alloca(sizeof(__procinfo.argbuf));
95         memcpy(argbuf,__procinfo.argbuf,sizeof(__procinfo.argbuf));
96
97         // touch up pointers, but don't mess up auxp!
98         for(int i = 0, zeros = 0; i < PROCINFO_MAX_ARGP; i++)
99         {
100                 if(argv[i])
101                         argv[i] += argbuf - __procinfo.argbuf;
102                 else if(++zeros == 2)
103                         break;
104         }
105
106         int argc = 0;
107         while(argv[argc])
108                 argc++;
109
110         extern char** _environ;
111         _environ = argv+argc+1;
112
113         __libc_start_main(&main, argc, argv, &__ros_libc_csu_init, &__libc_csu_fini,
114                           0, 0);
115
116         failmsg("why did main() return?");
117
118 diediedie:
119         abort();
120         #ifdef ABORT_INSTRUCTION
121         ABORT_INSTRUCTION;
122         #endif
123         while(1);
124 }