blob: 3afd9a3a3da379e5fbd41f33229d1764dc9c007c [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "common/vsoc/lib/fb_bcast_region_view.h"
#include "common/libs/glog/logging.h"
#include "common/vsoc/lib/lock_guard.h"
using vsoc::framebuffer::FBBroadcastRegionView;
// We can use a locking protocol because we decided that the streamer should
// have more priority than the hwcomposer, so it's OK to block the hwcomposer
// waiting for the streamer to complete, while the streamer will only block on
// the hwcomposer when it's ran out of work to do and needs to get more from the
// hwcomposer.
void FBBroadcastRegionView::BroadcastNewFrame(uint32_t seq_num,
vsoc_reg_off_t frame_offset) {
{
auto lock_guard(make_lock_guard(&data()->bcast_lock));
data()->seq_num = seq_num;
data()->frame_offset = frame_offset;
}
// Signaling after releasing the lock may cause spurious wake ups.
// Signaling while holding the lock may cause the just-awaken listener to
// block immediately trying to acquire the lock.
// The former is less costly and slightly less likely to happen.
layout::Sides side;
side.value_ = layout::Sides::Both;
SendSignal(side, &data()->seq_num);
}
vsoc_reg_off_t FBBroadcastRegionView::WaitForNewFrameSince(uint32_t* last_seq_num) {
static std::unique_ptr<RegionWorker> worker = StartWorker();
// It's ok to read seq_num here without holding the lock because the lock will
// be acquired immediately after so we'll block if necessary to wait for the
// critical section in BroadcastNewFrame to complete.
// Also, the call to WaitForSignal receives a pointer to seq_num (so the
// compiler should not optimize it out) and includes a memory barrier
// (FUTEX_WAIT).
while (data()->seq_num == *last_seq_num) {
// Don't hold the lock when waiting for a signal, will deadlock.
WaitForSignal(&data()->seq_num, *last_seq_num);
}
{
auto lock_guard(make_lock_guard(&data()->bcast_lock));
*last_seq_num = data()->seq_num;
return data()->frame_offset;
}
}