Skip to content

Commit

Permalink
Import libcxxrt master fd484be8d1e94a1fcf6bc5c67e5c07b65ada19b6
Browse files Browse the repository at this point in the history
Interesting fixes:
47661d0 Match libc++abi/libsupc++ when demangling array types
e44a05c Fix unitialized variable in __cxa_demangle_gnu3 after #6 (#8)
5088b05 Remove some code duplication.
fd484be Atomics cleanup (#11)
  • Loading branch information
DimitryAndric committed Mar 9, 2022
1 parent 3f8a54b commit 672085f
Show file tree
Hide file tree
Showing 8 changed files with 489 additions and 161 deletions.
13 changes: 12 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@

set(CXXRT_SOURCES
dynamic_cast.cc
exception.cc
guard.cc
stdexcept.cc
typeinfo.cc
Expand All @@ -10,6 +9,18 @@ set(CXXRT_SOURCES
libelftc_dem_gnu3.c
)

if (NOT CXXRT_NO_EXCEPTIONS)
set(CXXRT_SOURCES
${CXXRT_SOURCES}
exception.cc
)
else()
set(CXXRT_SOURCES
${CXXRT_SOURCES}
noexception.cc
)
endif()

add_definitions(-D_GNU_SOURCE)
add_library(cxxrt-static STATIC ${CXXRT_SOURCES})
add_library(cxxrt-shared SHARED ${CXXRT_SOURCES})
Expand Down
110 changes: 91 additions & 19 deletions atomic.h
Original file line number Diff line number Diff line change
@@ -1,30 +1,102 @@

#ifndef __has_builtin
#define __has_builtin(x) 0
# define __has_builtin(x) 0
#endif
#ifndef __has_feature
#define __has_feature(x) 0
# define __has_feature(x) 0
#endif
#ifndef __has_extension
# define __has_extension(x) 0
#endif

#if !__has_extension(c_atomic)
# define _Atomic(T) T
#endif
/**
* Swap macro that enforces a happens-before relationship with a corresponding
* ATOMIC_LOAD.
*/
#if __has_builtin(__c11_atomic_exchange)
#define ATOMIC_SWAP(addr, val)\
__c11_atomic_exchange(reinterpret_cast<_Atomic(__typeof__(val))*>(addr), val, __ATOMIC_ACQ_REL)
#elif __has_builtin(__sync_swap)
#define ATOMIC_SWAP(addr, val)\
__sync_swap(addr, val)
# define ATOMIC_BUILTIN(name) __c11_atomic_##name
#else
#define ATOMIC_SWAP(addr, val)\
__sync_lock_test_and_set(addr, val)
# define ATOMIC_BUILTIN(name) __atomic_##name##_n
#endif

#if __has_builtin(__c11_atomic_load)
#define ATOMIC_LOAD(addr)\
__c11_atomic_load(reinterpret_cast<_Atomic(__typeof__(*addr))*>(addr), __ATOMIC_ACQUIRE)
namespace
{
/**
* C++11 memory orders. We only need a subset of them.
*/
enum memory_order
{
/**
* Acquire order.
*/
acquire = __ATOMIC_ACQUIRE,

/**
* Release order.
*/
release = __ATOMIC_RELEASE,

/**
* Sequentially consistent memory ordering.
*/
seqcst = __ATOMIC_SEQ_CST
};

/**
* Atomic, implements a subset of `std::atomic`.
*/
template<typename T>
class atomic
{
/**
* The underlying value. Use C11 atomic qualification if available.
*/
_Atomic(T) val;

public:
/**
* Constructor, takes a value.
*/
atomic(T init) : val(init) {}

/**
* Atomically load with the specified memory order.
*/
T load(memory_order order = memory_order::seqcst)
{
return ATOMIC_BUILTIN(load)(&val, order);
}

/**
* Atomically store with the specified memory order.
*/
void store(T v, memory_order order = memory_order::seqcst)
{
return ATOMIC_BUILTIN(store)(&val, v, order);
}

/**
* Atomically exchange with the specified memory order.
*/
T exchange(T v, memory_order order = memory_order::seqcst)
{
return ATOMIC_BUILTIN(exchange)(&val, v, order);
}

/**
* Atomically exchange with the specified memory order.
*/
bool compare_exchange(T & expected,
T desired,
memory_order order = memory_order::seqcst)
{
#if __has_builtin(__c11_atomic_compare_exchange_strong)
return __c11_atomic_compare_exchange_strong(
&val, &expected, desired, order, order);
#else
#define ATOMIC_LOAD(addr)\
(__sync_synchronize(), *addr)
return __atomic_compare_exchange_n(
&val, &expected, desired, true, order, order);
#endif

}
};
} // namespace
#undef ATOMIC_BUILTIN
25 changes: 20 additions & 5 deletions auxhelper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,29 @@
#include <stdlib.h>
#include "stdexcept.h"

namespace {
/**
* Throw an exception if we're compiling with exceptions, otherwise abort.
*/
template<typename T>
void throw_exception()
{
#if !defined(_CXXRT_NO_EXCEPTIONS)
throw T();
#else
abort();
#endif
}
}

/**
* Called to generate a bad cast exception. This function is intended to allow
* compilers to insert code generating this exception without needing to
* duplicate the code for throwing the exception in every call site.
*/
extern "C" void __cxa_bad_cast()
{
throw std::bad_cast();
throw_exception<std::bad_cast>();
}

/**
Expand All @@ -51,7 +66,7 @@ extern "C" void __cxa_bad_cast()
*/
extern "C" void __cxa_bad_typeid()
{
throw std::bad_typeid();
throw_exception<std::bad_typeid>();
}

/**
Expand All @@ -62,7 +77,7 @@ extern "C" void __cxa_bad_typeid()
*/
extern "C" void __cxa_pure_virtual()
{
abort();
abort();
}

/**
Expand All @@ -73,10 +88,10 @@ extern "C" void __cxa_pure_virtual()
*/
extern "C" void __cxa_deleted_virtual()
{
abort();
abort();
}

extern "C" void __cxa_throw_bad_array_new_length()
{
throw std::bad_array_new_length();
throw_exception<std::bad_array_new_length>();
}
21 changes: 11 additions & 10 deletions exception.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright 2010-2011 PathScale, Inc. All rights reserved.
* Copyright 2021 David Chisnall. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
Expand Down Expand Up @@ -289,9 +290,9 @@ using namespace ABI_NAMESPACE;


/** The global termination handler. */
static terminate_handler terminateHandler = abort;
static atomic<terminate_handler> terminateHandler = abort;
/** The global unexpected exception handler. */
static unexpected_handler unexpectedHandler = std::terminate;
static atomic<unexpected_handler> unexpectedHandler = std::terminate;

/** Key used for thread-local data. */
static pthread_key_t eh_key;
Expand Down Expand Up @@ -742,12 +743,12 @@ static void throw_exception(__cxa_exception *ex)
ex->unexpectedHandler = info->unexpectedHandler;
if (0 == ex->unexpectedHandler)
{
ex->unexpectedHandler = unexpectedHandler;
ex->unexpectedHandler = unexpectedHandler.load();
}
ex->terminateHandler = info->terminateHandler;
if (0 == ex->terminateHandler)
{
ex->terminateHandler = terminateHandler;
ex->terminateHandler = terminateHandler.load();
}
info->globals.uncaughtExceptions++;

Expand Down Expand Up @@ -1447,7 +1448,7 @@ namespace std
{
if (thread_local_handlers) { return pathscale::set_unexpected(f); }

return ATOMIC_SWAP(&unexpectedHandler, f);
return unexpectedHandler.exchange(f);
}
/**
* Sets the function that is called to terminate the program.
Expand All @@ -1456,7 +1457,7 @@ namespace std
{
if (thread_local_handlers) { return pathscale::set_terminate(f); }

return ATOMIC_SWAP(&terminateHandler, f);
return terminateHandler.exchange(f);
}
/**
* Terminates the program, calling a custom terminate implementation if
Expand All @@ -1472,7 +1473,7 @@ namespace std
// return.
abort();
}
terminateHandler();
terminateHandler.load()();
}
/**
* Called when an unexpected exception is encountered (i.e. an exception
Expand All @@ -1489,7 +1490,7 @@ namespace std
// return.
abort();
}
unexpectedHandler();
unexpectedHandler.load()();
}
/**
* Returns whether there are any exceptions currently being thrown that
Expand Down Expand Up @@ -1519,7 +1520,7 @@ namespace std
{
return info->unexpectedHandler;
}
return ATOMIC_LOAD(&unexpectedHandler);
return unexpectedHandler.load();
}
/**
* Returns the current terminate handler.
Expand All @@ -1531,7 +1532,7 @@ namespace std
{
return info->terminateHandler;
}
return ATOMIC_LOAD(&terminateHandler);
return terminateHandler.load();
}
}
#if defined(__arm__) && !defined(__ARM_DWARF_EH__)
Expand Down
Loading

0 comments on commit 672085f

Please sign in to comment.