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,53 @@ 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 */ + int counter; /* counter on how much component still wait for connection */ +}; + +static struct init_rendezvous_softc rendezvous_softc = { 0 }; + +static void +create_init_rendezvous_softc(void) +{ + int error; + + if ((error = pthread_mutex_init(&rendezvous_softc.mtx, NULL)) != 0) + errc(1, error, "init rendezvous mutex"); + if ((error = pthread_cond_init(&rendezvous_softc.cond, NULL)) != 0) + errc(1, error, "init rendezvous cond variable"); +} + +static void +bhyve_init_wait(void) +{ + pthread_mutex_lock(&rendezvous_softc.mtx); + while (rendezvous_softc.counter > 0) + pthread_cond_wait(&rendezvous_softc.cond, + &rendezvous_softc.mtx); + pthread_mutex_unlock(&rendezvous_softc.mtx); +} + +void +bhyve_init_block(void) +{ + pthread_mutex_lock(&rendezvous_softc.mtx); + rendezvous_softc.counter++; + pthread_mutex_unlock(&rendezvous_softc.mtx); +} + +void +bhyve_init_notify(void) +{ + pthread_mutex_lock(&rendezvous_softc.mtx); + assert(rendezvous_softc.counter > 0); + rendezvous_softc.counter--; + pthread_cond_broadcast(&rendezvous_softc.cond); + pthread_mutex_unlock(&rendezvous_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 +438,8 @@ gdb_cpu_add(vi->vcpu); #endif + bhyve_init_wait(); + vm_loop(vi->ctx, vi->vcpu); /* not reached */ @@ -643,6 +692,8 @@ if (argc > 1) bhyve_usage(1); + create_init_rendezvous_softc(); + #ifdef BHYVE_SNAPSHOT if (restore_file != NULL) { error = load_restore_file(restore_file, &rstate); 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/gdb.c b/usr.sbin/bhyve/gdb.c --- a/usr.sbin/bhyve/gdb.c +++ b/usr.sbin/bhyve/gdb.c @@ -105,7 +105,7 @@ static cpuset_t vcpus_active, vcpus_suspended, vcpus_waiting; static pthread_mutex_t gdb_lock; static pthread_cond_t idle_vcpus; -static bool first_stop, report_next_stop, swbreak_enabled; +static bool first_stop, report_next_stop, swbreak_enabled, wait; static int xml_dfd = -1; /* @@ -2127,6 +2127,10 @@ } pthread_mutex_lock(&gdb_lock); + if (wait) { + wait = 0; + bhyve_init_notify(); + } if (cur_fd != -1) { close(s); warnx("Ignoring additional GDB connection."); @@ -2185,7 +2189,6 @@ struct addrinfo *gdbaddr; const char *saddr, *value; char *sport; - bool wait; value = get_config_value("gdb.port"); if (value == NULL) @@ -2238,16 +2241,8 @@ TAILQ_INIT(&breakpoints); vcpus = calloc(guest_ncpus, sizeof(*vcpus)); vcpu_state = calloc(guest_ncpus, sizeof(*vcpu_state)); - if (wait) { - /* - * Set vcpu 0 in vcpus_suspended. This will trigger the - * logic in gdb_cpu_add() to suspend the first vcpu before - * it starts execution. The vcpu will remain suspended - * until a debugger connects. - */ - CPU_SET(0, &vcpus_suspended); - stopped_vcpu = 0; - } + if (wait) + bhyve_init_block(); flags = fcntl(s, F_GETFL); if (fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1) 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,29 @@ int domain; struct addrinfo hints, *src_addr = NULL; struct uart_socket_softc *socket_softc = NULL; + const char *args; - if (sscanf(path, "tcp=[%255[^]]]:%5s", addr, port) == 2) { + args = strchr(path, ','); + + if (args != NULL) + ++args; + else + args = ""; + + if (sscanf(path, "tcp=[%255[^]]]:%5[^,]", addr, port) == 2) { domain = AF_INET6; - } else if (sscanf(path, "tcp=%255[^:]:%5s", addr, port) == 2) { + } else if (sscanf(path, "tcp=%255[^:]:%5[^,]", addr, port) == 2) { domain = AF_INET; } else { warnx("Invalid number of parameter"); goto clean; } + sc->wait = strncmp(args, "wait", 5) == 0; + + if (sc->wait == true) + bhyve_init_block(); + bind_fd = socket(domain, SOCK_STREAM, 0); if (bind_fd < 0) goto clean;