OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [uClibc/] [libpthread/] [linuxthreads/] [pthread.c] - Blame information for rev 1325

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1325 phoenix
/* Linuxthreads - a simple clone()-based implementation of Posix        */
2
/* threads for Linux.                                                   */
3
/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
4
/*                                                                      */
5
/* This program is free software; you can redistribute it and/or        */
6
/* modify it under the terms of the GNU Library General Public License  */
7
/* as published by the Free Software Foundation; either version 2       */
8
/* of the License, or (at your option) any later version.               */
9
/*                                                                      */
10
/* This program 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        */
13
/* GNU Library General Public License for more details.                 */
14
 
15
/* Thread creation, initialization, and basic low-level routines */
16
 
17
#define __FORCE_GLIBC
18
#include <features.h>
19
#define __USE_GNU
20
#include <errno.h>
21
#include <netdb.h>      /* for h_errno */
22
#include <stddef.h>
23
#include <stdio.h>
24
#include <stdlib.h>
25
#include <string.h>
26
#include <unistd.h>
27
#include <fcntl.h>
28
#include <sys/wait.h>
29
#include <sys/resource.h>
30
#include "pthread.h"
31
#include "internals.h"
32
#include "spinlock.h"
33
#include "restart.h"
34
#include "debug.h"      /* added to linuxthreads -StS */
35
 
36
 
37
/* Mods for uClibc: Some includes */
38
#include <signal.h>
39
#include <sys/types.h>
40
#include <sys/syscall.h>
41
 
42
/* mods for uClibc: getpwd and getpagesize are the syscalls */
43
#define __getpid getpid
44
#define __getpagesize getpagesize
45
/* mods for uClibc: __libc_sigaction is not in any standard headers */
46
extern int __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact);
47
 
48
 
49
/* These variables are used by the setup code.  */
50
extern int _errno;
51
extern int _h_errno;
52
 
53
 
54
/* Descriptor of the initial thread */
55
 
56
struct _pthread_descr_struct __pthread_initial_thread = {
57
  &__pthread_initial_thread,  /* pthread_descr p_nextlive */
58
  &__pthread_initial_thread,  /* pthread_descr p_prevlive */
59
  NULL,                       /* pthread_descr p_nextwaiting */
60
  NULL,                       /* pthread_descr p_nextlock */
61
  PTHREAD_THREADS_MAX,        /* pthread_t p_tid */
62
  0,                          /* int p_pid */
63
  0,                          /* int p_priority */
64
  &__pthread_handles[0].h_lock, /* struct _pthread_fastlock * p_lock */
65
  0,                          /* int p_signal */
66
  NULL,                       /* sigjmp_buf * p_signal_buf */
67
  NULL,                       /* sigjmp_buf * p_cancel_buf */
68
  0,                          /* char p_terminated */
69
  0,                          /* char p_detached */
70
  0,                          /* char p_exited */
71
  NULL,                       /* void * p_retval */
72
  0,                          /* int p_retval */
73
  NULL,                       /* pthread_descr p_joining */
74
  NULL,                       /* struct _pthread_cleanup_buffer * p_cleanup */
75
  0,                          /* char p_cancelstate */
76
  0,                          /* char p_canceltype */
77
  0,                          /* char p_canceled */
78
  &_errno,                       /* int *p_errnop */
79
  0,                          /* int p_errno */
80
  &_h_errno,                       /* int *p_h_errnop */
81
  0,                          /* int p_h_errno */
82
  NULL,                       /* char * p_in_sighandler */
83
  0,                          /* char p_sigwaiting */
84
  PTHREAD_START_ARGS_INITIALIZER, /* struct pthread_start_args p_start_args */
85
  {NULL},                     /* void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE] */
86
  {NULL},                     /* void * p_libc_specific[_LIBC_TSD_KEY_N] */
87
  0,                          /* int p_userstack */
88
  NULL,                       /* void * p_guardaddr */
89
  0,                          /* size_t p_guardsize */
90
  &__pthread_initial_thread,  /* pthread_descr p_self */
91
  0,                          /* Always index 0 */
92
  0,                          /* int p_report_events */
93
  {{{0, }}, 0, NULL},         /* td_eventbuf_t p_eventbuf */
94
  __ATOMIC_INITIALIZER,         /* struct pthread_atomic p_resume_count */
95
  0,                          /* char p_woken_by_cancel */
96
  0,                          /* char p_condvar_avail */
97
  0,                          /* char p_sem_avail */
98
  NULL,                       /* struct pthread_extricate_if *p_extricate */
99
  NULL,                       /* pthread_readlock_info *p_readlock_list; */
100
  NULL,                       /* pthread_readlock_info *p_readlock_free; */
101
 
102
#ifdef __UCLIBC_HAS_XLOCALE__
103
  ,
104
  NULL,                       /* __locale_t locale; */
105
#endif /* __UCLIBC_HAS_XLOCALE__ */
106
};
107
 
108
/* Descriptor of the manager thread; none of this is used but the error
109
   variables, the p_pid and p_priority fields,
110
   and the address for identification.  */
111
#define manager_thread (&__pthread_manager_thread)
112
struct _pthread_descr_struct __pthread_manager_thread = {
113
  NULL,                       /* pthread_descr p_nextlive */
114
  NULL,                       /* pthread_descr p_prevlive */
115
  NULL,                       /* pthread_descr p_nextwaiting */
116
  NULL,                       /* pthread_descr p_nextlock */
117
  0,                          /* int p_tid */
118
  0,                          /* int p_pid */
119
  0,                          /* int p_priority */
120
  &__pthread_handles[1].h_lock, /* struct _pthread_fastlock * p_lock */
121
  0,                          /* int p_signal */
122
  NULL,                       /* sigjmp_buf * p_signal_buf */
123
  NULL,                       /* sigjmp_buf * p_cancel_buf */
124
  0,                          /* char p_terminated */
125
  0,                          /* char p_detached */
126
  0,                          /* char p_exited */
127
  NULL,                       /* void * p_retval */
128
  0,                          /* int p_retval */
129
  NULL,                       /* pthread_descr p_joining */
130
  NULL,                       /* struct _pthread_cleanup_buffer * p_cleanup */
131
  0,                          /* char p_cancelstate */
132
  0,                          /* char p_canceltype */
133
  0,                          /* char p_canceled */
134
  &__pthread_manager_thread.p_errno, /* int *p_errnop */
135
  0,                          /* int p_errno */
136
  NULL,                       /* int *p_h_errnop */
137
  0,                          /* int p_h_errno */
138
  NULL,                       /* char * p_in_sighandler */
139
  0,                          /* char p_sigwaiting */
140
  PTHREAD_START_ARGS_INITIALIZER, /* struct pthread_start_args p_start_args */
141
  {NULL},                     /* void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE] */
142
  {NULL},                     /* void * p_libc_specific[_LIBC_TSD_KEY_N] */
143
  0,                          /* int p_userstack */
144
  NULL,                       /* void * p_guardaddr */
145
  0,                          /* size_t p_guardsize */
146
  &__pthread_manager_thread,  /* pthread_descr p_self */
147
  1,                          /* Always index 1 */
148
  0,                          /* int p_report_events */
149
  {{{0, }}, 0, NULL},         /* td_eventbuf_t p_eventbuf */
150
  __ATOMIC_INITIALIZER,         /* struct pthread_atomic p_resume_count */
151
  0,                          /* char p_woken_by_cancel */
152
  0,                          /* char p_condvar_avail */
153
  0,                          /* char p_sem_avail */
154
  NULL,                       /* struct pthread_extricate_if *p_extricate */
155
  NULL,                       /* pthread_readlock_info *p_readlock_list; */
156
  NULL,                       /* pthread_readlock_info *p_readlock_free; */
157
 
158
#ifdef __UCLIBC_HAS_XLOCALE__
159
  ,
160
  NULL,                       /* __locale_t locale; */
161
#endif /* __UCLIBC_HAS_XLOCALE__ */
162
};
163
 
164
/* Pointer to the main thread (the father of the thread manager thread) */
165
/* Originally, this is the initial thread, but this changes after fork() */
166
 
167
pthread_descr __pthread_main_thread = &__pthread_initial_thread;
168
 
169
/* Limit between the stack of the initial thread (above) and the
170
   stacks of other threads (below). Aligned on a STACK_SIZE boundary. */
171
 
172
char *__pthread_initial_thread_bos = NULL;
173
 
174
/* For non-MMU systems also remember to stack top of the initial thread.
175
 * This is adapted when other stacks are malloc'ed since we don't know
176
 * the bounds a-priori. -StS */
177
 
178
#ifndef __UCLIBC_HAS_MMU__
179
char *__pthread_initial_thread_tos = NULL;
180
#endif /* __UCLIBC_HAS_MMU__ */
181
 
182
/* File descriptor for sending requests to the thread manager. */
183
/* Initially -1, meaning that the thread manager is not running. */
184
 
185
int __pthread_manager_request = -1;
186
 
187
/* Other end of the pipe for sending requests to the thread manager. */
188
 
189
int __pthread_manager_reader;
190
 
191
/* Limits of the thread manager stack */
192
 
193
char *__pthread_manager_thread_bos = NULL;
194
char *__pthread_manager_thread_tos = NULL;
195
 
196
/* For process-wide exit() */
197
 
198
int __pthread_exit_requested = 0;
199
int __pthread_exit_code = 0;
200
 
201
/* Communicate relevant LinuxThreads constants to gdb */
202
 
203
const int __pthread_threads_max = PTHREAD_THREADS_MAX;
204
const int __pthread_sizeof_handle = sizeof(struct pthread_handle_struct);
205
const int __pthread_offsetof_descr = offsetof(struct pthread_handle_struct, h_descr);
206
const int __pthread_offsetof_pid = offsetof(struct _pthread_descr_struct,
207
                                            p_pid);
208
const int __linuxthreads_pthread_sizeof_descr
209
  = sizeof(struct _pthread_descr_struct);
210
 
211
const int __linuxthreads_initial_report_events;
212
 
213
const char __linuxthreads_version[] = VERSION;
214
 
215
/* Forward declarations */
216
static void pthread_onexit_process(int retcode, void *arg);
217
static void pthread_handle_sigcancel(int sig);
218
static void pthread_handle_sigrestart(int sig);
219
static void pthread_handle_sigdebug(int sig);
220
int __pthread_timedsuspend_new(pthread_descr self, const struct timespec *abstime);
221
 
222
/* Signal numbers used for the communication.
223
   In these variables we keep track of the used variables.  If the
224
   platform does not support any real-time signals we will define the
225
   values to some unreasonable value which will signal failing of all
226
   the functions below.  */
227
#ifndef __NR_rt_sigaction
228
static int current_rtmin = -1;
229
static int current_rtmax = -1;
230
int __pthread_sig_restart = SIGUSR1;
231
int __pthread_sig_cancel = SIGUSR2;
232
int __pthread_sig_debug;
233
#else
234
 
235
#if __SIGRTMAX - __SIGRTMIN >= 3
236
static int current_rtmin = __SIGRTMIN + 3;
237
static int current_rtmax = __SIGRTMAX;
238
int __pthread_sig_restart = __SIGRTMIN;
239
int __pthread_sig_cancel = __SIGRTMIN + 1;
240
int __pthread_sig_debug = __SIGRTMIN + 2;
241
void (*__pthread_restart)(pthread_descr) = __pthread_restart_new;
242
void (*__pthread_suspend)(pthread_descr) = __pthread_wait_for_restart_signal;
243
int (*__pthread_timedsuspend)(pthread_descr, const struct timespec *) = __pthread_timedsuspend_new;
244
#else
245
static int current_rtmin = __SIGRTMIN;
246
static int current_rtmax = __SIGRTMAX;
247
int __pthread_sig_restart = SIGUSR1;
248
int __pthread_sig_cancel = SIGUSR2;
249
int __pthread_sig_debug;
250
void (*__pthread_restart)(pthread_descr) = __pthread_restart_old;
251
void (*__pthread_suspend)(pthread_descr) = __pthread_suspend_old;
252
int (*__pthread_timedsuspend)(pthread_descr, const struct timespec *) = __pthread_timedsuspend_old;
253
 
254
#endif
255
 
256
/* Return number of available real-time signal with highest priority.  */
257
int __libc_current_sigrtmin (void)
258
{
259
    return current_rtmin;
260
}
261
 
262
/* Return number of available real-time signal with lowest priority.  */
263
int __libc_current_sigrtmax (void)
264
{
265
    return current_rtmax;
266
}
267
 
268
/* Allocate real-time signal with highest/lowest available
269
   priority.  Please note that we don't use a lock since we assume
270
   this function to be called at program start.  */
271
int __libc_allocate_rtsig (int high)
272
{
273
    if (current_rtmin == -1 || current_rtmin > current_rtmax)
274
        /* We don't have anymore signal available.  */
275
        return -1;
276
    return high ? current_rtmin++ : current_rtmax--;
277
}
278
#endif
279
 
280
/* Initialize the pthread library.
281
   Initialization is split in two functions:
282
   - a constructor function that blocks the __pthread_sig_restart signal
283
     (must do this very early, since the program could capture the signal
284
      mask with e.g. sigsetjmp before creating the first thread);
285
   - a regular function called from pthread_create when needed. */
286
 
287
static void pthread_initialize(void) __attribute__((constructor));
288
 
289
 /* Do some minimal initialization which has to be done during the
290
    startup of the C library.  */
291
void __pthread_initialize_minimal(void)
292
{
293
    /* If we have special thread_self processing, initialize
294
     * that for the main thread now.  */
295
#ifdef INIT_THREAD_SELF
296
    INIT_THREAD_SELF(&__pthread_initial_thread, 0);
297
#endif
298
}
299
 
300
 
301
static void pthread_initialize(void)
302
{
303
  struct sigaction sa;
304
  sigset_t mask;
305
  struct rlimit limit;
306
  int max_stack;
307
 
308
  /* If already done (e.g. by a constructor called earlier!), bail out */
309
  if (__pthread_initial_thread_bos != NULL) return;
310
#ifdef TEST_FOR_COMPARE_AND_SWAP
311
  /* Test if compare-and-swap is available */
312
  __pthread_has_cas = compare_and_swap_is_available();
313
#endif
314
  /* For the initial stack, reserve at least STACK_SIZE bytes of stack
315
     below the current stack address, and align that on a
316
     STACK_SIZE boundary. */
317
  __pthread_initial_thread_bos =
318
    (char *)(((long)CURRENT_STACK_FRAME - 2 * STACK_SIZE) & ~(STACK_SIZE - 1));
319
  /* Update the descriptor for the initial thread. */
320
  __pthread_initial_thread.p_pid = __getpid();
321
  /* If we have special thread_self processing, initialize that for the
322
     main thread now.  */
323
#ifdef INIT_THREAD_SELF
324
  INIT_THREAD_SELF(&__pthread_initial_thread, 0);
325
#endif
326
  /* The errno/h_errno variable of the main thread are the global ones.  */
327
  __pthread_initial_thread.p_errnop = &_errno;
328
  __pthread_initial_thread.p_h_errnop = &_h_errno;
329
 
330
#ifdef __UCLIBC_HAS_XLOCALE__
331
  /* The locale of the main thread is the current locale in use. */
332
  __pthread_initial_thread.locale = __curlocale_var;
333
#endif /* __UCLIBC_HAS_XLOCALE__ */
334
 
335
  /* Play with the stack size limit to make sure that no stack ever grows
336
     beyond STACK_SIZE minus two pages (one page for the thread descriptor
337
     immediately beyond, and one page to act as a guard page). */
338
 
339
#ifdef __UCLIBC_HAS_MMU__
340
  /* We cannot allocate a huge chunk of memory to mmap all thread stacks later
341
   * on a non-MMU system. Thus, we don't need the rlimit either. -StS */
342
  getrlimit(RLIMIT_STACK, &limit);
343
  max_stack = STACK_SIZE - 2 * __getpagesize();
344
  if (limit.rlim_cur > max_stack) {
345
    limit.rlim_cur = max_stack;
346
    setrlimit(RLIMIT_STACK, &limit);
347
  }
348
#else
349
  /* For non-MMU assume __pthread_initial_thread_tos at upper page boundary, and
350
   * __pthread_initial_thread_bos at address 0. These bounds are refined as we
351
   * malloc other stack frames such that they don't overlap. -StS
352
   */
353
  __pthread_initial_thread_tos =
354
    (char *)(((long)CURRENT_STACK_FRAME + __getpagesize()) & ~(__getpagesize() - 1));
355
  __pthread_initial_thread_bos = (char *) 1; /* set it non-zero so we know we have been here */
356
  PDEBUG("initial thread stack bounds: bos=%p, tos=%p\n",
357
         __pthread_initial_thread_bos, __pthread_initial_thread_tos);
358
#endif /* __UCLIBC_HAS_MMU__ */
359
 
360
  /* Setup signal handlers for the initial thread.
361
     Since signal handlers are shared between threads, these settings
362
     will be inherited by all other threads. */
363
  sa.sa_handler = pthread_handle_sigrestart;
364
  sigemptyset(&sa.sa_mask);
365
  sa.sa_flags = 0;
366
  __libc_sigaction(__pthread_sig_restart, &sa, NULL);
367
  sa.sa_handler = pthread_handle_sigcancel;
368
  // sa.sa_flags = 0;
369
  __libc_sigaction(__pthread_sig_cancel, &sa, NULL);
370
  if (__pthread_sig_debug > 0) {
371
      sa.sa_handler = pthread_handle_sigdebug;
372
      sigemptyset(&sa.sa_mask);
373
      // sa.sa_flags = 0;
374
      __libc_sigaction(__pthread_sig_debug, &sa, NULL);
375
  }
376
  /* Initially, block __pthread_sig_restart. Will be unblocked on demand. */
377
  sigemptyset(&mask);
378
  sigaddset(&mask, __pthread_sig_restart);
379
  sigprocmask(SIG_BLOCK, &mask, NULL);
380
  /* Register an exit function to kill all other threads. */
381
  /* Do it early so that user-registered atexit functions are called
382
     before pthread_onexit_process. */
383
  on_exit(pthread_onexit_process, NULL);
384
}
385
 
386
void __pthread_initialize(void)
387
{
388
  pthread_initialize();
389
}
390
 
391
int __pthread_initialize_manager(void)
392
{
393
  int manager_pipe[2];
394
  int pid;
395
  int report_events;
396
  struct pthread_request request;
397
 
398
  /* If basic initialization not done yet (e.g. we're called from a
399
     constructor run before our constructor), do it now */
400
  if (__pthread_initial_thread_bos == NULL) pthread_initialize();
401
  /* Setup stack for thread manager */
402
  __pthread_manager_thread_bos = malloc(THREAD_MANAGER_STACK_SIZE);
403
  if (__pthread_manager_thread_bos == NULL) return -1;
404
  __pthread_manager_thread_tos =
405
    __pthread_manager_thread_bos + THREAD_MANAGER_STACK_SIZE;
406
 
407
  /* On non-MMU systems we make sure that the initial thread bounds don't overlap
408
   * with the manager stack frame */
409
  NOMMU_INITIAL_THREAD_BOUNDS(__pthread_manager_thread_tos,__pthread_manager_thread_bos);
410
  PDEBUG("manager stack: size=%d, bos=%p, tos=%p\n", THREAD_MANAGER_STACK_SIZE,
411
         __pthread_manager_thread_bos, __pthread_manager_thread_tos);
412
#if 0
413
  PDEBUG("initial stack: estimate bos=%p, tos=%p\n",
414
         __pthread_initial_thread_bos, __pthread_initial_thread_tos);
415
#endif
416
 
417
  /* Setup pipe to communicate with thread manager */
418
  if (pipe(manager_pipe) == -1) {
419
    free(__pthread_manager_thread_bos);
420
    return -1;
421
  }
422
  /* Start the thread manager */
423
  pid = 0;
424
#ifdef USE_TLS
425
  if (__linuxthreads_initial_report_events != 0)
426
    THREAD_SETMEM (((pthread_descr) NULL), p_report_events,
427
                   __linuxthreads_initial_report_events);
428
  report_events = THREAD_GETMEM (((pthread_descr) NULL), p_report_events);
429
#else
430
  if (__linuxthreads_initial_report_events != 0)
431
    __pthread_initial_thread.p_report_events
432
      = __linuxthreads_initial_report_events;
433
  report_events = __pthread_initial_thread.p_report_events;
434
#endif
435
  if (__builtin_expect (report_events, 0))
436
    {
437
      /* It's a bit more complicated.  We have to report the creation of
438
         the manager thread.  */
439
      int idx = __td_eventword (TD_CREATE);
440
      uint32_t mask = __td_eventmask (TD_CREATE);
441
 
442
      if ((mask & (__pthread_threads_events.event_bits[idx]
443
                   | __pthread_initial_thread.p_eventbuf.eventmask.event_bits[idx]))
444
          != 0)
445
        {
446
 
447
         __pthread_lock(__pthread_manager_thread.p_lock, NULL);
448
 
449
          pid = clone(__pthread_manager_event,
450
                        (void **) __pthread_manager_thread_tos,
451
                        CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
452
                        (void *)(long)manager_pipe[0]);
453
 
454
          if (pid != -1)
455
            {
456
              /* Now fill in the information about the new thread in
457
                 the newly created thread's data structure.  We cannot let
458
                 the new thread do this since we don't know whether it was
459
                 already scheduled when we send the event.  */
460
              __pthread_manager_thread.p_eventbuf.eventdata =
461
                  &__pthread_manager_thread;
462
              __pthread_manager_thread.p_eventbuf.eventnum = TD_CREATE;
463
              __pthread_last_event = &__pthread_manager_thread;
464
              __pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1;
465
              __pthread_manager_thread.p_pid = pid;
466
 
467
              /* Now call the function which signals the event.  */
468
              __linuxthreads_create_event ();
469
            }
470
          /* Now restart the thread.  */
471
          __pthread_unlock(__pthread_manager_thread.p_lock);
472
        }
473
    }
474
 
475
  if (pid == 0) {
476
    pid = clone(__pthread_manager, (void **) __pthread_manager_thread_tos,
477
                  CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
478
                  (void *)(long)manager_pipe[0]);
479
  }
480
  if (pid == -1) {
481
    free(__pthread_manager_thread_bos);
482
    __libc_close(manager_pipe[0]);
483
    __libc_close(manager_pipe[1]);
484
    return -1;
485
  }
486
  __pthread_manager_request = manager_pipe[1]; /* writing end */
487
  __pthread_manager_reader = manager_pipe[0]; /* reading end */
488
  __pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1;
489
  __pthread_manager_thread.p_pid = pid;
490
 
491
  /* Make gdb aware of new thread manager */
492
  if (__pthread_threads_debug && __pthread_sig_debug > 0)
493
    {
494
      raise(__pthread_sig_debug);
495
      /* We suspend ourself and gdb will wake us up when it is
496
         ready to handle us. */
497
      __pthread_wait_for_restart_signal(thread_self());
498
    }
499
  /* Synchronize debugging of the thread manager */
500
PDEBUG("send REQ_DEBUG to manager thread\n");
501
  request.req_kind = REQ_DEBUG;
502
  TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request,
503
              (char *) &request, sizeof(request)));
504
  return 0;
505
}
506
 
507
/* Thread creation */
508
 
509
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
510
                         void * (*start_routine)(void *), void *arg)
511
{
512
  pthread_descr self = thread_self();
513
  struct pthread_request request;
514
  if (__pthread_manager_request < 0) {
515
    if (__pthread_initialize_manager() < 0) return EAGAIN;
516
  }
517
  request.req_thread = self;
518
  request.req_kind = REQ_CREATE;
519
  request.req_args.create.attr = attr;
520
  request.req_args.create.fn = start_routine;
521
  request.req_args.create.arg = arg;
522
  sigprocmask(SIG_SETMASK, (const sigset_t *) NULL,
523
              &request.req_args.create.mask);
524
  PDEBUG("write REQ_CREATE to manager thread\n");
525
  TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request,
526
              (char *) &request, sizeof(request)));
527
PDEBUG("before suspend(self)\n");
528
  suspend(self);
529
PDEBUG("after suspend(self)\n");
530
  if (THREAD_GETMEM(self, p_retcode) == 0)
531
    *thread = (pthread_t) THREAD_GETMEM(self, p_retval);
532
  return THREAD_GETMEM(self, p_retcode);
533
}
534
 
535
/* Simple operations on thread identifiers */
536
 
537
pthread_t pthread_self(void)
538
{
539
  pthread_descr self = thread_self();
540
  return THREAD_GETMEM(self, p_tid);
541
}
542
 
543
int pthread_equal(pthread_t thread1, pthread_t thread2)
544
{
545
  return thread1 == thread2;
546
}
547
 
548
/* Helper function for thread_self in the case of user-provided stacks */
549
 
550
#ifndef THREAD_SELF
551
 
552
pthread_descr __pthread_find_self()
553
{
554
  char * sp = CURRENT_STACK_FRAME;
555
  pthread_handle h;
556
 
557
  /* __pthread_handles[0] is the initial thread, __pthread_handles[1] is
558
     the manager threads handled specially in thread_self(), so start at 2 */
559
  h = __pthread_handles + 2;
560
  while (! (sp <= (char *) h->h_descr && sp >= h->h_bottom)) h++;
561
 
562
#ifdef DEBUG_PT
563
  if (h->h_descr == NULL) {
564
      printf("*** "__FUNCTION__" ERROR descriptor is NULL!!!!! ***\n\n");
565
      _exit(1);
566
  }
567
#endif
568
 
569
  return h->h_descr;
570
}
571
#else
572
 
573
static pthread_descr thread_self_stack(void)
574
{
575
    char *sp = CURRENT_STACK_FRAME;
576
    pthread_handle h;
577
 
578
    if (sp >= __pthread_manager_thread_bos && sp < __pthread_manager_thread_tos)
579
        return manager_thread;
580
    h = __pthread_handles + 2;
581
# ifdef USE_TLS
582
    while (h->h_descr == NULL
583
            || ! (sp <= (char *) h->h_descr->p_stackaddr && sp >= h->h_bottom))
584
        h++;
585
# else
586
    while (! (sp <= (char *) h->h_descr && sp >= h->h_bottom))
587
        h++;
588
# endif
589
    return h->h_descr;
590
}
591
 
592
#endif
593
 
594
/* Thread scheduling */
595
 
596
int pthread_setschedparam(pthread_t thread, int policy,
597
                          const struct sched_param *param)
598
{
599
  pthread_handle handle = thread_handle(thread);
600
  pthread_descr th;
601
 
602
  __pthread_lock(&handle->h_lock, NULL);
603
  if (invalid_handle(handle, thread)) {
604
    __pthread_unlock(&handle->h_lock);
605
    return ESRCH;
606
  }
607
  th = handle->h_descr;
608
  if (sched_setscheduler(th->p_pid, policy, param) == -1) {
609
    __pthread_unlock(&handle->h_lock);
610
    return errno;
611
  }
612
  th->p_priority = policy == SCHED_OTHER ? 0 : param->sched_priority;
613
  __pthread_unlock(&handle->h_lock);
614
  if (__pthread_manager_request >= 0)
615
    __pthread_manager_adjust_prio(th->p_priority);
616
  return 0;
617
}
618
 
619
int pthread_getschedparam(pthread_t thread, int *policy,
620
                          struct sched_param *param)
621
{
622
  pthread_handle handle = thread_handle(thread);
623
  int pid, pol;
624
 
625
  __pthread_lock(&handle->h_lock, NULL);
626
  if (invalid_handle(handle, thread)) {
627
    __pthread_unlock(&handle->h_lock);
628
    return ESRCH;
629
  }
630
  pid = handle->h_descr->p_pid;
631
  __pthread_unlock(&handle->h_lock);
632
  pol = sched_getscheduler(pid);
633
  if (pol == -1) return errno;
634
  if (sched_getparam(pid, param) == -1) return errno;
635
  *policy = pol;
636
  return 0;
637
}
638
 
639
/* Process-wide exit() request */
640
 
641
static void pthread_onexit_process(int retcode, void *arg)
642
{
643
    struct pthread_request request;
644
    pthread_descr self = thread_self();
645
 
646
    if (__pthread_manager_request >= 0) {
647
        request.req_thread = self;
648
        request.req_kind = REQ_PROCESS_EXIT;
649
        request.req_args.exit.code = retcode;
650
        TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request,
651
                    (char *) &request, sizeof(request)));
652
        suspend(self);
653
        /* Main thread should accumulate times for thread manager and its
654
           children, so that timings for main thread account for all threads. */
655
        if (self == __pthread_main_thread) {
656
            waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE);
657
            /* Since all threads have been asynchronously terminated
658
             * (possibly holding locks), free cannot be used any more.  */
659
            __pthread_manager_thread_bos = __pthread_manager_thread_tos = NULL;
660
        }
661
    }
662
}
663
 
664
/* The handler for the RESTART signal just records the signal received
665
   in the thread descriptor, and optionally performs a siglongjmp
666
   (for pthread_cond_timedwait). */
667
 
668
static void pthread_handle_sigrestart(int sig)
669
{
670
    pthread_descr self = thread_self();
671
    THREAD_SETMEM(self, p_signal, sig);
672
    if (THREAD_GETMEM(self, p_signal_jmp) != NULL)
673
        siglongjmp(*THREAD_GETMEM(self, p_signal_jmp), 1);
674
}
675
 
676
/* The handler for the CANCEL signal checks for cancellation
677
   (in asynchronous mode), for process-wide exit and exec requests.
678
   For the thread manager thread, redirect the signal to
679
   __pthread_manager_sighandler. */
680
 
681
static void pthread_handle_sigcancel(int sig)
682
{
683
  pthread_descr self = thread_self();
684
  sigjmp_buf * jmpbuf;
685
 
686
 
687
  if (self == &__pthread_manager_thread)
688
    {
689
#ifdef THREAD_SELF
690
      /* A new thread might get a cancel signal before it is fully
691
         initialized, so that the thread register might still point to the
692
         manager thread.  Double check that this is really the manager
693
         thread.  */
694
      pthread_descr real_self = thread_self_stack();
695
      if (real_self == &__pthread_manager_thread)
696
        {
697
          __pthread_manager_sighandler(sig);
698
          return;
699
        }
700
      /* Oops, thread_self() isn't working yet..  */
701
      self = real_self;
702
# ifdef INIT_THREAD_SELF
703
      INIT_THREAD_SELF(self, self->p_nr);
704
# endif
705
#else
706
      __pthread_manager_sighandler(sig);
707
      return;
708
#endif
709
    }
710
  if (__builtin_expect (__pthread_exit_requested, 0)) {
711
    /* Main thread should accumulate times for thread manager and its
712
       children, so that timings for main thread account for all threads. */
713
    if (self == __pthread_main_thread) {
714
#ifdef USE_TLS
715
      waitpid(__pthread_manager_thread->p_pid, NULL, __WCLONE);
716
#else
717
      waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE);
718
#endif
719
    }
720
    _exit(__pthread_exit_code);
721
  }
722
  if (__builtin_expect (THREAD_GETMEM(self, p_canceled), 0)
723
      && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
724
    if (THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS)
725
      pthread_exit(PTHREAD_CANCELED);
726
    jmpbuf = THREAD_GETMEM(self, p_cancel_jmp);
727
    if (jmpbuf != NULL) {
728
      THREAD_SETMEM(self, p_cancel_jmp, NULL);
729
      siglongjmp(*jmpbuf, 1);
730
    }
731
  }
732
}
733
 
734
/* Handler for the DEBUG signal.
735
   The debugging strategy is as follows:
736
   On reception of a REQ_DEBUG request (sent by new threads created to
737
   the thread manager under debugging mode), the thread manager throws
738
   __pthread_sig_debug to itself. The debugger (if active) intercepts
739
   this signal, takes into account new threads and continue execution
740
   of the thread manager by propagating the signal because it doesn't
741
   know what it is specifically done for. In the current implementation,
742
   the thread manager simply discards it. */
743
 
744
static void pthread_handle_sigdebug(int sig)
745
{
746
  /* Nothing */
747
}
748
 
749
/* Reset the state of the thread machinery after a fork().
750
   Close the pipe used for requests and set the main thread to the forked
751
   thread.
752
   Notice that we can't free the stack segments, as the forked thread
753
   may hold pointers into them. */
754
 
755
void __pthread_reset_main_thread()
756
{
757
  pthread_descr self = thread_self();
758
 
759
  if (__pthread_manager_request != -1) {
760
    /* Free the thread manager stack */
761
    free(__pthread_manager_thread_bos);
762
    __pthread_manager_thread_bos = __pthread_manager_thread_tos = NULL;
763
    /* Close the two ends of the pipe */
764
    __libc_close(__pthread_manager_request);
765
    __libc_close(__pthread_manager_reader);
766
    __pthread_manager_request = __pthread_manager_reader = -1;
767
  }
768
 
769
  /* Update the pid of the main thread */
770
  THREAD_SETMEM(self, p_pid, __getpid());
771
  /* Make the forked thread the main thread */
772
  __pthread_main_thread = self;
773
  THREAD_SETMEM(self, p_nextlive, self);
774
  THREAD_SETMEM(self, p_prevlive, self);
775
  /* Now this thread modifies the global variables.  */
776
  THREAD_SETMEM(self, p_errnop, &_errno);
777
  THREAD_SETMEM(self, p_h_errnop, &_h_errno);
778
}
779
 
780
/* Process-wide exec() request */
781
 
782
void __pthread_kill_other_threads_np(void)
783
{
784
  struct sigaction sa;
785
  /* Terminate all other threads and thread manager */
786
  pthread_onexit_process(0, NULL);
787
  /* Make current thread the main thread in case the calling thread
788
     changes its mind, does not exec(), and creates new threads instead. */
789
  __pthread_reset_main_thread();
790
  /* Reset the signal handlers behaviour for the signals the
791
     implementation uses since this would be passed to the new
792
     process.  */
793
  sigemptyset(&sa.sa_mask);
794
  sa.sa_flags = 0;
795
  sa.sa_handler = SIG_DFL;
796
  __libc_sigaction(__pthread_sig_restart, &sa, NULL);
797
  __libc_sigaction(__pthread_sig_cancel, &sa, NULL);
798
  if (__pthread_sig_debug > 0)
799
    __libc_sigaction(__pthread_sig_debug, &sa, NULL);
800
}
801
weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np)
802
 
803
/* Concurrency symbol level.  */
804
static int current_level;
805
 
806
int __pthread_setconcurrency(int level)
807
{
808
  /* We don't do anything unless we have found a useful interpretation.  */
809
  current_level = level;
810
  return 0;
811
}
812
weak_alias (__pthread_setconcurrency, pthread_setconcurrency)
813
 
814
int __pthread_getconcurrency(void)
815
{
816
  return current_level;
817
}
818
weak_alias (__pthread_getconcurrency, pthread_getconcurrency)
819
 
820
 
821
/* Primitives for controlling thread execution */
822
 
823
void __pthread_wait_for_restart_signal(pthread_descr self)
824
{
825
    sigset_t mask;
826
 
827
    sigprocmask(SIG_SETMASK, NULL, &mask); /* Get current signal mask */
828
    sigdelset(&mask, __pthread_sig_restart); /* Unblock the restart signal */
829
    THREAD_SETMEM(self, p_signal, 0);
830
    do {
831
        sigsuspend(&mask);                   /* Wait for signal */
832
    } while (THREAD_GETMEM(self, p_signal) !=__pthread_sig_restart);
833
 
834
    READ_MEMORY_BARRIER(); /* See comment in __pthread_restart_new */
835
}
836
 
837
#ifndef __NR_rt_sigaction
838
/* The _old variants are for 2.0 and early 2.1 kernels which don't have RT
839
   signals.
840
   On these kernels, we use SIGUSR1 and SIGUSR2 for restart and cancellation.
841
   Since the restart signal does not queue, we use an atomic counter to create
842
   queuing semantics. This is needed to resolve a rare race condition in
843
   pthread_cond_timedwait_relative. */
844
 
845
void __pthread_restart_old(pthread_descr th)
846
{
847
    if (atomic_increment(&th->p_resume_count) == -1)
848
        kill(th->p_pid, __pthread_sig_restart);
849
}
850
 
851
void __pthread_suspend_old(pthread_descr self)
852
{
853
    if (atomic_decrement(&self->p_resume_count) <= 0)
854
        __pthread_wait_for_restart_signal(self);
855
}
856
 
857
int
858
__pthread_timedsuspend_old(pthread_descr self, const struct timespec *abstime)
859
{
860
  sigset_t unblock, initial_mask;
861
  int was_signalled = 0;
862
  sigjmp_buf jmpbuf;
863
 
864
  if (atomic_decrement(&self->p_resume_count) == 0) {
865
    /* Set up a longjmp handler for the restart signal, unblock
866
       the signal and sleep. */
867
 
868
    if (sigsetjmp(jmpbuf, 1) == 0) {
869
      THREAD_SETMEM(self, p_signal_jmp, &jmpbuf);
870
      THREAD_SETMEM(self, p_signal, 0);
871
      /* Unblock the restart signal */
872
      sigemptyset(&unblock);
873
      sigaddset(&unblock, __pthread_sig_restart);
874
      sigprocmask(SIG_UNBLOCK, &unblock, &initial_mask);
875
 
876
      while (1) {
877
        struct timeval now;
878
        struct timespec reltime;
879
 
880
        /* Compute a time offset relative to now.  */
881
        __gettimeofday (&now, NULL);
882
        reltime.tv_nsec = abstime->tv_nsec - now.tv_usec * 1000;
883
        reltime.tv_sec = abstime->tv_sec - now.tv_sec;
884
        if (reltime.tv_nsec < 0) {
885
          reltime.tv_nsec += 1000000000;
886
          reltime.tv_sec -= 1;
887
        }
888
 
889
        /* Sleep for the required duration. If woken by a signal,
890
           resume waiting as required by Single Unix Specification.  */
891
        if (reltime.tv_sec < 0 || __libc_nanosleep(&reltime, NULL) == 0)
892
          break;
893
      }
894
 
895
      /* Block the restart signal again */
896
      sigprocmask(SIG_SETMASK, &initial_mask, NULL);
897
      was_signalled = 0;
898
    } else {
899
      was_signalled = 1;
900
    }
901
    THREAD_SETMEM(self, p_signal_jmp, NULL);
902
  }
903
 
904
  /* Now was_signalled is true if we exited the above code
905
     due to the delivery of a restart signal.  In that case,
906
     we know we have been dequeued and resumed and that the
907
     resume count is balanced.  Otherwise, there are some
908
     cases to consider. First, try to bump up the resume count
909
     back to zero. If it goes to 1, it means restart() was
910
     invoked on this thread. The signal must be consumed
911
     and the count bumped down and everything is cool. We
912
     can return a 1 to the caller.
913
     Otherwise, no restart was delivered yet, so a potential
914
     race exists; we return a 0 to the caller which must deal
915
     with this race in an appropriate way; for example by
916
     atomically removing the thread from consideration for a
917
     wakeup---if such a thing fails, it means a restart is
918
     being delivered. */
919
 
920
  if (!was_signalled) {
921
    if (atomic_increment(&self->p_resume_count) != -1) {
922
      __pthread_wait_for_restart_signal(self);
923
      atomic_decrement(&self->p_resume_count); /* should be zero now! */
924
      /* woke spontaneously and consumed restart signal */
925
      return 1;
926
    }
927
    /* woke spontaneously but did not consume restart---caller must resolve */
928
    return 0;
929
  }
930
  /* woken due to restart signal */
931
  return 1;
932
}
933
#endif /* __NR_rt_sigaction */
934
 
935
 
936
#ifdef __NR_rt_sigaction
937
void __pthread_restart_new(pthread_descr th)
938
{
939
    /* The barrier is proabably not needed, in which case it still documents
940
       our assumptions. The intent is to commit previous writes to shared
941
       memory so the woken thread will have a consistent view.  Complementary
942
       read barriers are present to the suspend functions. */
943
    WRITE_MEMORY_BARRIER();
944
    kill(th->p_pid, __pthread_sig_restart);
945
}
946
 
947
int __pthread_timedsuspend_new(pthread_descr self, const struct timespec *abstime)
948
{
949
    sigset_t unblock, initial_mask;
950
    int was_signalled = 0;
951
    sigjmp_buf jmpbuf;
952
 
953
    if (sigsetjmp(jmpbuf, 1) == 0) {
954
        THREAD_SETMEM(self, p_signal_jmp, &jmpbuf);
955
        THREAD_SETMEM(self, p_signal, 0);
956
        /* Unblock the restart signal */
957
        sigemptyset(&unblock);
958
        sigaddset(&unblock, __pthread_sig_restart);
959
        sigprocmask(SIG_UNBLOCK, &unblock, &initial_mask);
960
 
961
        while (1) {
962
            struct timeval now;
963
            struct timespec reltime;
964
 
965
            /* Compute a time offset relative to now.  */
966
            gettimeofday (&now, NULL);
967
            reltime.tv_nsec = abstime->tv_nsec - now.tv_usec * 1000;
968
            reltime.tv_sec = abstime->tv_sec - now.tv_sec;
969
            if (reltime.tv_nsec < 0) {
970
                reltime.tv_nsec += 1000000000;
971
                reltime.tv_sec -= 1;
972
            }
973
 
974
            /* Sleep for the required duration. If woken by a signal,
975
               resume waiting as required by Single Unix Specification.  */
976
            if (reltime.tv_sec < 0 || __libc_nanosleep(&reltime, NULL) == 0)
977
                break;
978
        }
979
 
980
        /* Block the restart signal again */
981
        sigprocmask(SIG_SETMASK, &initial_mask, NULL);
982
        was_signalled = 0;
983
    } else {
984
        was_signalled = 1;
985
    }
986
    THREAD_SETMEM(self, p_signal_jmp, NULL);
987
 
988
    /* Now was_signalled is true if we exited the above code
989
       due to the delivery of a restart signal.  In that case,
990
       everything is cool. We have been removed from whatever
991
       we were waiting on by the other thread, and consumed its signal.
992
 
993
       Otherwise we this thread woke up spontaneously, or due to a signal other
994
       than restart. This is an ambiguous case  that must be resolved by
995
       the caller; the thread is still eligible for a restart wakeup
996
       so there is a race. */
997
 
998
    READ_MEMORY_BARRIER(); /* See comment in __pthread_restart_new */
999
    return was_signalled;
1000
}
1001
#endif
1002
 
1003
/* Debugging aid */
1004
 
1005
#ifdef DEBUG_PT
1006
#include <stdarg.h>
1007
 
1008
void __pthread_message(char * fmt, ...)
1009
{
1010
  char buffer[1024];
1011
  va_list args;
1012
  sprintf(buffer, "%05d : ", __getpid());
1013
  va_start(args, fmt);
1014
  vsnprintf(buffer + 8, sizeof(buffer) - 8, fmt, args);
1015
  va_end(args);
1016
  TEMP_FAILURE_RETRY(__libc_write(2, buffer, strlen(buffer)));
1017
}
1018
 
1019
#endif
1020
 
1021
 
1022
#ifndef __PIC__
1023
/* We need a hook to force the cancelation wrappers to be linked in when
1024
   static libpthread is used.  */
1025
extern const int __pthread_provide_wrappers;
1026
static const int *const __pthread_require_wrappers =
1027
  &__pthread_provide_wrappers;
1028
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.