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 8 #include "../private/SkLeanWindows.h" 9 #include "../private/SkSemaphore.h" 10 11 #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) 12 #include <mach/mach.h> 13 struct SkBaseSemaphore::OSSemaphore { 14 semaphore_t fSemaphore; 15 16 OSSemaphore() { 17 semaphore_create(mach_task_self(), &fSemaphore, SYNC_POLICY_LIFO, 0/*initial count*/); 18 } 19 ~OSSemaphore() { semaphore_destroy(mach_task_self(), fSemaphore); } 20 21 void signal(int n) { while (n --> 0) { semaphore_signal(fSemaphore); } } 22 void wait() { semaphore_wait(fSemaphore); } 23 }; 24 #elif defined(SK_BUILD_FOR_WIN32) 25 struct SkBaseSemaphore::OSSemaphore { 26 HANDLE fSemaphore; 27 28 OSSemaphore() { 29 fSemaphore = CreateSemaphore(nullptr /*security attributes, optional*/, 30 0 /*initial count*/, 31 MAXLONG /*max count*/, 32 nullptr /*name, optional*/); 33 } 34 ~OSSemaphore() { CloseHandle(fSemaphore); } 35 36 void signal(int n) { 37 ReleaseSemaphore(fSemaphore, n, nullptr/*returns previous count, optional*/); 38 } 39 void wait() { WaitForSingleObject(fSemaphore, INFINITE/*timeout in ms*/); } 40 }; 41 #else 42 // It's important we test for Mach before this. This code will compile but not work there. 43 #include <errno.h> 44 #include <semaphore.h> 45 struct SkBaseSemaphore::OSSemaphore { 46 sem_t fSemaphore; 47 48 OSSemaphore() { sem_init(&fSemaphore, 0/*cross process?*/, 0/*initial count*/); } 49 ~OSSemaphore() { sem_destroy(&fSemaphore); } 50 51 void signal(int n) { while (n --> 0) { sem_post(&fSemaphore); } } 52 void wait() { 53 // Try until we're not interrupted. 54 while(sem_wait(&fSemaphore) == -1 && errno == EINTR); 55 } 56 }; 57 #endif 58 59 /////////////////////////////////////////////////////////////////////////////// 60 61 void SkBaseSemaphore::osSignal(int n) { 62 fOSSemaphoreOnce([this] { fOSSemaphore = new OSSemaphore; }); 63 fOSSemaphore->signal(n); 64 } 65 66 void SkBaseSemaphore::osWait() { 67 fOSSemaphoreOnce([this] { fOSSemaphore = new OSSemaphore; }); 68 fOSSemaphore->wait(); 69 } 70 71 void SkBaseSemaphore::cleanup() { 72 delete fOSSemaphore; 73 } 74 75 bool SkBaseSemaphore::try_wait() { 76 int count = fCount.load(std::memory_order_relaxed); 77 if (count > 0) { 78 return fCount.compare_exchange_weak(count, count-1, std::memory_order_acquire); 79 } 80 return false; 81 } 82