mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-22 05:27:20 +00:00
[client] implemented the new ivshmem interrupt sync system
This commit is contained in:
parent
3a7bff77f2
commit
b871d6d8d0
@ -23,6 +23,8 @@ struct KVMGFXHeader
|
||||
{
|
||||
char magic[sizeof(KVMGFX_HEADER_MAGIC)];
|
||||
uint32_t version; // version of this structure
|
||||
uint16_t hostID; // the host ivshmem client id
|
||||
uint16_t guestID; // the guest ivshmem client id
|
||||
FrameType frameType; // the frame type
|
||||
FrameComp compType; // frame compression mode
|
||||
uint32_t width; // the width
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <unistd.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/socket.h>
|
||||
@ -270,6 +271,7 @@ bool ivshmem_read_msg(int64_t * index, int * fd)
|
||||
if (!fd)
|
||||
return true;
|
||||
|
||||
*fd = -1;
|
||||
struct cmsghdr *cmsg;
|
||||
for(cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
|
||||
{
|
||||
@ -280,12 +282,14 @@ bool ivshmem_read_msg(int64_t * index, int * fd)
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(fd, CMSG_DATA(cmsg), sizeof(*fd));
|
||||
*fd = *(int*)CMSG_DATA(cmsg);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
||||
uint16_t ivshmem_get_id()
|
||||
{
|
||||
if (!ivshmem.connected)
|
||||
@ -456,3 +460,71 @@ bool ivshmem_process()
|
||||
client->irqs[client->irqCount++] = fd;
|
||||
return true;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
||||
enum IVSHMEMWaitResult ivshmem_wait_irq(uint16_t vector)
|
||||
{
|
||||
if (vector > ivshmem.server.irqCount - 1)
|
||||
return false;
|
||||
|
||||
int fd = ivshmem.server.irqs[vector];
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = 1;
|
||||
timeout.tv_usec = 0;
|
||||
|
||||
while(true)
|
||||
{
|
||||
int ret = select(fd+1, &fds, NULL, NULL, &timeout);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
|
||||
DEBUG_ERROR("select error");
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
return IVSHMEM_WAIT_RESULT_TIMEOUT;
|
||||
|
||||
if (FD_ISSET(fd, &fds))
|
||||
{
|
||||
uint64_t kick;
|
||||
read(fd, &kick, sizeof(kick));
|
||||
return IVSHMEM_WAIT_RESULT_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return IVSHMEM_WAIT_RESULT_ERROR;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
||||
bool ivshmem_kick_irq(uint16_t clientID, uint16_t vector)
|
||||
{
|
||||
struct IVSHMEMClient * client = ivshmem_get_client(clientID);
|
||||
if (!client)
|
||||
{
|
||||
DEBUG_ERROR("invalid client");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (vector > client->irqCount - 1)
|
||||
{
|
||||
DEBUG_ERROR("invalid vector for client");
|
||||
return false;
|
||||
}
|
||||
|
||||
int fd = client->irqs[vector];
|
||||
uint64_t kick = ivshmem.server.clientID;
|
||||
if (write(fd, &kick, sizeof(kick)) == sizeof(kick))
|
||||
return true;
|
||||
|
||||
DEBUG_ERROR("failed to send kick");
|
||||
return false;
|
||||
}
|
@ -9,3 +9,13 @@ bool ivshmem_process();
|
||||
uint16_t ivshmem_get_id();
|
||||
void * ivshmem_get_map();
|
||||
size_t ivshmem_get_map_size();
|
||||
|
||||
enum IVSHMEMWaitResult
|
||||
{
|
||||
IVSHMEM_WAIT_RESULT_OK,
|
||||
IVSHMEM_WAIT_RESULT_TIMEOUT,
|
||||
IVSHMEM_WAIT_RESULT_ERROR
|
||||
};
|
||||
|
||||
enum IVSHMEMWaitResult ivshmem_wait_irq(uint16_t vector);
|
||||
bool ivshmem_kick_irq(uint16_t clientID, uint16_t vector);
|
@ -211,7 +211,6 @@ void drawFunc_YUV420P(CompFunc compFunc, SDL_Texture * texture, uint8_t * dst, c
|
||||
|
||||
int renderThread(void * unused)
|
||||
{
|
||||
bool startup = true;
|
||||
struct KVMGFXHeader format;
|
||||
SDL_Texture *texture = NULL;
|
||||
uint8_t *pixels = (uint8_t*)(state.shm + 1);
|
||||
@ -254,16 +253,40 @@ int renderThread(void * unused)
|
||||
if (memcmp(state.shm->magic, KVMGFX_HEADER_MAGIC, sizeof(KVMGFX_HEADER_MAGIC)) != 0)
|
||||
continue;
|
||||
|
||||
// if the frame count hasn't changed, we don't do anything
|
||||
if (!startup && format.frames == state.shm->frames)
|
||||
{
|
||||
if (!state.running)
|
||||
break;
|
||||
|
||||
usleep(100);
|
||||
if (state.shm->version != 2)
|
||||
continue;
|
||||
|
||||
bool ready = false;
|
||||
bool error = false;
|
||||
while(state.running && !ready && !error)
|
||||
{
|
||||
// kick the guest and wait for a frame
|
||||
ivshmem_kick_irq(state.shm->guestID, 0);
|
||||
switch(ivshmem_wait_irq(0))
|
||||
{
|
||||
case IVSHMEM_WAIT_RESULT_OK:
|
||||
ready = true;
|
||||
break;
|
||||
|
||||
case IVSHMEM_WAIT_RESULT_TIMEOUT:
|
||||
ready = false;
|
||||
break;
|
||||
|
||||
case IVSHMEM_WAIT_RESULT_ERROR:
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
startup = false;
|
||||
|
||||
if (error)
|
||||
{
|
||||
DEBUG_ERROR("error during wait for host");
|
||||
break;
|
||||
}
|
||||
|
||||
// continue;
|
||||
// }
|
||||
// startup = false;
|
||||
|
||||
// if the format is invalid or it has changed
|
||||
if (format.frameType == FRAME_TYPE_INVALID || !areFormatsSame(format, *state.shm))
|
||||
@ -507,6 +530,7 @@ int main(int argc, char * argv[])
|
||||
DEBUG_ERROR("Failed to map memory");
|
||||
break;
|
||||
}
|
||||
state.shm->hostID = ivshmem_get_id();
|
||||
|
||||
if (!spice_connect("127.0.0.1", 5900, ""))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user