Blame nptl/libc_pthread_init.c

Packit 6c4009
/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#include <unistd.h>
Packit 6c4009
#include <list.h>
Packit 6c4009
#include <fork.h>
Packit 6c4009
#include <dl-sysdep.h>
Packit 6c4009
#include <tls.h>
Packit 6c4009
#include <string.h>
Packit 6c4009
#include <pthreadP.h>
Packit 6c4009
#include <libc-lock.h>
Packit 6c4009
#include <sysdep.h>
Packit 6c4009
#include <ldsodefs.h>
Packit 6c4009
Packit 6c4009
Packit 6c4009
unsigned long int *__fork_generation_pointer;
Packit 6c4009
Packit 6c4009
Packit 6c4009
#ifdef TLS_MULTIPLE_THREADS_IN_TCB
Packit 6c4009
void
Packit 6c4009
#else
Packit 6c4009
extern int __libc_multiple_threads attribute_hidden;
Packit 6c4009
Packit 6c4009
int *
Packit 6c4009
#endif
Packit 6c4009
__libc_pthread_init (unsigned long int *ptr, void (*reclaim) (void),
Packit 6c4009
		     const struct pthread_functions *functions)
Packit 6c4009
{
Packit 6c4009
  /* Remember the pointer to the generation counter in libpthread.  */
Packit 6c4009
  __fork_generation_pointer = ptr;
Packit 6c4009
Packit 6c4009
  /* Called by a child after fork.  */
Packit 6c4009
  __register_atfork (NULL, NULL, reclaim, NULL);
Packit 6c4009
Packit 6c4009
#ifdef SHARED
Packit 6c4009
  /* Copy the function pointers into an array in libc.  This enables
Packit 6c4009
     access with just one memory reference but moreso, it prevents
Packit 6c4009
     hijacking the function pointers with just one pointer change.  We
Packit 6c4009
     "encrypt" the function pointers since we cannot write-protect the
Packit 6c4009
     array easily enough.  */
Packit 6c4009
  union ptrhack
Packit 6c4009
  {
Packit 6c4009
    struct pthread_functions pf;
Packit 6c4009
# define NPTRS (sizeof (struct pthread_functions) / sizeof (void *))
Packit 6c4009
    void *parr[NPTRS];
Packit 6c4009
  } __attribute__ ((may_alias)) const *src;
Packit 6c4009
  union ptrhack *dest;
Packit 6c4009
Packit 6c4009
  src = (const void *) functions;
Packit 6c4009
  dest = (void *) &__libc_pthread_functions;
Packit 6c4009
Packit 6c4009
  for (size_t cnt = 0; cnt < NPTRS; ++cnt)
Packit 6c4009
    {
Packit 6c4009
      void *p = src->parr[cnt];
Packit 6c4009
      PTR_MANGLE (p);
Packit 6c4009
      dest->parr[cnt] = p;
Packit 6c4009
    }
Packit 6c4009
  __libc_pthread_functions_init = 1;
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#ifndef TLS_MULTIPLE_THREADS_IN_TCB
Packit 6c4009
  return &__libc_multiple_threads;
Packit 6c4009
#endif
Packit 6c4009
}