Re: move vmd vioblk handling to another thread

2022-11-16 Thread Uwe Werler
On 12 Nov 01:52, David Gwynne wrote:
> this updates a diff i had from a few years ago to move the vioblk
> handling in vmd into a separate thread.
> 
> basically disk io in your virtual machine should not block the vcpu from
> running now.
> 
> just throwing this out so people can give it a go and kick it around.
> 
> Index: Makefile
> ===
> RCS file: /cvs/src/usr.sbin/vmd/Makefile,v
> retrieving revision 1.28
> diff -u -p -r1.28 Makefile
> --- Makefile  10 Nov 2022 11:46:39 -  1.28
> +++ Makefile  11 Nov 2022 15:51:50 -
> @@ -5,7 +5,7 @@
>  PROG=vmd
>  SRCS=vmd.c control.c log.c priv.c proc.c config.c vmm.c
>  SRCS+=   vm.c loadfile_elf.c pci.c virtio.c i8259.c mc146818.c
> -SRCS+=   ns8250.c i8253.c dhcp.c packet.c mmio.c
> +SRCS+=   ns8250.c i8253.c dhcp.c packet.c mmio.c task.c
>  SRCS+=   parse.y atomicio.c vioscsi.c vioraw.c vioqcow2.c 
> fw_cfg.c
>  SRCS+=   vm_agentx.c
>  
> Index: task.c
> ===
> RCS file: task.c
> diff -N task.c
> --- /dev/null 1 Jan 1970 00:00:00 -
> +++ task.c11 Nov 2022 15:51:50 -
> @@ -0,0 +1,158 @@
> +/*   $OpenBSD: task.c,v 1.2 2018/06/19 17:12:34 reyk Exp $ */
> +
> +/*
> + * Copyright (c) 2017 David Gwynne 
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include "task.h"
> +
> +#define ISSET(_v, _m)((_v) & (_m))
> +#define SET(_v, _m)  ((_v) |= (_m))
> +#define CLR(_v, _m)  ((_v) &= ~(_m))
> +
> +struct taskq {
> + pthread_t thread;
> + struct task_list  list;
> + pthread_mutex_t   mtx;
> + pthread_cond_tcv;
> +};
> +
> +#define TASK_ONQUEUE (1 << 0)
> +
> +static void *taskq_run(void *);
> +
> +struct taskq *
> +taskq_create(const char *name)
> +{
> + struct taskq *tq;
> + int error;
> +
> + tq = malloc(sizeof(*tq));
> + if (tq == NULL)
> + return (NULL);
> +
> + TAILQ_INIT(>list);
> +
> + error = pthread_mutex_init(>mtx, NULL);
> + if (error != 0)
> + goto free;
> +
> + error = pthread_cond_init(>cv, NULL);
> + if (error != 0)
> + goto mtx;
> +
> + error = pthread_create(>thread, NULL, taskq_run, tq);
> + if (error != 0)
> + goto cv;
> +
> + pthread_set_name_np(tq->thread, name);
> +
> + return (tq);
> +
> +cv:
> + pthread_cond_destroy(>cv);
> +mtx:
> + pthread_mutex_destroy(>mtx); /* can this really fail? */
> +free:
> + free(tq);
> +
> + errno = error;
> + return (NULL);
> +}
> +
> +static void *
> +taskq_run(void *tqarg)
> +{
> + struct taskq *tq = tqarg;
> + struct task *t;
> +
> + void (*t_func)(void *);
> + void *t_arg;
> +
> + for (;;) {
> + pthread_mutex_lock(>mtx);
> + while ((t = TAILQ_FIRST(>list)) == NULL)
> + pthread_cond_wait(>cv, >mtx);
> +
> + TAILQ_REMOVE(>list, t, t_entry);
> + CLR(t->t_flags, TASK_ONQUEUE);
> +
> + t_func = t->t_func;
> + t_arg = t->t_arg;
> +
> + pthread_mutex_unlock(>mtx);
> +
> + (*t_func)(t_arg);
> + }
> +
> + return (NULL);
> +}
> +
> +void
> +task_set(struct task *t, void (*fn)(void *), void *arg)
> +{
> + t->t_func = fn;
> + t->t_arg = arg;
> + t->t_flags = 0;
> +}
> +
> +int
> +task_add(struct taskq *tq, struct task *t)
> +{
> + int rv = 1;
> +
> + if (ISSET(t->t_flags, TASK_ONQUEUE))
> + return (0);
> +
> + pthread_mutex_lock(>mtx);
> + if (ISSET(t->t_flags, TASK_ONQUEUE))
> + rv = 0;
> + else {
> + SET(t->t_flags, TASK_ONQUEUE);
> + TAILQ_INSERT_TAIL(>list, t, t_entry);
> + pthread_cond_signal(>cv);
> + }
> + pthread_mutex_unlock(>mtx);
> +
> + return (rv);
> +}
> +
> +int
> +task_del(struct taskq *tq, struct task *t)
> +{
> + int rv = 1;
> +
> + if (!ISSET(t->t_flags, TASK_ONQUEUE))
> + return (0);
> +
> + 

Re: move vmd vioblk handling to another thread

2022-11-12 Thread Mischa

Hi David,

Updated the machine to latest snap and applied the patch.
The VMs I have on the machine I am testing with aren't booting properly.


OpenBSD/amd64 BOOT 3.53

boot>
NOTE: random seed is being reused.
booting hd0a:/bsd: 15549720+3695624+345456+0+1171456 
[1142327+128+1218000+922932]=0x16f0dc0

entry point at 0x81001000
[ using 3284416 bytes of bsd ELF symbol table ]
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California.  All rights 
reserved.
Copyright (c) 1995-2022 OpenBSD. All rights reserved.  
https://www.OpenBSD.org


OpenBSD 7.1 (GENERIC) #3: Sun May 15 10:25:28 MDT 2022

r...@syspatch-71-amd64.openbsd.org:/usr/src/sys/arch/amd64/compile/GENERIC

real mem = 1056952320 (1007MB)
avail mem = 1007792128 (961MB)
random: good seed from bootblocks
mpath0 at root
scsibus0 at mpath0: 256 targets
mainbus0 at root
bios0 at mainbus0: SMBIOS rev. 2.4 @ 0xf36e0 (10 entries)
bios0: vendor SeaBIOS version "1.14.0p0-OpenBSD-vmm" date 01/01/2011
bios0: OpenBSD VMM
acpi at bios0 not configured
cpu0 at mainbus0: (uniprocessor)
cpu0: Intel(R) Xeon(R) CPU E5-2640 0 @ 2.50GHz, 2500.01 MHz, 06-2d-07
cpu0: 
FPU,VME,DE,PSE,TSC,MSR,PAE,CX8,SEP,PGE,CMOV,PAT,PSE36,CFLUSH,MMX,FXSR,SSE,SSE2,SSE3,PCLMUL,SSSE3,CX16,SSE4.1,SSE4.2,POPCNT,AES,XSAVE,AVX,HV,NXE,PAGE1GB,LONG,LAHF,ITSC,MD_CLEAR,MELTDOWN

cpu0: 256KB 64b/line 8-way L2 cache
cpu0: smt 0, core 0, package 0
cpu0: using VERW MDS workaround
pvbus0 at mainbus0: OpenBSD
pvclock0 at pvbus0
pci0 at mainbus0 bus 0
pchb0 at pci0 dev 0 function 0 "OpenBSD VMM Host" rev 0x00
virtio0 at pci0 dev 1 function 0 "Qumranet Virtio RNG" rev 0x00
viornd0 at virtio0
virtio0: irq 3
virtio1 at pci0 dev 2 function 0 "Qumranet Virtio Network" rev 0x00
vio0 at virtio1: address fe:e1:bb:6a:00:04
virtio1: irq 5
virtio2 at pci0 dev 3 function 0 "Qumranet Virtio Storage" rev 0x00
vioblk0 at virtio2
scsibus1 at vioblk0: 1 targets
sd0 at scsibus1 targ 0 lun 0: 
sd0: 51200MB, 512 bytes/sector, 104857600 sectors
virtio2: irq 6
virtio3 at pci0 dev 4 function 0 "OpenBSD VMM Control" rev 0x00
vmmci0 at virtio3
virtio3: irq 7
isa0 at mainbus0
isadma0 at isa0
com0 at isa0 port 0x3f8/8 irq 4: ns8250, no fifo
com0: console
vscsi0 at root
scsibus2 at vscsi0: 256 targets
softraid0 at root
scsibus3 at softraid0: 256 targets


After this nothing happens.

Mischa


On 2022-11-11 16:52, David Gwynne wrote:

this updates a diff i had from a few years ago to move the vioblk
handling in vmd into a separate thread.

basically disk io in your virtual machine should not block the vcpu 
from

running now.

just throwing this out so people can give it a go and kick it around.

Index: Makefile
===
RCS file: /cvs/src/usr.sbin/vmd/Makefile,v
retrieving revision 1.28
diff -u -p -r1.28 Makefile
--- Makefile10 Nov 2022 11:46:39 -  1.28
+++ Makefile11 Nov 2022 15:51:50 -
@@ -5,7 +5,7 @@
 PROG=  vmd
 SRCS=  vmd.c control.c log.c priv.c proc.c config.c vmm.c
 SRCS+= vm.c loadfile_elf.c pci.c virtio.c i8259.c mc146818.c
-SRCS+= ns8250.c i8253.c dhcp.c packet.c mmio.c
+SRCS+= ns8250.c i8253.c dhcp.c packet.c mmio.c task.c
 SRCS+= parse.y atomicio.c vioscsi.c vioraw.c vioqcow2.c fw_cfg.c
 SRCS+= vm_agentx.c

Index: task.c
===
RCS file: task.c
diff -N task.c
--- /dev/null   1 Jan 1970 00:00:00 -
+++ task.c  11 Nov 2022 15:51:50 -
@@ -0,0 +1,158 @@
+/* $OpenBSD: task.c,v 1.2 2018/06/19 17:12:34 reyk Exp $ */
+
+/*
+ * Copyright (c) 2017 David Gwynne 
+ *
+ * Permission to use, copy, modify, and distribute this software for 
any
+ * purpose with or without fee is hereby granted, provided that the 
above

+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 
WARRANTIES

+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE 
FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY 
DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 
OUT OF

+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "task.h"
+
+#define ISSET(_v, _m)  ((_v) & (_m))
+#define SET(_v, _m)((_v) |= (_m))
+#define CLR(_v, _m)((_v) &= ~(_m))
+
+struct taskq {
+   pthread_t thread;
+   struct task_list  list;
+   pthread_mutex_t   mtx;
+   pthread_cond_tcv;
+};
+
+#define TASK_ONQUEUE   (1 << 0)
+
+static void *taskq_run(void *);
+
+struct taskq *
+taskq_create(const char *name)
+{
+   struct taskq *tq;
+   int error;
+
+  

move vmd vioblk handling to another thread

2022-11-11 Thread David Gwynne
this updates a diff i had from a few years ago to move the vioblk
handling in vmd into a separate thread.

basically disk io in your virtual machine should not block the vcpu from
running now.

just throwing this out so people can give it a go and kick it around.

Index: Makefile
===
RCS file: /cvs/src/usr.sbin/vmd/Makefile,v
retrieving revision 1.28
diff -u -p -r1.28 Makefile
--- Makefile10 Nov 2022 11:46:39 -  1.28
+++ Makefile11 Nov 2022 15:51:50 -
@@ -5,7 +5,7 @@
 PROG=  vmd
 SRCS=  vmd.c control.c log.c priv.c proc.c config.c vmm.c
 SRCS+= vm.c loadfile_elf.c pci.c virtio.c i8259.c mc146818.c
-SRCS+= ns8250.c i8253.c dhcp.c packet.c mmio.c
+SRCS+= ns8250.c i8253.c dhcp.c packet.c mmio.c task.c
 SRCS+= parse.y atomicio.c vioscsi.c vioraw.c vioqcow2.c fw_cfg.c
 SRCS+= vm_agentx.c
 
Index: task.c
===
RCS file: task.c
diff -N task.c
--- /dev/null   1 Jan 1970 00:00:00 -
+++ task.c  11 Nov 2022 15:51:50 -
@@ -0,0 +1,158 @@
+/* $OpenBSD: task.c,v 1.2 2018/06/19 17:12:34 reyk Exp $ */
+
+/*
+ * Copyright (c) 2017 David Gwynne 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "task.h"
+
+#define ISSET(_v, _m)  ((_v) & (_m))
+#define SET(_v, _m)((_v) |= (_m))
+#define CLR(_v, _m)((_v) &= ~(_m))
+
+struct taskq {
+   pthread_t thread;
+   struct task_list  list;
+   pthread_mutex_t   mtx;
+   pthread_cond_tcv;
+};
+
+#define TASK_ONQUEUE   (1 << 0)
+
+static void *taskq_run(void *);
+
+struct taskq *
+taskq_create(const char *name)
+{
+   struct taskq *tq;
+   int error;
+
+   tq = malloc(sizeof(*tq));
+   if (tq == NULL)
+   return (NULL);
+
+   TAILQ_INIT(>list);
+
+   error = pthread_mutex_init(>mtx, NULL);
+   if (error != 0)
+   goto free;
+
+   error = pthread_cond_init(>cv, NULL);
+   if (error != 0)
+   goto mtx;
+
+   error = pthread_create(>thread, NULL, taskq_run, tq);
+   if (error != 0)
+   goto cv;
+
+   pthread_set_name_np(tq->thread, name);
+
+   return (tq);
+
+cv:
+   pthread_cond_destroy(>cv);
+mtx:
+   pthread_mutex_destroy(>mtx); /* can this really fail? */
+free:
+   free(tq);
+
+   errno = error;
+   return (NULL);
+}
+
+static void *
+taskq_run(void *tqarg)
+{
+   struct taskq *tq = tqarg;
+   struct task *t;
+
+   void (*t_func)(void *);
+   void *t_arg;
+
+   for (;;) {
+   pthread_mutex_lock(>mtx);
+   while ((t = TAILQ_FIRST(>list)) == NULL)
+   pthread_cond_wait(>cv, >mtx);
+
+   TAILQ_REMOVE(>list, t, t_entry);
+   CLR(t->t_flags, TASK_ONQUEUE);
+
+   t_func = t->t_func;
+   t_arg = t->t_arg;
+
+   pthread_mutex_unlock(>mtx);
+
+   (*t_func)(t_arg);
+   }
+
+   return (NULL);
+}
+
+void
+task_set(struct task *t, void (*fn)(void *), void *arg)
+{
+   t->t_func = fn;
+   t->t_arg = arg;
+   t->t_flags = 0;
+}
+
+int
+task_add(struct taskq *tq, struct task *t)
+{
+   int rv = 1;
+
+   if (ISSET(t->t_flags, TASK_ONQUEUE))
+   return (0);
+
+   pthread_mutex_lock(>mtx);
+   if (ISSET(t->t_flags, TASK_ONQUEUE))
+   rv = 0;
+   else {
+   SET(t->t_flags, TASK_ONQUEUE);
+   TAILQ_INSERT_TAIL(>list, t, t_entry);
+   pthread_cond_signal(>cv);
+   }
+   pthread_mutex_unlock(>mtx);
+
+   return (rv);
+}
+
+int
+task_del(struct taskq *tq, struct task *t)
+{
+   int rv = 1;
+
+   if (!ISSET(t->t_flags, TASK_ONQUEUE))
+   return (0);
+
+   pthread_mutex_lock(>mtx);
+   if (!ISSET(t->t_flags, TASK_ONQUEUE))
+   rv = 0;
+   else {
+   TAILQ_REMOVE(>list, t, t_entry);
+   CLR(t->t_flags, TASK_ONQUEUE);
+   }
+   pthread_mutex_unlock(>mtx);
+
+   return (rv);
+}
Index: task.h