fix bug in SYMBOL-VALUE CAS expansion for constant arguments
[sbcl.git] / src / runtime / linux-os.c
1 /*
2  * the Linux incarnation of OS-dependent routines.  See also
3  * $(sbcl_arch)-linux-os.c
4  *
5  * This file (along with os.h) exports an OS-independent interface to
6  * the operating system VM facilities. Surprise surprise, this
7  * interface looks a lot like the Mach interface (but simpler in some
8  * places). For some operating systems, a subset of these functions
9  * will have to be emulated.
10  */
11
12 /*
13  * This software is part of the SBCL system. See the README file for
14  * more information.
15  *
16  * This software is derived from the CMU CL system, which was
17  * written at Carnegie Mellon University and released into the
18  * public domain. The software is in the public domain and is
19  * provided with absolutely no warranty. See the COPYING and CREDITS
20  * files for more information.
21  */
22
23 #include <stdio.h>
24 #include <sys/param.h>
25 #include <sys/file.h>
26 #include "sbcl.h"
27 #include "./signal.h"
28 #include "os.h"
29 #include "arch.h"
30 #include "globals.h"
31 #include "interrupt.h"
32 #include "interr.h"
33 #include "lispregs.h"
34 #include "runtime.h"
35 #include "genesis/static-symbols.h"
36 #include "genesis/fdefn.h"
37
38 #include <sys/socket.h>
39 #include <sys/utsname.h>
40 #include <errno.h>
41
42 #include <sys/types.h>
43 #include <signal.h>
44 /* #include <sys/sysinfo.h> */
45 #include <sys/time.h>
46 #include <sys/stat.h>
47 #include <unistd.h>
48 #include <linux/version.h>
49
50 #include "validate.h"
51 #include "thread.h"
52 #include "gc.h"
53 #if defined LISP_FEATURE_GENCGC
54 #include "gencgc-internal.h"
55 #else
56 #include "cheneygc-internal.h"
57 #endif
58
59 #ifdef LISP_FEATURE_X86
60 /* Prototype for personality(2). Done inline here since the header file
61  * for this isn't available on old versions of glibc. */
62 int personality (unsigned long);
63 #endif
64
65 size_t os_vm_page_size;
66
67 #if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_SB_FUTEX) && !defined(LISP_FEATURE_SB_PTHREAD_FUTEX)
68 #include <sys/syscall.h>
69 #include <unistd.h>
70 #include <errno.h>
71
72 /* values taken from the kernel's linux/futex.h.  This header file
73    doesn't exist in userspace, which is our excuse for not grovelling
74    them automatically */
75 #define FUTEX_WAIT 0
76 #define FUTEX_WAKE 1
77 /* This is also copied from linux/futex.h so that a binary compiled on
78  * a not so recent Linux system can still take advantage of private
79  * futexes when available.*/
80 #define FUTEX_WAIT_PRIVATE (0+128)
81 #define FUTEX_WAKE_PRIVATE (1+128)
82 #define FUTEX_FD (2)
83 #define FUTEX_REQUEUE (3)
84
85 /* Not static so that Lisp may query it. */
86 boolean futex_private_supported_p;
87
88 static inline int
89 futex_wait_op()
90 {
91     return (futex_private_supported_p ? FUTEX_WAIT_PRIVATE : FUTEX_WAIT);
92 }
93
94 static inline int
95 futex_wake_op()
96 {
97     return (futex_private_supported_p ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE);
98 }
99
100 #define sys_futex sbcl_sys_futex
101 static inline int sys_futex (void *futex, int op, int val, struct timespec *rel)
102 {
103     return syscall (SYS_futex, futex, op, val, rel);
104 }
105
106 static void
107 futex_init()
108 {
109     int x = 0;
110     sys_futex(&x, FUTEX_WAIT, 1, 0);
111     if (errno == ENOSYS)
112         lose("This version of SBCL is compiled with threading support, but your kernel\n"
113              "is too old to support this. Please use a more recent kernel or\n"
114              "a version of SBCL without threading support.\n");
115     sys_futex(&x, FUTEX_WAIT_PRIVATE, 1, 0);
116     if (errno == EWOULDBLOCK) {
117         futex_private_supported_p = 1;
118     } else {
119         futex_private_supported_p = 0;
120         SHOW("No futex private suppport\n");
121     }
122 }
123
124 int
125 futex_wait(int *lock_word, int oldval, long sec, unsigned long usec)
126 {
127   struct timespec timeout;
128   int t;
129
130   if (sec<0) {
131       t = sys_futex(lock_word, futex_wait_op(), oldval, 0);
132   }
133   else {
134       timeout.tv_sec = sec;
135       timeout.tv_nsec = usec * 1000;
136       t = sys_futex(lock_word, futex_wait_op(), oldval, &timeout);
137   }
138   if (t==0)
139       return 0;
140   else if (errno==ETIMEDOUT)
141       return 1;
142   else if (errno==EINTR)
143       return 2;
144   else
145       /* EWOULDBLOCK and others, need to check the lock */
146       return -1;
147 }
148
149 int
150 futex_wake(int *lock_word, int n)
151 {
152     return sys_futex(lock_word, futex_wake_op(),n,0);
153 }
154 #endif
155
156 \f
157 int linux_sparc_siginfo_bug = 0;
158
159 /* This variable was in real use for a few months, basically for
160  * storing autodetected information about whether the Linux
161  * installation was recent enough to support SBCL threads, and make
162  * some run-time decisions based on that. But this turned out to be
163  * unstable, so now we just flat-out refuse to start on the old installations
164  * when thread support has been compiled in.
165  *
166  * Unfortunately, in the meanwhile Slime started depending on this
167  * variable for deciding which communication style to use. So even
168  * though this variable looks unused, it shouldn't be deleted until
169  * it's no longer used in the versions of Slime that people are
170  * likely to download first. -- JES, 2006-06-07
171  */
172 int linux_no_threads_p = 0;
173
174 #ifdef LISP_FEATURE_SB_THREAD
175 int
176 isnptl (void)
177 {
178   size_t n = confstr (_CS_GNU_LIBPTHREAD_VERSION, NULL, 0);
179   if (n > 0) {
180       char *buf = alloca (n);
181       confstr (_CS_GNU_LIBPTHREAD_VERSION, buf, n);
182       if (strstr (buf, "NPTL")) {
183           return 1;
184       }
185   }
186   return 0;
187 }
188 #endif
189
190 void
191 os_init(char *argv[], char *envp[])
192 {
193     /* Conduct various version checks: do we have enough mmap(), is
194      * this a sparc running 2.2, can we do threads? */
195     struct utsname name;
196     int major_version;
197     int minor_version;
198     int patch_version;
199     char *p;
200     uname(&name);
201
202     p=name.release;
203     major_version = atoi(p);
204     minor_version = patch_version = 0;
205     p=strchr(p,'.');
206     if (p != NULL) {
207             minor_version = atoi(++p);
208             p=strchr(p,'.');
209             if (p != NULL)
210                     patch_version = atoi(++p);
211     }
212
213     if (major_version<2) {
214         lose("linux kernel version too old: major version=%d (can't run in version < 2.0.0)\n",
215              major_version);
216     }
217     if (!(major_version>2 || minor_version >= 4)) {
218 #ifdef LISP_FEATURE_SPARC
219         FSHOW((stderr,"linux kernel %d.%d predates 2.4;\n enabling workarounds for SPARC kernel bugs in signal handling.\n", major_version,minor_version));
220         linux_sparc_siginfo_bug = 1;
221 #endif
222     }
223 #ifdef LISP_FEATURE_SB_THREAD
224 #if defined(LISP_FEATURE_SB_FUTEX) && !defined(LISP_FEATURE_SB_PTHREAD_FUTEX)
225     futex_init();
226 #endif
227     if(! isnptl()) {
228        lose("This version of SBCL only works correctly with the NPTL threading\n"
229             "library. Please use a newer glibc, use an older SBCL, or stop using\n"
230             "LD_ASSUME_KERNEL\n");
231     }
232 #endif
233
234     /* Don't use getpagesize(), since it's not constant across Linux
235      * kernel versions on some architectures (for example PPC). FIXME:
236      * possibly the same should be done on other architectures too.
237      */
238     os_vm_page_size = BACKEND_PAGE_BYTES;
239
240     /* KLUDGE: Disable memory randomization on new Linux kernels
241      * by setting a personality flag and re-executing. (We need
242      * to re-execute, since the memory maps that can conflict with
243      * the SBCL spaces have already been done at this point).
244      *
245      * Since randomization is currently implemented only on x86 kernels,
246      * don't do this trick on other platforms.
247      */
248 #if defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64)
249     if ((major_version == 2
250          /* Some old kernels will apparently lose unsupported personality flags
251           * on exec() */
252          && ((minor_version == 6 && patch_version >= 11)
253              || (minor_version > 6)
254              /* This is what RHEL 3 reports */
255              || (minor_version == 4 && patch_version > 20)))
256         || major_version >= 3)
257     {
258         int pers = personality(0xffffffffUL);
259         /* 0x40000 aka. ADDR_NO_RANDOMIZE */
260         if (!(pers & 0x40000)) {
261             int retval = personality(pers | 0x40000);
262             /* Allegedly some Linux kernels (the reported case was
263              * "hardened Linux 2.6.7") won't set the new personality,
264              * but nor will they return -1 for an error. So as a
265              * workaround query the new personality...
266              */
267             int newpers = personality(0xffffffffUL);
268             /* ... and don't re-execute if either the setting resulted
269              * in an error or if the value didn't change. Otherwise
270              * this might result in an infinite loop.
271              */
272             if (retval != -1 && newpers != pers) {
273                 /* Use /proc/self/exe instead of trying to figure out
274                  * the executable path from PATH and argv[0], since
275                  * that's unreliable. We follow the symlink instead of
276                  * executing the file directly in order to prevent top
277                  * from displaying the name of the process as "exe". */
278                 char runtime[PATH_MAX+1];
279                 int i = readlink("/proc/self/exe", runtime, PATH_MAX);
280                 if (i != -1) {
281                     runtime[i] = '\0';
282                     execve(runtime, argv, envp);
283                 }
284             }
285             /* Either changing the personality or execve() failed. Either
286              * way we might as well continue, and hope that the random
287              * memory maps are ok this time around.
288              */
289             fprintf(stderr, "WARNING: Couldn't re-execute SBCL with the proper personality flags (maybe /proc isn't mounted?). Trying to continue anyway.\n");
290         }
291     }
292 #ifdef LISP_FEATURE_X86
293     /* Use SSE detector.  Recent versions of Linux enable SSE support
294      * on SSE capable CPUs.  */
295     /* FIXME: Are there any old versions that does not support SSE?  */
296     fast_bzero_pointer = fast_bzero_detect;
297 #endif
298 #endif
299 }
300
301
302 #ifdef LISP_FEATURE_ALPHA
303 /* The Alpha is a 64 bit CPU.  SBCL is a 32 bit application.  Due to all
304  * the places that assume we can get a pointer into a fixnum with no
305  * information loss, we have to make sure it allocates all its ram in the
306  * 0-2Gb region.  */
307
308 static void * under_2gb_free_pointer=DYNAMIC_1_SPACE_END;
309 #endif
310
311 os_vm_address_t
312 os_validate(os_vm_address_t addr, os_vm_size_t len)
313 {
314     int flags =  MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE;
315     os_vm_address_t actual;
316
317 #ifdef LISP_FEATURE_ALPHA
318     if (!addr) {
319         addr=under_2gb_free_pointer;
320     }
321 #endif
322     actual = mmap(addr, len, OS_VM_PROT_ALL, flags, -1, 0);
323     if (actual == MAP_FAILED) {
324         perror("mmap");
325         return 0;               /* caller should check this */
326     }
327
328     if (addr && (addr!=actual)) {
329         fprintf(stderr, "mmap: wanted %lu bytes at %p, actually mapped at %p\n",
330                 (unsigned long) len, addr, actual);
331         return 0;
332     }
333
334 #ifdef LISP_FEATURE_ALPHA
335
336     len=(len+(os_vm_page_size-1))&(~(os_vm_page_size-1));
337     under_2gb_free_pointer+=len;
338 #endif
339
340     return actual;
341 }
342
343 void
344 os_invalidate(os_vm_address_t addr, os_vm_size_t len)
345 {
346     if (munmap(addr,len) == -1) {
347         perror("munmap");
348     }
349 }
350
351 os_vm_address_t
352 os_map(int fd, int offset, os_vm_address_t addr, os_vm_size_t len)
353 {
354     os_vm_address_t actual;
355
356     actual = mmap(addr, len, OS_VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED,
357                   fd, (off_t) offset);
358     if (actual == MAP_FAILED || (addr && (addr != actual))) {
359         perror("mmap");
360         lose("unexpected mmap(..) failure\n");
361     }
362
363     return actual;
364 }
365
366 void
367 os_protect(os_vm_address_t address, os_vm_size_t length, os_vm_prot_t prot)
368 {
369     if (mprotect(address, length, prot) == -1) {
370         if (errno == ENOMEM) {
371             lose("An mprotect call failed with ENOMEM. This probably means that the maximum amount\n"
372                  "of separate memory mappings was exceeded. To fix the problem, either increase\n"
373                  "the maximum with e.g. 'echo 262144 > /proc/sys/vm/max_map_count' or recompile\n"
374                  "SBCL with a larger value for GENCGC-CARD-BYTES in\n"
375                  "'src/compiler/target/backend-parms.lisp'.");
376         } else {
377             perror("mprotect");
378         }
379     }
380 }
381 \f
382 boolean
383 is_valid_lisp_addr(os_vm_address_t addr)
384 {
385     struct thread *th;
386     size_t ad = (size_t) addr;
387
388     if ((READ_ONLY_SPACE_START <= ad && ad < READ_ONLY_SPACE_END)
389         || (STATIC_SPACE_START <= ad && ad < STATIC_SPACE_END)
390 #if defined LISP_FEATURE_GENCGC
391         || (DYNAMIC_SPACE_START <= ad && ad < DYNAMIC_SPACE_END)
392 #else
393         || (DYNAMIC_0_SPACE_START <= ad && ad < DYNAMIC_0_SPACE_END)
394         || (DYNAMIC_1_SPACE_START <= ad && ad < DYNAMIC_1_SPACE_END)
395 #endif
396         )
397         return 1;
398     for_each_thread(th) {
399         if((size_t)(th->control_stack_start) <= ad
400            && ad < (size_t)(th->control_stack_end))
401             return 1;
402         if((size_t)(th->binding_stack_start) <= ad
403            && ad < (size_t)(th->binding_stack_start + BINDING_STACK_SIZE))
404             return 1;
405     }
406     return 0;
407 }
408 \f
409 /*
410  * any OS-dependent special low-level handling for signals
411  */
412
413 /*
414  * The GC needs to be hooked into whatever signal is raised for
415  * page fault on this OS.
416  */
417 static void
418 sigsegv_handler(int signal, siginfo_t *info, os_context_t *context)
419 {
420     os_vm_address_t addr = arch_get_bad_addr(signal, info, context);
421
422 #ifdef LISP_FEATURE_ALPHA
423     /* Alpha stuff: This is the end of a pseudo-atomic section during
424        which a signal was received.  We must deal with the pending
425        interrupt (see also interrupt.c, ../code/interrupt.lisp)
426
427        (how we got here: when interrupting, we set bit 63 in reg_ALLOC.
428        At the end of the atomic section we tried to write to reg_ALLOC,
429        got a SIGSEGV (there's nothing mapped there) so ended up here. */
430     if (addr != NULL &&
431         *os_context_register_addr(context, reg_ALLOC) & (1L<<63)) {
432         *os_context_register_addr(context, reg_ALLOC) -= (1L<<63);
433         interrupt_handle_pending(context);
434         return;
435     }
436 #endif
437
438 #ifdef LISP_FEATURE_SB_SAFEPOINT
439     if (!handle_safepoint_violation(context, addr))
440 #endif
441
442 #ifdef LISP_FEATURE_GENCGC
443     if (!gencgc_handle_wp_violation(addr))
444 #else
445     if (!cheneygc_handle_wp_violation(context, addr))
446 #endif
447         if (!handle_guard_page_triggered(context, addr))
448             lisp_memory_fault_error(context, addr);
449 }
450
451 void
452 os_install_interrupt_handlers(void)
453 {
454     undoably_install_low_level_interrupt_handler(SIG_MEMORY_FAULT,
455                                                  sigsegv_handler);
456
457     /* OAOOM c.f. sunos-os.c.
458      * Should we have a reusable function gc_install_interrupt_handlers? */
459 #ifdef LISP_FEATURE_SB_THREAD
460 # ifdef LISP_FEATURE_SB_SAFEPOINT
461 #  ifdef LISP_FEATURE_SB_THRUPTION
462     undoably_install_low_level_interrupt_handler(SIGPIPE, thruption_handler);
463 #  endif
464 # else
465     undoably_install_low_level_interrupt_handler(SIG_STOP_FOR_GC,
466                                                  sig_stop_for_gc_handler);
467 # endif
468 #endif
469 }
470
471 char *
472 os_get_runtime_executable_path(int external)
473 {
474     char path[PATH_MAX + 1];
475     int size;
476
477     size = readlink("/proc/self/exe", path, sizeof(path)-1);
478     if (size < 0)
479         return NULL;
480     else
481         path[size] = '\0';
482
483     return copied_string(path);
484 }