]> gcc.gnu.org Git - gcc.git/blame - libgcc/generic-morestack-thread.c
t-stack (LIB2ADD_ST): Set instead of LIB2ADD.
[gcc.git] / libgcc / generic-morestack-thread.c
CommitLineData
7458026b
ILT
1/* Thread library support for -fsplit-stack. */
2/* Copyright (C) 2009, 2010 Free Software Foundation, Inc.
3 Contributed by Ian Lance Taylor <iant@google.com>.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 3, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17Under Section 7 of GPL version 3, you are granted additional
18permissions described in the GCC Runtime Library Exception, version
193.1, as published by the Free Software Foundation.
20
21You should have received a copy of the GNU General Public License and
22a copy of the GCC Runtime Library Exception along with this program;
23see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24<http://www.gnu.org/licenses/>. */
25
26#include "tconfig.h"
27#include "tsystem.h"
28#include "coretypes.h"
29#include "tm.h"
30
31/* If inhibit_libc is defined, we can not compile this file. The
32 effect is that people will not be able to use -fsplit-stack. That
33 is much better than failing the build particularly since people
34 will want to define inhibit_libc while building a compiler which
35 can build glibc. */
36
37#ifndef inhibit_libc
38
39#include <pthread.h>
40
41#include "generic-morestack.h"
42
43/* We declare the pthread functions we need as weak, so that
44 libgcc_s.so does not need to be linked against -lpthread. */
45
46extern int pthread_once (pthread_once_t *, void (*) (void))
47 __attribute__ ((weak));
48
49extern int pthread_key_create (pthread_key_t *, void (*) (void *))
50 __attribute__ ((weak));
51
52extern int pthread_setspecific (pthread_key_t, const void *)
53 __attribute__ ((weak));
54
55/* The key for the list of stack segments to free when the thread
56 exits. This is created by pthread_key_create. */
57
58static pthread_key_t segment_list_key;
59
60/* Used to only run create_key once. */
61
62static pthread_once_t create_key_once = PTHREAD_ONCE_INIT;
63
64/* Release all the segments for a thread. This is the destructor
65 function used by pthread_key_create, and is called when a thread
66 exits. */
67
68static void
69free_segments (void* arg)
70{
71 __morestack_release_segments ((struct stack_segment **) arg, 1);
72}
73
74/* Set up the key for the list of segments. This is called via
75 pthread_once. */
76
77static void
78create_key (void)
79{
80 int err;
81
82 err = pthread_key_create (&segment_list_key, free_segments);
83 if (err != 0)
84 {
85 static const char msg[] = "pthread_key_create failed: errno ";
86 __morestack_fail (msg, sizeof msg - 1, err);
87 }
88}
89
90/* Pass information from the pthread_create wrapper to
91 stack_split_initialize_thread. */
92
93struct pthread_create_args
94{
95 void *(*start_routine) (void *);
96 void *arg;
97};
98
99/* Initialize a thread. This is called via pthread_create. It calls
100 a target dependent function to set up any required stack guard. */
101
102static void* stack_split_initialize_thread (void *)
103 __attribute__ ((no_split_stack));
104
105static void *
106stack_split_initialize_thread (void *varg)
107{
108 struct pthread_create_args *args = (struct pthread_create_args *) varg;
109 int err;
110 void *(*start_routine) (void *);
111 void *arg;
112
113 __stack_split_initialize ();
114
115 err = pthread_setspecific (segment_list_key, (void *) &__morestack_segments);
116 if (err != 0)
117 {
118 static const char msg[] = "pthread_setspecific failed: errno ";
119 __morestack_fail (msg, sizeof msg - 1, err);
120 }
121
122 start_routine = args->start_routine;
123 arg = args->arg;
124 free (args);
125 return (*start_routine) (arg);
126}
127
128/* This function wraps calls to pthread_create to make sure that the
129 stack guard is initialized for new threads. FIXME: This hack will
130 not be necessary if glibc supports -fsplit-stack directly. */
131
132int __wrap_pthread_create (pthread_t *, const pthread_attr_t *,
133 void *(*start_routine) (void *), void *)
134 __attribute__ ((visibility ("hidden")));
135
136extern int __real_pthread_create (pthread_t *, const pthread_attr_t *,
137 void *(*start_routine) (void *), void *)
138 __attribute__ ((weak));
139
140int
141__wrap_pthread_create (pthread_t *tid, const pthread_attr_t *attr,
142 void *(*start_routine) (void *), void *arg)
143{
144 int err;
145 struct pthread_create_args* args;
146
147 err = pthread_once (&create_key_once, create_key);
148 if (err != 0)
149 {
150 static const char msg[] = "pthread_once failed: errno ";
151 __morestack_fail (msg, sizeof msg - 1, err);
152 }
153
154 args = malloc (sizeof (struct pthread_create_args));
155 if (args == NULL)
156 return EAGAIN;
157 args->start_routine = start_routine;
158 args->arg = arg;
159 return __real_pthread_create (tid, attr, stack_split_initialize_thread, args);
160}
161
162#endif /* !defined (inhibit_libc) */
This page took 0.048448 seconds and 5 git commands to generate.