1 // Copyright 2018 The Fuchsia Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #pragma once 6 7 #include <fbl/intrusive_double_list.h> 8 #include <fbl/ref_counted.h> 9 #include <fbl/ref_ptr.h> 10 #include <lib/async/cpp/wait.h> 11 #include <threads.h> 12 #include <lib/zx/event.h> 13 14 #include "id-map.h" 15 16 namespace display { 17 18 class FenceReference; 19 class Fence; 20 21 class FenceCallback { 22 public: 23 virtual void OnFenceFired(FenceReference* ref) = 0; 24 virtual void OnRefForFenceDead(Fence* fence) = 0; 25 }; 26 27 // Class which wraps an event into a fence. A single Fence can have multiple FenceReference 28 // objects, which allows an event to be treated as a semaphore independently of it being 29 // imported/released (i.e. can be released while still in use). 30 class Fence : public fbl::RefCounted<Fence>, public IdMappable<fbl::RefPtr<Fence>> { 31 public: 32 Fence(FenceCallback* cb, async_dispatcher_t* dispatcher, uint64_t id, zx::event&& event); 33 ~Fence(); 34 35 // Creates a new FenceReference when an event is imported. 36 bool CreateRef(); 37 // Clears a FenceReference when an event is released. Note that references to the cleared 38 // FenceReference might still exist within the driver. 39 void ClearRef(); 40 // Decrements the reference count and returns true if the last ref died. 41 bool OnRefDead(); 42 43 // Gets the fence reference for the current import. An individual fence reference cannot 44 // be used for multiple things simultaniously. 45 fbl::RefPtr<FenceReference> GetReference(); 46 private: 47 void Signal(); 48 void OnRefDied(); 49 zx_status_t OnRefArmed(fbl::RefPtr<FenceReference>&& ref); 50 void OnRefDisarmed(FenceReference* ref); 51 52 // The fence reference corresponding to the current event import. 53 fbl::RefPtr<FenceReference> cur_ref_; 54 55 // A queue of fence references which are being waited upon. When the event is 56 // signaled, the signal will be cleared and the first fence ref will be marked ready. 57 fbl::DoublyLinkedList<fbl::RefPtr<FenceReference>> armed_refs_; 58 59 void OnReady(async_dispatcher_t* dispatcher, async::WaitBase* self, 60 zx_status_t status, const zx_packet_signal_t* signal); 61 async::WaitMethod<Fence, &Fence::OnReady> ready_wait_{this}; 62 63 FenceCallback* cb_; 64 async_dispatcher_t* dispatcher_; 65 zx::event event_; 66 int ref_count_ = 0; 67 68 friend FenceReference; 69 70 DISALLOW_COPY_ASSIGN_AND_MOVE(Fence); 71 }; 72 73 class FenceReference : public fbl::RefCounted<FenceReference> 74 , public fbl::DoublyLinkedListable<fbl::RefPtr<FenceReference>> { 75 public: 76 explicit FenceReference(fbl::RefPtr<Fence> fence); 77 ~FenceReference(); 78 79 void Signal(); 80 81 zx_status_t StartReadyWait(); 82 void ResetReadyWait(); 83 // Sets the fence which will be signaled immedately when this fence is ready. 84 void SetImmediateRelease(fbl::RefPtr<FenceReference>&& fence); 85 86 void OnReady(); 87 private: 88 fbl::RefPtr<Fence> fence_; 89 90 fbl::RefPtr<FenceReference> release_fence_; 91 92 DISALLOW_COPY_ASSIGN_AND_MOVE(FenceReference); 93 }; 94 95 } // namespace display 96