Module Name:    src
Committed By:   tls
Date:           Sun Aug 10 06:52:26 UTC 2014

Modified Files:
        src/lib/librumpuser [tls-earlyentropy]: Makefile rumpuser.c
            rumpuser_bio.c rumpuser_dl.c rumpuser_int.h rumpuser_port.h
            rumpuser_pth.c rumpuser_pth_dummy.c rumpuser_sp.c
Added Files:
        src/lib/librumpuser [tls-earlyentropy]: rumpfiber.c rumpfiber.h
            rumpfiber_bio.c rumpfiber_sp.c rumpuser_file.c rumpuser_mem.c
            rumpuser_random.c

Log Message:
Rebase.


To generate a diff of this commit:
cvs rdiff -u -r1.16 -r1.16.2.1 src/lib/librumpuser/Makefile
cvs rdiff -u -r0 -r1.3.2.2 src/lib/librumpuser/rumpfiber.c
cvs rdiff -u -r0 -r1.1.2.2 src/lib/librumpuser/rumpfiber.h \
    src/lib/librumpuser/rumpfiber_bio.c src/lib/librumpuser/rumpfiber_sp.c \
    src/lib/librumpuser/rumpuser_file.c src/lib/librumpuser/rumpuser_mem.c
cvs rdiff -u -r1.59 -r1.59.2.1 src/lib/librumpuser/rumpuser.c
cvs rdiff -u -r1.7 -r1.7.6.1 src/lib/librumpuser/rumpuser_bio.c
cvs rdiff -u -r1.28 -r1.28.2.1 src/lib/librumpuser/rumpuser_dl.c
cvs rdiff -u -r1.9 -r1.9.2.1 src/lib/librumpuser/rumpuser_int.h
cvs rdiff -u -r1.32 -r1.32.2.1 src/lib/librumpuser/rumpuser_port.h
cvs rdiff -u -r1.40 -r1.40.2.1 src/lib/librumpuser/rumpuser_pth.c
cvs rdiff -u -r1.16 -r1.16.4.1 src/lib/librumpuser/rumpuser_pth_dummy.c
cvs rdiff -u -r0 -r1.2.2.2 src/lib/librumpuser/rumpuser_random.c
cvs rdiff -u -r1.63 -r1.63.2.1 src/lib/librumpuser/rumpuser_sp.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/librumpuser/Makefile
diff -u src/lib/librumpuser/Makefile:1.16 src/lib/librumpuser/Makefile:1.16.2.1
--- src/lib/librumpuser/Makefile:1.16	Thu Feb 20 00:42:27 2014
+++ src/lib/librumpuser/Makefile	Sun Aug 10 06:52:25 2014
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.16 2014/02/20 00:42:27 pooka Exp $
+#	$NetBSD: Makefile,v 1.16.2.1 2014/08/10 06:52:25 tls Exp $
 #
 
 .include <bsd.own.mk>
@@ -8,8 +8,13 @@ WARNS?=		5
 # rumpuser.h is in sys/rump for inclusion by kernel components
 .PATH:		${.CURDIR}/../../sys/rump/include/rump
 
+RUMPUSER_THREADS?=pthread
+
 LIB=		rumpuser
+
+.if   ${RUMPUSER_THREADS} == "pthread"
 LIBDPLIBS+=	pthread ${.CURDIR}/../libpthread
+.endif
 .for lib in ${RUMPUSER_EXTERNAL_DPLIBS}
 LIBDO.${lib}=	_external
 LIBDPLIBS+=	${lib} lib
@@ -17,14 +22,32 @@ LIBDPLIBS+=	${lib} lib
 CPPFLAGS+=	-DLIBRUMPUSER
 #CPPFLAGS+=	-D_DIAGNOSTIC
 
-SRCS=		rumpuser.c
-SRCS+=		rumpuser_pth.c
-SRCS+=		rumpuser_component.c rumpuser_bio.c
+
+.if   ${RUMPUSER_THREADS} == "pthread"
+SRCS=		rumpuser.c rumpuser_pth.c rumpuser_bio.c
+SRCS+=		rumpuser_sp.c
+.elif ${RUMPUSER_THREADS} == "none"
+SRCS=		rumpuser.c rumpuser_pth_dummy.c rumpuser_bio.c
+SRCS+=		rumpuser_sp.c
+.elif ${RUMPUSER_THREADS} == "fiber"
+.if defined(RUMP_CURLWP)
+.if ${RUMP_CURLWP} != "hypercall"
+.error Unsupported curlwp scheme for thread model: ${RUMP_CURLWP}
+.endif
+.endif
+SRCS=		rumpfiber.c rumpfiber_bio.c
+SRCS+=		rumpfiber_sp.c
+.else
+.error Unsupported rumpuser threading type: ${RUMPUSER_THREADS}
+.endif
+
+SRCS+=		rumpuser_component.c rumpuser_random.c
+SRCS+=		rumpuser_file.c rumpuser_mem.c
 
 SRCS+=		rumpuser_errtrans.c rumpuser_sigtrans.c
 
 # optional
-SRCS+=		rumpuser_dl.c rumpuser_sp.c rumpuser_daemonize.c
+SRCS+=		rumpuser_dl.c rumpuser_daemonize.c
 
 INCSDIR=	/usr/include/rump
 INCS=		rumpuser.h rumpuser_component.h rumpuser_port.h
@@ -33,5 +56,4 @@ MAN=		rumpuser.3
 
 CPPFLAGS+=	-D_REENTRANT
 
-
 .include <bsd.lib.mk>

Index: src/lib/librumpuser/rumpuser.c
diff -u src/lib/librumpuser/rumpuser.c:1.59 src/lib/librumpuser/rumpuser.c:1.59.2.1
--- src/lib/librumpuser/rumpuser.c:1.59	Wed Apr  2 13:54:42 2014
+++ src/lib/librumpuser/rumpuser.c	Sun Aug 10 06:52:26 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: rumpuser.c,v 1.59 2014/04/02 13:54:42 pooka Exp $	*/
+/*	$NetBSD: rumpuser.c,v 1.59.2.1 2014/08/10 06:52:26 tls Exp $	*/
 
 /*
  * Copyright (c) 2007-2010 Antti Kantee.  All Rights Reserved.
@@ -28,29 +28,12 @@
 #include "rumpuser_port.h"
 
 #if !defined(lint)
-__RCSID("$NetBSD: rumpuser.c,v 1.59 2014/04/02 13:54:42 pooka Exp $");
+__RCSID("$NetBSD: rumpuser.c,v 1.59.2.1 2014/08/10 06:52:26 tls Exp $");
 #endif /* !lint */
 
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <sys/uio.h>
 #include <sys/stat.h>
 #include <sys/time.h>
-
-#ifdef __NetBSD__
-#include <sys/disk.h>
-#include <sys/disklabel.h>
-#include <sys/dkio.h>
-#endif
-
-#if defined(__NetBSD__) || defined(__FreeBSD__) || \
-    defined(__DragonFly__) || defined(__APPLE__)
-#define	__BSD__
-#endif
-
-#if defined(__BSD__)
-#include <sys/sysctl.h>
-#endif
+#include <sys/types.h>
 
 #include <assert.h>
 #include <errno.h>
@@ -74,27 +57,18 @@ struct rumpuser_hyperup rumpuser__hyp;
 int
 rumpuser_init(int version, const struct rumpuser_hyperup *hyp)
 {
+	int rv;
 
 	if (version != RUMPUSER_VERSION) {
 		fprintf(stderr, "rumpuser mismatch, kern: %d, hypervisor %d\n",
 		    version, RUMPUSER_VERSION);
-		return 1;
+		abort();
 	}
 
-#ifdef RUMPUSER_USE_DEVRANDOM
-	uint32_t rv;
-	int fd;
-
-	if ((fd = open("/dev/urandom", O_RDONLY)) == -1) {
-		srandom(time(NULL));
-	} else {
-		if (read(fd, &rv, sizeof(rv)) != sizeof(rv))
-			srandom(time(NULL));
-		else
-			srandom(rv);
-		close(fd);
+	rv = rumpuser__random_init();
+	if (rv != 0) {
+		ET(rv);
 	}
-#endif
 
 	rumpuser__thrinit();
 	rumpuser__hyp = *hyp;
@@ -103,342 +77,6 @@ rumpuser_init(int version, const struct 
 }
 
 int
-rumpuser_getfileinfo(const char *path, uint64_t *sizep, int *ftp)
-{
-	struct stat sb;
-	uint64_t size = 0;
-	int needsdev = 0, rv = 0, ft = 0;
-	int fd = -1;
-
-	if (stat(path, &sb) == -1) {
-		rv = errno;
-		goto out;
-	}
-
-	switch (sb.st_mode & S_IFMT) {
-	case S_IFDIR:
-		ft = RUMPUSER_FT_DIR;
-		break;
-	case S_IFREG:
-		ft = RUMPUSER_FT_REG;
-		break;
-	case S_IFBLK:
-		ft = RUMPUSER_FT_BLK;
-		needsdev = 1;
-		break;
-	case S_IFCHR:
-		ft = RUMPUSER_FT_CHR;
-		needsdev = 1;
-		break;
-	default:
-		ft = RUMPUSER_FT_OTHER;
-		break;
-	}
-
-	if (!needsdev) {
-		size = sb.st_size;
-	} else if (sizep) {
-		/*
-		 * Welcome to the jungle.  Of course querying the kernel
-		 * for a device partition size is supposed to be far from
-		 * trivial.  On NetBSD we use ioctl.  On $other platform
-		 * we have a problem.  We try "the lseek trick" and just
-		 * fail if that fails.  Platform specific code can later
-		 * be written here if appropriate.
-		 *
-		 * On NetBSD we hope and pray that for block devices nobody
-		 * else is holding them open, because otherwise the kernel
-		 * will not permit us to open it.  Thankfully, this is
-		 * usually called only in bootstrap and then we can
-		 * forget about it.
-		 */
-#ifndef __NetBSD__
-		off_t off;
-
-		fd = open(path, O_RDONLY);
-		if (fd == -1) {
-			rv = errno;
-			goto out;
-		}
-
-		off = lseek(fd, 0, SEEK_END);
-		if (off != 0) {
-			size = off;
-			goto out;
-		}
-		fprintf(stderr, "error: device size query not implemented on "
-		    "this platform\n");
-		rv = EOPNOTSUPP;
-		goto out;
-#else
-		struct disklabel lab;
-		struct partition *parta;
-		struct dkwedge_info dkw;
-
-		fd = open(path, O_RDONLY);
-		if (fd == -1) {
-			rv = errno;
-			goto out;
-		}
-
-		if (ioctl(fd, DIOCGDINFO, &lab) == 0) {
-			parta = &lab.d_partitions[DISKPART(sb.st_rdev)];
-			size = (uint64_t)lab.d_secsize * parta->p_size;
-			goto out;
-		}
-
-		if (ioctl(fd, DIOCGWEDGEINFO, &dkw) == 0) {
-			/*
-			 * XXX: should use DIOCGDISKINFO to query
-			 * sector size, but that requires proplib,
-			 * so just don't bother for now.  it's nice
-			 * that something as difficult as figuring out
-			 * a partition's size has been made so easy.
-			 */
-			size = dkw.dkw_size << DEV_BSHIFT;
-			goto out;
-		}
-
-		rv = errno;
-#endif /* __NetBSD__ */
-	}
-
- out:
-	if (rv == 0 && sizep)
-		*sizep = size;
-	if (rv == 0 && ftp)
-		*ftp = ft;
-	if (fd != -1)
-		close(fd);
-
-	ET(rv);
-}
-
-int
-rumpuser_malloc(size_t howmuch, int alignment, void **memp)
-{
-	void *mem = NULL;
-	int rv;
-
-	if (alignment == 0)
-		alignment = sizeof(void *);
-
-	rv = posix_memalign(&mem, (size_t)alignment, howmuch);
-	if (__predict_false(rv != 0)) {
-		if (rv == EINVAL) {
-			printf("rumpuser_malloc: invalid alignment %d\n",
-			    alignment);
-			abort();
-		}
-	}
-
-	*memp = mem;
-	ET(rv);
-}
-
-/*ARGSUSED1*/
-void
-rumpuser_free(void *ptr, size_t size)
-{
-
-	free(ptr);
-}
-
-int
-rumpuser_anonmmap(void *prefaddr, size_t size, int alignbit,
-	int exec, void **memp)
-{
-	void *mem;
-	int prot, rv;
-
-#ifndef MAP_ALIGNED
-#define MAP_ALIGNED(a) 0
-	if (alignbit)
-		fprintf(stderr, "rumpuser_anonmmap: warning, requested "
-		    "alignment not supported by hypervisor\n");
-#endif
-
-	prot = PROT_READ|PROT_WRITE;
-	if (exec)
-		prot |= PROT_EXEC;
-	mem = mmap(prefaddr, size, prot,
-	    MAP_PRIVATE | MAP_ANON | MAP_ALIGNED(alignbit), -1, 0);
-	if (mem == MAP_FAILED) {
-		rv = errno;
-	} else {
-		*memp = mem;
-		rv = 0;
-	}
-
-	ET(rv);
-}
-
-void
-rumpuser_unmap(void *addr, size_t len)
-{
-
-	munmap(addr, len);
-}
-
-int
-rumpuser_open(const char *path, int ruflags, int *fdp)
-{
-	int fd, flags, rv;
-
-	switch (ruflags & RUMPUSER_OPEN_ACCMODE) {
-	case RUMPUSER_OPEN_RDONLY:
-		flags = O_RDONLY;
-		break;
-	case RUMPUSER_OPEN_WRONLY:
-		flags = O_WRONLY;
-		break;
-	case RUMPUSER_OPEN_RDWR:
-		flags = O_RDWR;
-		break;
-	default:
-		rv = EINVAL;
-		goto out;
-	}
-
-#define TESTSET(_ru_, _h_) if (ruflags & _ru_) flags |= _h_;
-	TESTSET(RUMPUSER_OPEN_CREATE, O_CREAT);
-	TESTSET(RUMPUSER_OPEN_EXCL, O_EXCL);
-#undef TESTSET
-
-	KLOCK_WRAP(fd = open(path, flags, 0644));
-	if (fd == -1) {
-		rv = errno;
-	} else {
-		*fdp = fd;
-		rv = 0;
-	}
-
- out:
-	ET(rv);
-}
-
-int
-rumpuser_close(int fd)
-{
-	int nlocks;
-
-	rumpkern_unsched(&nlocks, NULL);
-	fsync(fd);
-	close(fd);
-	rumpkern_sched(nlocks, NULL);
-
-	ET(0);
-}
-
-/*
- * Assume "struct rumpuser_iovec" and "struct iovec" are the same.
- * If you encounter POSIX platforms where they aren't, add some
- * translation for iovlen > 1.
- */
-int
-rumpuser_iovread(int fd, struct rumpuser_iovec *ruiov, size_t iovlen,
-	int64_t roff, size_t *retp)
-{
-	struct iovec *iov = (struct iovec *)ruiov;
-	off_t off = (off_t)roff;
-	ssize_t nn;
-	int rv;
-
-	if (off == RUMPUSER_IOV_NOSEEK) {
-		KLOCK_WRAP(nn = readv(fd, iov, iovlen));
-	} else {
-		int nlocks;
-
-		rumpkern_unsched(&nlocks, NULL);
-		if (lseek(fd, off, SEEK_SET) == off) {
-			nn = readv(fd, iov, iovlen);
-		} else {
-			nn = -1;
-		}
-		rumpkern_sched(nlocks, NULL);
-	}
-
-	if (nn == -1) {
-		rv = errno;
-	} else {
-		*retp = (size_t)nn;
-		rv = 0;
-	}
-
-	ET(rv);
-}
-
-int
-rumpuser_iovwrite(int fd, const struct rumpuser_iovec *ruiov, size_t iovlen,
-	int64_t roff, size_t *retp)
-{
-	const struct iovec *iov = (const struct iovec *)ruiov;
-	off_t off = (off_t)roff;
-	ssize_t nn;
-	int rv;
-
-	if (off == RUMPUSER_IOV_NOSEEK) {
-		KLOCK_WRAP(nn = writev(fd, iov, iovlen));
-	} else {
-		int nlocks;
-
-		rumpkern_unsched(&nlocks, NULL);
-		if (lseek(fd, off, SEEK_SET) == off) {
-			nn = writev(fd, iov, iovlen);
-		} else {
-			nn = -1;
-		}
-		rumpkern_sched(nlocks, NULL);
-	}
-
-	if (nn == -1) {
-		rv = errno;
-	} else {
-		*retp = (size_t)nn;
-		rv = 0;
-	}
-
-	ET(rv);
-}
-
-int
-rumpuser_syncfd(int fd, int flags, uint64_t start, uint64_t len)
-{
-	int rv = 0;
-	
-	/*
-	 * For now, assume fd is regular file and does not care
-	 * about read syncing
-	 */
-	if ((flags & RUMPUSER_SYNCFD_BOTH) == 0) {
-		rv = EINVAL;
-		goto out;
-	}
-	if ((flags & RUMPUSER_SYNCFD_WRITE) == 0) {
-		rv = 0;
-		goto out;
-	}
-
-#ifdef __NetBSD__
-	{
-	int fsflags = FDATASYNC;
-
-	if (fsflags & RUMPUSER_SYNCFD_SYNC)
-		fsflags |= FDISKSYNC;
-	if (fsync_range(fd, fsflags, start, len) == -1)
-		rv = errno;
-	}
-#else
-	/* el-simplo */
-	if (fsync(fd) == -1)
-		rv = errno;
-#endif
-
- out:
-	ET(rv);
-}
-
-int
 rumpuser_clock_gettime(int enum_rumpclock, int64_t *sec, long *nsec)
 {
 	enum rumpclock rclk = enum_rumpclock;
@@ -629,23 +267,3 @@ rumpuser_kill(int64_t pid, int rumpsig)
 		raise(sig);
 	return 0;
 }
-
-int
-rumpuser_getrandom(void *buf, size_t buflen, int flags, size_t *retp)
-{
-	size_t origlen = buflen;
-	uint32_t *p = buf;
-	uint32_t tmp;
-	int chunk;
-
-	do {
-		chunk = buflen < 4 ? buflen : 4; /* portable MIN ... */
-		tmp = RUMPUSER_RANDOM();
-		memcpy(p, &tmp, chunk);
-		p++;
-		buflen -= chunk;
-	} while (chunk);
-
-	*retp = origlen;
-	ET(0);
-}

Index: src/lib/librumpuser/rumpuser_bio.c
diff -u src/lib/librumpuser/rumpuser_bio.c:1.7 src/lib/librumpuser/rumpuser_bio.c:1.7.6.1
--- src/lib/librumpuser/rumpuser_bio.c:1.7	Wed May 15 14:58:24 2013
+++ src/lib/librumpuser/rumpuser_bio.c	Sun Aug 10 06:52:26 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: rumpuser_bio.c,v 1.7 2013/05/15 14:58:24 pooka Exp $	*/
+/*	$NetBSD: rumpuser_bio.c,v 1.7.6.1 2014/08/10 06:52:26 tls Exp $	*/
 
 /*-
  * Copyright (c) 2013 Antti Kantee.  All Rights Reserved.
@@ -27,6 +27,10 @@
 
 #include "rumpuser_port.h"
 
+#if !defined(lint)
+__RCSID("$NetBSD: rumpuser_bio.c,v 1.7.6.1 2014/08/10 06:52:26 tls Exp $");
+#endif /* !lint */
+
 #include <sys/types.h>
 
 #include <assert.h>

Index: src/lib/librumpuser/rumpuser_dl.c
diff -u src/lib/librumpuser/rumpuser_dl.c:1.28 src/lib/librumpuser/rumpuser_dl.c:1.28.2.1
--- src/lib/librumpuser/rumpuser_dl.c:1.28	Wed Apr  2 17:09:23 2014
+++ src/lib/librumpuser/rumpuser_dl.c	Sun Aug 10 06:52:26 2014
@@ -1,4 +1,4 @@
-/*      $NetBSD: rumpuser_dl.c,v 1.28 2014/04/02 17:09:23 justin Exp $	*/
+/*      $NetBSD: rumpuser_dl.c,v 1.28.2.1 2014/08/10 06:52:26 tls Exp $	*/
 
 /*
  * Copyright (c) 2009 Antti Kantee.  All Rights Reserved.
@@ -40,7 +40,7 @@
 #include "rumpuser_port.h"
 
 #if !defined(lint)
-__RCSID("$NetBSD: rumpuser_dl.c,v 1.28 2014/04/02 17:09:23 justin Exp $");
+__RCSID("$NetBSD: rumpuser_dl.c,v 1.28.2.1 2014/08/10 06:52:26 tls Exp $");
 #endif /* !lint */
 
 #include <sys/types.h>
@@ -487,10 +487,3 @@ rumpuser_dl_bootstrap(rump_modinit_fn do
 	return;
 }
 #endif
-
-void *
-rumpuser_dl_globalsym(const char *symname)
-{
-
-	return dlsym(RTLD_DEFAULT, symname);
-}

Index: src/lib/librumpuser/rumpuser_int.h
diff -u src/lib/librumpuser/rumpuser_int.h:1.9 src/lib/librumpuser/rumpuser_int.h:1.9.2.1
--- src/lib/librumpuser/rumpuser_int.h:1.9	Thu Feb 20 01:24:49 2014
+++ src/lib/librumpuser/rumpuser_int.h	Sun Aug 10 06:52:26 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: rumpuser_int.h,v 1.9 2014/02/20 01:24:49 pooka Exp $	*/
+/*	$NetBSD: rumpuser_int.h,v 1.9.2.1 2014/08/10 06:52:26 tls Exp $	*/
 
 /*
  * Copyright (c) 2008 Antti Kantee.  All Rights Reserved.
@@ -101,3 +101,5 @@ int  rumpuser__errtrans(int);
 #else
 #define ET(_v_) return (_v_) ? rumpuser__errtrans(_v_) : 0;
 #endif
+
+int rumpuser__random_init(void);

Index: src/lib/librumpuser/rumpuser_port.h
diff -u src/lib/librumpuser/rumpuser_port.h:1.32 src/lib/librumpuser/rumpuser_port.h:1.32.2.1
--- src/lib/librumpuser/rumpuser_port.h:1.32	Wed Apr  2 17:09:23 2014
+++ src/lib/librumpuser/rumpuser_port.h	Sun Aug 10 06:52:26 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: rumpuser_port.h,v 1.32 2014/04/02 17:09:23 justin Exp $	*/
+/*	$NetBSD: rumpuser_port.h,v 1.32.2.1 2014/08/10 06:52:26 tls Exp $	*/
 
 /*
  * Portability header for non-NetBSD platforms.
@@ -58,7 +58,6 @@
 #define _XOPEN_SOURCE 600
 #define _BSD_SOURCE
 #define _GNU_SOURCE
-#include <features.h>
 #endif
 
 #ifdef __ANDROID__
@@ -218,11 +217,9 @@ posix_memalign(void **ptr, size_t align,
 #define __STRING(x)	#x
 #endif
 
-#if defined(__linux__) || defined(__sun__) || defined (__CYGWIN__)
-#define RUMPUSER_RANDOM() random()
-#define RUMPUSER_USE_DEVRANDOM
-#else
-#define RUMPUSER_RANDOM() arc4random()
+#if (defined(__NetBSD__) && __NetBSD_Version__ > 600000000) || \
+  defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
+#define PLATFORM_HAS_ARC4RANDOM_BUF
 #endif
 
 #ifndef __NetBSD_Prereq__

Index: src/lib/librumpuser/rumpuser_pth.c
diff -u src/lib/librumpuser/rumpuser_pth.c:1.40 src/lib/librumpuser/rumpuser_pth.c:1.40.2.1
--- src/lib/librumpuser/rumpuser_pth.c:1.40	Wed Apr  2 17:09:23 2014
+++ src/lib/librumpuser/rumpuser_pth.c	Sun Aug 10 06:52:26 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: rumpuser_pth.c,v 1.40 2014/04/02 17:09:23 justin Exp $	*/
+/*	$NetBSD: rumpuser_pth.c,v 1.40.2.1 2014/08/10 06:52:26 tls Exp $	*/
 
 /*
  * Copyright (c) 2007-2010 Antti Kantee.  All Rights Reserved.
@@ -28,7 +28,7 @@
 #include "rumpuser_port.h"
 
 #if !defined(lint)
-__RCSID("$NetBSD: rumpuser_pth.c,v 1.40 2014/04/02 17:09:23 justin Exp $");
+__RCSID("$NetBSD: rumpuser_pth.c,v 1.40.2.1 2014/08/10 06:52:26 tls Exp $");
 #endif /* !lint */
 
 #include <sys/queue.h>

Index: src/lib/librumpuser/rumpuser_pth_dummy.c
diff -u src/lib/librumpuser/rumpuser_pth_dummy.c:1.16 src/lib/librumpuser/rumpuser_pth_dummy.c:1.16.4.1
--- src/lib/librumpuser/rumpuser_pth_dummy.c:1.16	Wed May 15 14:52:49 2013
+++ src/lib/librumpuser/rumpuser_pth_dummy.c	Sun Aug 10 06:52:26 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: rumpuser_pth_dummy.c,v 1.16 2013/05/15 14:52:49 pooka Exp $	*/
+/*	$NetBSD: rumpuser_pth_dummy.c,v 1.16.4.1 2014/08/10 06:52:26 tls Exp $	*/
 
 /*
  * Copyright (c) 2009 Antti Kantee.  All Rights Reserved.
@@ -27,9 +27,8 @@
 
 #include "rumpuser_port.h"
 
-#include <sys/cdefs.h>
 #if !defined(lint)
-__RCSID("$NetBSD: rumpuser_pth_dummy.c,v 1.16 2013/05/15 14:52:49 pooka Exp $");
+__RCSID("$NetBSD: rumpuser_pth_dummy.c,v 1.16.4.1 2014/08/10 06:52:26 tls Exp $");
 #endif /* !lint */
 
 #include <sys/time.h>

Index: src/lib/librumpuser/rumpuser_sp.c
diff -u src/lib/librumpuser/rumpuser_sp.c:1.63 src/lib/librumpuser/rumpuser_sp.c:1.63.2.1
--- src/lib/librumpuser/rumpuser_sp.c:1.63	Fri Feb 28 13:55:36 2014
+++ src/lib/librumpuser/rumpuser_sp.c	Sun Aug 10 06:52:26 2014
@@ -1,4 +1,4 @@
-/*      $NetBSD: rumpuser_sp.c,v 1.63 2014/02/28 13:55:36 pooka Exp $	*/
+/*      $NetBSD: rumpuser_sp.c,v 1.63.2.1 2014/08/10 06:52:26 tls Exp $	*/
 
 /*
  * Copyright (c) 2010, 2011 Antti Kantee.  All Rights Reserved.
@@ -37,7 +37,7 @@
 #include "rumpuser_port.h"
 
 #if !defined(lint)
-__RCSID("$NetBSD: rumpuser_sp.c,v 1.63 2014/02/28 13:55:36 pooka Exp $");
+__RCSID("$NetBSD: rumpuser_sp.c,v 1.63.2.1 2014/08/10 06:52:26 tls Exp $");
 #endif /* !lint */
 
 #include <sys/types.h>
@@ -957,6 +957,7 @@ schedulework(struct spclient *spc, enum 
 struct spservarg {
 	int sps_sock;
 	connecthook_fn sps_connhook;
+	struct lwp *sps_l;
 };
 
 static void
@@ -983,7 +984,7 @@ handlereq(struct spclient *spc)
 			comm[commlen] = '\0';
 
 			if ((error = lwproc_rfork(spc,
-			    RUMP_RFCFDG, comm)) != 0) {
+			    RUMP_RFFDG, comm)) != 0) {
 				shutdown(spc->spc_fd, SHUT_RDWR);
 			}
 
@@ -1193,6 +1194,8 @@ spserver(void *arg)
 	int rv;
 	unsigned int nfds, maxidx;
 
+	lwproc_switch(sarg->sps_l);
+
 	for (idx = 0; idx < MAXCLI; idx++) {
 		pfdlist[idx].fd = -1;
 		pfdlist[idx].events = POLLIN;
@@ -1317,6 +1320,7 @@ rumpuser_sp_init(const char *url,
 	pthread_t pt;
 	struct spservarg *sarg;
 	struct sockaddr *sap;
+	struct lwp *calllwp;
 	char *p;
 	unsigned idx = 0; /* XXXgcc */
 	int error, s;
@@ -1361,13 +1365,28 @@ rumpuser_sp_init(const char *url,
 		fprintf(stderr, "rump_sp: server bind failed\n");
 		goto out;
 	}
-
 	if (listen(s, MAXCLI) == -1) {
 		error = errno;
 		fprintf(stderr, "rump_sp: server listen failed\n");
 		goto out;
 	}
 
+	/*
+	 * Create a context that the client threads run off of.
+	 * We fork a dedicated context so as to ensure that all
+	 * client threads get the same set of fd's.  We fork off
+	 * of whatever context the caller is running in (most likely
+	 * an implicit thread, i.e. proc 1) and do not
+	 * close fd's.  The assumption is that people who
+	 * write servers (i.e. "kernels") know what they're doing.
+	 */
+	calllwp = lwproc_curlwp();
+	if ((error = lwproc_rfork(NULL, RUMP_RFFDG, "spserver")) != 0) {
+		fprintf(stderr, "rump_sp: rfork failed");
+		goto out;
+	}
+	sarg->sps_l = lwproc_curlwp();
+	lwproc_switch(calllwp);
 	if ((error = pthread_create(&pt, NULL, spserver, sarg)) != 0) {
 		fprintf(stderr, "rump_sp: cannot create wrkr thread\n");
 		goto out;
@@ -1389,8 +1408,8 @@ rumpuser_sp_fini(void *arg)
 	}
 
 	/*
-	 * stuff response into the socket, since this process is just
-	 * about to exit
+	 * stuff response into the socket, since the rump kernel container
+	 * is just about to exit
 	 */
 	if (spc && spc->spc_syscallreq)
 		send_syscall_resp(spc, spc->spc_syscallreq, 0, retval);
@@ -1399,4 +1418,9 @@ rumpuser_sp_fini(void *arg)
 		shutdown(spclist[0].spc_fd, SHUT_RDWR);
 		spfini = 1;
 	}
+
+	/*
+	 * could release thread, but don't bother, since the container
+	 * will be stone dead in a moment.
+	 */
 }

Added files:

Index: src/lib/librumpuser/rumpfiber.c
diff -u /dev/null src/lib/librumpuser/rumpfiber.c:1.3.2.2
--- /dev/null	Sun Aug 10 06:52:26 2014
+++ src/lib/librumpuser/rumpfiber.c	Sun Aug 10 06:52:25 2014
@@ -0,0 +1,1012 @@
+/*
+ * Copyright (c) 2007-2013 Antti Kantee.  All Rights Reserved.
+ * Copyright (c) 2014 Justin Cormack.  All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* Based partly on code from Xen Minios with the following license */
+
+/* 
+ ****************************************************************************
+ * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
+ ****************************************************************************
+ *
+ *        File: sched.c
+ *      Author: Grzegorz Milos
+ *     Changes: Robert Kaiser
+ *              
+ *        Date: Aug 2005
+ * 
+ * Environment: Xen Minimal OS
+ * Description: simple scheduler for Mini-Os
+ *
+ * The scheduler is non-preemptive (cooperative), and schedules according 
+ * to Round Robin algorithm.
+ *
+ ****************************************************************************
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "rumpuser_port.h"
+
+#if !defined(lint)
+__RCSID("$NetBSD: rumpfiber.c,v 1.3.2.2 2014/08/10 06:52:25 tls Exp $");
+#endif /* !lint */
+
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <rump/rumpuser.h>
+
+#include "rumpuser_int.h"
+#include "rumpfiber.h"
+
+static void init_sched(void);
+static void join_thread(struct thread *);
+static void switch_threads(struct thread *prev, struct thread *next);
+static struct thread *get_current(void);
+static int64_t now(void);
+static void msleep(uint64_t millisecs);
+static void abssleep(uint64_t millisecs);
+
+TAILQ_HEAD(thread_list, thread);
+
+static struct thread_list exited_threads = TAILQ_HEAD_INITIALIZER(exited_threads);
+static struct thread_list thread_list = TAILQ_HEAD_INITIALIZER(thread_list);
+static struct thread *current_thread = NULL;
+
+static void (*scheduler_hook)(void *, void *);
+
+static struct thread *
+get_current(void)
+{
+
+	return current_thread;
+}
+
+static int64_t
+now(void)
+{
+	struct timespec ts;
+
+	clock_gettime(CLOCK_MONOTONIC, &ts);
+	return (ts.tv_sec * 1000LL) + (ts.tv_nsec / 1000000LL);
+}
+
+void
+schedule(void)
+{
+	struct thread *prev, *next, *thread, *tmp;
+	int64_t tm, wakeup;
+	struct timespec sl;
+
+	prev = get_current();
+
+	do {
+		tm = now();	
+		wakeup = tm + 1000; /* wake up in 1s max */
+		next = NULL;
+		TAILQ_FOREACH_SAFE(thread, &thread_list, thread_list, tmp) {
+			if (!is_runnable(thread) && thread->wakeup_time >= 0) {
+				if (thread->wakeup_time <= tm) {
+					thread->flags |= THREAD_TIMEDOUT;
+					wake(thread);
+				} else if (thread->wakeup_time < wakeup)
+					wakeup = thread->wakeup_time;
+			}
+			if (is_runnable(thread)) {
+				next = thread;
+				/* Put this thread on the end of the list */
+				TAILQ_REMOVE(&thread_list, thread, thread_list);
+				TAILQ_INSERT_TAIL(&thread_list, thread, thread_list);
+				break;
+			}
+		}
+		if (next)
+			break;
+		sl.tv_sec = (wakeup - tm) / 1000;
+		sl.tv_nsec = ((wakeup - tm) - 1000 * sl.tv_sec) * 1000000;
+#ifdef HAVE_CLOCK_NANOSLEEP
+		clock_nanosleep(CLOCK_MONOTONIC, 0, &sl, NULL);
+#else
+		nanosleep(&sl, NULL);
+#endif
+	} while (1);
+
+	if (prev != next)
+		switch_threads(prev, next);
+
+	TAILQ_FOREACH_SAFE(thread, &exited_threads, thread_list, tmp) {
+		if (thread != prev) {
+			TAILQ_REMOVE(&exited_threads, thread, thread_list);
+			if ((thread->flags & THREAD_EXTSTACK) == 0)
+				munmap(thread->ctx.uc_stack.ss_sp, STACKSIZE);
+			free(thread->name);
+			free(thread);
+		}
+	}
+}
+
+static void
+create_ctx(ucontext_t *ctx, void *stack, size_t stack_size)
+{
+
+	getcontext(ctx);
+	ctx->uc_stack.ss_sp = stack;
+	ctx->uc_stack.ss_size = stack_size;
+	ctx->uc_stack.ss_flags = 0;
+	ctx->uc_link = NULL; /* TODO may link to main thread */
+}
+
+/* may have to do bounce function to call, if args to makecontext are ints */
+/* TODO see notes in rumpuser_thread_create, have flags here */
+struct thread *
+create_thread(const char *name, void *cookie, void (*f)(void *), void *data,
+	void *stack, size_t stack_size)
+{
+	struct thread *thread = calloc(1, sizeof(struct thread));
+
+	if (!stack) {
+		assert(stack_size == 0);
+		stack = mmap(NULL, STACKSIZE, PROT_READ | PROT_WRITE,
+		    MAP_SHARED | MAP_ANON, -1, 0);
+		if (stack == MAP_FAILED) {
+			return NULL;
+		}
+		stack_size = STACKSIZE;
+	} else {
+		thread->flags = THREAD_EXTSTACK;
+	}
+	create_ctx(&thread->ctx, stack, stack_size);
+	makecontext(&thread->ctx, (void (*)(void))f, 1, data);
+	
+	thread->name = strdup(name);
+	thread->cookie = cookie;
+
+	/* Not runnable, not exited, not sleeping */
+	thread->wakeup_time = -1;
+	thread->lwp = NULL;
+	set_runnable(thread);
+	TAILQ_INSERT_TAIL(&thread_list, thread, thread_list);
+
+	return thread;
+}
+
+static void
+switch_threads(struct thread *prev, struct thread *next)
+{
+	int ret;
+
+	current_thread = next;
+	if (scheduler_hook)
+		scheduler_hook(prev->cookie, next->cookie);
+	ret = swapcontext(&prev->ctx, &next->ctx);
+	if (ret < 0) {
+		printk("swapcontext failed\n");
+		abort();
+	}
+}
+
+struct join_waiter {
+    struct thread *jw_thread;
+    struct thread *jw_wanted;
+    TAILQ_ENTRY(join_waiter) jw_entries;
+};
+static TAILQ_HEAD(, join_waiter) joinwq = TAILQ_HEAD_INITIALIZER(joinwq);
+
+void
+exit_thread(void)
+{
+	struct thread *thread = get_current();
+	struct join_waiter *jw_iter;
+
+	/* if joinable, gate until we are allowed to exit */
+	while (thread->flags & THREAD_MUSTJOIN) {
+		thread->flags |= THREAD_JOINED;
+
+		/* see if the joiner is already there */
+		TAILQ_FOREACH(jw_iter, &joinwq, jw_entries) {
+			if (jw_iter->jw_wanted == thread) {
+				wake(jw_iter->jw_thread);
+				break;
+			}
+		}
+		block(thread);
+		schedule();
+	}
+
+	/* Remove from the thread list */
+	TAILQ_REMOVE(&thread_list, thread, thread_list);
+	clear_runnable(thread);
+	/* Put onto exited list */
+	TAILQ_INSERT_HEAD(&exited_threads, thread, thread_list);
+
+	/* Schedule will free the resources */
+	while (1) {
+		schedule();
+		printk("schedule() returned!  Trying again\n");
+	}
+}
+
+static void
+join_thread(struct thread *joinable)
+{
+	struct join_waiter jw;
+	struct thread *thread = get_current();
+
+	assert(joinable->flags & THREAD_MUSTJOIN);
+
+	/* wait for exiting thread to hit thread_exit() */
+	while (! (joinable->flags & THREAD_JOINED)) {
+
+		jw.jw_thread = thread;
+		jw.jw_wanted = joinable;
+		TAILQ_INSERT_TAIL(&joinwq, &jw, jw_entries);
+		block(thread);
+		schedule();
+		TAILQ_REMOVE(&joinwq, &jw, jw_entries);
+	}
+
+	/* signal exiting thread that we have seen it and it may now exit */
+	assert(joinable->flags & THREAD_JOINED);
+	joinable->flags &= ~THREAD_MUSTJOIN;
+
+	wake(joinable);
+}
+
+static void msleep(uint64_t millisecs)
+{
+	struct thread *thread = get_current();
+
+	thread->wakeup_time = now() + millisecs;
+	clear_runnable(thread);
+	schedule();
+}
+
+static void abssleep(uint64_t millisecs)
+{
+	struct thread *thread = get_current();
+
+	thread->wakeup_time = millisecs;
+	clear_runnable(thread);
+	schedule();
+}
+
+/* like abssleep, except against realtime clock instead of monotonic clock */
+int abssleep_real(uint64_t millisecs)
+{
+	struct thread *thread = get_current();
+	struct timespec ts;
+	uint64_t real_now;
+	int rv;
+
+	clock_gettime(CLOCK_REALTIME, &ts);
+	real_now = 1000*ts.tv_sec + ts.tv_nsec/(1000*1000);
+	thread->wakeup_time = now() + (millisecs - real_now);
+
+	clear_runnable(thread);
+	schedule();
+
+	rv = !!(thread->flags & THREAD_TIMEDOUT);
+	thread->flags &= ~THREAD_TIMEDOUT;
+	return rv;
+}
+
+void wake(struct thread *thread)
+{
+
+	thread->wakeup_time = -1;
+	set_runnable(thread);
+}
+
+void block(struct thread *thread)
+{
+
+	thread->wakeup_time = -1;
+	clear_runnable(thread);
+}
+
+int is_runnable(struct thread *thread)
+{
+
+	return thread->flags & RUNNABLE_FLAG;
+}
+
+void set_runnable(struct thread *thread)
+{
+
+	thread->flags |= RUNNABLE_FLAG;
+}
+
+void clear_runnable(struct thread *thread)
+{
+
+	thread->flags &= ~RUNNABLE_FLAG;
+}
+
+static void
+init_sched(void)
+{
+	struct thread *thread = calloc(1, sizeof(struct thread));
+
+	getcontext(&thread->ctx);
+	thread->name = strdup("init");
+	thread->flags = 0;
+	thread->wakeup_time = -1;
+	thread->lwp = NULL;
+	set_runnable(thread);
+	TAILQ_INSERT_TAIL(&thread_list, thread, thread_list);
+	current_thread = thread;
+}
+
+void
+set_sched_hook(void (*f)(void *, void *))
+{
+
+	scheduler_hook = f;
+}
+
+struct thread *
+init_mainthread(void *cookie)
+{
+
+	current_thread->cookie = cookie;
+	return current_thread;
+}
+
+/* rump functions below */
+
+struct rumpuser_hyperup rumpuser__hyp;
+
+int
+rumpuser_init(int version, const struct rumpuser_hyperup *hyp)
+{
+	int rv;
+
+	if (version != RUMPUSER_VERSION) {
+		printk("rumpuser version mismatch\n");
+		abort();
+	}
+
+	rv = rumpuser__random_init();
+	if (rv != 0) {
+		ET(rv);
+	}
+
+        rumpuser__hyp = *hyp;
+
+	init_sched();
+
+        return 0;
+}
+
+int
+rumpuser_clock_gettime(int enum_rumpclock, int64_t *sec, long *nsec)
+{
+	enum rumpclock rclk = enum_rumpclock;
+	struct timespec ts;
+	clockid_t clk;
+	int rv;
+
+	switch (rclk) {
+	case RUMPUSER_CLOCK_RELWALL:
+		clk = CLOCK_REALTIME;
+		break;
+	case RUMPUSER_CLOCK_ABSMONO:
+		clk = CLOCK_MONOTONIC;
+		break;
+	default:
+		abort();
+	}
+
+	if (clock_gettime(clk, &ts) == -1) {
+		rv = errno;
+	} else {
+		*sec = ts.tv_sec;
+		*nsec = ts.tv_nsec;
+		rv = 0;
+	}
+
+	ET(rv);
+}
+
+int
+rumpuser_clock_sleep(int enum_rumpclock, int64_t sec, long nsec)
+{
+	enum rumpclock rclk = enum_rumpclock;
+	uint32_t msec;
+	int nlocks;
+
+	rumpkern_unsched(&nlocks, NULL);
+	switch (rclk) {
+	case RUMPUSER_CLOCK_RELWALL:
+		msec = sec * 1000 + nsec / (1000*1000UL);
+		msleep(msec);
+		break;
+	case RUMPUSER_CLOCK_ABSMONO:
+		msec = sec * 1000 + nsec / (1000*1000UL);
+		abssleep(msec);
+		break;
+	}
+	rumpkern_sched(nlocks, NULL);
+
+	return 0;
+}
+
+int
+rumpuser_getparam(const char *name, void *buf, size_t blen)
+{
+	int rv;
+	const char *ncpu = "1";
+
+	if (strcmp(name, RUMPUSER_PARAM_NCPU) == 0) {
+		strncpy(buf, ncpu, blen);
+		rv = 0;
+	} else if (strcmp(name, RUMPUSER_PARAM_HOSTNAME) == 0) {
+		char tmp[MAXHOSTNAMELEN];
+
+		if (gethostname(tmp, sizeof(tmp)) == -1) {
+			snprintf(buf, blen, "rump-%05d", (int)getpid());
+		} else {
+			snprintf(buf, blen, "rump-%05d.%s",
+			    (int)getpid(), tmp);
+		}
+		rv = 0;
+	} else if (*name == '_') {
+		rv = EINVAL;
+	} else {
+		if (getenv_r(name, buf, blen) == -1)
+			rv = errno;
+		else
+			rv = 0;
+	}
+
+	ET(rv);
+}
+
+void
+rumpuser_putchar(int c)
+{
+
+	putchar(c);
+}
+
+__dead void
+rumpuser_exit(int rv)
+{
+
+	if (rv == RUMPUSER_PANIC)
+		abort();
+	else
+		exit(rv);
+}
+
+void
+rumpuser_seterrno(int error)
+{
+
+	errno = error;
+}
+
+/*
+ * This is meant for safe debugging prints from the kernel.
+ */
+void
+rumpuser_dprintf(const char *format, ...)
+{
+	va_list ap;
+
+	va_start(ap, format);
+	vfprintf(stderr, format, ap);
+	va_end(ap);
+}
+
+int
+rumpuser_kill(int64_t pid, int rumpsig)
+{
+	int sig;
+
+	sig = rumpuser__sig_rump2host(rumpsig);
+	if (sig > 0)
+		raise(sig);
+	return 0;
+}
+
+/* thread functions */
+
+TAILQ_HEAD(waithead, waiter);
+struct waiter {
+	struct thread *who;
+	TAILQ_ENTRY(waiter) entries;
+	int onlist;
+};
+
+static int
+wait(struct waithead *wh, uint64_t msec)
+{
+	struct waiter w;
+
+	w.who = get_current();
+	TAILQ_INSERT_TAIL(wh, &w, entries);
+	w.onlist = 1;
+	block(w.who);
+	if (msec)
+		w.who->wakeup_time = now() + msec;
+	schedule();
+
+	/* woken up by timeout? */
+	if (w.onlist)
+		TAILQ_REMOVE(wh, &w, entries);
+
+	return w.onlist ? ETIMEDOUT : 0;
+}
+
+static void
+wakeup_one(struct waithead *wh)
+{
+	struct waiter *w;
+
+	if ((w = TAILQ_FIRST(wh)) != NULL) {
+		TAILQ_REMOVE(wh, w, entries);
+		w->onlist = 0;
+		wake(w->who);
+	}
+}
+
+static void
+wakeup_all(struct waithead *wh)
+{
+	struct waiter *w;
+
+	while ((w = TAILQ_FIRST(wh)) != NULL) {
+		TAILQ_REMOVE(wh, w, entries);
+		w->onlist = 0;
+		wake(w->who);
+	}
+}
+
+int
+rumpuser_thread_create(void *(*f)(void *), void *arg, const char *thrname,
+        int joinable, int pri, int cpuidx, void **tptr)
+{
+        struct thread *thr;
+
+        thr = create_thread(thrname, NULL, (void (*)(void *))f, arg, NULL, 0);
+        /*
+         * XXX: should be supplied as a flag to create_thread() so as to
+         * _ensure_ it's set before the thread runs (and could exit).
+         * now we're trusting unclear semantics of create_thread()
+         */
+        if (thr && joinable)
+                thr->flags |= THREAD_MUSTJOIN;
+
+        if (!thr)
+                return EINVAL;
+
+        *tptr = thr;
+        return 0;
+}
+
+void
+rumpuser_thread_exit(void)
+{
+
+        exit_thread();
+}
+
+int
+rumpuser_thread_join(void *p)
+{
+
+        join_thread(p);
+        return 0;
+}
+
+struct rumpuser_mtx {
+	struct waithead waiters;
+	int v;
+	int flags;
+	struct lwp *o;
+};
+
+void
+rumpuser_mutex_init(struct rumpuser_mtx **mtxp, int flags)
+{
+	struct rumpuser_mtx *mtx;
+
+	mtx = malloc(sizeof(*mtx));
+	memset(mtx, 0, sizeof(*mtx));
+	mtx->flags = flags;
+	TAILQ_INIT(&mtx->waiters);
+	*mtxp = mtx;
+}
+
+void
+rumpuser_mutex_enter(struct rumpuser_mtx *mtx)
+{
+	int nlocks;
+
+	if (rumpuser_mutex_tryenter(mtx) != 0) {
+		rumpkern_unsched(&nlocks, NULL);
+		while (rumpuser_mutex_tryenter(mtx) != 0)
+			wait(&mtx->waiters, 0);
+		rumpkern_sched(nlocks, NULL);
+	}
+}
+
+void
+rumpuser_mutex_enter_nowrap(struct rumpuser_mtx *mtx)
+{
+	int rv;
+
+	rv = rumpuser_mutex_tryenter(mtx);
+	/* one VCPU supported, no preemption => must succeed */
+	if (rv != 0) {
+		printk("no voi ei\n");
+	}
+}
+
+int
+rumpuser_mutex_tryenter(struct rumpuser_mtx *mtx)
+{
+	struct lwp *l = get_current()->lwp;
+
+	if (mtx->v && mtx->o != l)
+		return EBUSY;
+
+	mtx->v++;
+	mtx->o = l;
+
+	return 0;
+}
+
+void
+rumpuser_mutex_exit(struct rumpuser_mtx *mtx)
+{
+
+	assert(mtx->v > 0);
+	if (--mtx->v == 0) {
+		mtx->o = NULL;
+		wakeup_one(&mtx->waiters);
+	}
+}
+
+void
+rumpuser_mutex_destroy(struct rumpuser_mtx *mtx)
+{
+
+	assert(TAILQ_EMPTY(&mtx->waiters) && mtx->o == NULL);
+	free(mtx);
+}
+
+void
+rumpuser_mutex_owner(struct rumpuser_mtx *mtx, struct lwp **lp)
+{
+
+	*lp = mtx->o;
+}
+
+struct rumpuser_rw {
+	struct waithead rwait;
+	struct waithead wwait;
+	int v;
+	struct lwp *o;
+};
+
+void
+rumpuser_rw_init(struct rumpuser_rw **rwp)
+{
+	struct rumpuser_rw *rw;
+
+	rw = malloc(sizeof(*rw));
+	memset(rw, 0, sizeof(*rw));
+	TAILQ_INIT(&rw->rwait);
+	TAILQ_INIT(&rw->wwait);
+
+	*rwp = rw;
+}
+
+void
+rumpuser_rw_enter(int enum_rumprwlock, struct rumpuser_rw *rw)
+{
+	enum rumprwlock lk = enum_rumprwlock;
+	struct waithead *w = NULL;
+	int nlocks;
+
+	switch (lk) {
+	case RUMPUSER_RW_WRITER:
+		w = &rw->wwait;
+		break;
+	case RUMPUSER_RW_READER:
+		w = &rw->rwait;
+		break;
+	}
+
+	if (rumpuser_rw_tryenter(enum_rumprwlock, rw) != 0) {
+		rumpkern_unsched(&nlocks, NULL);
+		while (rumpuser_rw_tryenter(enum_rumprwlock, rw) != 0)
+			wait(w, 0);
+		rumpkern_sched(nlocks, NULL);
+	}
+}
+
+int
+rumpuser_rw_tryenter(int enum_rumprwlock, struct rumpuser_rw *rw)
+{
+	enum rumprwlock lk = enum_rumprwlock;
+	int rv;
+
+	switch (lk) {
+	case RUMPUSER_RW_WRITER:
+		if (rw->o == NULL) {
+			rw->o = rumpuser_curlwp();
+			rv = 0;
+		} else {
+			rv = EBUSY;
+		}
+		break;
+	case RUMPUSER_RW_READER:
+		if (rw->o == NULL && TAILQ_EMPTY(&rw->wwait)) {
+			rw->v++;
+			rv = 0;
+		} else {
+			rv = EBUSY;
+		}
+		break;
+	default:
+		rv = EINVAL;
+	}
+
+	return rv;
+}
+
+void
+rumpuser_rw_exit(struct rumpuser_rw *rw)
+{
+
+	if (rw->o) {
+		rw->o = NULL;
+	} else {
+		rw->v--;
+	}
+
+	/* standard procedure, don't let readers starve out writers */
+	if (!TAILQ_EMPTY(&rw->wwait)) {
+		if (rw->o == NULL)
+			wakeup_one(&rw->wwait);
+	} else if (!TAILQ_EMPTY(&rw->rwait) && rw->o == NULL) {
+		wakeup_all(&rw->rwait);
+	}
+}
+
+void
+rumpuser_rw_destroy(struct rumpuser_rw *rw)
+{
+
+	free(rw);
+}
+
+void
+rumpuser_rw_held(int enum_rumprwlock, struct rumpuser_rw *rw, int *rvp)
+{
+	enum rumprwlock lk = enum_rumprwlock;
+
+	switch (lk) {
+	case RUMPUSER_RW_WRITER:
+		*rvp = rw->o == rumpuser_curlwp();
+		break;
+	case RUMPUSER_RW_READER:
+		*rvp = rw->v > 0;
+		break;
+	}
+}
+
+void
+rumpuser_rw_downgrade(struct rumpuser_rw *rw)
+{
+
+	assert(rw->o == rumpuser_curlwp());
+	rw->v = -1;
+}
+
+int
+rumpuser_rw_tryupgrade(struct rumpuser_rw *rw)
+{
+
+	if (rw->v == -1) {
+		rw->v = 1;
+		rw->o = rumpuser_curlwp();
+		return 0;
+	}
+
+	return EBUSY;
+}
+
+struct rumpuser_cv {
+	struct waithead waiters;
+	int nwaiters;
+};
+
+void
+rumpuser_cv_init(struct rumpuser_cv **cvp)
+{
+	struct rumpuser_cv *cv;
+
+	cv = malloc(sizeof(*cv));
+	memset(cv, 0, sizeof(*cv));
+	TAILQ_INIT(&cv->waiters);
+	*cvp = cv;
+}
+
+void
+rumpuser_cv_destroy(struct rumpuser_cv *cv)
+{
+
+	assert(cv->nwaiters == 0);
+	free(cv);
+}
+
+static void
+cv_unsched(struct rumpuser_mtx *mtx, int *nlocks)
+{
+
+	rumpkern_unsched(nlocks, mtx);
+	rumpuser_mutex_exit(mtx);
+}
+
+static void
+cv_resched(struct rumpuser_mtx *mtx, int nlocks)
+{
+
+	/* see rumpuser(3) */
+	if ((mtx->flags & (RUMPUSER_MTX_KMUTEX | RUMPUSER_MTX_SPIN)) ==
+	    (RUMPUSER_MTX_KMUTEX | RUMPUSER_MTX_SPIN)) {
+		rumpkern_sched(nlocks, mtx);
+		rumpuser_mutex_enter_nowrap(mtx);
+	} else {
+		rumpuser_mutex_enter_nowrap(mtx);
+		rumpkern_sched(nlocks, mtx);
+	}
+}
+
+void
+rumpuser_cv_wait(struct rumpuser_cv *cv, struct rumpuser_mtx *mtx)
+{
+	int nlocks;
+
+	cv->nwaiters++;
+	cv_unsched(mtx, &nlocks);
+	wait(&cv->waiters, 0);
+	cv_resched(mtx, nlocks);
+	cv->nwaiters--;
+}
+
+void
+rumpuser_cv_wait_nowrap(struct rumpuser_cv *cv, struct rumpuser_mtx *mtx)
+{
+
+	cv->nwaiters++;
+	rumpuser_mutex_exit(mtx);
+	wait(&cv->waiters, 0);
+	rumpuser_mutex_enter_nowrap(mtx);
+	cv->nwaiters--;
+}
+
+int
+rumpuser_cv_timedwait(struct rumpuser_cv *cv, struct rumpuser_mtx *mtx,
+	int64_t sec, int64_t nsec)
+{
+	int nlocks;
+	int rv;
+
+	cv->nwaiters++;
+	cv_unsched(mtx, &nlocks);
+	rv = wait(&cv->waiters, sec * 1000 + nsec / (1000*1000));
+	cv_resched(mtx, nlocks);
+	cv->nwaiters--;
+
+	return rv;
+}
+
+void
+rumpuser_cv_signal(struct rumpuser_cv *cv)
+{
+
+	wakeup_one(&cv->waiters);
+}
+
+void
+rumpuser_cv_broadcast(struct rumpuser_cv *cv)
+{
+
+	wakeup_all(&cv->waiters);
+}
+
+void
+rumpuser_cv_has_waiters(struct rumpuser_cv *cv, int *rvp)
+{
+
+	*rvp = cv->nwaiters != 0;
+}
+
+/*
+ * curlwp
+ */
+
+void
+rumpuser_curlwpop(int enum_rumplwpop, struct lwp *l)
+{
+	struct thread *thread;
+	enum rumplwpop op = enum_rumplwpop;
+
+	switch (op) {
+	case RUMPUSER_LWP_CREATE:
+	case RUMPUSER_LWP_DESTROY:
+		break;
+	case RUMPUSER_LWP_SET:
+		thread = get_current();
+		thread->lwp = l;
+		break;
+	case RUMPUSER_LWP_CLEAR:
+		thread = get_current();
+		assert(thread->lwp == l);
+		thread->lwp = NULL;
+		break;
+	}
+}
+
+struct lwp *
+rumpuser_curlwp(void)
+{
+
+	return get_current()->lwp;
+}

Index: src/lib/librumpuser/rumpfiber.h
diff -u /dev/null src/lib/librumpuser/rumpfiber.h:1.1.2.2
--- /dev/null	Sun Aug 10 06:52:26 2014
+++ src/lib/librumpuser/rumpfiber.h	Sun Aug 10 06:52:25 2014
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2014 Justin Cormack.  All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/queue.h>
+
+#include <stdint.h>
+#include <string.h>
+#include <time.h>
+#include <ucontext.h>
+#include <unistd.h>
+
+static void printk(const char *s);
+
+static void
+printk(const char *msg)
+{
+	int ret __attribute__((unused));
+
+	ret = write(2, msg, strlen(msg));
+}
+
+struct thread {
+    char *name;
+    void *lwp;
+    void *cookie;
+    int64_t wakeup_time;
+    TAILQ_ENTRY(thread) thread_list;
+    ucontext_t ctx;
+    uint32_t flags;
+    int threrrno;
+};
+
+#define RUNNABLE_FLAG   0x00000001
+#define THREAD_MUSTJOIN 0x00000002
+#define THREAD_JOINED   0x00000004
+#define THREAD_EXTSTACK 0x00000008
+#define THREAD_TIMEDOUT 0x00000010
+
+#define STACKSIZE 65536
+
+/* used by experimental _lwp code */
+void schedule(void);
+void wake(struct thread *thread);
+void block(struct thread *thread);
+struct thread *init_mainthread(void *);
+void exit_thread(void) __attribute__((noreturn));
+void set_sched_hook(void (*f)(void *, void *));
+int abssleep_real(uint64_t millisecs);
+struct thread* create_thread(const char *name, void *cookie,
+			     void (*f)(void *), void *data,
+			     void *stack, size_t stack_size);
+int is_runnable(struct thread *);
+void set_runnable(struct thread *);
+void clear_runnable(struct thread *);
+
Index: src/lib/librumpuser/rumpfiber_bio.c
diff -u /dev/null src/lib/librumpuser/rumpfiber_bio.c:1.1.2.2
--- /dev/null	Sun Aug 10 06:52:26 2014
+++ src/lib/librumpuser/rumpfiber_bio.c	Sun Aug 10 06:52:25 2014
@@ -0,0 +1,65 @@
+/*-
+ * Copyright (c) 2014 Antti Kantee.  All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "rumpuser_port.h"
+
+#if !defined(lint)
+__RCSID("$NetBSD: rumpfiber_bio.c,v 1.1.2.2 2014/08/10 06:52:25 tls Exp $");
+#endif /* !lint */
+
+#include <sys/types.h>
+
+#include <stdint.h>
+#include <unistd.h>
+
+#include <rump/rumpuser.h>
+
+#include "rumpuser_int.h"
+
+void
+rumpuser_bio(int fd, int op, void *data, size_t dlen, int64_t doff,
+	rump_biodone_fn biodone, void *bioarg)
+{
+	ssize_t rv;
+	int error = 0;
+
+	if (op & RUMPUSER_BIO_READ) {
+		if ((rv = pread(fd, data, dlen, doff)) == -1)
+			error = errno;
+	} else {
+		if ((rv = pwrite(fd, data, dlen, doff)) == -1)
+			error = errno;
+		if (error == 0 && (op & RUMPUSER_BIO_SYNC)) {
+#ifdef __NetBSD__
+			fsync_range(fd, FDATASYNC, doff, dlen);
+#else
+			fsync(fd);
+#endif
+		}
+	}
+	if (rv == -1)
+		rv = 0;
+	biodone(bioarg, (size_t)rv, error);
+}
Index: src/lib/librumpuser/rumpfiber_sp.c
diff -u /dev/null src/lib/librumpuser/rumpfiber_sp.c:1.1.2.2
--- /dev/null	Sun Aug 10 06:52:26 2014
+++ src/lib/librumpuser/rumpfiber_sp.c	Sun Aug 10 06:52:25 2014
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2014 Justin Cormack.  All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* stubs for sp functions as not supported for fibers yet */
+
+#include "rumpuser_port.h"
+
+#if !defined(lint)
+__RCSID("$NetBSD: rumpfiber_sp.c,v 1.1.2.2 2014/08/10 06:52:25 tls Exp $");
+#endif /* !lint */
+
+#include <stdlib.h>
+
+#include <rump/rumpuser.h>
+
+#include "rumpfiber.h"
+
+/*ARGSUSED*/
+int
+rumpuser_sp_init(const char *url,
+	const char *ostype, const char *osrelease, const char *machine)
+{
+
+	return 0;
+}
+
+/*ARGSUSED*/
+void
+rumpuser_sp_fini(void *arg)
+{
+
+}
+
+/*ARGSUSED*/
+int
+rumpuser_sp_raise(void *arg, int signo)
+{
+
+	printk("rumphyper: unimplemented rumpuser_sp_raise\n");
+	exit(1);
+}
+
+/*ARGSUSED*/
+int
+rumpuser_sp_copyin(void *arg, const void *raddr, void *laddr, size_t len)
+{
+
+	printk("rumphyper: unimplemented rumpuser_sp_copyin\n");
+	exit(1);
+}
+
+/*ARGSUSED*/
+int
+rumpuser_sp_copyinstr(void *arg, const void *raddr, void *laddr, size_t *len)
+{
+
+	printk("rumphyper: unimplemented rumpuser_sp_copyinstr\n");
+	exit(1);
+}
+
+/*ARGSUSED*/
+int
+rumpuser_sp_copyout(void *arg, const void *laddr, void *raddr, size_t dlen)
+{
+
+	printk("rumphyper: unimplemented rumpuser_sp_copyout\n");
+	exit(1);
+}
+
+/*ARGSUSED*/
+int
+rumpuser_sp_copyoutstr(void *arg, const void *laddr, void *raddr, size_t *dlen)
+{
+
+	printk("rumphyper: unimplemented rumpuser_sp_copyoutstr\n");
+	exit(1);
+}
+
+/*ARGSUSED*/
+int
+rumpuser_sp_anonmmap(void *arg, size_t howmuch, void **addr)
+{
+
+	printk("rumphyper: unimplemented rumpuser_sp_anonmmap\n");
+	exit(1);
+}
Index: src/lib/librumpuser/rumpuser_file.c
diff -u /dev/null src/lib/librumpuser/rumpuser_file.c:1.1.2.2
--- /dev/null	Sun Aug 10 06:52:26 2014
+++ src/lib/librumpuser/rumpuser_file.c	Sun Aug 10 06:52:26 2014
@@ -0,0 +1,339 @@
+/*
+ * Copyright (c) 2007-2010 Antti Kantee.  All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* NOTE this code will move to a new driver in the next hypercall revision */
+
+#include "rumpuser_port.h"
+
+#if !defined(lint)
+__RCSID("$NetBSD: rumpuser_file.c,v 1.1.2.2 2014/08/10 06:52:26 tls Exp $");
+#endif /* !lint */
+
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/uio.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+#ifdef __NetBSD__
+#include <sys/disk.h>
+#include <sys/disklabel.h>
+#include <sys/dkio.h>
+#endif
+
+#if defined(__NetBSD__) || defined(__FreeBSD__) || \
+    defined(__DragonFly__) || defined(__APPLE__)
+#define	__BSD__
+#endif
+
+#if defined(__BSD__)
+#include <sys/sysctl.h>
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rump/rumpuser.h>
+
+#include "rumpuser_int.h"
+
+int
+rumpuser_getfileinfo(const char *path, uint64_t *sizep, int *ftp)
+{
+	struct stat sb;
+	uint64_t size = 0;
+	int needsdev = 0, rv = 0, ft = 0;
+	int fd = -1;
+
+	if (stat(path, &sb) == -1) {
+		rv = errno;
+		goto out;
+	}
+
+	switch (sb.st_mode & S_IFMT) {
+	case S_IFDIR:
+		ft = RUMPUSER_FT_DIR;
+		break;
+	case S_IFREG:
+		ft = RUMPUSER_FT_REG;
+		break;
+	case S_IFBLK:
+		ft = RUMPUSER_FT_BLK;
+		needsdev = 1;
+		break;
+	case S_IFCHR:
+		ft = RUMPUSER_FT_CHR;
+		needsdev = 1;
+		break;
+	default:
+		ft = RUMPUSER_FT_OTHER;
+		break;
+	}
+
+	if (!needsdev) {
+		size = sb.st_size;
+	} else if (sizep) {
+		/*
+		 * Welcome to the jungle.  Of course querying the kernel
+		 * for a device partition size is supposed to be far from
+		 * trivial.  On NetBSD we use ioctl.  On $other platform
+		 * we have a problem.  We try "the lseek trick" and just
+		 * fail if that fails.  Platform specific code can later
+		 * be written here if appropriate.
+		 *
+		 * On NetBSD we hope and pray that for block devices nobody
+		 * else is holding them open, because otherwise the kernel
+		 * will not permit us to open it.  Thankfully, this is
+		 * usually called only in bootstrap and then we can
+		 * forget about it.
+		 */
+#ifndef __NetBSD__
+		off_t off;
+
+		fd = open(path, O_RDONLY);
+		if (fd == -1) {
+			rv = errno;
+			goto out;
+		}
+
+		off = lseek(fd, 0, SEEK_END);
+		if (off != 0) {
+			size = off;
+			goto out;
+		}
+		fprintf(stderr, "error: device size query not implemented on "
+		    "this platform\n");
+		rv = EOPNOTSUPP;
+		goto out;
+#else
+		struct disklabel lab;
+		struct partition *parta;
+		struct dkwedge_info dkw;
+
+		fd = open(path, O_RDONLY);
+		if (fd == -1) {
+			rv = errno;
+			goto out;
+		}
+
+		if (ioctl(fd, DIOCGDINFO, &lab) == 0) {
+			parta = &lab.d_partitions[DISKPART(sb.st_rdev)];
+			size = (uint64_t)lab.d_secsize * parta->p_size;
+			goto out;
+		}
+
+		if (ioctl(fd, DIOCGWEDGEINFO, &dkw) == 0) {
+			/*
+			 * XXX: should use DIOCGDISKINFO to query
+			 * sector size, but that requires proplib,
+			 * so just don't bother for now.  it's nice
+			 * that something as difficult as figuring out
+			 * a partition's size has been made so easy.
+			 */
+			size = dkw.dkw_size << DEV_BSHIFT;
+			goto out;
+		}
+
+		rv = errno;
+#endif /* __NetBSD__ */
+	}
+
+ out:
+	if (rv == 0 && sizep)
+		*sizep = size;
+	if (rv == 0 && ftp)
+		*ftp = ft;
+	if (fd != -1)
+		close(fd);
+
+	ET(rv);
+}
+
+int
+rumpuser_open(const char *path, int ruflags, int *fdp)
+{
+	int fd, flags, rv;
+
+	switch (ruflags & RUMPUSER_OPEN_ACCMODE) {
+	case RUMPUSER_OPEN_RDONLY:
+		flags = O_RDONLY;
+		break;
+	case RUMPUSER_OPEN_WRONLY:
+		flags = O_WRONLY;
+		break;
+	case RUMPUSER_OPEN_RDWR:
+		flags = O_RDWR;
+		break;
+	default:
+		rv = EINVAL;
+		goto out;
+	}
+
+#define TESTSET(_ru_, _h_) if (ruflags & _ru_) flags |= _h_;
+	TESTSET(RUMPUSER_OPEN_CREATE, O_CREAT);
+	TESTSET(RUMPUSER_OPEN_EXCL, O_EXCL);
+#undef TESTSET
+
+	KLOCK_WRAP(fd = open(path, flags, 0644));
+	if (fd == -1) {
+		rv = errno;
+	} else {
+		*fdp = fd;
+		rv = 0;
+	}
+
+ out:
+	ET(rv);
+}
+
+int
+rumpuser_close(int fd)
+{
+	int nlocks;
+
+	rumpkern_unsched(&nlocks, NULL);
+	fsync(fd);
+	close(fd);
+	rumpkern_sched(nlocks, NULL);
+
+	ET(0);
+}
+
+/*
+ * Assume "struct rumpuser_iovec" and "struct iovec" are the same.
+ * If you encounter POSIX platforms where they aren't, add some
+ * translation for iovlen > 1.
+ */
+int
+rumpuser_iovread(int fd, struct rumpuser_iovec *ruiov, size_t iovlen,
+	int64_t roff, size_t *retp)
+{
+	struct iovec *iov = (struct iovec *)ruiov;
+	off_t off = (off_t)roff;
+	ssize_t nn;
+	int rv;
+
+	if (off == RUMPUSER_IOV_NOSEEK) {
+		KLOCK_WRAP(nn = readv(fd, iov, iovlen));
+	} else {
+		int nlocks;
+
+		rumpkern_unsched(&nlocks, NULL);
+		if (lseek(fd, off, SEEK_SET) == off) {
+			nn = readv(fd, iov, iovlen);
+		} else {
+			nn = -1;
+		}
+		rumpkern_sched(nlocks, NULL);
+	}
+
+	if (nn == -1) {
+		rv = errno;
+	} else {
+		*retp = (size_t)nn;
+		rv = 0;
+	}
+
+	ET(rv);
+}
+
+int
+rumpuser_iovwrite(int fd, const struct rumpuser_iovec *ruiov, size_t iovlen,
+	int64_t roff, size_t *retp)
+{
+	const struct iovec *iov = (const struct iovec *)ruiov;
+	off_t off = (off_t)roff;
+	ssize_t nn;
+	int rv;
+
+	if (off == RUMPUSER_IOV_NOSEEK) {
+		KLOCK_WRAP(nn = writev(fd, iov, iovlen));
+	} else {
+		int nlocks;
+
+		rumpkern_unsched(&nlocks, NULL);
+		if (lseek(fd, off, SEEK_SET) == off) {
+			nn = writev(fd, iov, iovlen);
+		} else {
+			nn = -1;
+		}
+		rumpkern_sched(nlocks, NULL);
+	}
+
+	if (nn == -1) {
+		rv = errno;
+	} else {
+		*retp = (size_t)nn;
+		rv = 0;
+	}
+
+	ET(rv);
+}
+
+int
+rumpuser_syncfd(int fd, int flags, uint64_t start, uint64_t len)
+{
+	int rv = 0;
+	
+	/*
+	 * For now, assume fd is regular file and does not care
+	 * about read syncing
+	 */
+	if ((flags & RUMPUSER_SYNCFD_BOTH) == 0) {
+		rv = EINVAL;
+		goto out;
+	}
+	if ((flags & RUMPUSER_SYNCFD_WRITE) == 0) {
+		rv = 0;
+		goto out;
+	}
+
+#ifdef __NetBSD__
+	{
+	int fsflags = FDATASYNC;
+
+	if (fsflags & RUMPUSER_SYNCFD_SYNC)
+		fsflags |= FDISKSYNC;
+	if (fsync_range(fd, fsflags, start, len) == -1)
+		rv = errno;
+	}
+#else
+	/* el-simplo */
+	if (fsync(fd) == -1)
+		rv = errno;
+#endif
+
+ out:
+	ET(rv);
+}
Index: src/lib/librumpuser/rumpuser_mem.c
diff -u /dev/null src/lib/librumpuser/rumpuser_mem.c:1.1.2.2
--- /dev/null	Sun Aug 10 06:52:26 2014
+++ src/lib/librumpuser/rumpuser_mem.c	Sun Aug 10 06:52:26 2014
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2007-2010 Antti Kantee.  All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "rumpuser_port.h"
+
+#if !defined(lint)
+__RCSID("$NetBSD: rumpuser_mem.c,v 1.1.2.2 2014/08/10 06:52:26 tls Exp $");
+#endif /* !lint */
+
+#include <sys/mman.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <rump/rumpuser.h>
+
+#include "rumpuser_int.h"
+
+int
+rumpuser_malloc(size_t howmuch, int alignment, void **memp)
+{
+	void *mem = NULL;
+	int rv;
+
+	if (alignment == 0)
+		alignment = sizeof(void *);
+
+	rv = posix_memalign(&mem, (size_t)alignment, howmuch);
+	if (__predict_false(rv != 0)) {
+		if (rv == EINVAL) {
+			printf("rumpuser_malloc: invalid alignment %d\n",
+			    alignment);
+			abort();
+		}
+	}
+
+	*memp = mem;
+	ET(rv);
+}
+
+/*ARGSUSED1*/
+void
+rumpuser_free(void *ptr, size_t size)
+{
+
+	free(ptr);
+}
+
+int
+rumpuser_anonmmap(void *prefaddr, size_t size, int alignbit,
+	int exec, void **memp)
+{
+	void *mem;
+	int prot, rv;
+
+#ifndef MAP_ALIGNED
+#define MAP_ALIGNED(a) 0
+	if (alignbit)
+		fprintf(stderr, "rumpuser_anonmmap: warning, requested "
+		    "alignment not supported by hypervisor\n");
+#endif
+
+	prot = PROT_READ|PROT_WRITE;
+	if (exec)
+		prot |= PROT_EXEC;
+	mem = mmap(prefaddr, size, prot,
+	    MAP_PRIVATE | MAP_ANON | MAP_ALIGNED(alignbit), -1, 0);
+	if (mem == MAP_FAILED) {
+		rv = errno;
+	} else {
+		*memp = mem;
+		rv = 0;
+	}
+
+	ET(rv);
+}
+
+void
+rumpuser_unmap(void *addr, size_t len)
+{
+
+	munmap(addr, len);
+}
+

Index: src/lib/librumpuser/rumpuser_random.c
diff -u /dev/null src/lib/librumpuser/rumpuser_random.c:1.2.2.2
--- /dev/null	Sun Aug 10 06:52:26 2014
+++ src/lib/librumpuser/rumpuser_random.c	Sun Aug 10 06:52:26 2014
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2014 Justin Cormack.  All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "rumpuser_port.h"
+
+#if !defined(lint)
+__RCSID("$NetBSD: rumpuser_random.c,v 1.2.2.2 2014/08/10 06:52:26 tls Exp $");
+#endif /* !lint */
+
+#include <sys/types.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rump/rumpuser.h>
+
+#include "rumpuser_int.h"
+
+static const size_t random_maxread = 32;
+
+#ifdef PLATFORM_HAS_ARC4RANDOM_BUF
+int
+rumpuser__random_init(void)
+{
+
+	return 0;
+}
+#else
+static const char *random_device = "/dev/urandom";
+static int random_fd = -1;
+
+int
+rumpuser__random_init(void)
+{
+
+	random_fd = open(random_device, O_RDONLY);
+	if (random_fd < 0) {
+		fprintf(stderr, "random init open failed\n");
+		return errno;
+	}
+	return 0;
+}
+#endif
+
+int
+rumpuser_getrandom(void *buf, size_t buflen, int flags, size_t *retp)
+{
+#ifndef PLATFORM_HAS_ARC4RANDOM_BUF
+	ssize_t rv;
+
+	rv = read(random_fd, buf, buflen > random_maxread ? random_maxread : buflen);
+	if (rv < 0) {
+		ET(errno);
+	}
+	*retp = rv;
+#else
+	buflen = buflen > random_maxread ? random_maxread : buflen;
+	arc4random_buf(buf, buflen);
+	*retp = buflen;
+#endif
+
+	return 0;
+}

Reply via email to