~ubuntu-branches/ubuntu/trusty/eglibc/trusty

« back to all changes in this revision

Viewing changes to ports/sysdeps/unix/sysv/linux/aarch64/nptl/pthread_once.c

  • Committer: Package Import Robot
  • Author(s): Adam Conrad
  • Date: 2013-01-10 18:39:35 UTC
  • mfrom: (1.5.2) (4.4.24 experimental)
  • Revision ID: package-import@ubuntu.com-20130110183935-afsgfxkmg7wk5eaj
Tags: 2.17-0ubuntu1
* Merge with Debian, bringing in a new upstream and many small fixes:
  - patches/any/cvs-malloc-deadlock.diff: Dropped, merged upstream.
  - patches/ubuntu/lddebug-scopes.diff: Rebase for upstream changes.
  - patches/ubuntu/local-CVE-2012-3406.diff: Rebased against upstream.
  - patches/ubuntu/no-asm-mtune-i686.diff: Fixed in recent binutils.
* This upstream merge fixes a nasty hang in pulseaudio (LP: #1085342)
* Bump MIN_KERNEL_SUPPORTED to 2.6.32 on ARM, now that we no longer
  have to support shonky 2.6.31 kernels on imx51 babbage builders.
* Drop patches/ubuntu/local-disable-nscd-host-caching.diff, as these
  issues were apparently resolved upstream a while ago (LP: #613662)
* Fix the compiled-in bug URL to point to launchpad.net, not Debian.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2004-2012 Free Software Foundation, Inc.
 
2
 
 
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 Lesser General Public License as
 
7
   published by the Free Software Foundation; either version 2.1 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
   Lesser General Public License for more details.
 
14
 
 
15
   You should have received a copy of the GNU Lesser General Public
 
16
   License along with the GNU C Library; if not, see
 
17
   <http://www.gnu.org/licenses/>.  */
 
18
 
 
19
#include "pthreadP.h"
 
20
#include <lowlevellock.h>
 
21
 
 
22
unsigned long int __fork_generation attribute_hidden;
 
23
 
 
24
static void
 
25
clear_once_control (void *arg)
 
26
{
 
27
  pthread_once_t *once_control = (pthread_once_t *) arg;
 
28
 
 
29
  *once_control = 0;
 
30
  lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE);
 
31
}
 
32
 
 
33
int
 
34
__pthread_once (pthread_once_t *once_control, void (*init_routine) (void))
 
35
{
 
36
  for (;;)
 
37
    {
 
38
      int oldval;
 
39
      int newval;
 
40
 
 
41
      /* Pseudo code:
 
42
         newval = __fork_generation | 1;
 
43
         oldval = *once_control;
 
44
         if ((oldval & 2) == 0)
 
45
           *once_control = newval;
 
46
         Do this atomically.
 
47
      */
 
48
      do
 
49
        {
 
50
          newval = __fork_generation | 1;
 
51
          oldval = *once_control;
 
52
          if (oldval & 2)
 
53
            break;
 
54
        } while (atomic_compare_and_exchange_val_acq (once_control, newval, oldval) != oldval);
 
55
 
 
56
      /* Check if the initializer has already been done.  */
 
57
      if ((oldval & 2) != 0)
 
58
        return 0;
 
59
 
 
60
      /* Check if another thread already runs the initializer.  */
 
61
      if ((oldval & 1) == 0)
 
62
        break;
 
63
 
 
64
      /* Check whether the initializer execution was interrupted by a fork.  */
 
65
      if (oldval != newval)
 
66
        break;
 
67
 
 
68
      /* Same generation, some other thread was faster. Wait.  */
 
69
      lll_futex_wait (once_control, oldval, LLL_PRIVATE);
 
70
    }
 
71
 
 
72
  /* This thread is the first here.  Do the initialization.
 
73
     Register a cleanup handler so that in case the thread gets
 
74
     interrupted the initialization can be restarted.  */
 
75
  pthread_cleanup_push (clear_once_control, once_control);
 
76
 
 
77
  init_routine ();
 
78
 
 
79
  pthread_cleanup_pop (0);
 
80
 
 
81
  /* Say that the initialisation is done.  */
 
82
  *once_control = __fork_generation | 2;
 
83
 
 
84
  /* Wake up all other threads.  */
 
85
  lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE);
 
86
 
 
87
  return 0;
 
88
}
 
89
weak_alias (__pthread_once, pthread_once)
 
90
hidden_def (__pthread_once)