1// -*- C++ -*- std::terminate, std::unexpected and friends.
2// Copyright (C) 1994-2020 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  __terminate (get_terminate ());
59}
60
61void
62__cxxabiv1::__unexpected (std::unexpected_handler handler)
63{
64  handler();
65  std::terminate ();
66}
67
68void
69std::unexpected ()
70{
71  __unexpected (get_unexpected ());
72}
73
74std::terminate_handler
75std::set_terminate (std::terminate_handler func) throw()
76{
77  if (!func)
78    func = _GLIBCXX_DEFAULT_TERM_HANDLER;
79
80  std::terminate_handler old;
81#if ATOMIC_POINTER_LOCK_FREE > 1
82  __atomic_exchange (&__terminate_handler, &func, &old, __ATOMIC_ACQ_REL);
83#else
84  __gnu_cxx::__scoped_lock l(mx);
85  old = __terminate_handler;
86  __terminate_handler = func;
87#endif
88  return old;
89}
90
91std::terminate_handler
92std::get_terminate () noexcept
93{
94  std::terminate_handler func;
95#if ATOMIC_POINTER_LOCK_FREE > 1
96  __atomic_load (&__terminate_handler, &func, __ATOMIC_ACQUIRE);
97#else
98  __gnu_cxx::__scoped_lock l(mx);
99  func = __terminate_handler;
100#endif
101  return func;
102}
103
104std::unexpected_handler
105std::set_unexpected (std::unexpected_handler func) throw()
106{
107  if (!func)
108    func = std::terminate;
109
110  std::unexpected_handler old;
111#if ATOMIC_POINTER_LOCK_FREE > 1
112  __atomic_exchange (&__unexpected_handler, &func, &old, __ATOMIC_ACQ_REL);
113#else
114  __gnu_cxx::__scoped_lock l(mx);
115  old = __unexpected_handler;
116  __unexpected_handler = func;
117#endif
118  return old;
119}
120
121std::unexpected_handler
122std::get_unexpected () noexcept
123{
124  std::unexpected_handler func;
125#if ATOMIC_POINTER_LOCK_FREE > 1
126  __atomic_load (&__unexpected_handler, &func, __ATOMIC_ACQUIRE);
127#else
128  __gnu_cxx::__scoped_lock l(mx);
129  func = __unexpected_handler;
130#endif
131  return func;
132}
133