1// -*- C++ -*- std::terminate, std::unexpected and friends.
2// Copyright (C) 1994-2017 Free Software Foundation, Inc.
3//
4// This file is part of GCC.
5//
6// GCC is free software; you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation; either version 3, or (at your option)
9// any later version.
10//
11// GCC is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15//
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25#include "typeinfo"
26#include "exception"
27#include <cstdlib>
28#include "unwind-cxx.h"
29#include <bits/exception_defines.h>
30#include <bits/atomic_lockfree_defines.h>
31
32#if ATOMIC_POINTER_LOCK_FREE < 2
33#include <ext/concurrence.h>
34namespace
35{
36 __gnu_cxx::__mutex mx;
37}
38#endif
39
40using namespace __cxxabiv1;
41
42void
43__cxxabiv1::__terminate (std::terminate_handler handler) throw ()
44{
45 __try
46 {
47 handler ();
48 std::abort ();
49 }
50 __catch(...)
51 { std::abort (); }
52}
53
54void
55std::terminate () throw()
56{
57 __terminate (get_terminate ());
58}
59
60void
61__cxxabiv1::__unexpected (std::unexpected_handler handler)
62{
63 handler();
64 std::terminate ();
65}
66
67void
68std::unexpected ()
69{
70 __unexpected (get_unexpected ());
71}
72
73std::terminate_handler
74std::set_terminate (std::terminate_handler func) throw()
75{
76 std::terminate_handler old;
77#if ATOMIC_POINTER_LOCK_FREE > 1
78 __atomic_exchange (&__terminate_handler, &func, &old, __ATOMIC_ACQ_REL);
79#else
80 __gnu_cxx::__scoped_lock l(mx);
81 old = __terminate_handler;
82 __terminate_handler = func;
83#endif
84 return old;
85}
86
87std::terminate_handler
88std::get_terminate () noexcept
89{
90 std::terminate_handler func;
91#if ATOMIC_POINTER_LOCK_FREE > 1
92 __atomic_load (&__terminate_handler, &func, __ATOMIC_ACQUIRE);
93#else
94 __gnu_cxx::__scoped_lock l(mx);
95 func = __terminate_handler;
96#endif
97 return func;
98}
99
100std::unexpected_handler
101std::set_unexpected (std::unexpected_handler func) throw()
102{
103 std::unexpected_handler old;
104#if ATOMIC_POINTER_LOCK_FREE > 1
105 __atomic_exchange (&__unexpected_handler, &func, &old, __ATOMIC_ACQ_REL);
106#else
107 __gnu_cxx::__scoped_lock l(mx);
108 old = __unexpected_handler;
109 __unexpected_handler = func;
110#endif
111 return old;
112}
113
114std::unexpected_handler
115std::get_unexpected () noexcept
116{
117 std::unexpected_handler func;
118#if ATOMIC_POINTER_LOCK_FREE > 1
119 __atomic_load (&__unexpected_handler, &func, __ATOMIC_ACQUIRE);
120#else
121 __gnu_cxx::__scoped_lock l(mx);
122 func = __unexpected_handler;
123#endif
124 return func;
125}
126