1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2015 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkSemaphore.h"
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkFeatures.h" // IWYU pragma: keep
11*c8dee2aaSAndroid Build Coastguard Worker
12*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
13*c8dee2aaSAndroid Build Coastguard Worker #include <dispatch/dispatch.h>
14*c8dee2aaSAndroid Build Coastguard Worker
15*c8dee2aaSAndroid Build Coastguard Worker struct SkSemaphore::OSSemaphore {
16*c8dee2aaSAndroid Build Coastguard Worker dispatch_semaphore_t fSemaphore;
17*c8dee2aaSAndroid Build Coastguard Worker
OSSemaphoreSkSemaphore::OSSemaphore18*c8dee2aaSAndroid Build Coastguard Worker OSSemaphore() { fSemaphore = dispatch_semaphore_create(0/*initial count*/); }
~OSSemaphoreSkSemaphore::OSSemaphore19*c8dee2aaSAndroid Build Coastguard Worker ~OSSemaphore() { dispatch_release(fSemaphore); }
20*c8dee2aaSAndroid Build Coastguard Worker
signalSkSemaphore::OSSemaphore21*c8dee2aaSAndroid Build Coastguard Worker void signal(int n) { while (n --> 0) { dispatch_semaphore_signal(fSemaphore); } }
waitSkSemaphore::OSSemaphore22*c8dee2aaSAndroid Build Coastguard Worker void wait() { dispatch_semaphore_wait(fSemaphore, DISPATCH_TIME_FOREVER); }
23*c8dee2aaSAndroid Build Coastguard Worker };
24*c8dee2aaSAndroid Build Coastguard Worker #elif defined(SK_BUILD_FOR_WIN)
25*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkLeanWindows.h"
26*c8dee2aaSAndroid Build Coastguard Worker
27*c8dee2aaSAndroid Build Coastguard Worker struct SkSemaphore::OSSemaphore {
28*c8dee2aaSAndroid Build Coastguard Worker HANDLE fSemaphore;
29*c8dee2aaSAndroid Build Coastguard Worker
OSSemaphoreSkSemaphore::OSSemaphore30*c8dee2aaSAndroid Build Coastguard Worker OSSemaphore() {
31*c8dee2aaSAndroid Build Coastguard Worker fSemaphore = CreateSemaphore(nullptr /*security attributes, optional*/,
32*c8dee2aaSAndroid Build Coastguard Worker 0 /*initial count*/,
33*c8dee2aaSAndroid Build Coastguard Worker MAXLONG /*max count*/,
34*c8dee2aaSAndroid Build Coastguard Worker nullptr /*name, optional*/);
35*c8dee2aaSAndroid Build Coastguard Worker }
~OSSemaphoreSkSemaphore::OSSemaphore36*c8dee2aaSAndroid Build Coastguard Worker ~OSSemaphore() { CloseHandle(fSemaphore); }
37*c8dee2aaSAndroid Build Coastguard Worker
signalSkSemaphore::OSSemaphore38*c8dee2aaSAndroid Build Coastguard Worker void signal(int n) {
39*c8dee2aaSAndroid Build Coastguard Worker ReleaseSemaphore(fSemaphore, n, nullptr/*returns previous count, optional*/);
40*c8dee2aaSAndroid Build Coastguard Worker }
waitSkSemaphore::OSSemaphore41*c8dee2aaSAndroid Build Coastguard Worker void wait() { WaitForSingleObject(fSemaphore, INFINITE/*timeout in ms*/); }
42*c8dee2aaSAndroid Build Coastguard Worker };
43*c8dee2aaSAndroid Build Coastguard Worker #else
44*c8dee2aaSAndroid Build Coastguard Worker // It's important we test for Mach before this. This code will compile but not work there.
45*c8dee2aaSAndroid Build Coastguard Worker #include <errno.h>
46*c8dee2aaSAndroid Build Coastguard Worker #include <semaphore.h>
47*c8dee2aaSAndroid Build Coastguard Worker struct SkSemaphore::OSSemaphore {
48*c8dee2aaSAndroid Build Coastguard Worker sem_t fSemaphore;
49*c8dee2aaSAndroid Build Coastguard Worker
OSSemaphoreSkSemaphore::OSSemaphore50*c8dee2aaSAndroid Build Coastguard Worker OSSemaphore() { sem_init(&fSemaphore, 0/*cross process?*/, 0/*initial count*/); }
~OSSemaphoreSkSemaphore::OSSemaphore51*c8dee2aaSAndroid Build Coastguard Worker ~OSSemaphore() { sem_destroy(&fSemaphore); }
52*c8dee2aaSAndroid Build Coastguard Worker
signalSkSemaphore::OSSemaphore53*c8dee2aaSAndroid Build Coastguard Worker void signal(int n) { while (n --> 0) { sem_post(&fSemaphore); } }
waitSkSemaphore::OSSemaphore54*c8dee2aaSAndroid Build Coastguard Worker void wait() {
55*c8dee2aaSAndroid Build Coastguard Worker // Try until we're not interrupted.
56*c8dee2aaSAndroid Build Coastguard Worker while(sem_wait(&fSemaphore) == -1 && errno == EINTR);
57*c8dee2aaSAndroid Build Coastguard Worker }
58*c8dee2aaSAndroid Build Coastguard Worker };
59*c8dee2aaSAndroid Build Coastguard Worker #endif
60*c8dee2aaSAndroid Build Coastguard Worker
61*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
62*c8dee2aaSAndroid Build Coastguard Worker
~SkSemaphore()63*c8dee2aaSAndroid Build Coastguard Worker SkSemaphore::~SkSemaphore() {
64*c8dee2aaSAndroid Build Coastguard Worker delete fOSSemaphore;
65*c8dee2aaSAndroid Build Coastguard Worker }
66*c8dee2aaSAndroid Build Coastguard Worker
osSignal(int n)67*c8dee2aaSAndroid Build Coastguard Worker void SkSemaphore::osSignal(int n) {
68*c8dee2aaSAndroid Build Coastguard Worker fOSSemaphoreOnce([this] { fOSSemaphore = new OSSemaphore; });
69*c8dee2aaSAndroid Build Coastguard Worker fOSSemaphore->signal(n);
70*c8dee2aaSAndroid Build Coastguard Worker }
71*c8dee2aaSAndroid Build Coastguard Worker
osWait()72*c8dee2aaSAndroid Build Coastguard Worker void SkSemaphore::osWait() {
73*c8dee2aaSAndroid Build Coastguard Worker fOSSemaphoreOnce([this] { fOSSemaphore = new OSSemaphore; });
74*c8dee2aaSAndroid Build Coastguard Worker fOSSemaphore->wait();
75*c8dee2aaSAndroid Build Coastguard Worker }
76*c8dee2aaSAndroid Build Coastguard Worker
try_wait()77*c8dee2aaSAndroid Build Coastguard Worker bool SkSemaphore::try_wait() {
78*c8dee2aaSAndroid Build Coastguard Worker int count = fCount.load(std::memory_order_relaxed);
79*c8dee2aaSAndroid Build Coastguard Worker if (count > 0) {
80*c8dee2aaSAndroid Build Coastguard Worker return fCount.compare_exchange_weak(count, count-1, std::memory_order_acquire);
81*c8dee2aaSAndroid Build Coastguard Worker }
82*c8dee2aaSAndroid Build Coastguard Worker return false;
83*c8dee2aaSAndroid Build Coastguard Worker }
84