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
17175a7206c5aea70236b916d7707ab25025eb9cd6Brian Anderson#include <ui/Fence.h>
18175a7206c5aea70236b916d7707ab25025eb9cd6Brian Anderson
19f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis#define LOG_TAG "Fence"
20f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis#define ATRACE_TAG ATRACE_TAG_GRAPHICS
21f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis//#define LOG_NDEBUG 0
22f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis
23d31824004277f554000417cea349d69f18655e95Dan Stoza// We would eliminate the non-conforming zero-length array, but we can't since
24d31824004277f554000417cea349d69f18655e95Dan Stoza// this is effectively included from the Linux kernel
25d31824004277f554000417cea349d69f18655e95Dan Stoza#pragma clang diagnostic push
26d31824004277f554000417cea349d69f18655e95Dan Stoza#pragma clang diagnostic ignored "-Wzero-length-array"
27f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis#include <sync/sync.h>
28d31824004277f554000417cea349d69f18655e95Dan Stoza#pragma clang diagnostic pop
29d31824004277f554000417cea349d69f18655e95Dan Stoza
30175a7206c5aea70236b916d7707ab25025eb9cd6Brian Anderson#include <sys/types.h>
31f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis#include <unistd.h>
32f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis#include <utils/Log.h>
33175a7206c5aea70236b916d7707ab25025eb9cd6Brian Anderson#include <utils/String8.h>
34f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis#include <utils/Trace.h>
35f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis
36f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennisnamespace android {
37f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis
381df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennisconst sp<Fence> Fence::NO_FENCE = sp<Fence>(new Fence);
39ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall
40f25e183a70bd631f75dce51e85b7d568472a0cdbJamie GennisFence::Fence() :
41f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    mFenceFd(-1) {
42f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis}
43f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis
44f25e183a70bd631f75dce51e85b7d568472a0cdbJamie GennisFence::Fence(int fenceFd) :
45f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    mFenceFd(fenceFd) {
46f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis}
47f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis
48f25e183a70bd631f75dce51e85b7d568472a0cdbJamie GennisFence::~Fence() {
49f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    if (mFenceFd != -1) {
50f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis        close(mFenceFd);
51f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    }
52f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis}
53f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis
54d31824004277f554000417cea349d69f18655e95Dan Stozastatus_t Fence::wait(int timeout) {
55f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    ATRACE_CALL();
56f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    if (mFenceFd == -1) {
57f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis        return NO_ERROR;
58f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    }
59b5c9dcdf3bdab1862047060b8e18c9d1831db8bbMathias Agopian    int err = sync_wait(mFenceFd, timeout);
60b5c9dcdf3bdab1862047060b8e18c9d1831db8bbMathias Agopian    return err < 0 ? -errno : status_t(NO_ERROR);
61f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis}
62f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis
63ea74d3b78d607cde17790a7bb83e6f68ffd34cfdMathias Agopianstatus_t Fence::waitForever(const char* logname) {
64ba607d53c6a94ea8c4c12571980c4ad159af308bJesse Hall    ATRACE_CALL();
65ba607d53c6a94ea8c4c12571980c4ad159af308bJesse Hall    if (mFenceFd == -1) {
66ba607d53c6a94ea8c4c12571980c4ad159af308bJesse Hall        return NO_ERROR;
67ba607d53c6a94ea8c4c12571980c4ad159af308bJesse Hall    }
68d31824004277f554000417cea349d69f18655e95Dan Stoza    int warningTimeout = 3000;
69ba607d53c6a94ea8c4c12571980c4ad159af308bJesse Hall    int err = sync_wait(mFenceFd, warningTimeout);
70b5c9dcdf3bdab1862047060b8e18c9d1831db8bbMathias Agopian    if (err < 0 && errno == ETIME) {
71ba607d53c6a94ea8c4c12571980c4ad159af308bJesse Hall        ALOGE("%s: fence %d didn't signal in %u ms", logname, mFenceFd,
72ba607d53c6a94ea8c4c12571980c4ad159af308bJesse Hall                warningTimeout);
73ba607d53c6a94ea8c4c12571980c4ad159af308bJesse Hall        err = sync_wait(mFenceFd, TIMEOUT_NEVER);
74ba607d53c6a94ea8c4c12571980c4ad159af308bJesse Hall    }
75b5c9dcdf3bdab1862047060b8e18c9d1831db8bbMathias Agopian    return err < 0 ? -errno : status_t(NO_ERROR);
76ba607d53c6a94ea8c4c12571980c4ad159af308bJesse Hall}
77ba607d53c6a94ea8c4c12571980c4ad159af308bJesse Hall
78fd4c8c38051f9dad028e4e43e0eb39ba412b2c0aMatthew Bouyacksp<Fence> Fence::merge(const char* name, const sp<Fence>& f1,
79f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis        const sp<Fence>& f2) {
80f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    ATRACE_CALL();
811df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    int result;
821df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    // Merge the two fences.  In the case where one of the fences is not a
831df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    // valid fence (e.g. NO_FENCE) we merge the one valid fence with itself so
841df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    // that a new fence with the given name is created.
851df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    if (f1->isValid() && f2->isValid()) {
86fd4c8c38051f9dad028e4e43e0eb39ba412b2c0aMatthew Bouyack        result = sync_merge(name, f1->mFenceFd, f2->mFenceFd);
871df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    } else if (f1->isValid()) {
88fd4c8c38051f9dad028e4e43e0eb39ba412b2c0aMatthew Bouyack        result = sync_merge(name, f1->mFenceFd, f1->mFenceFd);
891df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    } else if (f2->isValid()) {
90fd4c8c38051f9dad028e4e43e0eb39ba412b2c0aMatthew Bouyack        result = sync_merge(name, f2->mFenceFd, f2->mFenceFd);
911df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    } else {
921df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis        return NO_FENCE;
931df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    }
94f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    if (result == -1) {
95d83d67b5d5e98b7f0bdf54b68f6ea28fa4905a33Mathias Agopian        status_t err = -errno;
96d83d67b5d5e98b7f0bdf54b68f6ea28fa4905a33Mathias Agopian        ALOGE("merge: sync_merge(\"%s\", %d, %d) returned an error: %s (%d)",
97fd4c8c38051f9dad028e4e43e0eb39ba412b2c0aMatthew Bouyack                name, f1->mFenceFd, f2->mFenceFd,
98d83d67b5d5e98b7f0bdf54b68f6ea28fa4905a33Mathias Agopian                strerror(-err), err);
99ef19414bd8b77a26f5751f3845be79025a8263feJesse Hall        return NO_FENCE;
100f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    }
101f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    return sp<Fence>(new Fence(result));
102f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis}
103f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis
104fd4c8c38051f9dad028e4e43e0eb39ba412b2c0aMatthew Bouyacksp<Fence> Fence::merge(const String8& name, const sp<Fence>& f1,
105fd4c8c38051f9dad028e4e43e0eb39ba412b2c0aMatthew Bouyack        const sp<Fence>& f2) {
106fd4c8c38051f9dad028e4e43e0eb39ba412b2c0aMatthew Bouyack    return merge(name.string(), f1, f2);
107fd4c8c38051f9dad028e4e43e0eb39ba412b2c0aMatthew Bouyack}
108fd4c8c38051f9dad028e4e43e0eb39ba412b2c0aMatthew Bouyack
109f9783af225aa3b41ec0af36f90941a714269abb7Jesse Hallint Fence::dup() const {
110f9783af225aa3b41ec0af36f90941a714269abb7Jesse Hall    return ::dup(mFenceFd);
111f9783af225aa3b41ec0af36f90941a714269abb7Jesse Hall}
112f9783af225aa3b41ec0af36f90941a714269abb7Jesse Hall
11382dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennisnsecs_t Fence::getSignalTime() const {
11482dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    if (mFenceFd == -1) {
115221de2a33d456738f7f64db0b015a960211d4834Brian Anderson        return SIGNAL_TIME_INVALID;
11682dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    }
11782dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
11882dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    struct sync_fence_info_data* finfo = sync_fence_info(mFenceFd);
11982dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    if (finfo == NULL) {
12082dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis        ALOGE("sync_fence_info returned NULL for fd %d", mFenceFd);
121221de2a33d456738f7f64db0b015a960211d4834Brian Anderson        return SIGNAL_TIME_INVALID;
12282dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    }
12382dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    if (finfo->status != 1) {
1247c36cd231542990e0ef8240fcc8dfd35a9e4b38bJesse Hall        sync_fence_info_free(finfo);
125221de2a33d456738f7f64db0b015a960211d4834Brian Anderson        return SIGNAL_TIME_PENDING;
12682dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    }
12782dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
12882dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    struct sync_pt_info* pinfo = NULL;
12982dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    uint64_t timestamp = 0;
13082dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    while ((pinfo = sync_pt_info(finfo, pinfo)) != NULL) {
13182dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis        if (pinfo->timestamp_ns > timestamp) {
13282dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis            timestamp = pinfo->timestamp_ns;
13382dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis        }
13482dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    }
13582dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    sync_fence_info_free(finfo);
13682dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
13782dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    return nsecs_t(timestamp);
13882dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis}
13982dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
140f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennissize_t Fence::getFlattenedSize() const {
1416fbefbbd8edc9953041289fbd77bb18c4964dce5Dan Stoza    return 4;
142f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis}
143f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis
144f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennissize_t Fence::getFdCount() const {
1451df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    return isValid() ? 1 : 0;
146f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis}
147f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis
148e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopianstatus_t Fence::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const {
149e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian    if (size < getFlattenedSize() || count < getFdCount()) {
150e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian        return NO_MEMORY;
151f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    }
1526fbefbbd8edc9953041289fbd77bb18c4964dce5Dan Stoza    // Cast to uint32_t since the size of a size_t can vary between 32- and
1536fbefbbd8edc9953041289fbd77bb18c4964dce5Dan Stoza    // 64-bit processes
1546fbefbbd8edc9953041289fbd77bb18c4964dce5Dan Stoza    FlattenableUtils::write(buffer, size, static_cast<uint32_t>(getFdCount()));
1551df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    if (isValid()) {
156e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian        *fds++ = mFenceFd;
157e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian        count--;
1581df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    }
159f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    return NO_ERROR;
160f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis}
161f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis
162e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopianstatus_t Fence::unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count) {
163f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    if (mFenceFd != -1) {
164f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis        // Don't unflatten if we already have a valid fd.
165f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis        return INVALID_OPERATION;
166f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    }
167f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis
1689809602ac32dcb7bceaa5bc34df5b7fb68aacd38Chris Forbes    if (size < getFlattenedSize()) {
169e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian        return NO_MEMORY;
170e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian    }
171e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian
172288f2ef6294b99a4a53355273ae8ad0f5a525f65Colin Cross    uint32_t numFds;
173e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian    FlattenableUtils::read(buffer, size, numFds);
174e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian
175e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian    if (numFds > 1) {
176e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian        return BAD_VALUE;
177e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian    }
178e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian
179e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian    if (count < numFds) {
180e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian        return NO_MEMORY;
181e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian    }
182e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian
183e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian    if (numFds) {
184e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian        mFenceFd = *fds++;
185e142428a9c8b9d2380032cd4d7b55ee440fe8770Mathias Agopian        count--;
1861df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis    }
1871df8c345854155cbbcb9f80de9d12d66ea70ac08Jamie Gennis
188f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis    return NO_ERROR;
189f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis}
190f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis
191f25e183a70bd631f75dce51e85b7d568472a0cdbJamie Gennis} // namespace android
192