mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-25 23:00:15 +00:00
Make support for thread-unsafe C functions optional.
One of the aspects of CloudABI is that it aims to help you write code that is thread-safe out of the box. This is very important if you want to write libraries that are easy to reuse. For CloudABI we decided to not provide the thread-unsafe functions. So far this is working out pretty well, as thread-unsafety issues are detected really early on. The following patch adds a knob to libc++, _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS, that can be set to disable thread-unsafe functions that can easily be avoided in practice. The following functions are not thread-safe: - <clocale>: locale handles should be preferred over setlocale(). - <cstdlib>: mbrlen(), mbrtowc() and wcrtomb() should be preferred over their non-restartable counterparts. - <ctime>: asctime(), ctime(), gmtime() and localtime() are not thread-safe. The first two are also deprecated by POSIX. Differential Revision: http://reviews.llvm.org/D8703 Reviewed by: marshall llvm-svn: 240527
This commit is contained in:
parent
aa315fbb4c
commit
e0cf3b9a3c
@ -58,6 +58,7 @@ option(LIBCXX_ENABLE_GLOBAL_FILESYSTEM_NAMESPACE "Build libc++ with support for
|
||||
option(LIBCXX_ENABLE_STDIN "Build libc++ with support for stdin/std::cin." ON)
|
||||
option(LIBCXX_ENABLE_STDOUT "Build libc++ with support for stdout/std::cout." ON)
|
||||
option(LIBCXX_ENABLE_THREADS "Build libc++ with support for threads." ON)
|
||||
option(LIBCXX_ENABLE_THREAD_UNSAFE_C_FUNCTIONS "Build libc++ with support for thread-unsafe C functions" ON)
|
||||
option(LIBCXX_BUILD_32_BITS "Build 32 bit libc++" OFF)
|
||||
option(LIBCXX_ENABLE_MONOTONIC_CLOCK
|
||||
"Build libc++ with support for a monotonic clock.
|
||||
@ -274,6 +275,11 @@ elseif(NOT LIBCXX_ENABLE_MONOTONIC_CLOCK)
|
||||
" when LIBCXX_ENABLE_THREADS is also set to OFF.")
|
||||
endif()
|
||||
|
||||
# LIBCXX_ENABLE_THREAD_UNSAFE_C_FUNCTIONS configuration
|
||||
if (NOT LIBCXX_ENABLE_THREAD_UNSAFE_C_FUNCTIONS)
|
||||
add_definitions(-D_LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS)
|
||||
endif()
|
||||
|
||||
# Configure for sanitizers. If LIBCXX_BUILT_STANDALONE then we have to do
|
||||
# the flag translation ourselves. Othewise LLVM's CMakeList.txt will handle it.
|
||||
if (LIBCXX_BUILT_STANDALONE)
|
||||
|
@ -766,4 +766,10 @@ extern "C" void __sanitizer_annotate_contiguous_container(
|
||||
#define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
|
||||
#endif
|
||||
|
||||
// Thread-unsafe functions such as strtok(), mbtowc() and localtime()
|
||||
// are not available.
|
||||
#ifdef __CloudABI__
|
||||
#define _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
|
||||
#endif
|
||||
|
||||
#endif // _LIBCPP_CONFIG
|
||||
|
@ -45,7 +45,9 @@ lconv* localeconv();
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
using ::lconv;
|
||||
#ifndef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
|
||||
using ::setlocale;
|
||||
#endif
|
||||
using ::localeconv;
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
@ -147,9 +147,11 @@ using ::ldiv;
|
||||
#undef lldiv
|
||||
using ::lldiv;
|
||||
#endif // _LIBCPP_HAS_NO_LONG_LONG
|
||||
#ifndef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
|
||||
using ::mblen;
|
||||
using ::mbtowc;
|
||||
using ::wctomb;
|
||||
#endif
|
||||
using ::mbstowcs;
|
||||
using ::wcstombs;
|
||||
#ifdef _LIBCPP_HAS_QUICK_EXIT
|
||||
|
@ -102,7 +102,9 @@ inline _LIBCPP_INLINE_VISIBILITY void* memchr( void* __s, int __c, si
|
||||
inline _LIBCPP_INLINE_VISIBILITY char* strstr( char* __s1, const char* __s2) {return ::strstr(__s1, __s2);}
|
||||
#endif
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
|
||||
using ::strtok;
|
||||
#endif
|
||||
using ::memset;
|
||||
using ::strerror;
|
||||
using ::strlen;
|
||||
|
@ -61,10 +61,12 @@ using ::clock;
|
||||
using ::difftime;
|
||||
using ::mktime;
|
||||
using ::time;
|
||||
#ifndef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
|
||||
using ::asctime;
|
||||
using ::ctime;
|
||||
using ::gmtime;
|
||||
using ::localtime;
|
||||
#endif
|
||||
using ::strftime;
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
@ -46,6 +46,7 @@ if (LIT_EXECUTABLE)
|
||||
pythonize_bool(LIBCXX_ENABLE_STDIN)
|
||||
pythonize_bool(LIBCXX_ENABLE_STDOUT)
|
||||
pythonize_bool(LIBCXX_ENABLE_THREADS)
|
||||
pythonize_bool(LIBCXX_ENABLE_THREAD_UNSAFE_C_FUNCTIONS)
|
||||
pythonize_bool(LIBCXX_ENABLE_MONOTONIC_CLOCK)
|
||||
pythonize_bool(LIBCXX_GENERATE_COVERAGE)
|
||||
pythonize_bool(LIBCXXABI_USE_LLVM_UNWINDER)
|
||||
|
@ -372,6 +372,8 @@ class Configuration(object):
|
||||
elif not enable_monotonic_clock:
|
||||
self.lit_config.fatal('enable_monotonic_clock cannot be false when'
|
||||
' enable_threads is true.')
|
||||
self.configure_compile_flags_no_thread_unsafe_c_functions()
|
||||
|
||||
# Use verbose output for better errors
|
||||
self.cxx.flags += ['-v']
|
||||
sysroot = self.get_lit_conf('sysroot')
|
||||
@ -431,6 +433,15 @@ class Configuration(object):
|
||||
self.cxx.compile_flags += ['-D_LIBCPP_HAS_NO_THREADS']
|
||||
self.config.available_features.add('libcpp-has-no-threads')
|
||||
|
||||
def configure_compile_flags_no_thread_unsafe_c_functions(self):
|
||||
enable_thread_unsafe_c_functions = self.get_lit_bool(
|
||||
'enable_thread_unsafe_c_functions', True)
|
||||
if not enable_thread_unsafe_c_functions:
|
||||
self.cxx.compile_flags += [
|
||||
'-D_LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS']
|
||||
self.config.available_features.add(
|
||||
'libcpp-has-no-thread-unsafe-c-functions')
|
||||
|
||||
def configure_compile_flags_no_monotonic_clock(self):
|
||||
self.cxx.compile_flags += ['-D_LIBCPP_HAS_NO_MONOTONIC_CLOCK']
|
||||
self.config.available_features.add('libcpp-has-no-monotonic-clock')
|
||||
@ -522,7 +533,7 @@ class Configuration(object):
|
||||
else:
|
||||
self.cxx.link_flags += ['-lgcc_s']
|
||||
elif target_platform.startswith('freebsd'):
|
||||
self.cxx.link_flags += ['-lc', '-lm', '-lpthread', '-lgcc_s']
|
||||
self.cxx.link_flags += ['-lc', '-lm', '-lpthread', '-lgcc_s', '-lcxxrt']
|
||||
else:
|
||||
self.lit_config.fatal("unrecognized system: %r" % target_platform)
|
||||
|
||||
|
@ -12,6 +12,7 @@ config.enable_global_filesystem_namespace = "@LIBCXX_ENABLE_GLOBAL_FILESYSTEM_NA
|
||||
config.enable_stdin = "@LIBCXX_ENABLE_STDIN@"
|
||||
config.enable_stdout = "@LIBCXX_ENABLE_STDOUT@"
|
||||
config.enable_threads = "@LIBCXX_ENABLE_THREADS@"
|
||||
config.enable_thread_unsafe_c_functions = "@LIBCXX_ENABLE_THREAD_UNSAFE_C_FUNCTIONS@"
|
||||
config.enable_monotonic_clock = "@LIBCXX_ENABLE_MONOTONIC_CLOCK@"
|
||||
config.cxx_abi = "@LIBCXX_CXX_ABI_LIBNAME@"
|
||||
config.use_sanitizer = "@LLVM_USE_SANITIZER@"
|
||||
|
@ -71,12 +71,14 @@ int main()
|
||||
static_assert((std::is_same<decltype(div(0,0)), div_t>::value), "");
|
||||
static_assert((std::is_same<decltype(ldiv(0L,0L)), ldiv_t>::value), "");
|
||||
static_assert((std::is_same<decltype(lldiv(0LL,0LL)), lldiv_t>::value), "");
|
||||
static_assert((std::is_same<decltype(mblen("",0)), int>::value), "");
|
||||
wchar_t* pw = 0;
|
||||
const wchar_t* pwc = 0;
|
||||
char* pc = 0;
|
||||
#ifndef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
|
||||
static_assert((std::is_same<decltype(mblen("",0)), int>::value), "");
|
||||
static_assert((std::is_same<decltype(mbtowc(pw,"",0)), int>::value), "");
|
||||
static_assert((std::is_same<decltype(wctomb(pc,L' ')), int>::value), "");
|
||||
#endif
|
||||
static_assert((std::is_same<decltype(mbstowcs(pw,"",0)), size_t>::value), "");
|
||||
static_assert((std::is_same<decltype(wcstombs(pc,pwc,0)), size_t>::value), "");
|
||||
}
|
||||
|
@ -41,7 +41,9 @@ int main()
|
||||
static_assert((std::is_same<decltype(strrchr(cp, 0)), char*>::value), "");
|
||||
static_assert((std::is_same<decltype(strspn(cpc, cpc)), size_t>::value), "");
|
||||
static_assert((std::is_same<decltype(strstr(cp, cpc)), char*>::value), "");
|
||||
#ifndef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
|
||||
static_assert((std::is_same<decltype(strtok(cp, cpc)), char*>::value), "");
|
||||
#endif
|
||||
static_assert((std::is_same<decltype(memset(vp, 0, s)), void*>::value), "");
|
||||
static_assert((std::is_same<decltype(strerror(0)), char*>::value), "");
|
||||
static_assert((std::is_same<decltype(strlen(cpc)), size_t>::value), "");
|
||||
|
@ -75,12 +75,14 @@ int main()
|
||||
static_assert((std::is_same<decltype(std::div(0LL,0LL)), std::lldiv_t>::value), "");
|
||||
static_assert((std::is_same<decltype(std::ldiv(0L,0L)), std::ldiv_t>::value), "");
|
||||
static_assert((std::is_same<decltype(std::lldiv(0LL,0LL)), std::lldiv_t>::value), "");
|
||||
static_assert((std::is_same<decltype(std::mblen("",0)), int>::value), "");
|
||||
wchar_t* pw = 0;
|
||||
const wchar_t* pwc = 0;
|
||||
char* pc = 0;
|
||||
#ifndef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
|
||||
static_assert((std::is_same<decltype(std::mblen("",0)), int>::value), "");
|
||||
static_assert((std::is_same<decltype(std::mbtowc(pw,"",0)), int>::value), "");
|
||||
static_assert((std::is_same<decltype(std::wctomb(pc,L' ')), int>::value), "");
|
||||
#endif
|
||||
static_assert((std::is_same<decltype(std::mbstowcs(pw,"",0)), std::size_t>::value), "");
|
||||
static_assert((std::is_same<decltype(std::wcstombs(pc,pwc,0)), std::size_t>::value), "");
|
||||
}
|
||||
|
@ -30,10 +30,12 @@ int main()
|
||||
static_assert((std::is_same<decltype(std::difftime(t,t)), double>::value), "");
|
||||
static_assert((std::is_same<decltype(std::mktime(&tm)), std::time_t>::value), "");
|
||||
static_assert((std::is_same<decltype(std::time(&t)), std::time_t>::value), "");
|
||||
#ifndef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
|
||||
static_assert((std::is_same<decltype(std::asctime(&tm)), char*>::value), "");
|
||||
static_assert((std::is_same<decltype(std::ctime(&t)), char*>::value), "");
|
||||
static_assert((std::is_same<decltype(std::gmtime(&t)), std::tm*>::value), "");
|
||||
static_assert((std::is_same<decltype(std::localtime(&t)), std::tm*>::value), "");
|
||||
#endif
|
||||
char* c1 = 0;
|
||||
const char* c2 = 0;
|
||||
static_assert((std::is_same<decltype(std::strftime(c1,s,c2,&tm)), std::size_t>::value), "");
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include <clocale>
|
||||
#include <type_traits>
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
|
||||
|
||||
#ifndef LC_ALL
|
||||
#error LC_ALL not defined
|
||||
#endif
|
||||
@ -36,6 +38,8 @@
|
||||
#error LC_TIME not defined
|
||||
#endif
|
||||
|
||||
#endif // !_LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
|
||||
|
||||
#ifndef NULL
|
||||
#error NULL not defined
|
||||
#endif
|
||||
@ -43,6 +47,8 @@
|
||||
int main()
|
||||
{
|
||||
std::lconv lc;
|
||||
#ifndef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
|
||||
static_assert((std::is_same<decltype(std::setlocale(0, "")), char*>::value), "");
|
||||
#endif
|
||||
static_assert((std::is_same<decltype(std::localeconv()), std::lconv*>::value), "");
|
||||
}
|
||||
|
@ -46,7 +46,9 @@ int main()
|
||||
static_assert((std::is_same<decltype(std::strspn(cpc, cpc)), std::size_t>::value), "");
|
||||
// static_assert((std::is_same<decltype(std::strstr(cpc, cpc)), const char*>::value), "");
|
||||
static_assert((std::is_same<decltype(std::strstr(cp, cpc)), char*>::value), "");
|
||||
#ifndef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
|
||||
static_assert((std::is_same<decltype(std::strtok(cp, cpc)), char*>::value), "");
|
||||
#endif
|
||||
static_assert((std::is_same<decltype(std::memset(vp, 0, s)), void*>::value), "");
|
||||
static_assert((std::is_same<decltype(std::strerror(0)), char*>::value), "");
|
||||
static_assert((std::is_same<decltype(std::strlen(cpc)), std::size_t>::value), "");
|
||||
|
@ -0,0 +1,18 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: libcpp-has-no-thread-unsafe-c-functions
|
||||
|
||||
#include <ctime>
|
||||
|
||||
int main() {
|
||||
// asctime is not thread-safe.
|
||||
std::time_t t = 0;
|
||||
std::asctime(&t);
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: libcpp-has-no-thread-unsafe-c-functions
|
||||
|
||||
#include <ctime>
|
||||
|
||||
int main() {
|
||||
// ctime is not thread-safe.
|
||||
std::time_t t = 0;
|
||||
std::ctime(&t);
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: libcpp-has-no-thread-unsafe-c-functions
|
||||
|
||||
#include <ctime>
|
||||
|
||||
int main() {
|
||||
// gmtime is not thread-safe.
|
||||
std::time_t t = 0;
|
||||
std::gmtime(&t);
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: libcpp-has-no-thread-unsafe-c-functions
|
||||
|
||||
#include <ctime>
|
||||
|
||||
int main() {
|
||||
// localtime is not thread-safe.
|
||||
std::time_t t = 0;
|
||||
std::localtime(&t);
|
||||
}
|
Loading…
Reference in New Issue
Block a user