OSDN Git Service

d6cc29922e85eae6eb026dcf8066fc92b9b198a0
[pf3gnuchains/gcc-fork.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 }