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