1f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis/*
2f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis * Copyright (C) 2012 The Android Open Source Project
3f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis *
4f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis * Licensed under the Apache License, Version 2.0 (the "License");
5f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis * you may not use this file except in compliance with the License.
6f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis * You may obtain a copy of the License at
7f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis *
8f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis *      http://www.apache.org/licenses/LICENSE-2.0
9f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis *
10f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis * Unless required by applicable law or agreed to in writing, software
11f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis * distributed under the License is distributed on an "AS IS" BASIS,
12f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis * See the License for the specific language governing permissions and
14f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis * limitations under the License.
15f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis */
16f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis
17f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis#define LOG_TAG "Fence"
18f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis#define ATRACE_TAG ATRACE_TAG_GRAPHICS
19f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis//#define LOG_NDEBUG 0
20f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis
2182dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis // This is needed for stdint.h to define INT64_MAX in C++
2282dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis #define __STDC_LIMIT_MACROS
2382dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
24f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis#include <sync/sync.h>
25f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis#include <ui/Fence.h>
26f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis#include <unistd.h>
27f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis#include <utils/Log.h>
28f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis#include <utils/Trace.h>
29f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis
30f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennisnamespace android {
31f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis
321df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennisconst sp<Fence> Fence::NO_FENCE = sp<Fence>(new Fence);
33ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall
34f25e183a70bd631f75dce51e85b7d568472a0cdbJamie GennisFence::Fence() :
35f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    mFenceFd(-1) {
36f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis}
37f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis
38f25e183a70bd631f75dce51e85b7d568472a0cdbJamie GennisFence::Fence(int fenceFd) :
39f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    mFenceFd(fenceFd) {
40f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis}
41f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis
42f25e183a70bd631f75dce51e85b7d568472a0cdbJamie GennisFence::~Fence() {
43f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    if (mFenceFd != -1) {
44f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis        close(mFenceFd);
45f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    }
46f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis}
47f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis
48b5c9dcdf3bdab1862047060b8e18c9d1831db8bbMathias Agopianstatus_t Fence::wait(unsigned int timeout) {
49f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    ATRACE_CALL();
50f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    if (mFenceFd == -1) {
51f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis        return NO_ERROR;
52f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    }
53b5c9dcdf3bdab1862047060b8e18c9d1831db8bbMathias Agopian    int err = sync_wait(mFenceFd, timeout);
54b5c9dcdf3bdab1862047060b8e18c9d1831db8bbMathias Agopian    return err < 0 ? -errno : status_t(NO_ERROR);
55f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis}
56f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis
57ea74d3b78d607cde17790a7bb83e6f68ffd34cfdMathias Agopianstatus_t Fence::waitForever(const char* logname) {
58ba607d53c6a94ea8c4c12571980c4ad159af308bJesse Hall    ATRACE_CALL();
59ba607d53c6a94ea8c4c12571980c4ad159af308bJesse Hall    if (mFenceFd == -1) {
60ba607d53c6a94ea8c4c12571980c4ad159af308bJesse Hall        return NO_ERROR;
61ba607d53c6a94ea8c4c12571980c4ad159af308bJesse Hall    }
62ea74d3b78d607cde17790a7bb83e6f68ffd34cfdMathias Agopian    unsigned int warningTimeout = 3000;
63ba607d53c6a94ea8c4c12571980c4ad159af308bJesse Hall    int err = sync_wait(mFenceFd, warningTimeout);
64b5c9dcdf3bdab1862047060b8e18c9d1831db8bbMathias Agopian    if (err < 0 && errno == ETIME) {
65ba607d53c6a94ea8c4c12571980c4ad159af308bJesse Hall        ALOGE("%s: fence %d didn't signal in %u ms", logname, mFenceFd,
66ba607d53c6a94ea8c4c12571980c4ad159af308bJesse Hall                warningTimeout);
67ba607d53c6a94ea8c4c12571980c4ad159af308bJesse Hall        err = sync_wait(mFenceFd, TIMEOUT_NEVER);
68ba607d53c6a94ea8c4c12571980c4ad159af308bJesse Hall    }
69b5c9dcdf3bdab1862047060b8e18c9d1831db8bbMathias Agopian    return err < 0 ? -errno : status_t(NO_ERROR);
70ba607d53c6a94ea8c4c12571980c4ad159af308bJesse Hall}
71ba607d53c6a94ea8c4c12571980c4ad159af308bJesse Hall
72f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennissp<Fence> Fence::merge(const String8& name, const sp<Fence>& f1,
73f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis        const sp<Fence>& f2) {
74f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    ATRACE_CALL();
751df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    int result;
761df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    // Merge the two fences.  In the case where one of the fences is not a
771df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    // valid fence (e.g. NO_FENCE) we merge the one valid fence with itself so
781df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    // that a new fence with the given name is created.
791df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    if (f1->isValid() && f2->isValid()) {
801df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis        result = sync_merge(name.string(), f1->mFenceFd, f2->mFenceFd);
811df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    } else if (f1->isValid()) {
821df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis        result = sync_merge(name.string(), f1->mFenceFd, f1->mFenceFd);
831df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    } else if (f2->isValid()) {
841df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis        result = sync_merge(name.string(), f2->mFenceFd, f2->mFenceFd);
851df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    } else {
861df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis        return NO_FENCE;
871df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    }
88f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    if (result == -1) {
89d83d67b5d5e98b7f0bdf54b68f6ea28fa4905a33Mathias Agopian        status_t err = -errno;
90d83d67b5d5e98b7f0bdf54b68f6ea28fa4905a33Mathias Agopian        ALOGE("merge: sync_merge(\"%s\", %d, %d) returned an error: %s (%d)",
91d83d67b5d5e98b7f0bdf54b68f6ea28fa4905a33Mathias Agopian                name.string(), f1->mFenceFd, f2->mFenceFd,
92d83d67b5d5e98b7f0bdf54b68f6ea28fa4905a33Mathias Agopian                strerror(-err), err);
93ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall        return NO_FENCE;
94f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    }
95f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    return sp<Fence>(new Fence(result));
96f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis}
97f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis
98f9783af225aa3b41ec0af36f90941a714269abb7Jesse Hallint Fence::dup() const {
99f9783af225aa3b41ec0af36f90941a714269abb7Jesse Hall    return ::dup(mFenceFd);
100f9783af225aa3b41ec0af36f90941a714269abb7Jesse Hall}
101f9783af225aa3b41ec0af36f90941a714269abb7Jesse Hall
10282dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennisnsecs_t Fence::getSignalTime() const {
10382dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    if (mFenceFd == -1) {
10482dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis        return -1;
10582dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    }
10682dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
10782dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    struct sync_fence_info_data* finfo = sync_fence_info(mFenceFd);
10882dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    if (finfo == NULL) {
10982dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis        ALOGE("sync_fence_info returned NULL for fd %d", mFenceFd);
11082dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis        return -1;
11182dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    }
11282dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    if (finfo->status != 1) {
1137c36cd231542990e0ef8240fcc8dfd35a9e4b38bJesse Hall        sync_fence_info_free(finfo);
11482dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis        return INT64_MAX;
11582dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    }
11682dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
11782dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    struct sync_pt_info* pinfo = NULL;
11882dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    uint64_t timestamp = 0;
11982dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    while ((pinfo = sync_pt_info(finfo, pinfo)) != NULL) {
12082dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis        if (pinfo->timestamp_ns > timestamp) {
12182dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis            timestamp = pinfo->timestamp_ns;
12282dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis        }
12382dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    }
12482dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    sync_fence_info_free(finfo);
12582dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
12682dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    return nsecs_t(timestamp);
12782dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis}
12882dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
129f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennissize_t Fence::getFlattenedSize() const {
130e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian    return 1;
131f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis}
132f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis
133f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennissize_t Fence::getFdCount() const {
1341df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    return isValid() ? 1 : 0;
135f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis}
136f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis
137e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopianstatus_t Fence::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const {
138e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian    if (size < getFlattenedSize() || count < getFdCount()) {
139e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian        return NO_MEMORY;
140f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    }
141288f2ef6294b99a4a53355273ae8ad0f5a525f65Colin Cross    FlattenableUtils::write(buffer, size, (uint32_t)getFdCount());
1421df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    if (isValid()) {
143e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian        *fds++ = mFenceFd;
144e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian        count--;
1451df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    }
146f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    return NO_ERROR;
147f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis}
148f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis
149e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopianstatus_t Fence::unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count) {
150f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    if (mFenceFd != -1) {
151f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis        // Don't unflatten if we already have a valid fd.
152f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis        return INVALID_OPERATION;
153f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    }
154f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis
155e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian    if (size < 1) {
156e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian        return NO_MEMORY;
157e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian    }
158e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian
159288f2ef6294b99a4a53355273ae8ad0f5a525f65Colin Cross    uint32_t numFds;
160e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian    FlattenableUtils::read(buffer, size, numFds);
161e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian
162e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian    if (numFds > 1) {
163e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian        return BAD_VALUE;
164e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian    }
165e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian
166e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian    if (count < numFds) {
167e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian        return NO_MEMORY;
168e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian    }
169e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian
170e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian    if (numFds) {
171e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian        mFenceFd = *fds++;
172e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian        count--;
1731df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    }
1741df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis
175f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    return NO_ERROR;
176f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis}
177f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis
178f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis} // namespace android
179