~ubuntu-branches/ubuntu/utopic/eglibc/utopic

« back to all changes in this revision

Viewing changes to libpthread/pthread/pt-create.c

  • Committer: Package Import Robot
  • Author(s): Adam Conrad
  • Date: 2012-10-26 05:14:58 UTC
  • mfrom: (1.5.1) (4.4.22 experimental)
  • Revision ID: package-import@ubuntu.com-20121026051458-oryotr4i03ob5pab
Tags: 2.16-0ubuntu1
* Merge with unreleased 2.16 in Debian experimental, remaining changes:
  - Drop the Breaks line from libc6, which refers to a Debian transition
  - Remove the libc6 recommends on libc6-i686, which we don't build
  - Enable libc6{,-dev}-armel on armhf and libc6{-dev}-armhf on armel
  - Ship update-locale and validlocale in /usr/sbin in libc-bin
  - Don't build locales or locales-all in Ubuntu, we rely on langpacks
  - Heavily mangle the way we do service restarting on major upgrades
  - Use different MIN_KERNEL_SUPPORTED versions than Debian, due to
    buildd needs.  This should be universally bumped to 3.2.0 once all
    our buildds (including the PPA guests) are running precise kernels
  - Build i386 variants as -march=i686, build amd64 with -O3, and build
    ppc64 variants (both 64-bit and 32-bit) with -O3 -fno-tree-vectorize
  - Re-enable unsubmitted-ldconfig-cache-abi.diff and rebuild the cache
    on upgrades from previous versions that used a different constant
  - debian/patches/any/local-CVE-2012-3406.diff: switch to malloc when
    array grows too large to handle via alloca extension (CVE-2012-3406)
  - Build generic i386/i686 flavour with -mno-tls-direct-seg-refs
* Changes added/dropped with this merge while reducing our delta:
  - Stop building glibc docs from the eglibc source, and instead make
    the glibc-docs stub have a hard dependency on glibc-doc-reference
  - Remove outdated conflicts against ancient versions of ia32-libs
  - Drop the tzdata dependency from libc6, it's in required and minimal
  - Use gcc-4.7/g++-4.7 by default on all our supported architectures
  - Save our historical changelog as changelog.ubuntu in the source
  - Drop nscd's libaudit build-dep for now, as libaudit is in universe
  - Drop the unnecessary Breaks from libc6 to locales and locales-all
  - Ship xen's ld.so.conf.d snippet as /etc/ld.so.conf.d/libc6-xen.conf
* Disable hard failures on the test suite for the first upload to raring

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Thread creation.
 
2
   Copyright (C) 2000, 2002, 2005, 2007 Free Software Foundation, Inc.
 
3
   This file is part of the GNU C Library.
 
4
 
 
5
   The GNU C Library is free software; you can redistribute it and/or
 
6
   modify it under the terms of the GNU Library General Public License as
 
7
   published by the Free Software Foundation; either version 2 of the
 
8
   License, or (at your option) any later version.
 
9
 
 
10
   The GNU C Library is distributed in the hope that it will be useful,
 
11
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
   Library General Public License for more details.
 
14
 
 
15
   You should have received a copy of the GNU Library General Public
 
16
   License along with the GNU C Library; see the file COPYING.LIB.  If not,
 
17
   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
18
   Boston, MA 02111-1307, USA.  */
 
19
 
 
20
#include <assert.h>
 
21
#include <errno.h>
 
22
#include <pthread.h>
 
23
#include <signal.h>
 
24
 
 
25
#include <bits/pt-atomic.h>
 
26
 
 
27
#include <pt-internal.h>
 
28
 
 
29
#ifdef HAVE_USELOCALE
 
30
# include <locale.h>
 
31
#endif
 
32
 
 
33
/* The total number of pthreads currently active.  This is defined
 
34
   here since it would be really stupid to have a threads-using
 
35
   program that doesn't call `pthread_create'.  */
 
36
__atomic_t __pthread_total;
 
37
 
 
38
 
 
39
/* The entry-point for new threads.  */
 
40
static void
 
41
entry_point (void *(*start_routine)(void *), void *arg)
 
42
{
 
43
#ifdef HAVE_USELOCALE
 
44
  /* A fresh thread needs to be bound to the global locale.  */
 
45
  uselocale (LC_GLOBAL_LOCALE);
 
46
#endif
 
47
 
 
48
  __pthread_startup ();
 
49
 
 
50
  pthread_exit (start_routine (arg));
 
51
}
 
52
 
 
53
/* Create a thread with attributes given by ATTR, executing
 
54
   START_ROUTINE with argument ARG.  */
 
55
int
 
56
pthread_create (pthread_t *thread, const pthread_attr_t *attr,
 
57
                void *(*start_routine)(void *), void *arg)
 
58
{
 
59
  int err;
 
60
  struct __pthread *pthread;
 
61
 
 
62
  err = __pthread_create_internal (&pthread, attr, start_routine, arg);
 
63
  if (! err)
 
64
    *thread = pthread->thread;
 
65
 
 
66
  return err;
 
67
}
 
68
 
 
69
/* Internal version of pthread_create.  See comment in
 
70
   pt-internal.h.  */
 
71
int
 
72
__pthread_create_internal (struct __pthread **thread,
 
73
                           const pthread_attr_t *attr,
 
74
                           void *(*start_routine)(void *), void *arg)
 
75
{
 
76
  int err;
 
77
  struct __pthread *pthread;
 
78
  const struct __pthread_attr *setup;
 
79
  sigset_t sigset;
 
80
 
 
81
  /* Allocate a new thread structure.  */
 
82
  err = __pthread_alloc (&pthread);
 
83
  if (err)
 
84
    goto failed;
 
85
 
 
86
  /* Use the default attributes if ATTR is NULL.  */
 
87
  setup = attr ? attr : &__pthread_default_attr;
 
88
 
 
89
  /* Initialize the thread state.  */
 
90
  pthread->state = (setup->detachstate == PTHREAD_CREATE_DETACHED
 
91
                    ? PTHREAD_DETACHED : PTHREAD_JOINABLE);
 
92
 
 
93
  /* If the user supplied a stack, it is not our responsibility to
 
94
     setup a stack guard.  */
 
95
  if (setup->stackaddr)
 
96
    pthread->guardsize = 0;
 
97
  else
 
98
    pthread->guardsize = (setup->guardsize <= setup->stacksize
 
99
                          ? setup->guardsize : setup->stacksize);
 
100
 
 
101
  /* Find a stack.  There are several scenarios: if a detached thread
 
102
     kills itself, it has no way to deallocate its stack, thus it
 
103
     leaves PTHREAD->stack set to true.  We try to reuse it here,
 
104
     however, if the user supplied a stack, we cannot use the old one.
 
105
     Right now, we simply deallocate it.  */
 
106
  if (pthread->stack)
 
107
    {
 
108
      if (setup->stackaddr != __pthread_default_attr.stackaddr)
 
109
        {
 
110
          __pthread_stack_dealloc (pthread->stackaddr,
 
111
                                   pthread->stacksize);
 
112
          pthread->stackaddr = setup->stackaddr;
 
113
          pthread->stacksize = setup->stacksize;
 
114
        }
 
115
    }
 
116
  else
 
117
    {
 
118
      err = __pthread_stack_alloc (&pthread->stackaddr,
 
119
                                   setup->stacksize);
 
120
      if (err)
 
121
        goto failed_stack_alloc;
 
122
 
 
123
      pthread->stacksize = setup->stacksize;
 
124
      pthread->stack = 1;
 
125
    }
 
126
 
 
127
  /* Allocate the kernel thread and other required resources.  */
 
128
  err = __pthread_thread_alloc (pthread);
 
129
  if (err)
 
130
    goto failed_thread_alloc;
 
131
 
 
132
#ifdef ENABLE_TLS
 
133
  pthread->tcb = _dl_allocate_tls (NULL);
 
134
  if (!pthread->tcb)
 
135
    goto failed_thread_tls_alloc;
 
136
  pthread->tcb->tcb = pthread->tcb;
 
137
#endif /* ENABLE_TLS */
 
138
 
 
139
  /* And initialize the rest of the machine context.  This may include
 
140
     additional machine- and system-specific initializations that
 
141
     prove convenient.  */
 
142
  err = __pthread_setup (pthread, entry_point, start_routine, arg);
 
143
  if (err)
 
144
    goto failed_setup;
 
145
 
 
146
  /* Initialize the system-specific signal state for the new
 
147
     thread.  */
 
148
  err = __pthread_sigstate_init (pthread);
 
149
  if (err)
 
150
    goto failed_sigstate;
 
151
 
 
152
  /* Set the new thread's signal mask and set the pending signals to
 
153
     empty.  POSIX says: "The signal mask shall be inherited from the
 
154
     creating thread.  The set of signals pending for the new thread
 
155
     shall be empty."  If the currnet thread is not a pthread then we
 
156
     just inherit the process' sigmask.  */
 
157
  if (__pthread_num_threads == 1)
 
158
    err = sigprocmask (0, 0, &sigset);
 
159
  else
 
160
    err = __pthread_sigstate (_pthread_self (), 0, 0, &sigset, 0);
 
161
  assert_perror (err);
 
162
 
 
163
  err = __pthread_sigstate (pthread, SIG_SETMASK, &sigset, 0, 1);
 
164
  assert_perror (err);
 
165
 
 
166
  /* Increase the total number of threads.  We do this before actually
 
167
     starting the new thread, since the new thread might immediately
 
168
     call `pthread_exit' which decreases the number of threads and
 
169
     calls `exit' if the number of threads reaches zero.  Increasing
 
170
     the number of threads from within the new thread isn't an option
 
171
     since this thread might return and call `pthread_exit' before the
 
172
     new thread runs.  */
 
173
  __atomic_inc (&__pthread_total);
 
174
 
 
175
  /* Store a pointer to this thread in the thread ID lookup table.  We
 
176
     could use __thread_setid, however, we only lock for reading as no
 
177
     other thread should be using this entry (we also assume that the
 
178
     store is atomic).  */
 
179
  pthread_rwlock_rdlock (&__pthread_threads_lock);
 
180
  __pthread_threads[pthread->thread - 1] = pthread;
 
181
  pthread_rwlock_unlock (&__pthread_threads_lock);
 
182
 
 
183
  /* At this point it is possible to guess our pthread ID.  We have to
 
184
     make sure that all functions taking a pthread_t argument can
 
185
     handle the fact that this thread isn't really running yet.  */
 
186
 
 
187
  /* Schedule the new thread.  */
 
188
  err = __pthread_thread_start (pthread);
 
189
  if (err)
 
190
    goto failed_starting;
 
191
 
 
192
  /* At this point the new thread is up and running.  */
 
193
 
 
194
  *thread = pthread;
 
195
 
 
196
  return 0;
 
197
 
 
198
 failed_starting:
 
199
  __pthread_setid (pthread->thread, NULL);
 
200
  __atomic_dec (&__pthread_total);
 
201
 failed_sigstate:
 
202
  __pthread_sigstate_destroy (pthread);
 
203
 failed_setup:
 
204
#ifdef ENABLE_TLS
 
205
  _dl_deallocate_tls (pthread->tcb, 1);
 
206
 failed_thread_tls_alloc:
 
207
#endif /* ENABLE_TLS */
 
208
  __pthread_thread_dealloc (pthread);
 
209
  __pthread_thread_halt (pthread);
 
210
 failed_thread_alloc:
 
211
  __pthread_stack_dealloc (pthread->stackaddr, pthread->stacksize);
 
212
  pthread->stack = 0;
 
213
 failed_stack_alloc:
 
214
  __pthread_dealloc (pthread);
 
215
 failed:
 
216
  return err;
 
217
}