VNC: More updates from testing. There are issues with high rate, large TCP transfers.

This commit is contained in:
Gregory Nutt
2016-04-19 15:39:58 -06:00
parent e0509b4256
commit 65f21d0edb
5 changed files with 111 additions and 44 deletions
+6 -3
View File
@@ -98,12 +98,15 @@ config VNCSERVER_NUPDATES
config VNCSERVER_UPDATE_BUFSIZE
int "Max update buffer size (bytes)"
default 4096
default 1024
---help---
A single buffer is pre-allocated for rendering updates. This
setting specifies the maximum in bytes of that update buffer. For
example, an update buffers of 32 pixels at 32-bits per pixel and
32-rows would yield a buffer size of 4096.
example, an update buffers of 32 pixels at 8-bits per pixel and
32-rows would yield a buffer size of 1024!
Ideally, this buffer should fit in one network packet to avoid
accessive re-assembly of partial TCP packets.
config VNCSERVER_KBDENCODE
bool "Encode keyboard input"
+3 -14
View File
@@ -90,8 +90,6 @@ FAR struct vnc_session_s *g_vnc_sessions[RFB_MAX_DISPLAYS];
static void vnc_reset_session(FAR struct vnc_session_s *session,
FAR uint8_t *fb, int display)
{
FAR struct vnc_fbupdate_s *curr;
FAR struct vnc_fbupdate_s *next;
int i;
/* Close any open sockets */
@@ -112,22 +110,13 @@ static void vnc_reset_session(FAR struct vnc_session_s *session,
/* Put all of the pre-allocated update structures into the freelist */
sq_init(&session->updqueue);
sq_init(&session->updfree);
session->updfree.head =
(FAR sq_entry_t *)&session->updpool[0];
session->updfree.tail =
(FAR sq_entry_t *)&session->updpool[CONFIG_VNCSERVER_NUPDATES-1];
next = &session->updpool[0];
for (i = 1; i < CONFIG_VNCSERVER_NUPDATES-1; i++)
for (i = 0; i < CONFIG_VNCSERVER_NUPDATES; i++)
{
curr = next;
next = &session->updpool[i];
curr->flink = next;
sq_addlast((FAR sq_entry_t *)&session->updpool[i], &session->updfree);
}
next->flink = NULL;
/* Set the INITIALIZED state */
sem_reset(&session->freesem, CONFIG_VNCSERVER_NUPDATES);
+94 -9
View File
@@ -51,6 +51,12 @@
#include "vnc_server.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#undef VNCSERVER_SEM_DEBUG
/****************************************************************************
* Private Types
****************************************************************************/
@@ -69,15 +75,73 @@ typedef CODE uint32_t(*vnc_convert32_t)(uint32_t rgb);
# error Unspecified/unsupported color format
#endif
/****************************************************************************
* Private Data
****************************************************************************/
#ifdef VNCSERVER_SEM_DEBUG
static sem_t g_dbgsem = SEM_INITIALIZER(1);
#endif
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: vnc_sem_debug
*
* Description:
* Dump information about the freesem to verify that it is sync.
*
* Input Parameters:
* session - A reference to the VNC session structure.
*
* Returned Value:
* A non-NULL structure pointer should always be returned. This function
* will wait if no structure is available.
*
****************************************************************************/
#ifdef VNCSERVER_SEM_DEBUG
static void vnc_sem_debug(FAR struct vnc_session_s *session,
FAR const char *msg, unsigned int unattached)
{
FAR struct vnc_fbupdate_s *update;
unsigned int nqueued;
unsigned int nfree;
while (sem_wait(&g_dbgsem) < 0)
{
DEBUGASSERT(get_errno() == EINTR);
}
/* Count structures in the list */
for (nqueued = 0, update = (FAR struct vnc_fbupdate_s *)session->updqueue.head;
update != NULL;
nqueued++, update = update->flink);
for (nfree = 0, update = (FAR struct vnc_fbupdate_s *)session->updfree.head;
update != NULL;
nfree++, update = update->flink);
syslog(LOG_INFO, "FREESEM DEBUG: %s\n", msg);
syslog(LOG_INFO, " freesem: %d\n", session->freesem.semcount);
syslog(LOG_INFO, " queued: %u\n", nqueued);
syslog(LOG_INFO, " free: %u\n", nfree);
syslog(LOG_INFO, " unattached: %u\n", unattached);
sem_post(&g_dbgsem);
}
#else
# define vnc_sem_debug(s,m,u)
#endif
/****************************************************************************
* Name: vnc_alloc_update
*
* Description:
* Allocate one update structure by taking it from the freelist.
* Allocate one update structure by taking it from the freelist.
*
* Input Parameters:
* session - A reference to the VNC session structure.
@@ -99,6 +163,8 @@ vnc_alloc_update(FAR struct vnc_session_s *session)
*/
sched_lock();
vnc_sem_debug(session, "Before alloc", 0);
while (sem_wait(&session->freesem) < 0)
{
DEBUGASSERT(get_errno() == EINTR);
@@ -107,6 +173,8 @@ vnc_alloc_update(FAR struct vnc_session_s *session)
/* It is reserved.. go get it */
update = (FAR struct vnc_fbupdate_s *)sq_remfirst(&session->updfree);
vnc_sem_debug(session, "After alloc", 1);
sched_unlock();
DEBUGASSERT(update != NULL);
@@ -135,6 +203,7 @@ static void vnc_free_update(FAR struct vnc_session_s *session,
*/
sched_lock();
vnc_sem_debug(session, "Before free", 1);
/* Put the entry into the free list */
@@ -143,6 +212,8 @@ static void vnc_free_update(FAR struct vnc_session_s *session,
/* Post the semaphore to indicate the availability of one more update */
sem_post(&session->freesem);
vnc_sem_debug(session, "After free", 0);
DEBUGASSERT(session->freesem.semcount <= CONFIG_VNCSERVER_NUPDATES);
sched_unlock();
@@ -176,6 +247,8 @@ vnc_remove_queue(FAR struct vnc_session_s *session)
*/
sched_lock();
vnc_sem_debug(session, "Before remove", 0);
while (sem_wait(&session->queuesem) < 0)
{
DEBUGASSERT(get_errno() == EINTR);
@@ -184,6 +257,8 @@ vnc_remove_queue(FAR struct vnc_session_s *session)
/* It is reserved.. go get it */
rect = (FAR struct vnc_fbupdate_s *)sq_remfirst(&session->updqueue);
vnc_sem_debug(session, "After remove", 0);
sched_unlock();
DEBUGASSERT(rect != NULL);
@@ -213,6 +288,7 @@ static void vnc_add_queue(FAR struct vnc_session_s *session,
*/
sched_lock();
vnc_sem_debug(session, "Before add", 1);
/* Put the entry into the list of queued rectangles. */
@@ -223,6 +299,8 @@ static void vnc_add_queue(FAR struct vnc_session_s *session,
*/
sem_post(&session->queuesem);
vnc_sem_debug(session, "After add", 0);
DEBUGASSERT(session->queuesem.semcount <= CONFIG_VNCSERVER_NUPDATES);
sched_unlock();
@@ -666,6 +744,7 @@ static FAR void *vnc_updater(FAR void *arg)
FAR struct vnc_session_s *session = (FAR struct vnc_session_s *)arg;
FAR struct rfb_framebufferupdate_s *update;
FAR struct vnc_fbupdate_s *srcrect;
FAR const uint8_t *src;
nxgl_coord_t srcwidth;
nxgl_coord_t srcheight;
nxgl_coord_t destwidth;
@@ -849,15 +928,21 @@ static FAR void *vnc_updater(FAR void *arg)
/* Then send the update packet to the VNC client */
size += SIZEOF_RFB_FRAMEBUFFERUPDATE_S(0);
nsent = psock_send(&session->connect, session->outbuf, size, 0);
if (nsent < 0)
{
gdbg("ERROR: Send FrameBufferUpdate failed: %d\n",
get_errno());
goto errout;
}
src = session->outbuf;
DEBUGASSERT(nsent == size);
while (size > 0)
{
nsent = psock_send(&session->connect, src, size, 0);
if (nsent < 0)
{
gdbg("ERROR: Send FrameBufferUpdate failed: %d\n",
get_errno());
goto errout;
}
src += nsent;
size -= nsent;
}
}
}