Import Upstream version 20180207
[hcoop/debian/mlton.git] / runtime / platform / linux.c
CommitLineData
7f918cf1
CE
1#define _GNU_SOURCE
2
3#include "platform.h"
4
5#include "diskBack.unix.c"
6#include "displayMem.proc.c"
7#include "mmap-protect.c"
8#include "nonwin.c"
9#include "use-mmap.c"
10
11static void catcher (__attribute__ ((unused)) int signo,
12 __attribute__ ((unused)) siginfo_t* info,
13 void* context) {
14#if (defined (__x86_64__))
15#ifndef REG_RIP
16#define REG_INDEX(NAME) (offsetof(struct sigcontext, NAME) / sizeof(greg_t))
17#define REG_RIP REG_INDEX(rip) /* seems to be 16 */
18#endif
19 ucontext_t* ucp = (ucontext_t*)context;
20 GC_handleSigProf ((code_pointer) ucp->uc_mcontext.gregs[REG_RIP]);
21#elif (defined (__alpha__))
22 ucontext_t* ucp = (ucontext_t*)context;
23 GC_handleSigProf ((code_pointer) (ucp->uc_mcontext.sc_pc));
24#elif (defined (__hppa__))
25 ucontext_t* ucp = (ucontext_t*)context;
26 GC_handleSigProf ((code_pointer) (ucp->uc_mcontext.sc_iaoq[0] & ~0x3UL));
27#elif (defined(__ia64__))
28 ucontext_t* ucp = (ucontext_t*)context;
29 GC_handleSigProf ((code_pointer) ucp->_u._mc.sc_ip);
30#elif (defined (__ppc__)) || (defined (__powerpc__))
31 ucontext_t* ucp = (ucontext_t*)context;
32 GC_handleSigProf ((code_pointer) ucp->uc_mcontext.regs->nip);
33#elif (defined (__sparc__))
34 struct sigcontext* scp = (struct sigcontext*)context;
35#if __WORDSIZE == 64
36 GC_handleSigProf ((code_pointer) scp->sigc_regs.tpc);
37#else
38 GC_handleSigProf ((code_pointer) scp->si_regs.pc);
39#endif
40#elif (defined (__mips__))
41 ucontext_t* ucp = (ucontext_t*)context;
42#ifdef __UCLIBC__
43 GC_handleSigProf ((code_pointer) ucp->uc_mcontext.gpregs[CTX_EPC]);
44#else
45 GC_handleSigProf ((code_pointer) ucp->uc_mcontext.pc);
46#endif
47#elif (defined (__i386__))
48#ifndef EIP
49#define EIP 14
50#endif
51 ucontext_t* ucp = (ucontext_t*)context;
52 GC_handleSigProf ((code_pointer) ucp->uc_mcontext.gregs[EIP]);
53#elif (defined (__arm__))
54 ucontext_t* ucp = (ucontext_t*)context;
55 GC_handleSigProf ((code_pointer) ucp->uc_mcontext.arm_pc);
56#elif (defined (__aarch64__))
57 ucontext_t* ucp = (ucontext_t*)context;
58 GC_handleSigProf ((code_pointer) ucp->uc_mcontext.pc);
59#elif (defined (__s390__))
60 ucontext_t* ucp = (ucontext_t*)context;
61 GC_handleSigProf ((code_pointer) ucp->uc_mcontext.psw.addr);
62#else
63#error Profiling handler is missing for this architecture
64#endif
65}
66
67void GC_setSigProfHandler (struct sigaction *sa) {
68 sa->sa_flags = SA_ONSTACK | SA_RESTART | SA_SIGINFO;
69 sa->sa_sigaction = (void (*)(int, siginfo_t*, void*))catcher;
70}
71
72/* We need the value of MREMAP_MAYMOVE, which should come from sys/mman.h, but
73 * isn't there. It is in linux/mman.h, but we can't #include that here, because
74 * kernel headers don't mix with system headers. We could create a separate
75 * file, include the kernel headers there, and define a global. But there
76 * sometimes seem to be problems including kernel headers, so the easiest thing
77 * to do is just define MREMAP_MAYMOVE.
78 */
79#define MREMAP_MAYMOVE 1
80
81void *GC_mremap (void *start, size_t oldLength, size_t newLength) {
82 return mremap (start, oldLength, newLength, MREMAP_MAYMOVE);
83}
84
85size_t GC_pageSize (void) {
86 long int pageSize;
87
88 pageSize = sysconf (_SC_PAGESIZE);
89 if (pageSize < 0)
90 diee ("GC_pageSize error: sysconf (_SC_PAGESIZE) failed");
91
92 return (size_t)pageSize;
93}
94
95/* sysconf(_SC_PHYS_PAGES) is not portable (mipsel uclibc) */
96uintmax_t GC_physMem (void) {
97 struct sysinfo si;
98 if (sysinfo(&si) < 0)
99 diee ("GC_physMem error: sysinfo failed");
100
101 return (uintmax_t)si.totalram * (uintmax_t)si.mem_unit;
102}