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