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; +}