16d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov/*
26d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov * Copyright (C) 2012 The Android Open Source Project
36d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov *
46d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov * Licensed under the Apache License, Version 2.0 (the "License");
56d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov * you may not use this file except in compliance with the License.
66d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov * You may obtain a copy of the License at
76d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov *
86d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov *      http://www.apache.org/licenses/LICENSE-2.0
96d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov *
106d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov * Unless required by applicable law or agreed to in writing, software
116d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov * distributed under the License is distributed on an "AS IS" BASIS,
126d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov * See the License for the specific language governing permissions and
146d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov * limitations under the License.
156d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov */
166d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov
176d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov#define LOG_TAG "Fence"
186d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov#define ATRACE_TAG ATRACE_TAG_GRAPHICS
196d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov//#define LOG_NDEBUG 0
206d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov
216d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov // This is needed for stdint.h to define INT64_MAX in C++
226d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov #define __STDC_LIMIT_MACROS
236d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov
246d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov#include <sync/sync.h>
256d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov#include <ui/Fence.h>
266d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov#include <unistd.h>
276d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov#include <utils/Log.h>
286d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov#include <utils/Trace.h>
296d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov
306d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovnamespace android {
316d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov
326d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovconst sp<Fence> Fence::NO_FENCE = sp<Fence>(new Fence);
336d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov
346d429cda69b7ccc007ee368a73a6040c6b125afbAlexey SamsonovFence::Fence() :
356d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    mFenceFd(-1) {
366d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov}
37e374e4ece521692173aad355420d03e1b2cd819aAlexey Samsonov
386d429cda69b7ccc007ee368a73a6040c6b125afbAlexey SamsonovFence::Fence(int fenceFd) :
396d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    mFenceFd(fenceFd) {
406d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov}
416d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov
426d429cda69b7ccc007ee368a73a6040c6b125afbAlexey SamsonovFence::~Fence() {
436d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    if (mFenceFd != -1) {
446d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov        close(mFenceFd);
456d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    }
466d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov}
476d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov
486d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovstatus_t Fence::wait(unsigned int timeout) {
496d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    ATRACE_CALL();
506d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    if (mFenceFd == -1) {
516d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov        return NO_ERROR;
526d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    }
536d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    int err = sync_wait(mFenceFd, timeout);
546d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    return err < 0 ? -errno : status_t(NO_ERROR);
556d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov}
566d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov
576d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovstatus_t Fence::waitForever(const char* logname) {
586d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    ATRACE_CALL();
596d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    if (mFenceFd == -1) {
60ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov        return NO_ERROR;
616d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    }
626d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    unsigned int warningTimeout = 3000;
636d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    int err = sync_wait(mFenceFd, warningTimeout);
646d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    if (err < 0 && errno == ETIME) {
656d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov        ALOGE("%s: fence %d didn't signal in %u ms", logname, mFenceFd,
666d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov                warningTimeout);
676d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov        err = sync_wait(mFenceFd, TIMEOUT_NEVER);
686d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    }
696d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    return err < 0 ? -errno : status_t(NO_ERROR);
70ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov}
716d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov
726d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovsp<Fence> Fence::merge(const String8& name, const sp<Fence>& f1,
736d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov        const sp<Fence>& f2) {
746d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    ATRACE_CALL();
756d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    int result;
766d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    // Merge the two fences.  In the case where one of the fences is not a
77827d4ef8b76760ef8c58612d916b8f53081bf368Alexey Samsonov    // valid fence (e.g. NO_FENCE) we merge the one valid fence with itself so
78827d4ef8b76760ef8c58612d916b8f53081bf368Alexey Samsonov    // that a new fence with the given name is created.
796d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    if (f1->isValid() && f2->isValid()) {
806d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov        result = sync_merge(name.string(), f1->mFenceFd, f2->mFenceFd);
816d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    } else if (f1->isValid()) {
826d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov        result = sync_merge(name.string(), f1->mFenceFd, f1->mFenceFd);
836d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    } else if (f2->isValid()) {
846d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov        result = sync_merge(name.string(), f2->mFenceFd, f2->mFenceFd);
856d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    } else {
866d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov        return NO_FENCE;
876d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    }
886d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    if (result == -1) {
896d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov        status_t err = -errno;
906d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov        ALOGE("merge: sync_merge(\"%s\", %d, %d) returned an error: %s (%d)",
916d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov                name.string(), f1->mFenceFd, f2->mFenceFd,
926d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov                strerror(-err), err);
936d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov        return NO_FENCE;
946d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    }
956d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    return sp<Fence>(new Fence(result));
966d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov}
976d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov
986d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovint Fence::dup() const {
996d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    return ::dup(mFenceFd);
1006d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov}
1016d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov
1026d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovnsecs_t Fence::getSignalTime() const {
1036d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    if (mFenceFd == -1) {
1046d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov        return -1;
1056d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    }
1066d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov
1076d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    struct sync_fence_info_data* finfo = sync_fence_info(mFenceFd);
1086d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    if (finfo == NULL) {
1096d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov        ALOGE("sync_fence_info returned NULL for fd %d", mFenceFd);
1106d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov        return -1;
1116d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    }
1126d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    if (finfo->status != 1) {
1136d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov        sync_fence_info_free(finfo);
1146d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov        return INT64_MAX;
115116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov    }
116116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov
117116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov    struct sync_pt_info* pinfo = NULL;
118116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov    uint64_t timestamp = 0;
119116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov    while ((pinfo = sync_pt_info(finfo, pinfo)) != NULL) {
120116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov        if (pinfo->timestamp_ns > timestamp) {
121116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov            timestamp = pinfo->timestamp_ns;
122116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov        }
123116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov    }
124116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov    sync_fence_info_free(finfo);
125116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov
126116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov    return nsecs_t(timestamp);
127116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov}
128116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov
129116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonovsize_t Fence::getFlattenedSize() const {
130116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov    return 1;
131116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov}
132116c8029f506b074a8b9c83605b14ac4bf0259c6Alexey Samsonov
133ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukovsize_t Fence::getFdCount() const {
134ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov    return isValid() ? 1 : 0;
135ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov}
136ce85e03620f64ce7e4cd0598f2e93090f52a9e99Dmitry Vyukov
1376d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonovstatus_t Fence::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const {
1386d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    if (size < getFlattenedSize() || count < getFdCount()) {
1396d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov        return NO_MEMORY;
1406d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    }
1416d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    FlattenableUtils::write(buffer, size, (uint32_t)getFdCount());
1426d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov    if (isValid()) {
1436d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov        *fds++ = mFenceFd;
1446d429cda69b7ccc007ee368a73a6040c6b125afbAlexey Samsonov        count--;
145    }
146    return NO_ERROR;
147}
148
149status_t Fence::unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count) {
150    if (mFenceFd != -1) {
151        // Don't unflatten if we already have a valid fd.
152        return INVALID_OPERATION;
153    }
154
155    if (size < 1) {
156        return NO_MEMORY;
157    }
158
159    uint32_t numFds;
160    FlattenableUtils::read(buffer, size, numFds);
161
162    if (numFds > 1) {
163        return BAD_VALUE;
164    }
165
166    if (count < numFds) {
167        return NO_MEMORY;
168    }
169
170    if (numFds) {
171        mFenceFd = *fds++;
172        count--;
173    }
174
175    return NO_ERROR;
176}
177
178} // namespace android
179