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 wps_.erase(std::remove_if(wps_.begin(), wps_.end(), [](const std::weak_ptr<Fence> &wp) {
54 return wp.expired();
55 }), wps_.end());
56 }
57
Set(BufferSyncHandler * buffer_sync_handler)58 void Fence::Set(BufferSyncHandler *buffer_sync_handler) {
59 g_buffer_sync_handler_ = buffer_sync_handler;
60 }
61
Create(int fd,const string & name)62 shared_ptr<Fence> Fence::Create(int fd, const string &name) {
63 // Do not create Fence object for invalid fd, so that nullptr can be used for invalid fences.
64 if (fd < 0) {
65 return nullptr;
66 }
67
68 shared_ptr<Fence> fence(new Fence(fd, name));
69 if (!fence) {
70 close(fd);
71 }
72
73 wps_.push_back(fence);
74
75 return fence;
76 }
77
Dup(const shared_ptr<Fence> & fence)78 int Fence::Dup(const shared_ptr<Fence> &fence) {
79 return (fence ? dup(fence->fd_) : -1);
80 }
81
Get(const shared_ptr<Fence> & fence)82 int Fence::Get(const shared_ptr<Fence> &fence) {
83 return (fence ? fence->fd_ : -1);
84 }
85
Merge(const shared_ptr<Fence> & fence1,const shared_ptr<Fence> & fence2)86 shared_ptr<Fence> Fence::Merge(const shared_ptr<Fence> &fence1, const shared_ptr<Fence> &fence2) {
87 ASSERT_IF_NO_BUFFER_SYNC(g_buffer_sync_handler_);
88
89 // Sync merge will return a new unique fd if source fds are same.
90 int fd1 = fence1 ? fence1->fd_ : -1;
91 int fd2 = fence2 ? fence2->fd_ : -1;
92 int merged = -1;
93 std::string name = "merged[" + to_string(fd1) + ", " + to_string(fd2) + "]";
94
95 g_buffer_sync_handler_->SyncMerge(fd1, fd2, &merged);
96
97 return Create(merged, name);
98 }
99
Wait(const shared_ptr<Fence> & fence)100 DisplayError Fence::Wait(const shared_ptr<Fence> &fence) {
101 ASSERT_IF_NO_BUFFER_SYNC(g_buffer_sync_handler_);
102
103 return g_buffer_sync_handler_->SyncWait(Fence::Get(fence), 1000);
104 }
105
Wait(const shared_ptr<Fence> & fence,int timeout)106 DisplayError Fence::Wait(const shared_ptr<Fence> &fence, int timeout) {
107 ASSERT_IF_NO_BUFFER_SYNC(g_buffer_sync_handler_);
108
109 return g_buffer_sync_handler_->SyncWait(Fence::Get(fence), timeout);
110 }
111
GetStatus(const shared_ptr<Fence> & fence)112 Fence::Status Fence::GetStatus(const shared_ptr<Fence> &fence) {
113 ASSERT_IF_NO_BUFFER_SYNC(g_buffer_sync_handler_);
114
115 if (!fence) {
116 return Fence::Status::kSignaled;
117 }
118
119 // Treat only timeout error as pending, assume other errors as signaled.
120 return (g_buffer_sync_handler_->SyncWait(Fence::Get(fence), 0) == kErrorTimeOut ?
121 Fence::Status::kPending : Fence::Status::kSignaled);
122 }
123
GetStr(const shared_ptr<Fence> & fence)124 string Fence::GetStr(const shared_ptr<Fence> &fence) {
125 return std::to_string(Fence::Get(fence));
126 }
127
Dump(std::ostringstream * os)128 void Fence::Dump(std::ostringstream *os) {
129 ASSERT_IF_NO_BUFFER_SYNC(g_buffer_sync_handler_);
130
131 *os << "\n------------Active Fences Info---------";
132 for (auto &wp : wps_) {
133 *os << "\n";
134 shared_ptr<Fence> fence = wp.lock();
135 if (!fence) {
136 continue;
137 }
138 *os << "FD: " << fence->fd_;
139 *os << ", name: " << fence->name_;
140 *os << ", use_count: " << fence.use_count() - 1; // Do not count wp lock reference
141 *os << ", ";
142 g_buffer_sync_handler_->GetSyncInfo(fence->fd_, os);
143 }
144 *os << "\n---------------------------------------\n";
145 }
146
~ScopedRef()147 Fence::ScopedRef::~ScopedRef() {
148 for (int dup_fd : dup_fds_) {
149 close(dup_fd);
150 }
151 }
152
Get(const shared_ptr<Fence> & fence)153 int Fence::ScopedRef::Get(const shared_ptr<Fence> &fence) {
154 int dup_fd = Fence::Dup(fence);
155 if (dup_fd >= 0) {
156 dup_fds_.push_back(dup_fd);
157 }
158
159 return dup_fd;
160 }
161
162 } // namespace sdm
163