~vcs-imports/eglibc/trunk

« back to all changes in this revision

Viewing changes to libc/elf/dl-tls.c

  • Committer: joseph
  • Date: 2014-01-22 02:56:41 UTC
  • Revision ID: svn-v4:7b3dc134-2b1b-0410-93df-9e9f96275f8d:trunk:25088
Merge changes between r24941 and r25087 from /fsf/trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
   <http://www.gnu.org/licenses/>.  */
18
18
 
19
19
#include <assert.h>
 
20
#include <atomic.h>
20
21
#include <errno.h>
21
22
#include <libintl.h>
22
23
#include <signal.h>
533
534
# endif
534
535
 
535
536
 
536
 
static void *
537
 
allocate_and_init (struct link_map *map)
 
537
static void
 
538
allocate_and_init (dtv_t *dtv, struct link_map *map)
538
539
{
539
540
  void *newp;
540
541
  newp = __signal_safe_memalign (map->l_tls_align, map->l_tls_blocksize);
541
542
  if (newp == NULL)
542
543
    oom ();
543
544
 
544
 
  /* Initialize the memory.  */
 
545
  /* Initialize the memory. Since this is our thread's space, we are
 
546
     under a signal mask, and no one has touched this section before,
 
547
     we can safely just overwrite whatever's there.  */
545
548
  memset (__mempcpy (newp, map->l_tls_initimage, map->l_tls_initimage_size),
546
549
          '\0', map->l_tls_blocksize - map->l_tls_initimage_size);
547
550
 
548
 
  return newp;
 
551
  dtv->pointer.val = newp;
549
552
}
550
553
 
551
554
 
587
590
         the entry we need.  */
588
591
      size_t new_gen = listp->slotinfo[idx].gen;
589
592
      size_t total = 0;
 
593
      sigset_t old;
590
594
 
 
595
      _dl_mask_all_signals (&old);
 
596
      /* We use the signal mask as a lock against reentrancy here.
 
597
         Check that a signal taken before the lock didn't already
 
598
         update us.  */
 
599
      dtv = THREAD_DTV ();
 
600
      if (dtv[0].counter >= listp->slotinfo[idx].gen)
 
601
        goto out;
591
602
      /* We have to look through the entire dtv slotinfo list.  */
592
603
      listp =  GL(dl_tls_dtv_slotinfo_list);
593
604
      do
699
710
 
700
711
      /* This will be the new maximum generation counter.  */
701
712
      dtv[0].counter = new_gen;
 
713
   out:
 
714
      _dl_unmask_signals (&old);
702
715
    }
703
716
 
704
717
  return the_map;
724
737
 
725
738
      the_map = listp->slotinfo[idx].map;
726
739
    }
727
 
 
728
 
 again:
729
 
  /* Make sure that, if a dlopen running in parallel forces the
730
 
     variable into static storage, we'll wait until the address in the
731
 
     static TLS block is set up, and use that.  If we're undecided
732
 
     yet, make sure we make the decision holding the lock as well.  */
733
 
  if (__builtin_expect (the_map->l_tls_offset
734
 
                        != FORCED_DYNAMIC_TLS_OFFSET, 0))
735
 
    {
736
 
      __rtld_lock_lock_recursive (GL(dl_load_lock));
737
 
      if (__builtin_expect (the_map->l_tls_offset == NO_TLS_OFFSET, 1))
738
 
        {
739
 
          the_map->l_tls_offset = FORCED_DYNAMIC_TLS_OFFSET;
740
 
          __rtld_lock_unlock_recursive (GL(dl_load_lock));
741
 
        }
742
 
      else
743
 
        {
744
 
          __rtld_lock_unlock_recursive (GL(dl_load_lock));
745
 
          if (__builtin_expect (the_map->l_tls_offset
746
 
                                != FORCED_DYNAMIC_TLS_OFFSET, 1))
747
 
            {
748
 
              void *p = dtv[GET_ADDR_MODULE].pointer.val;
749
 
              if (__builtin_expect (p == TLS_DTV_UNALLOCATED, 0))
750
 
                goto again;
751
 
 
752
 
              return (char *) p + GET_ADDR_OFFSET;
753
 
            }
754
 
        }
755
 
    }
756
 
  void *p = dtv[GET_ADDR_MODULE].pointer.val = allocate_and_init (the_map);
757
 
  dtv[GET_ADDR_MODULE].pointer.is_static = false;
758
 
 
759
 
  return (char *) p + GET_ADDR_OFFSET;
 
740
  sigset_t old;
 
741
  _dl_mask_all_signals (&old);
 
742
 
 
743
  /* As with update_slotinfo, we use the sigmask as a check against
 
744
     reentrancy.  */
 
745
  if (dtv[GET_ADDR_MODULE].pointer.val != TLS_DTV_UNALLOCATED)
 
746
    goto out;
 
747
 
 
748
  /* Synchronize against a parallel dlopen() forcing this variable
 
749
     into static storage.  If that happens, we have to be more careful
 
750
     about initializing the area, as that dlopen() will be iterating
 
751
     the threads to do so itself.  */
 
752
  ptrdiff_t offset;
 
753
  if ((offset = the_map->l_tls_offset) == NO_TLS_OFFSET)
 
754
    {
 
755
      /* l_tls_offset starts out at NO_TLS_OFFSET, and all attempts to
 
756
         change it go from NO_TLS_OFFSET to some other value.  We use
 
757
         compare_and_exchange to ensure only one attempt succeeds.  We
 
758
         don't actually need any memory ordering here, but _acq is the
 
759
         weakest available.  */
 
760
      (void) atomic_compare_and_exchange_bool_acq (&the_map->l_tls_offset,
 
761
                                                   FORCED_DYNAMIC_TLS_OFFSET,
 
762
                                                   NO_TLS_OFFSET);
 
763
      offset = the_map->l_tls_offset;
 
764
      assert (offset != NO_TLS_OFFSET);
 
765
    }
 
766
  if (offset == FORCED_DYNAMIC_TLS_OFFSET)
 
767
    {
 
768
      allocate_and_init (&dtv[GET_ADDR_MODULE], the_map);
 
769
    }
 
770
  else
 
771
    {
 
772
      void **pp = &dtv[GET_ADDR_MODULE].pointer.val;
 
773
      while (atomic_forced_read (*pp) == TLS_DTV_UNALLOCATED)
 
774
        {
 
775
          /* for lack of a better (safe) thing to do, just spin.
 
776
            Someone else (not us; it's done under a signal mask) set
 
777
            this map to a static TLS offset, and they'll iterate all
 
778
            threads to initialize it.  They'll eventually write
 
779
            to pointer.val, at which point we know they've fully
 
780
            completed initialization.  */
 
781
          atomic_delay ();
 
782
        }
 
783
      /* Make sure we've picked up their initialization of the actual
 
784
         block; this pairs against the write barrier in
 
785
         init_one_static_tls, guaranteeing that we see their write of
 
786
         the tls_initimage into the static region.  */
 
787
      atomic_read_barrier ();
 
788
    }
 
789
out:
 
790
  assert (dtv[GET_ADDR_MODULE].pointer.val != TLS_DTV_UNALLOCATED);
 
791
  _dl_unmask_signals (&old);
 
792
 
 
793
  return (char *) dtv[GET_ADDR_MODULE].pointer.val + GET_ADDR_OFFSET;
760
794
}
761
795
 
762
796