SkSemaphore.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. /*
  2. * Copyright 2015 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #include "include/private/SkSemaphore.h"
  8. #include "src/core/SkLeanWindows.h"
  9. #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
  10. #include <mach/mach.h>
  11. // We've got to teach TSAN that there is a happens-before edge between
  12. // semaphore_signal() and semaphore_wait().
  13. #if __has_feature(thread_sanitizer)
  14. extern "C" void AnnotateHappensBefore(const char*, int, void*);
  15. extern "C" void AnnotateHappensAfter (const char*, int, void*);
  16. #else
  17. static void AnnotateHappensBefore(const char*, int, void*) {}
  18. static void AnnotateHappensAfter (const char*, int, void*) {}
  19. #endif
  20. struct SkSemaphore::OSSemaphore {
  21. semaphore_t fSemaphore;
  22. OSSemaphore() {
  23. semaphore_create(mach_task_self(), &fSemaphore, SYNC_POLICY_LIFO, 0/*initial count*/);
  24. }
  25. ~OSSemaphore() { semaphore_destroy(mach_task_self(), fSemaphore); }
  26. void signal(int n) {
  27. while (n --> 0) {
  28. AnnotateHappensBefore(__FILE__, __LINE__, &fSemaphore);
  29. semaphore_signal(fSemaphore);
  30. }
  31. }
  32. void wait() {
  33. while (true) {
  34. kern_return_t result = semaphore_wait(fSemaphore);
  35. if (result == KERN_SUCCESS) {
  36. AnnotateHappensAfter(__FILE__, __LINE__, &fSemaphore);
  37. return;
  38. }
  39. SkASSERT(result == KERN_ABORTED);
  40. }
  41. }
  42. };
  43. #elif defined(SK_BUILD_FOR_WIN)
  44. struct SkSemaphore::OSSemaphore {
  45. HANDLE fSemaphore;
  46. OSSemaphore() {
  47. fSemaphore = CreateSemaphore(nullptr /*security attributes, optional*/,
  48. 0 /*initial count*/,
  49. MAXLONG /*max count*/,
  50. nullptr /*name, optional*/);
  51. }
  52. ~OSSemaphore() { CloseHandle(fSemaphore); }
  53. void signal(int n) {
  54. ReleaseSemaphore(fSemaphore, n, nullptr/*returns previous count, optional*/);
  55. }
  56. void wait() { WaitForSingleObject(fSemaphore, INFINITE/*timeout in ms*/); }
  57. };
  58. #else
  59. // It's important we test for Mach before this. This code will compile but not work there.
  60. #include <errno.h>
  61. #include <semaphore.h>
  62. struct SkSemaphore::OSSemaphore {
  63. sem_t fSemaphore;
  64. OSSemaphore() { sem_init(&fSemaphore, 0/*cross process?*/, 0/*initial count*/); }
  65. ~OSSemaphore() { sem_destroy(&fSemaphore); }
  66. void signal(int n) { while (n --> 0) { sem_post(&fSemaphore); } }
  67. void wait() {
  68. // Try until we're not interrupted.
  69. while(sem_wait(&fSemaphore) == -1 && errno == EINTR);
  70. }
  71. };
  72. #endif
  73. ///////////////////////////////////////////////////////////////////////////////
  74. SkSemaphore::~SkSemaphore() {
  75. delete fOSSemaphore;
  76. }
  77. void SkSemaphore::osSignal(int n) {
  78. fOSSemaphoreOnce([this] { fOSSemaphore = new OSSemaphore; });
  79. fOSSemaphore->signal(n);
  80. }
  81. void SkSemaphore::osWait() {
  82. fOSSemaphoreOnce([this] { fOSSemaphore = new OSSemaphore; });
  83. fOSSemaphore->wait();
  84. }
  85. bool SkSemaphore::try_wait() {
  86. int count = fCount.load(std::memory_order_relaxed);
  87. if (count > 0) {
  88. return fCount.compare_exchange_weak(count, count-1, std::memory_order_acquire);
  89. }
  90. return false;
  91. }