1 /*
2 * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *     * Redistributions of source code must retain the above copyright
8 *       notice, this list of conditions and the following disclaimer.
9 *     * Redistributions in binary form must reproduce the above
10 *       copyright notice, this list of conditions and the following
11 *       disclaimer in the documentation and/or other materials provided
12 *       with the distribution.
13 *     * Neither the name of The Linux Foundation nor the names of its
14 *       contributors may be used to endorse or promote products derived
15 *       from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 
30 #include <utils/fence.h>
31 #include <debug_handler.h>
32 #include <assert.h>
33 #include <string>
34 #include <vector>
35 #include <algorithm>
36 
37 #define __CLASS__ "Fence"
38 
39 namespace sdm {
40 
41 #define ASSERT_IF_NO_BUFFER_SYNC(x) if (!x) { assert(false); }
42 
43 BufferSyncHandler* Fence::g_buffer_sync_handler_ = nullptr;
44 std::vector<std::weak_ptr<Fence>> Fence::wps_;
45 
Fence(int fd,const string & name)46 Fence::Fence(int fd, const string &name) : fd_(fd), name_(name) {
47 }
48 
~Fence()49 Fence::~Fence() {
50   close(fd_);
51 
52   // erase all expired weak references.
53   /*
54   wps_.erase(std::remove_if(wps_.begin(), wps_.end(), [](const std::weak_ptr<Fence> &wp) {
55     return wp.expired();
56   }), wps_.end());
57   */
58 }
59 
Set(BufferSyncHandler * buffer_sync_handler)60 void Fence::Set(BufferSyncHandler *buffer_sync_handler) {
61   g_buffer_sync_handler_ = buffer_sync_handler;
62 }
63 
Create(int fd,const string & name)64 shared_ptr<Fence> Fence::Create(int fd, const string &name) {
65   // Do not create Fence object for invalid fd, so that nullptr can be used for invalid fences.
66   if (fd < 0) {
67     return nullptr;
68   }
69 
70   shared_ptr<Fence> fence(new Fence(fd, name));
71   if (!fence) {
72     close(fd);
73   }
74 
75   // wps_.push_back(fence);
76 
77   return fence;
78 }
79 
Dup(const shared_ptr<Fence> & fence)80 int Fence::Dup(const shared_ptr<Fence> &fence) {
81   return (fence ? dup(fence->fd_) : -1);
82 }
83 
Get(const shared_ptr<Fence> & fence)84 int Fence::Get(const shared_ptr<Fence> &fence) {
85   return (fence ? fence->fd_ : -1);
86 }
87 
Merge(const shared_ptr<Fence> & fence1,const shared_ptr<Fence> & fence2)88 shared_ptr<Fence> Fence::Merge(const shared_ptr<Fence> &fence1, const shared_ptr<Fence> &fence2) {
89   ASSERT_IF_NO_BUFFER_SYNC(g_buffer_sync_handler_);
90 
91   // Sync merge will return a new unique fd if source fds are same.
92   int fd1 = fence1 ? fence1->fd_ : -1;
93   int fd2 = fence2 ? fence2->fd_ : -1;
94   int merged = -1;
95   std::string name = "merged[" + to_string(fd1) + ", " + to_string(fd2) + "]";
96 
97   g_buffer_sync_handler_->SyncMerge(fd1, fd2, &merged);
98 
99   return Create(merged, name);
100 }
101 
Merge(const std::vector<shared_ptr<Fence>> & fences,bool ignore_signaled)102 shared_ptr<Fence> Fence::Merge(const std::vector<shared_ptr<Fence>> &fences, bool ignore_signaled) {
103   ASSERT_IF_NO_BUFFER_SYNC(g_buffer_sync_handler_);
104 
105   shared_ptr<Fence> merged_fence = nullptr;
106   for (auto &fence : fences) {
107     if (ignore_signaled && (Fence::Wait(fence, 0) == kErrorNone)) {
108       continue;
109     }
110 
111     merged_fence = Fence::Merge(fence, merged_fence);
112   }
113 
114   return merged_fence;
115 }
116 
Wait(const shared_ptr<Fence> & fence)117 DisplayError Fence::Wait(const shared_ptr<Fence> &fence) {
118   ASSERT_IF_NO_BUFFER_SYNC(g_buffer_sync_handler_);
119 
120   return g_buffer_sync_handler_->SyncWait(Fence::Get(fence), 1000);
121 }
122 
Wait(const shared_ptr<Fence> & fence,int timeout)123 DisplayError Fence::Wait(const shared_ptr<Fence> &fence, int timeout) {
124   ASSERT_IF_NO_BUFFER_SYNC(g_buffer_sync_handler_);
125 
126   return g_buffer_sync_handler_->SyncWait(Fence::Get(fence), timeout);
127 }
128 
GetStatus(const shared_ptr<Fence> & fence)129 Fence::Status Fence::GetStatus(const shared_ptr<Fence> &fence) {
130   ASSERT_IF_NO_BUFFER_SYNC(g_buffer_sync_handler_);
131 
132   if (!fence) {
133     return Fence::Status::kSignaled;
134   }
135 
136   // Treat only timeout error as pending, assume other errors as signaled.
137   return (g_buffer_sync_handler_->SyncWait(Fence::Get(fence), 0) == kErrorTimeOut ?
138                                     Fence::Status::kPending : Fence::Status::kSignaled);
139 }
140 
GetStr(const shared_ptr<Fence> & fence)141 string Fence::GetStr(const shared_ptr<Fence> &fence) {
142   return std::to_string(Fence::Get(fence));
143 }
144 
Dump(std::ostringstream * os)145 void Fence::Dump(std::ostringstream *os) {
146   ASSERT_IF_NO_BUFFER_SYNC(g_buffer_sync_handler_);
147 
148   *os << "\n------------Active Fences Info---------";
149   /*
150   for (auto &wp : wps_) {
151     *os << "\n";
152     shared_ptr<Fence> fence = wp.lock();
153     if (!fence) {
154       continue;
155     }
156     *os << "FD: " << fence->fd_;
157     *os << ", name: " << fence->name_;
158     *os << ", use_count: " << fence.use_count() - 1;   // Do not count wp lock reference
159     *os << ", ";
160     g_buffer_sync_handler_->GetSyncInfo(fence->fd_, os);
161   }
162   */
163   *os << "\n---------------------------------------\n";
164 }
165 
~ScopedRef()166 Fence::ScopedRef::~ScopedRef() {
167   for (int dup_fd : dup_fds_) {
168     close(dup_fd);
169   }
170 }
171 
Get(const shared_ptr<Fence> & fence)172 int Fence::ScopedRef::Get(const shared_ptr<Fence> &fence) {
173   int dup_fd = Fence::Dup(fence);
174   if (dup_fd >= 0) {
175     dup_fds_.push_back(dup_fd);
176   }
177 
178   return dup_fd;
179 }
180 
181 }  // namespace sdm
182