Added more syscalls
[akaros.git] / user / parlib / src / parlibmain.c
1 // Called from entry.S to get us going.
2
3 #include <sys/reent.h>
4 #include <parlib.h>
5 #include <stdlib.h>
6 #include <unistd.h>
7 #include <debug.h>
8 #include <hart.h>
9 #include <assert.h>
10
11 char core0_tls[PARLIB_TLS_SIZE];
12
13 // call static destructors.
14 void parlib_dtors()
15 {
16         typedef void (*dtor)(void);
17         extern char __DTOR_LIST__[],__DTOR_END__[];
18         int ndtor = ((unsigned int)(__DTOR_END__-__DTOR_LIST__))/sizeof(void*);
19
20         // make sure only one thread actually runs the dtors
21         static int already_done = 0;
22         if(hart_swap(&already_done,1) == 1)
23                 return;
24
25         for(int i = 0; i < ndtor; i++)
26                 ((dtor*)__DTOR_LIST__)[i]();
27 }
28
29 // call static constructors.
30 void parlib_ctors()
31 {
32         typedef void (*ctor)(void);
33         extern char __CTOR_LIST__[],__CTOR_END__[];
34         int nctor = ((unsigned int)(__CTOR_END__-__CTOR_LIST__))/sizeof(void*);
35
36         for(int i = 0; i < nctor; i++)
37                 ((ctor*)__CTOR_LIST__)[nctor-i-1]();
38 }
39
40 // build argv from procinfo.argv_buf
41 char** parlib_build_argc_argv(char* buf, int* argc)
42 {
43         intreg_t* offset = (intreg_t*)buf;
44         for(*argc = 0; offset[*argc]; (*argc)++)
45                 ;
46
47         char** argv = (char**)malloc((*argc+1)*sizeof(char*));
48         assert(argv);
49         for(int i = 0; i < *argc; i++)
50         {
51                 argv[i] = strdup(buf + offset[i]);
52                 assert(argv[i]);
53         }
54         argv[*argc] = 0;
55         return argv;
56 }
57
58 struct timeval timeval_start;
59
60 // the first time any thread enters, it calls this function
61 void parlib_initthread()
62 {
63         // initialize the newlib reentrancy structure
64         extern __thread struct _reent _thread_reent;
65         _REENT_INIT_PTR(&_thread_reent);
66 }
67
68 // entry point for not-core 0
69 void parlib_unmain()
70 {
71         parlib_initthread();
72         hart_entry();
73         hart_yield();
74 }
75
76 // entry point for core 0
77 void parlib_main()
78 {
79         // only core 0 runs parlibmain, but if it yields then
80         // is given back, we don't want it to reinit things
81         static int initialized = 0;
82         if(initialized)
83                 parlib_unmain();
84         initialized = 1;
85
86         parlib_initthread();
87
88         // get start time (for times)
89         if(gettimeofday(&timeval_start,NULL))
90                 timeval_start.tv_sec = timeval_start.tv_usec = 0;
91
92         // call static destructors
93         parlib_ctors();
94
95         // call static destructors on exit
96         atexit(&parlib_dtors);
97
98         // set up argc/argv/envp
99         int argc,envc;
100         char** argv = parlib_build_argc_argv(procinfo.argv_buf,&argc);
101         environ = parlib_build_argc_argv(procinfo.env_buf,&envc);
102
103         // call user main routine
104         extern int main(int argc, char * NTS * COUNT(argc) NT argv,
105                                   char * NTS * COUNT(envc) NT envp);
106         int r = main(argc,argv,environ);
107
108         // here I'd free(argv), but since we're exiting, it doesn't matter...
109
110         // exit gracefully
111         exit(r);
112 }
113