scudo_tsd_exclusive.cpp 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. //===-- scudo_tsd_exclusive.cpp ---------------------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. ///
  9. /// Scudo exclusive TSD implementation.
  10. ///
  11. //===----------------------------------------------------------------------===//
  12. #include "scudo_tsd.h"
  13. #if SCUDO_TSD_EXCLUSIVE
  14. namespace __scudo {
  15. static pthread_once_t GlobalInitialized = PTHREAD_ONCE_INIT;
  16. static pthread_key_t PThreadKey;
  17. __attribute__((tls_model("initial-exec")))
  18. THREADLOCAL ThreadState ScudoThreadState = ThreadNotInitialized;
  19. __attribute__((tls_model("initial-exec")))
  20. THREADLOCAL ScudoTSD TSD;
  21. // Fallback TSD for when the thread isn't initialized yet or is torn down. It
  22. // can be shared between multiple threads and as such must be locked.
  23. ScudoTSD FallbackTSD;
  24. static void teardownThread(void *Ptr) {
  25. uptr I = reinterpret_cast<uptr>(Ptr);
  26. // The glibc POSIX thread-local-storage deallocation routine calls user
  27. // provided destructors in a loop of PTHREAD_DESTRUCTOR_ITERATIONS.
  28. // We want to be called last since other destructors might call free and the
  29. // like, so we wait until PTHREAD_DESTRUCTOR_ITERATIONS before draining the
  30. // quarantine and swallowing the cache.
  31. if (I > 1) {
  32. // If pthread_setspecific fails, we will go ahead with the teardown.
  33. if (LIKELY(pthread_setspecific(PThreadKey,
  34. reinterpret_cast<void *>(I - 1)) == 0))
  35. return;
  36. }
  37. TSD.commitBack();
  38. ScudoThreadState = ThreadTornDown;
  39. }
  40. static void initOnce() {
  41. CHECK_EQ(pthread_key_create(&PThreadKey, teardownThread), 0);
  42. initScudo();
  43. FallbackTSD.init();
  44. }
  45. void initThread(bool MinimalInit) {
  46. CHECK_EQ(pthread_once(&GlobalInitialized, initOnce), 0);
  47. if (UNLIKELY(MinimalInit))
  48. return;
  49. CHECK_EQ(pthread_setspecific(PThreadKey, reinterpret_cast<void *>(
  50. GetPthreadDestructorIterations())), 0);
  51. TSD.init();
  52. ScudoThreadState = ThreadInitialized;
  53. }
  54. } // namespace __scudo
  55. #endif // SCUDO_TSD_EXCLUSIVE