1// -*- C++ -*- std::terminate, std::unexpected and friends.
2// Copyright (C) 1994-2022 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 "eh_term_handler.h"
30#include <bits/exception_defines.h>
31#include <bits/atomic_lockfree_defines.h>
32
33#if ATOMIC_POINTER_LOCK_FREE < 2
34#include <ext/concurrence.h>
35namespace
36{
37  __gnu_cxx::__mutex mx;
38}
39#endif
40
41using namespace __cxxabiv1;
42
43void
44__cxxabiv1::__terminate (std::terminate_handler handler) throw ()
45{
46  __try
47    {
48      handler ();
49      std::abort ();
50    }
51  __catch(...)
52    { std::abort (); }
53}
54
55void
56std::terminate () throw()
57{
58  __cxxabiv1::__terminate (get_terminate ());
59}
60
61#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
62void
63__cxxabiv1::__unexpected (std::unexpected_handler handler)
64{
65  handler();
66  std::terminate ();
67}
68
69void
70std::unexpected ()
71{
72  __unexpected (get_unexpected ());
73}
74
75std::terminate_handler
76std::set_terminate (std::terminate_handler func) throw()
77{
78  if (!func)
79    func = _GLIBCXX_DEFAULT_TERM_HANDLER;
80
81  std::terminate_handler old;
82#if ATOMIC_POINTER_LOCK_FREE > 1
83  __atomic_exchange (&__terminate_handler, &func, &old, __ATOMIC_ACQ_REL);
84#else
85  __gnu_cxx::__scoped_lock l(mx);
86  old = __terminate_handler;
87  __terminate_handler = func;
88#endif
89  return old;
90}
91
92std::terminate_handler
93std::get_terminate () noexcept
94{
95  std::terminate_handler func;
96#if ATOMIC_POINTER_LOCK_FREE > 1
97  __atomic_load (&__terminate_handler, &func, __ATOMIC_ACQUIRE);
98#else
99  __gnu_cxx::__scoped_lock l(mx);
100  func = __terminate_handler;
101#endif
102  return func;
103}
104
105std::unexpected_handler
106std::set_unexpected (std::unexpected_handler func) throw()
107{
108  if (!func)
109    func = std::terminate;
110
111  std::unexpected_handler old;
112#if ATOMIC_POINTER_LOCK_FREE > 1
113  __atomic_exchange (&__unexpected_handler, &func, &old, __ATOMIC_ACQ_REL);
114#else
115  __gnu_cxx::__scoped_lock l(mx);
116  old = __unexpected_handler;
117  __unexpected_handler = func;
118#endif
119  return old;
120}
121
122std::unexpected_handler
123std::get_unexpected () noexcept
124{
125  std::unexpected_handler func;
126#if ATOMIC_POINTER_LOCK_FREE > 1
127  __atomic_load (&__unexpected_handler, &func, __ATOMIC_ACQUIRE);
128#else
129  __gnu_cxx::__scoped_lock l(mx);
130  func = __unexpected_handler;
131#endif
132  return func;
133}
134