Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6515 serge 1
/* Thread library support for -fsplit-stack.  */
2
/* Copyright (C) 2009-2015 Free Software Foundation, Inc.
3
   Contributed by Ian Lance Taylor .
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
.  */
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 
41
#include 
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) */