~ubuntu-branches/ubuntu/utopic/golang/utopic

« back to all changes in this revision

Viewing changes to src/pkg/runtime/cgo/gcc_freebsd_arm.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-08-20 14:06:23 UTC
  • mfrom: (14.1.23 saucy-proposed)
  • Revision ID: package-import@ubuntu.com-20130820140623-b414jfxi3m0qkmrq
Tags: 2:1.1.2-2ubuntu1
* Merge from Debian unstable (LP: #1211749, #1202027). Remaining changes:
  - 016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.
  - d/control,control.cross: Update Breaks/Replaces for Ubuntu
    versions to ensure smooth upgrades, regenerate control file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2012 The Go Authors.  All rights reserved.
 
2
// Use of this source code is governed by a BSD-style
 
3
// license that can be found in the LICENSE file.
 
4
 
 
5
#include <sys/types.h>
 
6
#include <machine/sysarch.h>
 
7
#include <pthread.h>
 
8
#include <string.h>
 
9
#include "libcgo.h"
 
10
 
 
11
static void *threadentry(void*);
 
12
 
 
13
// We have to resort to TLS variable to save g(R10) and
 
14
// m(R9). One reason is that external code might trigger
 
15
// SIGSEGV, and our runtime.sigtramp don't even know we
 
16
// are in external code, and will continue to use R10/R9,
 
17
// this might as well result in another SIGSEGV.
 
18
// Note: all three functions will clobber R0, and the last
 
19
// two can be called from 5c ABI code.
 
20
void __aeabi_read_tp(void) __attribute__((naked));
 
21
void x_cgo_save_gm(void) __attribute__((naked));
 
22
void x_cgo_load_gm(void) __attribute__((naked));
 
23
 
 
24
void
 
25
__aeabi_read_tp(void)
 
26
{
 
27
        __asm__ __volatile__ (
 
28
#ifdef ARM_TP_ADDRESS
 
29
                // ARM_TP_ADDRESS is (ARM_VECTORS_HIGH + 0x1000) or 0xffff1000
 
30
                // GCC inline asm doesn't provide a way to provide a constant
 
31
                // to "ldr r0, =??" pseudo instruction, so we hardcode the value
 
32
                // and check it with cpp.
 
33
#if ARM_TP_ADDRESS != 0xffff1000
 
34
#error Wrong ARM_TP_ADDRESS!
 
35
#endif
 
36
                "ldr r0, =0xffff1000\n\t"
 
37
                "ldr r0, [r0]\n\t"
 
38
#else
 
39
                "mrc p15, 0, r0, c13, c0, 3\n\t"
 
40
#endif
 
41
                "mov pc, lr\n\t"
 
42
        );
 
43
}
 
44
 
 
45
// g (R10) at 8(TP), m (R9) at 12(TP)
 
46
void
 
47
x_cgo_load_gm(void)
 
48
{
 
49
        __asm__ __volatile__ (
 
50
                "push {lr}\n\t"
 
51
                "bl __aeabi_read_tp\n\t"
 
52
                "ldr r10, [r0, #8]\n\t"
 
53
                "ldr r9, [r0, #12]\n\t"
 
54
                "pop {pc}\n\t"
 
55
        );
 
56
}
 
57
 
 
58
void
 
59
x_cgo_save_gm(void)
 
60
{
 
61
        __asm__ __volatile__ (
 
62
                "push {lr}\n\t"
 
63
                "bl __aeabi_read_tp\n\t"
 
64
                "str r10, [r0, #8]\n\t"
 
65
                "str r9, [r0, #12]\n\t"
 
66
                "pop {pc}\n\t"
 
67
        );
 
68
}
 
69
 
 
70
void
 
71
x_cgo_init(G *g)
 
72
{
 
73
        pthread_attr_t attr;
 
74
        size_t size;
 
75
        x_cgo_save_gm(); // save g and m for the initial thread
 
76
 
 
77
        pthread_attr_init(&attr);
 
78
        pthread_attr_getstacksize(&attr, &size);
 
79
        g->stackguard = (uintptr)&attr - size + 4096;
 
80
        pthread_attr_destroy(&attr);
 
81
}
 
82
 
 
83
 
 
84
void
 
85
_cgo_sys_thread_start(ThreadStart *ts)
 
86
{
 
87
        pthread_attr_t attr;
 
88
        pthread_t p;
 
89
        size_t size;
 
90
        int err;
 
91
 
 
92
        // Not sure why the memset is necessary here,
 
93
        // but without it, we get a bogus stack size
 
94
        // out of pthread_attr_getstacksize.  C'est la Linux.
 
95
        memset(&attr, 0, sizeof attr);
 
96
        pthread_attr_init(&attr);
 
97
        size = 0;
 
98
        pthread_attr_getstacksize(&attr, &size);
 
99
        ts->g->stackguard = size;
 
100
        err = pthread_create(&p, &attr, threadentry, ts);
 
101
        if (err != 0) {
 
102
                fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err));
 
103
                abort();
 
104
        }
 
105
}
 
106
 
 
107
extern void crosscall_arm2(void (*fn)(void), void *g, void *m);
 
108
static void*
 
109
threadentry(void *v)
 
110
{
 
111
        ThreadStart ts;
 
112
 
 
113
        ts = *(ThreadStart*)v;
 
114
        free(v);
 
115
 
 
116
        ts.g->stackbase = (uintptr)&ts;
 
117
 
 
118
        /*
 
119
         * _cgo_sys_thread_start set stackguard to stack size;
 
120
         * change to actual guard pointer.
 
121
         */
 
122
        ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096 * 2;
 
123
 
 
124
        crosscall_arm2(ts.fn, (void *)ts.g, (void *)ts.m);
 
125
        return nil;
 
126
}