mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2025-12-27 07:29:32 +00:00
Merging the functionality of reds::channel, into RedChannel. In addition, cleanup and fix disconnection code: before this patch, red_dispatcher_disconnect_display_client could have been called from the red_worker thread (and it must be called only from the io thread). RedChannel holds only connected channel clients. RedClient holds all the channel clients that were created till it is destroyed (and then it destroys them as well). Note: snd_channel still doesn't use red_channel, however it creates dummy channel and channel clients, in order to register itself in reds. server/red_channel.c: a channel is connected if it holds at least one channel client Previously I changed RedChannel to hold only connected channel clients and RedClient, to hold all the channel clients as long as it is not destroyed. usbredir: multichannel has not been tested, it just compiles.
168 lines
4.4 KiB
C
168 lines
4.4 KiB
C
/*
|
|
Copyright (C) 2009 Red Hat, Inc.
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
This library 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
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef _H_REDWORKER
|
|
#define _H_REDWORKER
|
|
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#include "red_common.h"
|
|
|
|
|
|
static inline void set_bit(int index, uint32_t *addr)
|
|
{
|
|
uint32_t mask = 1 << index;
|
|
__sync_or_and_fetch(addr, mask);
|
|
}
|
|
|
|
static inline void clear_bit(int index, uint32_t *addr)
|
|
{
|
|
uint32_t mask = ~(1 << index);
|
|
__sync_and_and_fetch(addr, mask);
|
|
}
|
|
|
|
static inline int test_bit(int index, uint32_t val)
|
|
{
|
|
return val & (1u << index);
|
|
}
|
|
|
|
enum {
|
|
RED_WORKER_PENDING_WAKEUP,
|
|
RED_WORKER_PENDING_OOM,
|
|
};
|
|
|
|
enum {
|
|
RED_WORKER_MESSAGE_NOP,
|
|
RED_WORKER_MESSAGE_UPDATE,
|
|
RED_WORKER_MESSAGE_WAKEUP,
|
|
RED_WORKER_MESSAGE_OOM,
|
|
RED_WORKER_MESSAGE_READY,
|
|
RED_WORKER_MESSAGE_DISPLAY_CONNECT,
|
|
RED_WORKER_MESSAGE_DISPLAY_DISCONNECT,
|
|
RED_WORKER_MESSAGE_DISPLAY_MIGRATE,
|
|
RED_WORKER_MESSAGE_START,
|
|
RED_WORKER_MESSAGE_STOP,
|
|
RED_WORKER_MESSAGE_CURSOR_CONNECT,
|
|
RED_WORKER_MESSAGE_CURSOR_DISCONNECT,
|
|
RED_WORKER_MESSAGE_CURSOR_MIGRATE,
|
|
RED_WORKER_MESSAGE_SET_COMPRESSION,
|
|
RED_WORKER_MESSAGE_SET_STREAMING_VIDEO,
|
|
RED_WORKER_MESSAGE_SET_MOUSE_MODE,
|
|
RED_WORKER_MESSAGE_ADD_MEMSLOT,
|
|
RED_WORKER_MESSAGE_DEL_MEMSLOT,
|
|
RED_WORKER_MESSAGE_RESET_MEMSLOTS,
|
|
RED_WORKER_MESSAGE_DESTROY_SURFACES,
|
|
RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE,
|
|
RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE,
|
|
RED_WORKER_MESSAGE_RESET_CURSOR,
|
|
RED_WORKER_MESSAGE_RESET_IMAGE_CACHE,
|
|
RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT,
|
|
RED_WORKER_MESSAGE_LOADVM_COMMANDS,
|
|
/* async commands */
|
|
RED_WORKER_MESSAGE_UPDATE_ASYNC,
|
|
RED_WORKER_MESSAGE_ADD_MEMSLOT_ASYNC,
|
|
RED_WORKER_MESSAGE_DESTROY_SURFACES_ASYNC,
|
|
RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE_ASYNC,
|
|
RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE_ASYNC,
|
|
RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC,
|
|
/* suspend/windows resolution change command */
|
|
RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC,
|
|
|
|
RED_WORKER_MESSAGE_DISPLAY_CHANNEL_CREATE,
|
|
RED_WORKER_MESSAGE_CURSOR_CHANNEL_CREATE,
|
|
};
|
|
|
|
typedef uint32_t RedWorkerMessage;
|
|
|
|
#define RED_MAX_RENDERERS 4
|
|
|
|
enum {
|
|
RED_RENDERER_INVALID,
|
|
RED_RENDERER_SW,
|
|
RED_RENDERER_OGL_PBUF,
|
|
RED_RENDERER_OGL_PIXMAP,
|
|
};
|
|
|
|
typedef struct RedDispatcher RedDispatcher;
|
|
|
|
typedef struct WorkerInitData {
|
|
struct QXLInstance *qxl;
|
|
int id;
|
|
int channel;
|
|
uint32_t *pending;
|
|
uint32_t num_renderers;
|
|
uint32_t renderers[RED_MAX_RENDERERS];
|
|
spice_image_compression_t image_compression;
|
|
spice_wan_compression_t jpeg_state;
|
|
spice_wan_compression_t zlib_glz_state;
|
|
int streaming_video;
|
|
uint32_t num_memslots;
|
|
uint32_t num_memslots_groups;
|
|
uint8_t memslot_gen_bits;
|
|
uint8_t memslot_id_bits;
|
|
uint8_t internal_groupslot_id;
|
|
uint32_t n_surfaces;
|
|
RedDispatcher *dispatcher;
|
|
} WorkerInitData;
|
|
|
|
void *red_worker_main(void *arg);
|
|
|
|
static inline void send_data(int fd, void *in_buf, int n)
|
|
{
|
|
uint8_t *buf = in_buf;
|
|
do {
|
|
int now;
|
|
if ((now = write(fd, buf, n)) == -1) {
|
|
if (errno == EINTR) {
|
|
continue;
|
|
}
|
|
red_error("%s", strerror(errno));
|
|
}
|
|
buf += now;
|
|
n -= now;
|
|
} while (n);
|
|
}
|
|
|
|
static inline void write_message(int fd, RedWorkerMessage *message)
|
|
{
|
|
send_data(fd, message, sizeof(RedWorkerMessage));
|
|
}
|
|
|
|
static inline void receive_data(int fd, void *in_buf, int n)
|
|
{
|
|
uint8_t *buf = in_buf;
|
|
do {
|
|
int now;
|
|
if ((now = read(fd, buf, n)) == -1) {
|
|
if (errno == EINTR) {
|
|
continue;
|
|
}
|
|
red_error("%s", strerror(errno));
|
|
}
|
|
buf += now;
|
|
n -= now;
|
|
} while (n);
|
|
}
|
|
|
|
static inline void read_message(int fd, RedWorkerMessage *message)
|
|
{
|
|
receive_data(fd, message, sizeof(RedWorkerMessage));
|
|
}
|
|
|
|
#endif
|
|
|