Skip to content

Commit 9cc5f52

Browse files
author
Volodymyr Samokhatko
committed
tight: multithreaded
1 parent 0353465 commit 9cc5f52

5 files changed

Lines changed: 1633 additions & 1310 deletions

File tree

include/rfb/rfb.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ typedef UINT32 in_addr_t;
8484
#endif
8585
#endif
8686

87+
/* Maximum number of threads to use for multithreaded encoding, regardless of
88+
the CPU count */
89+
#define MAX_ENCODING_THREADS 8
90+
8791
struct _rfbClientRec;
8892
struct _rfbScreenInfo;
8993
struct rfbCursor;
@@ -372,6 +376,8 @@ typedef struct _rfbScreenInfo
372376
#ifdef LIBVNCSERVER_HAVE_LIBZ
373377
rfbSetXCutTextUTF8ProcPtr setXCutTextUTF8;
374378
#endif
379+
rfbBool rfbMT;
380+
int rfbNumThreads;
375381
} rfbScreenInfo, *rfbScreenInfoPtr;
376382

377383

@@ -705,6 +711,16 @@ typedef struct _rfbClientRec {
705711
rfbBool tightUsePixelFormat24;
706712
void *tightTJ;
707713
int tightPngDstDataLen;
714+
715+
/* Multithreaded tight encoding. */
716+
717+
rfbBool threadInit;
718+
#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
719+
pthread_t thnd[MAX_ENCODING_THREADS];
720+
#elif defined(LIBVNCSERVER_HAVE_WIN32THREADS)
721+
uintptr_t thnd[MAX_ENCODING_THREADS];
722+
#endif
723+
708724
#endif
709725
#endif
710726
} rfbClientRec, *rfbClientPtr;

src/libvncserver/cargs.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@ rfbUsage(void)
6060
fprintf(stderr, "-listenv6 ipv6addr listen for IPv6 connections only on network interface with\n");
6161
fprintf(stderr, " addr ipv6addr. '-listen localhost' and hostname work too.\n");
6262
#endif
63+
#if defined(LIBVNCSERVER_HAVE_LIBPTHREAD) || defined(LIBVNCSERVER_HAVE_WIN32THREADS)
64+
fprintf(stderr, "-nomt disable multithreaded Tight encoding\n");
65+
fprintf(stderr, "-nthreads N specify number of threads (1 <= N <= %d) to use with\n",
66+
MAX_ENCODING_THREADS);
67+
fprintf(stderr, " multithreaded Tight encoding [default: 1 per CPU core,\n");
68+
fprintf(stderr, " max. %d]\n", MAX_ENCODING_THREADS);
69+
#endif
6370

6471
for(extension=rfbGetExtensionIterator();extension;extension=extension->next)
6572
if(extension->usage)
@@ -202,6 +209,20 @@ rfbProcessArguments(rfbScreenInfoPtr rfbScreen,int* argc, char *argv[])
202209
}
203210
rfbScreen->listen6Interface = argv[++i];
204211
#endif
212+
#if defined(LIBVNCSERVER_HAVE_LIBPTHREAD) || defined(LIBVNCSERVER_HAVE_WIN32THREADS)
213+
} else if (strcmp(argv[i], "-nomt") == 0) {
214+
rfbScreen->rfbMT = FALSE;
215+
} else if (strcmp(argv[i], "-nthreads") == 0) {
216+
if (i + 1 >= *argc) {
217+
rfbUsage();
218+
return FALSE;
219+
}
220+
rfbScreen->rfbNumThreads = atoi(argv[++i]);
221+
if (rfbScreen->rfbNumThreads < 1 || rfbScreen->rfbNumThreads > MAX_ENCODING_THREADS) {
222+
rfbUsage();
223+
return FALSE;
224+
}
225+
#endif
205226
#ifdef LIBVNCSERVER_WITH_WEBSOCKETS
206227
} else if (strcmp(argv[i], "-sslkeyfile") == 0) { /* -sslkeyfile sslkeyfile */
207228
if (i + 1 >= *argc) {

src/libvncserver/main.c

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@
1010
* see GPL (latest version) for full details
1111
*/
1212

13+
#include <rfb/rfbconfig.h>
14+
15+
#if LIBVNCSERVER_HAVE_SCHED_H
16+
#define _GNU_SOURCE
17+
#include <sched.h>
18+
#endif
19+
1320
#ifdef __STRICT_ANSI__
1421
#define _BSD_SOURCE
1522
#endif
@@ -55,6 +62,42 @@ char rfbEndianTest = (1==0);
5562
char rfbEndianTest = (1==1);
5663
#endif
5764

65+
#ifndef min
66+
inline static int min(int a, int b)
67+
{
68+
return a > b ? b : a;
69+
}
70+
#endif
71+
72+
#ifdef __APPLE__
73+
typedef struct cpu_set {
74+
uint64_t count;
75+
} cpu_set_t;
76+
77+
static inline void
78+
CPU_ZERO(cpu_set_t *cs) { cs->count = 0; }
79+
80+
static inline int
81+
CPU_COUNT(cpu_set_t *cs) { return __builtin_popcountll(cs->count); }
82+
83+
int sched_getaffinity(pid_t pid, size_t cpu_size, cpu_set_t *cpu_set)
84+
{
85+
int32_t core_count = 0;
86+
size_t len = sizeof(core_count);
87+
int ret = sysctlbyname("machdep.cpu.core_count", &core_count, &len, 0, 0);
88+
if (ret) {
89+
rfbErr("error while get core count %d\n", ret);
90+
return -1;
91+
}
92+
cpu_set->count = 0;
93+
for (int i = 0; i < core_count; i++) {
94+
cpu_set->count |= (1 << i);
95+
}
96+
97+
return 0;
98+
}
99+
#endif
100+
58101
/*
59102
* Protocol extensions
60103
*/
@@ -996,11 +1039,43 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
9961039

9971040
screen->permitFileTransfer = FALSE;
9981041

1042+
screen->rfbMT = TRUE;
1043+
screen->rfbNumThreads = 0;
1044+
9991045
if(!rfbProcessArguments(screen,argc,argv)) {
10001046
free(screen);
10011047
return NULL;
10021048
}
10031049

1050+
#if defined(LIBVNCSERVER_HAVE_LIBPTHREAD) || defined(LIBVNCSERVER_HAVE_WIN32THREADS)
1051+
#if defined(WIN32) || defined(__MINGW32__)
1052+
DWORD64 dwProcessAffinity, dwSystemAffinity;
1053+
GetProcessAffinityMask(GetCurrentProcess(), &dwProcessAffinity, &dwSystemAffinity);
1054+
const int np = __popcnt64(dwProcessAffinity);
1055+
#elif LIBVNCSERVER_HAVE_SCHED_H
1056+
cpu_set_t cs;
1057+
CPU_ZERO(&cs);
1058+
int cpus = -1;
1059+
if (sched_getaffinity(0, sizeof(cs), &cs) == 0) {
1060+
cpus = CPU_COUNT(&cs);
1061+
}
1062+
const int np = cpus;
1063+
#else
1064+
const int np = -1;
1065+
#endif
1066+
if (np == -1 && screen->rfbMT) {
1067+
rfbLog("WARNING: Could not determine CPU count. Multithreaded encoding disabled.\n");
1068+
screen->rfbMT = FALSE;
1069+
}
1070+
if (!screen->rfbMT) screen->rfbNumThreads = 1;
1071+
else if (screen->rfbNumThreads < 1) screen->rfbNumThreads = min(np, 4);
1072+
if (screen->rfbNumThreads > np) {
1073+
rfbLog("NOTICE: Encoding thread count has been clamped to CPU count\n");
1074+
screen->rfbNumThreads = np;
1075+
}
1076+
#endif
1077+
1078+
10041079
#ifdef WIN32
10051080
{
10061081
DWORD dummy=255;

src/libvncserver/rfbserver.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,15 @@ rfbNewTCPOrUDPClient(rfbScreenInfoPtr rfbScreen,
504504
}
505505
}
506506

507+
#ifdef LIBVNCSERVER_HAVE_LIBJPEG
508+
/* Multithreaded tight encoding. */
509+
510+
cl->threadInit = FALSE;
511+
#if defined(LIBVNCSERVER_HAVE_LIBPTHREAD) || defined(LIBVNCSERVER_HAVE_WIN32THREADS)
512+
memset(cl->thnd, 0, sizeof(cl->thnd));
513+
#endif
514+
#endif
515+
507516
for(extension = rfbGetExtensionIterator(); extension;
508517
extension=extension->next) {
509518
void* data = NULL;

0 commit comments

Comments
 (0)