Merge from mainline (167278:168000).
[official-gcc/graphite-test-results.git] / libgo / runtime / go-trampoline.c
blob43003e81c93f0408b7f8063595be32dacb088359
1 /* go-trampoline.c -- allocate a trampoline for a nested function.
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. */
7 #include "config.h"
9 #include <stddef.h>
10 #include <stdint.h>
11 #include <unistd.h>
13 #ifdef HAVE_SYS_MMAN_H
14 #include <sys/mman.h>
15 #endif
17 #include "go-alloc.h"
18 #include "go-assert.h"
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. */
24 void *
25 __go_allocate_trampoline (size_t size, void *closure)
27 unsigned int page_size;
28 void *ret;
29 size_t off;
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));
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 *));
44 #ifdef HAVE_SYS_MMAN_H
46 int i;
47 i = mprotect (ret, size, PROT_READ | PROT_WRITE | PROT_EXEC);
48 __go_assert (i == 0);
50 #endif
52 return ret;