blob: 15c24b54242c75ed53a7678230025a2ed773e0f3
1 | /* |
2 | // Copyright(c) 2016 Amlogic Corporation |
3 | */ |
4 | |
5 | #include <sync/sync.h> |
6 | #include <sw_sync.h> |
7 | |
8 | #include <HwcFenceControl.h> |
9 | #include <unistd.h> |
10 | #include <utils/Log.h> |
11 | #include <HwcTrace.h> |
12 | |
13 | namespace android { |
14 | namespace amlogic { |
15 | |
16 | const sp<HwcFenceControl> HwcFenceControl::NO_FENCE = sp<HwcFenceControl>(new HwcFenceControl); |
17 | |
18 | HwcFenceControl::HwcFenceControl() : |
19 | mFenceFd(-1) { |
20 | } |
21 | |
22 | HwcFenceControl::HwcFenceControl(int32_t fenceFd) : |
23 | mFenceFd(fenceFd) { |
24 | } |
25 | |
26 | HwcFenceControl::~HwcFenceControl() { |
27 | if (mFenceFd != -1) { |
28 | close(mFenceFd); |
29 | } |
30 | } |
31 | |
32 | int32_t HwcFenceControl::createFenceTimeline() { |
33 | int32_t syncTimelineFd; |
34 | |
35 | syncTimelineFd = sw_sync_timeline_create(); |
36 | if (syncTimelineFd < 0) { |
37 | ETRACE("Stark, can't create sw_sync_timeline:"); |
38 | return -1; |
39 | } |
40 | |
41 | return syncTimelineFd; |
42 | } |
43 | |
44 | int32_t HwcFenceControl::createFence(int32_t syncTimelineFd, |
45 | char* str, uint32_t val) { |
46 | |
47 | int32_t fenceFd = sw_sync_fence_create(syncTimelineFd, str, val); |
48 | if (fenceFd < 0) { |
49 | ETRACE("can't create sync pt %d: %s", val, strerror(errno)); |
50 | return -1; |
51 | } |
52 | |
53 | return fenceFd; |
54 | } |
55 | |
56 | status_t HwcFenceControl::syncTimelineInc(int32_t syncTimelineFd) { |
57 | status_t err; |
58 | |
59 | err = sw_sync_timeline_inc(syncTimelineFd, 1); |
60 | if (err < 0) { |
61 | ETRACE("can't increment sync obj:"); |
62 | return -1; |
63 | } |
64 | return err; |
65 | } |
66 | |
67 | status_t HwcFenceControl::traceFenceInfo(int32_t fence) { |
68 | status_t err; |
69 | struct sync_fence_info_data *info; |
70 | |
71 | err = sync_wait(fence, 10000); |
72 | |
73 | if (err < 0) { |
74 | ITRACE("wait %d failed: %s\n", fence, strerror(errno)); |
75 | } else { |
76 | ITRACE("wait %d done\n", fence); |
77 | } |
78 | info = sync_fence_info(fence); |
79 | if (info) { |
80 | struct sync_pt_info *pt_info = NULL; |
81 | ITRACE(" fence %s %d\n", info->name, info->status); |
82 | |
83 | while ((pt_info = sync_pt_info(info, pt_info))) { |
84 | int ts_sec = pt_info->timestamp_ns / 1000000000LL; |
85 | int ts_usec = (pt_info->timestamp_ns % 1000000000LL) / 1000LL; |
86 | ITRACE(" pt %s %s %d %d.%06d", pt_info->obj_name, |
87 | pt_info->driver_name, pt_info->status, |
88 | ts_sec, ts_usec); |
89 | if (!strcmp(pt_info->driver_name, "sw_sync")) |
90 | ITRACE(" val=%d\n", *(uint32_t *)pt_info->driver_data); |
91 | else |
92 | ITRACE("\n"); |
93 | } |
94 | sync_fence_info_free(info); |
95 | } |
96 | |
97 | // closeFd( fence); |
98 | return err; |
99 | } |
100 | |
101 | status_t HwcFenceControl::wait(int32_t fence, int32_t timeout) { |
102 | if (fence == -1) { |
103 | return NO_ERROR; |
104 | } |
105 | int32_t err = sync_wait(fence, timeout); |
106 | return err < 0 ? -errno : status_t(NO_ERROR); |
107 | } |
108 | |
109 | status_t HwcFenceControl::waitForever(const char* logname) { |
110 | if (mFenceFd == -1) { |
111 | return NO_ERROR; |
112 | } |
113 | int32_t warningTimeout = 3000; |
114 | int32_t err = sync_wait(mFenceFd, warningTimeout); |
115 | if (err < 0 && errno == ETIME) { |
116 | ETRACE("%s: fence %d didn't signal in %u ms", logname, mFenceFd, |
117 | warningTimeout); |
118 | err = sync_wait(mFenceFd, TIMEOUT_NEVER); |
119 | } |
120 | return err < 0 ? -errno : status_t(NO_ERROR); |
121 | } |
122 | |
123 | int32_t HwcFenceControl::merge(const String8& name, const int32_t& f1, |
124 | const int32_t& f2) { |
125 | int32_t result; |
126 | // Merge the two fences. In the case where one of the fences is not a |
127 | // valid fence (e.g. NO_FENCE) we merge the one valid fence with itself so |
128 | // that a new fence with the given name is created. |
129 | if (f1 != -1 && f2 != -1) { |
130 | result = sync_merge(name.string(), f1, f2); |
131 | } else if (f1 != -1) { |
132 | result = sync_merge(name.string(), f1, f1); |
133 | } else if (f2 != -1) { |
134 | result = sync_merge(name.string(), f2, f2); |
135 | } else { |
136 | return -1; |
137 | } |
138 | if (result == -1) { |
139 | status_t err = -errno; |
140 | ETRACE("merge: sync_merge(\"%s\", %d, %d) returned an error: %s (%d)", |
141 | name.string(), f1, f2, |
142 | strerror(-err), err); |
143 | return -1; |
144 | } |
145 | return result; |
146 | } |
147 | |
148 | int32_t HwcFenceControl::dupFence(int32_t fence) { |
149 | if (-1 == fence) { |
150 | DTRACE("acquire fence already been signaled."); |
151 | return -1; |
152 | } |
153 | |
154 | int32_t dupFence = ::dup(fence); |
155 | if (dupFence < 0) { |
156 | ETRACE("acquire fence dup failed! please check it immeditely!"); |
157 | } |
158 | |
159 | return dupFence; |
160 | } |
161 | |
162 | } // namespace amlogic |
163 | } // namespace android |
164 |