blob: 72590bba1404ba7ba5951a5553e931bdb3925254 [file] [log] [blame]
/* Copyright (C) 2016 The Android Open Source Project
**
** This software is licensed under the terms of the GNU General Public
** License version 2, as published by the Free Software Foundation, and
** may be copied, distributed, and modified under those terms.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
*/
#pragma once
#include "android/base/memory/LazyInstance.h"
#include "android/emulation/DeviceContextRunner.h"
#include "android/emulation/goldfish_sync.h"
#include "android/emulation/VmLock.h"
#include <vector>
#define DEBUG 0
#if DEBUG
#define DPRINT(...) do { \
if (!VERBOSE_CHECK(goldfishsync)) VERBOSE_ENABLE(goldfishsync); \
VERBOSE_TID_FUNCTION_DPRINT(goldfishsync, __VA_ARGS__); } while(0)
#else
#define DPRINT(...)
#endif
#define ERR(...) do { \
derror(__VA_ARGS__); \
} while(0)
namespace android {
////////////////////////////////////////////////////////////////////////////////
// GoldfishSyncCommandQueue ensures that commands sent to the Goldfish Sync
// virtual device take place in "device context"; that is, the commands
// are only executed while the main loop has the VM lock. Like PipeWaker
// of AndroidPipe, this class derives from DeviceContextRunner for this
// functionality.
// This class is only used for host->guest commands for goldfish sync device,
// and mainly timeline increment at that. The way to use
// GoldfishSyncCommandQueue in general is to call |hostSignal| with the
// particular details of the host->guest command being issued.
//
// However, make sure that |setQueueCommand| has been called on
// goldifish sync device initialization, which properly hooks up the
// GoldfishSyncCommandQueue with the particular virtual device function
// that actually raises IRQ's, and that |initThreading| has been called
// in a main loop context, preferably in qemu-setup.cpp.
struct GoldfishSyncWakeInfo {
uint64_t handle;
uint64_t hostcmd_handle;
uint32_t cmd;
uint32_t time_arg;
};
class GoldfishSyncCommandQueue final :
public DeviceContextRunner<GoldfishSyncWakeInfo> {
public:
// Like with the PipeWaker for AndroidPipe,
// we need to process all commands
// in a context where we hold the VM lock.
static void initThreading(VmLock* vmLock);
// Goldfish sync virtual device will give out its own
// callback for queueing commands to it.
static void setQueueCommand(queue_device_command_t fx);
// Main interface for all Goldfish sync device
// communications.
static void hostSignal(uint32_t cmd,
uint64_t handle,
uint32_t time_arg,
uint64_t hostcmd_handle);
private:
static base::LazyInstance<GoldfishSyncCommandQueue> sCommandQueue;
virtual void performDeviceOperation(const GoldfishSyncWakeInfo& cmd) override;
queue_device_command_t tellSyncDevice = nullptr;
};
} // namespace android