diff --git a/usr.sbin/bhyve/bhyverun.h b/usr.sbin/bhyve/bhyverun.h --- a/usr.sbin/bhyve/bhyverun.h +++ b/usr.sbin/bhyve/bhyverun.h @@ -79,4 +79,14 @@ int bhyve_init_platform(struct vmctx *ctx, struct vcpu *bsp); int bhyve_init_platform_late(struct vmctx *ctx, struct vcpu *bsp); +/* + * called to register a notifier and block startup thread on + */ +void bhyve_init_block(void); + +/* + * notify the startup thread + */ +void bhyve_init_notify(void); + #endif diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c --- a/usr.sbin/bhyve/bhyverun.c +++ b/usr.sbin/bhyve/bhyverun.c @@ -118,6 +118,76 @@ static cpuset_t **vcpumap; + +struct init_rendezvous_softc { + pthread_mutex_t + mtx; /* lock prevent race condition from member and wait thread */ + pthread_cond_t cond; /* cond variable to notify the wait thread */ + pthread_t thread; /* thread for wait initialization */ + int counter; +}; + +typedef struct init_rendezvous_softc* init_rendezvous_softc_t; + +static init_rendezvous_softc_t +get_init_rendezvous_softc(void) +{ + static init_rendezvous_softc_t softc = NULL; + int error; + + if (softc == NULL) { + softc = malloc(sizeof(struct init_rendezvous_softc)); + if ((error = pthread_mutex_init(&softc->mtx, NULL)) != 0) + errc(1, error, "init rendezvous mutex"); + if ((error = pthread_cond_init(&softc->cond, NULL)) != 0) + errc(1, error, "init rendezvous cond variable"); + softc->counter = 0; + } + + return (softc); +} + +static void +bhyve_init_wait(void) +{ + init_rendezvous_softc_t softc = get_init_rendezvous_softc(); + + pthread_mutex_lock(&softc->mtx); + while (softc->counter > 0) + pthread_cond_wait(&softc->cond, &softc->mtx); + pthread_mutex_unlock(&softc->mtx); +} + +void +bhyve_init_block(void) +{ + init_rendezvous_softc_t softc = get_init_rendezvous_softc(); + + if (softc == NULL) + return; + + pthread_mutex_lock(&softc->mtx); + softc->counter += 1; + pthread_mutex_unlock(&softc->mtx); + + return; +} + +void +bhyve_init_notify(void) +{ + init_rendezvous_softc_t softc = get_init_rendezvous_softc(); + + if (softc == NULL) + return; + + pthread_mutex_lock(&softc->mtx); + assert(softc->counter > 0); + softc->counter--; + pthread_cond_broadcast(&softc->cond); + pthread_mutex_unlock(&softc->mtx); +} + /* * XXX This parser is known to have the following issues: * 1. It accepts null key=value tokens ",," as setting "cpus" to an @@ -391,6 +461,8 @@ gdb_cpu_add(vi->vcpu); #endif + bhyve_init_wait(); + vm_loop(vi->ctx, vi->vcpu); /* not reached */ diff --git a/usr.sbin/bhyve/debug.h b/usr.sbin/bhyve/debug.h --- a/usr.sbin/bhyve/debug.h +++ b/usr.sbin/bhyve/debug.h @@ -28,6 +28,7 @@ #ifndef _DEBUG_H_ #define _DEBUG_H_ +#include extern int raw_stdio; diff --git a/usr.sbin/bhyve/rfb.c b/usr.sbin/bhyve/rfb.c --- a/usr.sbin/bhyve/rfb.c +++ b/usr.sbin/bhyve/rfb.c @@ -52,17 +52,17 @@ #include #include #include -#include #include +#include #include #include #include - #include #include "bhyvegc.h" -#include "debug.h" +#include "bhyverun.h" #include "console.h" +#include "debug.h" #include "rfb.h" #include "sockstream.h" @@ -140,9 +140,7 @@ atomic_bool input_detected; atomic_bool update_pixfmt; - pthread_mutex_t mtx; pthread_mutex_t pixfmt_mtx; - pthread_cond_t cond; int hw_crc; uint32_t *crc; /* WxH crc cells */ @@ -1225,9 +1223,7 @@ cfd = accept(rc->sfd, NULL, NULL); if (rc->conn_wait) { - pthread_mutex_lock(&rc->mtx); - pthread_cond_signal(&rc->cond); - pthread_mutex_unlock(&rc->mtx); + bhyve_init_notify(); rc->conn_wait = 0; } rfb_handle(rc, cfd); @@ -1328,23 +1324,13 @@ rc->hw_crc = sse42_supported(); rc->conn_wait = wait; - if (wait) { - pthread_mutex_init(&rc->mtx, NULL); - pthread_cond_init(&rc->cond, NULL); - } + if (wait) + bhyve_init_block(); pthread_mutex_init(&rc->pixfmt_mtx, NULL); pthread_create(&rc->tid, NULL, rfb_thr, rc); pthread_set_name_np(rc->tid, "rfb"); - if (wait) { - DPRINTF(("Waiting for rfb client...")); - pthread_mutex_lock(&rc->mtx); - pthread_cond_wait(&rc->cond, &rc->mtx); - pthread_mutex_unlock(&rc->mtx); - DPRINTF(("rfb client connected")); - } - freeaddrinfo(ai); return (0); diff --git a/usr.sbin/bhyve/uart_backend.c b/usr.sbin/bhyve/uart_backend.c --- a/usr.sbin/bhyve/uart_backend.c +++ b/usr.sbin/bhyve/uart_backend.c @@ -48,6 +48,7 @@ #include #include +#include "bhyverun.h" #include "debug.h" #include "mevent.h" #include "uart_backend.h" @@ -74,6 +75,7 @@ struct fifo rxfifo; struct mevent *mev; pthread_mutex_t mtx; + bool wait; }; struct uart_socket_softc { @@ -82,7 +84,7 @@ void *arg; }; -static bool uart_stdio; /* stdio in use for i/o */ +static bool uart_stdio; /* stdio in use for i/o */ static struct termios tio_stdio_orig; static void uart_tcp_disconnect(struct uart_softc *); @@ -319,6 +321,11 @@ socket_softc->arg); } + if (sc->wait) { + sc->wait = false; + bhyve_init_notify(); + } + pthread_mutex_unlock(&sc->mtx); return; @@ -427,16 +434,23 @@ int domain; struct addrinfo hints, *src_addr = NULL; struct uart_socket_softc *socket_softc = NULL; + int consumed = 0; - if (sscanf(path, "tcp=[%255[^]]]:%5s", addr, port) == 2) { + if (sscanf(path, "tcp=[%255[^]]]:%5[^,],%n", addr, port, &consumed) == 2) { domain = AF_INET6; - } else if (sscanf(path, "tcp=%255[^:]:%5s", addr, port) == 2) { + } else if (sscanf(path, "tcp=%255[^:]:%5[^,],%n", addr, port, &consumed) == 2) { domain = AF_INET; } else { warnx("Invalid number of parameter"); goto clean; } + path += consumed; + sc->wait = strcmp(path, "wait") == 0; + + if (sc->wait == true) + bhyve_init_block(); + bind_fd = socket(domain, SOCK_STREAM, 0); if (bind_fd < 0) goto clean;