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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gcc-4.5.1/] [gcc/] [emutls.c] - Diff between revs 816 and 826

Only display areas with differences | Details | Blame | View Log

Rev 816 Rev 826
/* TLS emulation.
/* TLS emulation.
   Copyright (C) 2006, 2008, 2009 Free Software Foundation, Inc.
   Copyright (C) 2006, 2008, 2009 Free Software Foundation, Inc.
   Contributed by Jakub Jelinek <jakub@redhat.com>.
   Contributed by Jakub Jelinek <jakub@redhat.com>.
 
 
This file is part of GCC.
This file is part of GCC.
 
 
GCC is free software; you can redistribute it and/or modify it under
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
Software Foundation; either version 3, or (at your option) any later
version.
version.
 
 
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.
for more details.
 
 
Under Section 7 of GPL version 3, you are granted additional
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
3.1, as published by the Free Software Foundation.
 
 
You should have received a copy of the GNU General Public License and
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
<http://www.gnu.org/licenses/>.  */
<http://www.gnu.org/licenses/>.  */
 
 
#include "tconfig.h"
#include "tconfig.h"
#include "tsystem.h"
#include "tsystem.h"
#include "coretypes.h"
#include "coretypes.h"
#include "tm.h"
#include "tm.h"
#include "gthr.h"
#include "gthr.h"
 
 
typedef unsigned int word __attribute__((mode(word)));
typedef unsigned int word __attribute__((mode(word)));
typedef unsigned int pointer __attribute__((mode(pointer)));
typedef unsigned int pointer __attribute__((mode(pointer)));
 
 
struct __emutls_object
struct __emutls_object
{
{
  word size;
  word size;
  word align;
  word align;
  union {
  union {
    pointer offset;
    pointer offset;
    void *ptr;
    void *ptr;
  } loc;
  } loc;
  void *templ;
  void *templ;
};
};
 
 
struct __emutls_array
struct __emutls_array
{
{
  pointer size;
  pointer size;
  void **data[];
  void **data[];
};
};
 
 
void *__emutls_get_address (struct __emutls_object *);
void *__emutls_get_address (struct __emutls_object *);
void __emutls_register_common (struct __emutls_object *, word, word, void *);
void __emutls_register_common (struct __emutls_object *, word, word, void *);
 
 
#ifdef __GTHREADS
#ifdef __GTHREADS
#ifdef __GTHREAD_MUTEX_INIT
#ifdef __GTHREAD_MUTEX_INIT
static __gthread_mutex_t emutls_mutex = __GTHREAD_MUTEX_INIT;
static __gthread_mutex_t emutls_mutex = __GTHREAD_MUTEX_INIT;
#else
#else
static __gthread_mutex_t emutls_mutex;
static __gthread_mutex_t emutls_mutex;
#endif
#endif
static __gthread_key_t emutls_key;
static __gthread_key_t emutls_key;
static pointer emutls_size;
static pointer emutls_size;
 
 
static void
static void
emutls_destroy (void *ptr)
emutls_destroy (void *ptr)
{
{
  struct __emutls_array *arr = ptr;
  struct __emutls_array *arr = ptr;
  pointer size = arr->size;
  pointer size = arr->size;
  pointer i;
  pointer i;
 
 
  for (i = 0; i < size; ++i)
  for (i = 0; i < size; ++i)
    {
    {
      if (arr->data[i])
      if (arr->data[i])
        free (arr->data[i][-1]);
        free (arr->data[i][-1]);
    }
    }
 
 
  free (ptr);
  free (ptr);
}
}
 
 
static void
static void
emutls_init (void)
emutls_init (void)
{
{
#ifndef __GTHREAD_MUTEX_INIT
#ifndef __GTHREAD_MUTEX_INIT
  __GTHREAD_MUTEX_INIT_FUNCTION (&emutls_mutex);
  __GTHREAD_MUTEX_INIT_FUNCTION (&emutls_mutex);
#endif
#endif
  if (__gthread_key_create (&emutls_key, emutls_destroy) != 0)
  if (__gthread_key_create (&emutls_key, emutls_destroy) != 0)
    abort ();
    abort ();
}
}
#endif
#endif
 
 
static void *
static void *
emutls_alloc (struct __emutls_object *obj)
emutls_alloc (struct __emutls_object *obj)
{
{
  void *ptr;
  void *ptr;
  void *ret;
  void *ret;
 
 
  /* We could use here posix_memalign if available and adjust
  /* We could use here posix_memalign if available and adjust
     emutls_destroy accordingly.  */
     emutls_destroy accordingly.  */
  if (obj->align <= sizeof (void *))
  if (obj->align <= sizeof (void *))
    {
    {
      ptr = malloc (obj->size + sizeof (void *));
      ptr = malloc (obj->size + sizeof (void *));
      if (ptr == NULL)
      if (ptr == NULL)
        abort ();
        abort ();
      ((void **) ptr)[0] = ptr;
      ((void **) ptr)[0] = ptr;
      ret = ptr + sizeof (void *);
      ret = ptr + sizeof (void *);
    }
    }
  else
  else
    {
    {
      ptr = malloc (obj->size + sizeof (void *) + obj->align - 1);
      ptr = malloc (obj->size + sizeof (void *) + obj->align - 1);
      if (ptr == NULL)
      if (ptr == NULL)
        abort ();
        abort ();
      ret = (void *) (((pointer) (ptr + sizeof (void *) + obj->align - 1))
      ret = (void *) (((pointer) (ptr + sizeof (void *) + obj->align - 1))
                      & ~(pointer)(obj->align - 1));
                      & ~(pointer)(obj->align - 1));
      ((void **) ret)[-1] = ptr;
      ((void **) ret)[-1] = ptr;
    }
    }
 
 
  if (obj->templ)
  if (obj->templ)
    memcpy (ret, obj->templ, obj->size);
    memcpy (ret, obj->templ, obj->size);
  else
  else
    memset (ret, 0, obj->size);
    memset (ret, 0, obj->size);
 
 
  return ret;
  return ret;
}
}
 
 
void *
void *
__emutls_get_address (struct __emutls_object *obj)
__emutls_get_address (struct __emutls_object *obj)
{
{
  if (! __gthread_active_p ())
  if (! __gthread_active_p ())
    {
    {
      if (__builtin_expect (obj->loc.ptr == NULL, 0))
      if (__builtin_expect (obj->loc.ptr == NULL, 0))
        obj->loc.ptr = emutls_alloc (obj);
        obj->loc.ptr = emutls_alloc (obj);
      return obj->loc.ptr;
      return obj->loc.ptr;
    }
    }
 
 
#ifndef __GTHREADS
#ifndef __GTHREADS
  abort ();
  abort ();
#else
#else
  pointer offset = obj->loc.offset;
  pointer offset = obj->loc.offset;
 
 
  if (__builtin_expect (offset == 0, 0))
  if (__builtin_expect (offset == 0, 0))
    {
    {
      static __gthread_once_t once = __GTHREAD_ONCE_INIT;
      static __gthread_once_t once = __GTHREAD_ONCE_INIT;
      __gthread_once (&once, emutls_init);
      __gthread_once (&once, emutls_init);
      __gthread_mutex_lock (&emutls_mutex);
      __gthread_mutex_lock (&emutls_mutex);
      offset = obj->loc.offset;
      offset = obj->loc.offset;
      if (offset == 0)
      if (offset == 0)
        {
        {
          offset = ++emutls_size;
          offset = ++emutls_size;
          obj->loc.offset = offset;
          obj->loc.offset = offset;
        }
        }
      __gthread_mutex_unlock (&emutls_mutex);
      __gthread_mutex_unlock (&emutls_mutex);
    }
    }
 
 
  struct __emutls_array *arr = __gthread_getspecific (emutls_key);
  struct __emutls_array *arr = __gthread_getspecific (emutls_key);
  if (__builtin_expect (arr == NULL, 0))
  if (__builtin_expect (arr == NULL, 0))
    {
    {
      pointer size = offset + 32;
      pointer size = offset + 32;
      arr = calloc (size + 1, sizeof (void *));
      arr = calloc (size + 1, sizeof (void *));
      if (arr == NULL)
      if (arr == NULL)
        abort ();
        abort ();
      arr->size = size;
      arr->size = size;
      __gthread_setspecific (emutls_key, (void *) arr);
      __gthread_setspecific (emutls_key, (void *) arr);
    }
    }
  else if (__builtin_expect (offset > arr->size, 0))
  else if (__builtin_expect (offset > arr->size, 0))
    {
    {
      pointer orig_size = arr->size;
      pointer orig_size = arr->size;
      pointer size = orig_size * 2;
      pointer size = orig_size * 2;
      if (offset > size)
      if (offset > size)
        size = offset + 32;
        size = offset + 32;
      arr = realloc (arr, (size + 1) * sizeof (void *));
      arr = realloc (arr, (size + 1) * sizeof (void *));
      if (arr == NULL)
      if (arr == NULL)
        abort ();
        abort ();
      arr->size = size;
      arr->size = size;
      memset (arr->data + orig_size, 0,
      memset (arr->data + orig_size, 0,
              (size - orig_size) * sizeof (void *));
              (size - orig_size) * sizeof (void *));
      __gthread_setspecific (emutls_key, (void *) arr);
      __gthread_setspecific (emutls_key, (void *) arr);
    }
    }
 
 
  void *ret = arr->data[offset - 1];
  void *ret = arr->data[offset - 1];
  if (__builtin_expect (ret == NULL, 0))
  if (__builtin_expect (ret == NULL, 0))
    {
    {
      ret = emutls_alloc (obj);
      ret = emutls_alloc (obj);
      arr->data[offset - 1] = ret;
      arr->data[offset - 1] = ret;
    }
    }
  return ret;
  return ret;
#endif
#endif
}
}
 
 
void
void
__emutls_register_common (struct __emutls_object *obj,
__emutls_register_common (struct __emutls_object *obj,
                          word size, word align, void *templ)
                          word size, word align, void *templ)
{
{
  if (obj->size < size)
  if (obj->size < size)
    {
    {
      obj->size = size;
      obj->size = size;
      obj->templ = NULL;
      obj->templ = NULL;
    }
    }
  if (obj->align < align)
  if (obj->align < align)
    obj->align = align;
    obj->align = align;
  if (templ && size == obj->size)
  if (templ && size == obj->size)
    obj->templ = templ;
    obj->templ = templ;
}
}
 
 

powered by: WebSVN 2.1.0

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