re PR go/52358 (math FAILs on Solaris 8 and 9)
[gcc.git] / libgo / runtime / go-trampoline.c
1 /* go-trampoline.c -- allocate a trampoline for a nested function.
2
3 Copyright 2009 The Go Authors. All rights reserved.
4 Use of this source code is governed by a BSD-style
5 license that can be found in the LICENSE file. */
6
7 #include "config.h"
8
9 #include <stddef.h>
10 #include <stdint.h>
11 #include <unistd.h>
12
13 #ifdef HAVE_SYS_MMAN_H
14 #include <sys/mman.h>
15 #endif
16
17 #include "go-alloc.h"
18 #include "go-assert.h"
19
20 /* In order to build a trampoline we need space which is both writable
21 and executable. We currently just allocate a whole page. This
22 needs to be more system dependent. */
23
24 void *
25 __go_allocate_trampoline (uintptr_t size, void *closure)
26 {
27 unsigned int page_size;
28 void *ret;
29 size_t off;
30
31 page_size = getpagesize ();
32 __go_assert (page_size >= size);
33 ret = __go_alloc (2 * page_size - 1);
34 ret = (void *) (((uintptr_t) ret + page_size - 1)
35 & ~ ((uintptr_t) page_size - 1));
36
37 /* Because the garbage collector only looks at correct address
38 offsets, we need to ensure that it will see the closure
39 address. */
40 off = ((size + sizeof (void *) - 1) / sizeof (void *)) * sizeof (void *);
41 __go_assert (size + off + sizeof (void *) <= page_size);
42 __builtin_memcpy (ret + off, &closure, sizeof (void *));
43
44 #ifdef HAVE_SYS_MMAN_H
45 {
46 int i;
47 i = mprotect (ret, size, PROT_READ | PROT_WRITE | PROT_EXEC);
48 __go_assert (i == 0);
49 }
50 #endif
51
52 return ret;
53 }