]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgcc/generic-morestack-thread.c
tree-optimization/95495 - use SLP_TREE_REPRESENTATIVE in assertion
[thirdparty/gcc.git] / libgcc / generic-morestack-thread.c
CommitLineData
7458026b 1/* Thread library support for -fsplit-stack. */
8d9254fc 2/* Copyright (C) 2009-2020 Free Software Foundation, Inc.
7458026b
ILT
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"
852b75ed 30#include "libgcc_tm.h"
7458026b 31
67914693 32/* If inhibit_libc is defined, we cannot compile this file. The
7458026b
ILT
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
b5204884 40#include <errno.h>
7458026b
ILT
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
48extern int pthread_once (pthread_once_t *, void (*) (void))
49 __attribute__ ((weak));
50
51extern int pthread_key_create (pthread_key_t *, void (*) (void *))
52 __attribute__ ((weak));
53
54extern 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
60static pthread_key_t segment_list_key;
61
62/* Used to only run create_key once. */
63
64static 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
70static void
71free_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
79static void
80create_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
95struct 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
104static void* stack_split_initialize_thread (void *)
105 __attribute__ ((no_split_stack));
106
107static void *
108stack_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
134int __wrap_pthread_create (pthread_t *, const pthread_attr_t *,
135 void *(*start_routine) (void *), void *)
136 __attribute__ ((visibility ("hidden")));
137
138extern int __real_pthread_create (pthread_t *, const pthread_attr_t *,
4bd18fae
ILT
139 void *(*start_routine) (void *), void *)
140 __attribute__ ((weak));
7458026b
ILT
141
142int
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) */