| // Copyright 2017 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef GARNET_LIB_MAGMA_SRC_MAGMA_UTIL_PLATFORM_PLATFORM_SEMAPHORE_H_ |
| #define GARNET_LIB_MAGMA_SRC_MAGMA_UTIL_PLATFORM_PLATFORM_SEMAPHORE_H_ |
| |
| #include <memory> |
| |
| #include "magma_util/macros.h" |
| #include "magma_util/status.h" |
| #include "platform_object.h" |
| |
| namespace magma { |
| |
| class PlatformPort; |
| |
| // Semantics of PlatformSemaphore match Vulkan semaphores. From: |
| // |
| // https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#synchronization-semaphores |
| // |
| // "Semaphores are a synchronization primitive that can be used to insert a dependency between |
| // batches submitted to queues. Semaphores have two states - signaled and unsignaled. The state |
| // of a semaphore can be signaled after execution of a batch of commands is completed. A batch |
| // can wait for a semaphore to become signaled before it begins execution, and the semaphore is |
| // also unsignaled before the batch begins execution." |
| // |
| // "Unlike fences or events, the act of waiting for a semaphore also unsignals that semaphore. |
| // If two operations are separately specified to wait for the same semaphore, and there are no |
| // other execution dependencies between those operations, behaviour is undefined. An execution |
| // dependency must be present that guarantees that the semaphore unsignal operation for the first |
| // of those waits, happens-before the semaphore is signalled again, and before the second unsignal |
| // operation. Semaphore waits and signals should thus occur in discrete 1:1 pairs." |
| // |
| class PlatformSemaphore : public PlatformObject { |
| public: |
| static std::unique_ptr<PlatformSemaphore> Create(); |
| |
| // Imports and takes ownership of |handle|. |
| static std::unique_ptr<PlatformSemaphore> Import(uint32_t handle); |
| |
| virtual ~PlatformSemaphore() {} |
| |
| std::unique_ptr<PlatformSemaphore> Clone() |
| { |
| uint32_t handle; |
| if (!duplicate_handle(&handle)) |
| return DRETP(nullptr, "failed to duplicate handle"); |
| return Import(handle); |
| } |
| |
| // Signal the semaphore. State must be unsignalled. |
| // Called only by the driver device thread. |
| virtual void Signal() = 0; |
| |
| // Resets the state to unsignalled. State may be signalled or unsignalled. |
| // Called by the client (apps thread) and by the driver device thread. |
| virtual void Reset() = 0; |
| |
| // Returns MAGMA_STATUS_OK if the event is signaled before the timeout expires. |
| virtual magma::Status WaitNoReset(uint64_t timeout_ms) = 0; |
| |
| // If the event is signaled before the timeout expires resets the state to |
| // unsignalled and returns MAGMA_STATUS_OK. Only one thread should ever wait on |
| // a given semaphore. |
| virtual magma::Status Wait(uint64_t timeout_ms) = 0; |
| |
| magma::Status Wait() { return Wait(UINT64_MAX); } |
| |
| // Registers an async wait delivered on the given port when this semaphore is signalled. |
| // Note that a port wait completion will not autoreset the semaphore. |
| virtual bool WaitAsync(PlatformPort* platform_port) = 0; |
| }; |
| |
| } // namespace magma |
| |
| #endif // GARNET_LIB_MAGMA_SRC_MAGMA_UTIL_PLATFORM_PLATFORM_SEMAPHORE_H_ |