1169691Skan// Copyright (C) 2002, 2004, 2006 Free Software Foundation, Inc.
2117397Skan//
3117397Skan// This file is part of GCC.
4117397Skan//
5117397Skan// GCC is free software; you can redistribute it and/or modify
6117397Skan// it under the terms of the GNU General Public License as published by
7117397Skan// the Free Software Foundation; either version 2, or (at your option)
8117397Skan// any later version.
9117397Skan
10117397Skan// GCC is distributed in the hope that it will be useful,
11117397Skan// but WITHOUT ANY WARRANTY; without even the implied warranty of
12117397Skan// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13117397Skan// GNU General Public License for more details.
14117397Skan
15117397Skan// You should have received a copy of the GNU General Public License
16117397Skan// along with GCC; see the file COPYING.  If not, write to
17169691Skan// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
18169691Skan// Boston, MA 02110-1301, USA.
19117397Skan
20117397Skan// As a special exception, you may use this file as part of a free software
21117397Skan// library without restriction.  Specifically, if other files instantiate
22117397Skan// templates or use macros or inline functions from this file, or you compile
23117397Skan// this file and link it with other files to produce an executable, this
24117397Skan// file does not by itself cause the resulting executable to be covered by
25117397Skan// the GNU General Public License.  This exception does not however
26117397Skan// invalidate any other reasons why the executable file might be covered by
27117397Skan// the GNU General Public License.
28117397Skan
29117397Skan// Written by Mark Mitchell, CodeSourcery LLC, <mark@codesourcery.com>
30169691Skan// Thread support written by Jason Merrill, Red Hat Inc. <jason@redhat.com>
31117397Skan
32169691Skan#include <bits/c++config.h>
33117397Skan#include <cxxabi.h>
34169691Skan#include <exception>
35169691Skan#include <new>
36169691Skan#include <ext/atomicity.h>
37169691Skan#include <ext/concurrence.h>
38117397Skan
39169691Skan// The IA64/generic ABI uses the first byte of the guard variable.
40169691Skan// The ARM EABI uses the least significant bit.
41169691Skan
42169691Skan// Thread-safe static local initialization support.
43169691Skan#ifdef __GTHREADS
44169691Skannamespace
45169691Skan{
46169691Skan  // A single mutex controlling all static initializations.
47169691Skan  static __gnu_cxx::__recursive_mutex* static_mutex;
48169691Skan
49169691Skan  typedef char fake_recursive_mutex[sizeof(__gnu_cxx::__recursive_mutex)]
50169691Skan  __attribute__ ((aligned(__alignof__(__gnu_cxx::__recursive_mutex))));
51169691Skan  fake_recursive_mutex fake_mutex;
52169691Skan
53169691Skan  static void init()
54169691Skan  { static_mutex =  new (&fake_mutex) __gnu_cxx::__recursive_mutex(); }
55169691Skan
56169691Skan  __gnu_cxx::__recursive_mutex&
57169691Skan  get_static_mutex()
58169691Skan  {
59169691Skan    static __gthread_once_t once = __GTHREAD_ONCE_INIT;
60169691Skan    __gthread_once(&once, init);
61169691Skan    return *static_mutex;
62169691Skan  }
63169691Skan}
64169691Skan
65169691Skan#ifndef _GLIBCXX_GUARD_TEST_AND_ACQUIRE
66169691Skaninline bool
67169691Skan__test_and_acquire (__cxxabiv1::__guard *g)
68169691Skan{
69169691Skan  bool b = _GLIBCXX_GUARD_TEST (g);
70169691Skan  _GLIBCXX_READ_MEM_BARRIER;
71169691Skan  return b;
72169691Skan}
73169691Skan#define _GLIBCXX_GUARD_TEST_AND_ACQUIRE(G) __test_and_acquire (G)
74169691Skan#endif
75169691Skan
76169691Skan#ifndef _GLIBCXX_GUARD_SET_AND_RELEASE
77169691Skaninline void
78169691Skan__set_and_release (__cxxabiv1::__guard *g)
79169691Skan{
80169691Skan  _GLIBCXX_WRITE_MEM_BARRIER;
81169691Skan  _GLIBCXX_GUARD_SET (g);
82169691Skan}
83169691Skan#define _GLIBCXX_GUARD_SET_AND_RELEASE(G) __set_and_release (G)
84169691Skan#endif
85169691Skan
86169691Skan#else /* !__GTHREADS */
87169691Skan
88169691Skan#undef _GLIBCXX_GUARD_TEST_AND_ACQUIRE
89169691Skan#undef _GLIBCXX_GUARD_SET_AND_RELEASE
90169691Skan#define _GLIBCXX_GUARD_SET_AND_RELEASE(G) _GLIBCXX_GUARD_SET (G)
91169691Skan
92169691Skan#endif /* __GTHREADS */
93169691Skan
94169691Skannamespace __gnu_cxx
95169691Skan{
96169691Skan  // 6.7[stmt.dcl]/4: If control re-enters the declaration (recursively)
97169691Skan  // while the object is being initialized, the behavior is undefined.
98169691Skan
99169691Skan  // Since we already have a library function to handle locking, we might
100169691Skan  // as well check for this situation and throw an exception.
101169691Skan  // We use the second byte of the guard variable to remember that we're
102169691Skan  // in the middle of an initialization.
103169691Skan  class recursive_init_error: public std::exception
104169691Skan  {
105169691Skan  public:
106169691Skan    recursive_init_error() throw() { }
107169691Skan    virtual ~recursive_init_error() throw ();
108169691Skan  };
109169691Skan
110169691Skan  recursive_init_error::~recursive_init_error() throw() { }
111169691Skan}
112169691Skan
113117397Skannamespace __cxxabiv1
114117397Skan{
115169691Skan  static inline int
116169691Skan  recursion_push (__guard* g)
117169691Skan  { return ((char *)g)[1]++; }
118169691Skan
119169691Skan  static inline void
120169691Skan  recursion_pop (__guard* g)
121169691Skan  { --((char *)g)[1]; }
122169691Skan
123169691Skan  static int
124169691Skan  acquire (__guard *g)
125169691Skan  {
126169691Skan    if (_GLIBCXX_GUARD_TEST (g))
127169691Skan      return 0;
128169691Skan
129169691Skan    if (recursion_push (g))
130169691Skan      {
131169691Skan#ifdef __EXCEPTIONS
132169691Skan	throw __gnu_cxx::recursive_init_error();
133169691Skan#else
134169691Skan	// Use __builtin_trap so we don't require abort().
135169691Skan	__builtin_trap ();
136169691Skan#endif
137169691Skan      }
138169691Skan    return 1;
139169691Skan  }
140169691Skan
141117397Skan  extern "C"
142117397Skan  int __cxa_guard_acquire (__guard *g)
143117397Skan  {
144169691Skan#ifdef __GTHREADS
145169691Skan    // If the target can reorder loads, we need to insert a read memory
146169691Skan    // barrier so that accesses to the guarded variable happen after the
147169691Skan    // guard test.
148169691Skan    if (_GLIBCXX_GUARD_TEST_AND_ACQUIRE (g))
149169691Skan      return 0;
150169691Skan
151169691Skan    if (__gthread_active_p ())
152169691Skan      {
153169691Skan	// Simple wrapper for exception safety.
154169691Skan	struct mutex_wrapper
155169691Skan	{
156169691Skan	  bool unlock;
157169691Skan	  mutex_wrapper() : unlock(true)
158169691Skan	  { get_static_mutex().lock(); }
159169691Skan
160169691Skan	  ~mutex_wrapper()
161169691Skan	  {
162169691Skan	    if (unlock)
163169691Skan	      static_mutex->unlock();
164169691Skan	  }
165169691Skan	};
166169691Skan
167169691Skan	mutex_wrapper mw;
168169691Skan	if (acquire (g))
169169691Skan	  {
170169691Skan	    mw.unlock = false;
171169691Skan	    return 1;
172169691Skan	  }
173169691Skan
174169691Skan	return 0;
175169691Skan      }
176169691Skan#endif
177169691Skan
178169691Skan    return acquire (g);
179117397Skan  }
180117397Skan
181117397Skan  extern "C"
182169691Skan  void __cxa_guard_abort (__guard *g)
183117397Skan  {
184169691Skan    recursion_pop (g);
185169691Skan#ifdef __GTHREADS
186169691Skan    if (__gthread_active_p ())
187169691Skan      static_mutex->unlock();
188169691Skan#endif
189117397Skan  }
190117397Skan
191117397Skan  extern "C"
192169691Skan  void __cxa_guard_release (__guard *g)
193117397Skan  {
194169691Skan    recursion_pop (g);
195169691Skan    _GLIBCXX_GUARD_SET_AND_RELEASE (g);
196169691Skan#ifdef __GTHREADS
197169691Skan    if (__gthread_active_p ())
198169691Skan      static_mutex->unlock();
199169691Skan#endif
200117397Skan  }
201117397Skan}
202