1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "unique_timeline.h"
18 
19 #include <errno.h>
20 #include <limits>
21 #include <string.h>
22 #include <sw_sync.h>
23 
24 #include <android-base/logging.h>
25 
26 namespace android {
27 namespace automotive {
28 namespace evs {
29 namespace V1_1 {
30 namespace implementation {
31 
UniqueTimeline(unsigned offset)32 UniqueTimeline::UniqueTimeline(unsigned offset)
33       : fd_(sw_sync_timeline_create()), fence_counter_(offset) {
34     if (!fd_) {
35         LOG(FATAL) << "Failed to create a timeline.";
36     }
37 }
38 
~UniqueTimeline()39 UniqueTimeline::~UniqueTimeline() {
40     // Force any fences waiting on the timeline to be released by incrementing
41     // by the difference between the two counters. The sw_sync driver has
42     // changed behavior several times, and no longer releases fences when the
43     // timeline fd is closed. While at one point adding MAX_UINT worked (by
44     // adding MAX_INT with two separate calls), even that stopped working.
45     // (See b/35115489 for background)
46     BumpTimelineEventCounter(fence_counter_ - timeline_counter_);
47 }
48 
Supported()49 bool UniqueTimeline::Supported() {
50     UniqueFd fd{sw_sync_timeline_create()};
51     return !!fd;
52 }
53 
CreateFence(const char * name)54 UniqueFence UniqueTimeline::CreateFence(const char* name) {
55     UniqueFence fence(sw_sync_fence_create(fd_.Get(), name, fence_counter_));
56     if (!fence) {
57         PLOG(FATAL) << "Cannot create fence";
58     }
59     return fence;
60 }
61 
BumpTimelineEventCounter()62 void UniqueTimeline::BumpTimelineEventCounter() {
63     BumpTimelineEventCounter(1);
64 }
65 
BumpTimelineEventCounter(unsigned count)66 void UniqueTimeline::BumpTimelineEventCounter(unsigned count) {
67     timeline_counter_ += count;
68     int err = sw_sync_timeline_inc(fd_.Get(), count);
69     if (err < 0) {
70         PLOG(FATAL) << "Cannot bump timeline counter";
71     }
72 }
73 
74 }  // namespace implementation
75 }  // namespace V1_1
76 }  // namespace evs
77 }  // namespace automotive
78 }  // namespace android
79