optimising includes
[cilux] / src / platform / linux / kernelplat.c
1
2 /* -------------------------------------------------------------------------- */
3
4 #include <errno.h>
5 #include <dlfcn.h>
6 #include <stdarg.h>
7 #include <signal.h>
8 #include <fcntl.h>
9 #include <sys/stat.h>
10 #include <sys/mman.h>
11 #include <netdb.h>
12 #include <dirent.h>
13
14 /* -------------------------------------------------------------------------- */
15
16 static fd_set rd_fd_set;
17 static fd_set wr_fd_set;
18 static fd_set ex_fd_set;
19
20 /* -------------------------------------------------------------------------- */
21
22 static void signal_terminate(int);
23 static void signal_alarm(int);
24 static void signal_other(int);
25 static void set_timeval_ms(struct timeval* t, int ms);
26
27 /* -------------------------------------------------------------------------- */
28
29 void init_thread(void)
30 {
31         signal(SIGTERM, signal_terminate);
32         signal(SIGINT,  signal_terminate);
33         signal(SIGQUIT, signal_terminate);
34         signal(SIGALRM, signal_alarm);
35         signal(SIGPIPE, signal_other);
36         signal(SIGCHLD, SIG_IGN);
37         signal(SIGHUP,  SIG_IGN);
38         signal(SIGUSR1, SIG_IGN);
39         signal(SIGUSR2, SIG_IGN);
40 }
41
42 void init_gl(void)
43 {
44 }
45
46 void init_net(void)
47 {
48         FD_ZERO(&rd_fd_set);
49         FD_ZERO(&wr_fd_set);
50         FD_ZERO(&ex_fd_set);
51 }
52
53 /* -------------------------------------------------------------------------- */
54
55 OTHER_THREAD void signal_terminate(int signum)
56 {
57         c_running(0);
58 }
59
60 OTHER_THREAD void signal_alarm(int signum)
61 {
62         c_signal(signum);
63 }
64
65 OTHER_THREAD void signal_other(int signum)
66 {
67         c_signal(signum);
68 }
69
70 /* -------------------------------------------------------------------------- */
71
72 void set_callback(k_channel* chan, int rdwr)
73 {
74         if(rdwr & SETCB_RD) FD_SET(chan->priv->SOCK, &rd_fd_set);
75         if(rdwr & SETCB_WR) FD_SET(chan->priv->SOCK, &wr_fd_set);
76 }
77
78 void un_set_callback(k_channel* chan, int rdwr)
79 {
80         if(rdwr & SETCB_RD) FD_CLR(chan->priv->SOCK, &rd_fd_set);
81         if(rdwr & SETCB_WR) FD_CLR(chan->priv->SOCK, &wr_fd_set);
82 }
83
84 void poller(int no_block)
85 {
86         fd_set rd=rd_fd_set;
87         fd_set wr=wr_fd_set;
88         fd_set ex=ex_fd_set;
89
90         k_channel* chan;
91
92         int highest=0;
93         for(chan=k_channels; chan; chan=chan->next){
94                 if(chan->priv->state==CHAN_CLOSE) continue;
95                 if(highest < chan->priv->SOCK) highest=chan->priv->SOCK;
96         }
97
98         struct timeval  t;
99         struct timeval* tp=&t;
100         set_timeval_ms(tp, no_block? 0: LOOP_TICK);
101
102         if(highest==0){
103                 select(0, 0, 0, 0, tp);
104                 next_keys();
105                 if(!no_block) do_regular_things();
106                 return;
107         }
108
109         int len=select(highest+1, &rd, &wr, &ex, tp);
110         GETERRNO(len);
111
112         next_keys();
113
114         if(len==0){
115                 do_regular_things();
116                 return;
117         }
118         if(len== -1){
119                 if(ERRNO==INTERRUPTED) return;
120                 log_net_err("select", ERRNO);
121                 sleep(1);
122                 do_regular_things();
123                 return;
124         }
125
126         for(chan=k_channels; chan; chan=chan->next){
127                 if(FD_ISSET(chan->priv->SOCK, &ex)){
128                         exception_socket(chan);
129                         continue;
130                 }
131                 if(FD_ISSET(chan->priv->SOCK, &wr)){
132                         int err; socklen_t len=sizeof(int);
133                         if(getsockopt(chan->priv->SOCK,
134                                       SOL_SOCKET,
135                                       SO_ERROR, &err, &len) || err){
136                                 exception_socket(chan);
137                                 continue;
138                         }
139                         else{
140                                 writeable_socket(chan);
141                         }
142                 }
143                 if(FD_ISSET(chan->priv->SOCK, &rd)){
144                         readable_socket(chan);
145                 }
146         }
147 }
148
149 void set_timeval_ms(struct timeval* t, int ms)
150 {
151         t->tv_sec=ms/1000;
152         t->tv_usec=(ms-(t->tv_sec)*1000)*1000;
153 }
154
155 char* str_error(int e)
156 {
157         return strerror(e);
158 }
159
160 /* -------------------------------------------------------------------------- */
161
162 void stat_only(char* fullname, k_stat* kstat)
163 {
164         kstat->type=0;
165         struct stat s;
166         if(stat(fullname, &s)) return;
167         kstat->type=s.st_mode & 0170000;
168         kstat->size=s.st_size;
169         kstat->time=s.st_mtime;
170         kstat->perm=s.st_mode & 0007777;
171 }
172
173 FILE_T stat_open(char* fullname, k_stat* kstat)
174 {
175         stat_only(fullname, kstat);
176         if(!kstat->type) return 0;
177         FILE_T filehandle=open(fullname, O_RDONLY);
178         if(filehandle<0) return 0;
179         return filehandle;
180 }
181
182 FILE_T open_only(char* fullname, int wr)
183 {
184         int rw=wr? O_RDWR|O_CREAT|O_TRUNC: O_RDONLY;
185         FILE_T filehandle=open(fullname, rw, 0644);
186         if(filehandle<0) return 0;
187         return filehandle;
188 }
189
190 void* mmap_malloc(void* s, size_t size, int prot, int f, char* fullname, int o)
191 {
192         FILE_T fh=open(fullname, O_RDONLY, 0644);
193         if(fh<0) return MAP_FAILED;
194
195         char* data=k_malloc(size);
196         int charsread=0;
197         int len;
198         do{
199                 len=read(fh, data+charsread, size-charsread);
200                 if(len< 0 && FERRNO(len)==EINTR) continue;
201                 if(len<=0) break;
202                 charsread+=len;
203         } while(charsread<size);
204
205         close(fh);
206         if(len<0 || charsread!=size){ k_free(data); return MAP_FAILED; }
207         return data;
208 }
209
210 void* mmap_name(void* s, size_t size, int prot, int f, char* fullname, int o)
211 {
212         if(!size) return MAP_FAILED;
213         int w=(prot & PROT_WRITE);
214         FILE_T fh=open(fullname, (w? O_RDWR|O_CREAT: O_RDONLY), 0644);
215         if(fh<0) return MAP_FAILED;
216         return mmap(s, size, prot, f, fh, o);
217 }
218
219 /* -------------------------------------------------------------------------- */
220
221 EXPORT void k_random_bytes(char* buf, size_t size)
222 {
223         *(short*)buf=getpid();
224         if(size!=2) k_log_err("Linux randomness not implemented yet!");
225 }
226
227 /* -------------------------------------------------------------------------- */
228
229 EXPORT void* k_malloc(size_t size)
230 {
231         void* p=malloc(size);
232         if(!p){
233                 k_fatal(OOM_STRING);
234         }
235         return p;
236 }
237
238 EXPORT void* k_realloc(void* o, size_t size)
239 {
240         void* p=realloc(o, size);
241         if(!p){
242                 k_fatal(OOM_STRING);
243         }
244         return p;
245 }
246
247 EXPORT void k_free(void* o)
248 {
249         if(o) free(o);
250 }
251
252 EXPORT char* k_strdup(char* s)
253 {
254         if(!s) return 0;
255         char* p=strdup(s);
256         if(!p){
257                 k_fatal(OOM_STRING);
258         }
259         return p;
260 }
261
262 EXPORT void* k_memdup(void* s, size_t size)
263 {
264         void* p=malloc(size);
265         if(!p){
266                 k_fatal(OOM_STRING);
267         }
268         memcpy(p, s, size);
269         return p;
270 }
271
272 /* -------------------------------------------------------------------------- */
273