Module Name: src
Committed By: pooka
Date: Fri Feb 26 18:54:21 UTC 2010
Modified Files:
src/lib/librumpuser: Makefile
src/sys/rump/librump: Makefile
Added Files:
src/lib/librumpuser: rumpuser.3 rumpuser.c rumpuser_dl.c rumpuser_int.h
rumpuser_net.c rumpuser_pth.c rumpuser_pth_dummy.c shlib_version
Removed Files:
src/sys/rump/librump/rumpuser: Makefile rumpuser.3 rumpuser.c
rumpuser_dl.c rumpuser_int.h rumpuser_net.c rumpuser_pth.c
rumpuser_pth_dummy.c
Log Message:
librumpuser is not _KERNEL code and does not belong in sys. Move
the source files from src/sys/rump/librump/rumpuser to src/lib/librumpuser
(from where it is already built). Even so, keep rumpuser.h in
sys/rump/include for kernel source tree self-containment.
To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 src/lib/librumpuser/Makefile
cvs rdiff -u -r0 -r1.1 src/lib/librumpuser/rumpuser.3 \
src/lib/librumpuser/rumpuser.c src/lib/librumpuser/rumpuser_dl.c \
src/lib/librumpuser/rumpuser_int.h src/lib/librumpuser/rumpuser_net.c \
src/lib/librumpuser/rumpuser_pth.c \
src/lib/librumpuser/rumpuser_pth_dummy.c \
src/lib/librumpuser/shlib_version
cvs rdiff -u -r1.7 -r1.8 src/sys/rump/librump/Makefile
cvs rdiff -u -r1.16 -r0 src/sys/rump/librump/rumpuser/Makefile
cvs rdiff -u -r1.1 -r0 src/sys/rump/librump/rumpuser/rumpuser.3
cvs rdiff -u -r1.49 -r0 src/sys/rump/librump/rumpuser/rumpuser.c
cvs rdiff -u -r1.12 -r0 src/sys/rump/librump/rumpuser/rumpuser_dl.c
cvs rdiff -u -r1.4 -r0 src/sys/rump/librump/rumpuser/rumpuser_int.h
cvs rdiff -u -r1.7 -r0 src/sys/rump/librump/rumpuser/rumpuser_net.c
cvs rdiff -u -r1.40 -r0 src/sys/rump/librump/rumpuser/rumpuser_pth.c
cvs rdiff -u -r1.8 -r0 src/sys/rump/librump/rumpuser/rumpuser_pth_dummy.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.1 src/lib/librumpuser/Makefile:1.2
--- src/lib/librumpuser/Makefile:1.1 Tue Jul 29 13:17:41 2008
+++ src/lib/librumpuser/Makefile Fri Feb 26 18:54:20 2010
@@ -1,9 +1,24 @@
-# $NetBSD: Makefile,v 1.1 2008/07/29 13:17:41 pooka Exp $
+# $NetBSD: Makefile,v 1.2 2010/02/26 18:54:20 pooka Exp $
#
-.PATH: ${.CURDIR}/../../sys/rump/librump/rumpuser
+WARNS= 4
+# rumpuser.h is in sys/rump for inclusion by kernel components
+.PATH: ${.CURDIR}/../../sys/rump/include/rump
+
+LIB= rumpuser
LIBDPLIBS+= pthread ${.CURDIR}/../libpthread
+
+SRCS= rumpuser.c rumpuser_net.c
+SRCS+= rumpuser_pth.c
+SRCS+= rumpuser_dl.c
+
+INCSDIR= /usr/include/rump
+INCS= rumpuser.h
+
MAN= rumpuser.3
-.include "${.CURDIR}/../../sys/rump/librump/rumpuser/Makefile"
+CPPFLAGS+= -D_REENTRANT
+
+
+.include <bsd.lib.mk>
Index: src/sys/rump/librump/Makefile
diff -u src/sys/rump/librump/Makefile:1.7 src/sys/rump/librump/Makefile:1.8
--- src/sys/rump/librump/Makefile:1.7 Tue Nov 17 15:36:28 2009
+++ src/sys/rump/librump/Makefile Fri Feb 26 18:54:20 2010
@@ -1,11 +1,7 @@
-# $NetBSD: Makefile,v 1.7 2009/11/17 15:36:28 pooka Exp $
+# $NetBSD: Makefile,v 1.8 2010/02/26 18:54:20 pooka Exp $
#
SUBDIR= rumpkern
-.if !defined(NORUMPUSER)
-SUBDIR+= rumpuser
-.endif
-
SUBDIR+= rumpcrypto rumpdev rumpnet rumpvfs
.include <bsd.subdir.mk>
Added files:
Index: src/lib/librumpuser/rumpuser.3
diff -u /dev/null src/lib/librumpuser/rumpuser.3:1.1
--- /dev/null Fri Feb 26 18:54:21 2010
+++ src/lib/librumpuser/rumpuser.3 Fri Feb 26 18:54:20 2010
@@ -0,0 +1,50 @@
+.\" $NetBSD: rumpuser.3,v 1.1 2010/02/26 18:54:20 pooka Exp $
+.\"
+.\" Copyright (c) 2008 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 AND CONTRIBUTORS ``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.
+.\"
+.Dd July 28, 2008
+.Dt RUMPUSER 3
+.Os
+.Sh NAME
+.Nm rumpuser
+.Nd rump user namespace helper routines
+.Sh LIBRARY
+rump User Library (librumpuser, \-lrumpuser)
+.Sh SYNOPSIS
+.In rump/rumpuser.h
+.Sh DESCRIPTION
+.Nm
+is a user namespace helper library for runnable userspace meta programs.
+From rump emulation code compiled with
+.Dv -D_KERNEL
+is it not possible to directly call routines such as system calls
+for reading and writing files or devices.
+This is where
+.Nm
+comes into play by providing a bridge between the two namespaces.
+Another example of its services is a way to call pthread routines,
+used for emulating kernel threads and synchronization mechanisms
+in rump.
+.Sh SEE ALSO
+.Xr rump 3
Index: src/lib/librumpuser/rumpuser.c
diff -u /dev/null src/lib/librumpuser/rumpuser.c:1.1
--- /dev/null Fri Feb 26 18:54:21 2010
+++ src/lib/librumpuser/rumpuser.c Fri Feb 26 18:54:20 2010
@@ -0,0 +1,573 @@
+/* $NetBSD: rumpuser.c,v 1.1 2010/02/26 18:54:20 pooka Exp $ */
+
+/*
+ * 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 <sys/cdefs.h>
+#if !defined(lint)
+__RCSID("$NetBSD: rumpuser.c,v 1.1 2010/02/26 18:54:20 pooka Exp $");
+#endif /* !lint */
+
+/* thank the maker for this */
+#ifdef __linux__
+#define _XOPEN_SOURCE 500
+#define _BSD_SOURCE
+#define _FILE_OFFSET_BITS 64
+#include <features.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/event.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/uio.h>
+
+#ifdef __NetBSD__
+#include <sys/disklabel.h>
+#endif
+
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <poll.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"
+
+int
+rumpuser_getfileinfo(const char *path, uint64_t *sizep, int *ftp, int *error)
+{
+ struct stat sb;
+ uint64_t size;
+ int needsdev = 0, rv = 0, ft;
+
+ if (stat(path, &sb) == -1) {
+ *error = errno;
+ return -1;
+ }
+
+ 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;
+ int fd;
+
+ fd = open(path, O_RDONLY);
+ if (fd == -1) {
+ *error = errno;
+ rv = -1;
+ goto out;
+ }
+
+ off = lseek(fd, 0, SEEK_END);
+ close(fd);
+ if (off != 0) {
+ size = off;
+ goto out;
+ }
+ fprintf(stderr, "error: device size query not implemented on "
+ "this platform\n");
+ *error = EOPNOTSUPP;
+ rv = -1;
+ goto out;
+#else
+ struct disklabel lab;
+ struct partition *parta;
+ int fd;
+
+ fd = open(path, O_RDONLY);
+ if (fd == -1) {
+ *error = errno;
+ rv = -1;
+ goto out;
+ }
+
+ if (ioctl(fd, DIOCGDINFO, &lab) == -1) {
+ *error = errno;
+ rv = -1;
+ goto out;
+ }
+ close(fd);
+
+ parta = &lab.d_partitions[DISKPART(sb.st_rdev)];
+ size = (uint64_t)lab.d_secsize * parta->p_size;
+#endif /* __NetBSD__ */
+ }
+
+ out:
+ if (rv == 0 && sizep)
+ *sizep = size;
+ if (rv == 0 && ftp)
+ *ftp = ft;
+
+ return rv;
+}
+
+int
+rumpuser_nanosleep(uint64_t *sec, uint64_t *nsec, int *error)
+{
+ struct timespec rqt, rmt;
+ int rv;
+
+ /*LINTED*/
+ rqt.tv_sec = *sec;
+ /*LINTED*/
+ rqt.tv_nsec = *nsec;
+
+ KLOCK_WRAP(rv = nanosleep(&rqt, &rmt));
+ if (rv == -1)
+ *error = errno;
+
+ *sec = rmt.tv_sec;
+ *nsec = rmt.tv_nsec;
+
+ return rv;
+}
+
+void *
+rumpuser__malloc(size_t howmuch, int canfail, const char *func, int line)
+{
+ void *rv;
+
+ rv = malloc(howmuch);
+ if (rv == NULL && canfail == 0) {
+ warn("malloc failed %s (%d)", func, line);
+ abort();
+ }
+
+ return rv;
+}
+
+void *
+rumpuser__realloc(void *ptr, size_t howmuch, int canfail,
+ const char *func, int line)
+{
+ void *rv;
+
+ rv = realloc(ptr, howmuch);
+ if (rv == NULL && canfail == 0) {
+ warn("realloc failed %s (%d)", func, line);
+ abort();
+ }
+
+ return rv;
+}
+
+void
+rumpuser_free(void *ptr)
+{
+
+ free(ptr);
+}
+
+void *
+rumpuser_anonmmap(size_t size, int alignbit, int exec, int *error)
+{
+ void *rv;
+ int prot;
+
+ prot = PROT_READ|PROT_WRITE;
+ if (exec)
+ prot |= PROT_EXEC;
+ /* XXX: MAP_ALIGNED() is not portable */
+ rv = mmap(NULL, size, prot, MAP_ANON | MAP_ALIGNED(alignbit), -1, 0);
+ if (rv == MAP_FAILED) {
+ *error = errno;
+ return NULL;
+ }
+ return rv;
+}
+
+void
+rumpuser_unmap(void *addr, size_t len)
+{
+ int rv;
+
+ rv = munmap(addr, len);
+ assert(rv == 0);
+}
+
+void *
+rumpuser_filemmap(int fd, off_t offset, size_t len, int flags, int *error)
+{
+ void *rv;
+ int mmflags, prot;
+
+ if (flags & RUMPUSER_FILEMMAP_TRUNCATE)
+ ftruncate(fd, offset + len);
+
+ mmflags = MAP_FILE;
+ if (flags & RUMPUSER_FILEMMAP_SHARED)
+ mmflags |= MAP_SHARED;
+ else
+ mmflags |= MAP_PRIVATE;
+
+ prot = 0;
+ if (flags & RUMPUSER_FILEMMAP_READ)
+ prot |= PROT_READ;
+ if (flags & RUMPUSER_FILEMMAP_WRITE)
+ prot |= PROT_WRITE;
+
+ rv = mmap(NULL, len, PROT_READ|PROT_WRITE, mmflags, fd, offset);
+ if (rv == MAP_FAILED) {
+ *error = errno;
+ return NULL;
+ }
+
+ *error = 0;
+ return rv;
+}
+
+int
+rumpuser_memsync(void *addr, size_t len, int *error)
+{
+
+ DOCALL_KLOCK(int, (msync(addr, len, MS_SYNC)));
+}
+
+int
+rumpuser_open(const char *path, int flags, int *error)
+{
+
+ DOCALL(int, (open(path, flags, 0644)));
+}
+
+int
+rumpuser_ioctl(int fd, u_long cmd, void *data, int *error)
+{
+
+ DOCALL_KLOCK(int, (ioctl(fd, cmd, data)));
+}
+
+int
+rumpuser_close(int fd, int *error)
+{
+
+ DOCALL(int, close(fd));
+}
+
+int
+rumpuser_fsync(int fd, int *error)
+{
+
+ DOCALL_KLOCK(int, fsync(fd));
+}
+
+ssize_t
+rumpuser_read(int fd, void *data, size_t size, int *error)
+{
+ ssize_t rv;
+
+ KLOCK_WRAP(rv = read(fd, data, size));
+ if (rv == -1)
+ *error = errno;
+
+ return rv;
+}
+
+ssize_t
+rumpuser_pread(int fd, void *data, size_t size, off_t offset, int *error)
+{
+ ssize_t rv;
+
+ KLOCK_WRAP(rv = pread(fd, data, size, offset));
+ if (rv == -1)
+ *error = errno;
+
+ return rv;
+}
+
+void
+rumpuser_read_bio(int fd, void *data, size_t size, off_t offset,
+ rump_biodone_fn biodone, void *biodonecookie)
+{
+ ssize_t rv;
+ int error = 0;
+
+ rv = rumpuser_pread(fd, data, size, offset, &error);
+ /* check against <0 instead of ==-1 to get typing below right */
+ if (rv < 0)
+ rv = 0;
+
+ /* LINTED: see above */
+ biodone(biodonecookie, rv, error);
+}
+
+ssize_t
+rumpuser_write(int fd, const void *data, size_t size, int *error)
+{
+ ssize_t rv;
+
+ KLOCK_WRAP(rv = write(fd, data, size));
+ if (rv == -1)
+ *error = errno;
+
+ return rv;
+}
+
+ssize_t
+rumpuser_pwrite(int fd, const void *data, size_t size, off_t offset, int *error)
+{
+ ssize_t rv;
+
+ KLOCK_WRAP(rv = pwrite(fd, data, size, offset));
+ if (rv == -1)
+ *error = errno;
+
+ return rv;
+}
+
+void
+rumpuser_write_bio(int fd, const void *data, size_t size, off_t offset,
+ rump_biodone_fn biodone, void *biodonecookie)
+{
+ ssize_t rv;
+ int error = 0;
+
+ rv = rumpuser_pwrite(fd, data, size, offset, &error);
+ /* check against <0 instead of ==-1 to get typing below right */
+ if (rv < 0)
+ rv = 0;
+
+ /* LINTED: see above */
+ biodone(biodonecookie, rv, error);
+}
+
+ssize_t
+rumpuser_readv(int fd, const struct rumpuser_iovec *riov, int iovcnt,
+ int *error)
+{
+ struct iovec *iovp;
+ ssize_t rv;
+ int i;
+
+ iovp = malloc(iovcnt * sizeof(struct iovec));
+ if (iovp == NULL) {
+ *error = ENOMEM;
+ return -1;
+ }
+ for (i = 0; i < iovcnt; i++) {
+ iovp[i].iov_base = riov[i].iov_base;
+ /*LINTED*/
+ iovp[i].iov_len = riov[i].iov_len;
+ }
+
+ KLOCK_WRAP(rv = readv(fd, iovp, iovcnt));
+ if (rv == -1)
+ *error = errno;
+ free(iovp);
+
+ return rv;
+}
+
+ssize_t
+rumpuser_writev(int fd, const struct rumpuser_iovec *riov, int iovcnt,
+ int *error)
+{
+ struct iovec *iovp;
+ ssize_t rv;
+ int i;
+
+ iovp = malloc(iovcnt * sizeof(struct iovec));
+ if (iovp == NULL) {
+ *error = ENOMEM;
+ return -1;
+ }
+ for (i = 0; i < iovcnt; i++) {
+ iovp[i].iov_base = riov[i].iov_base;
+ /*LINTED*/
+ iovp[i].iov_len = riov[i].iov_len;
+ }
+
+ KLOCK_WRAP(rv = writev(fd, iovp, iovcnt));
+ if (rv == -1)
+ *error = errno;
+ free(iovp);
+
+ return rv;
+}
+
+int
+rumpuser_gettime(uint64_t *sec, uint64_t *nsec, int *error)
+{
+ struct timeval tv;
+ int rv;
+
+ rv = gettimeofday(&tv, NULL);
+ if (rv == -1) {
+ *error = errno;
+ return rv;
+ }
+
+ *sec = tv.tv_sec;
+ *nsec = tv.tv_usec * 1000;
+
+ return 0;
+}
+
+int
+rumpuser_getenv(const char *name, char *buf, size_t blen, int *error)
+{
+
+ DOCALL(int, getenv_r(name, buf, blen));
+}
+
+int
+rumpuser_gethostname(char *name, size_t namelen, int *error)
+{
+
+ DOCALL(int, (gethostname(name, namelen)));
+}
+
+int
+rumpuser_poll(struct pollfd *fds, int nfds, int timeout, int *error)
+{
+
+ DOCALL_KLOCK(int, (poll(fds, (nfds_t)nfds, timeout)));
+}
+
+int
+rumpuser_putchar(int c, int *error)
+{
+
+ DOCALL(int, (putchar(c)));
+}
+
+void
+rumpuser_exit(int rv)
+{
+
+ if (rv == RUMPUSER_PANIC)
+ abort();
+ else
+ exit(rv);
+}
+
+void
+rumpuser_seterrno(int error)
+{
+
+ errno = error;
+}
+
+int
+rumpuser_writewatchfile_setup(int kq, int fd, intptr_t opaque, int *error)
+{
+ struct kevent kev;
+
+ if (kq == -1) {
+ kq = kqueue();
+ if (kq == -1) {
+ *error = errno;
+ return -1;
+ }
+ }
+
+ EV_SET(&kev, fd, EVFILT_VNODE, EV_ADD|EV_ENABLE|EV_CLEAR,
+ NOTE_WRITE, 0, opaque);
+ if (kevent(kq, &kev, 1, NULL, 0, NULL) == -1) {
+ *error = errno;
+ return -1;
+ }
+
+ return kq;
+}
+
+int
+rumpuser_writewatchfile_wait(int kq, intptr_t *opaque, int *error)
+{
+ struct kevent kev;
+ int rv;
+
+ KLOCK_WRAP(rv = kevent(kq, NULL, 0, &kev, 1, NULL));
+ if (rv == -1) {
+ *error = errno;
+ return -1;
+ }
+
+ if (opaque)
+ *opaque = kev.udata;
+ return rv;
+}
+
+/*
+ * This is meant for safe debugging prints from the kernel.
+ */
+int
+rumpuser_dprintf(const char *format, ...)
+{
+ va_list ap;
+ int rv;
+
+ va_start(ap, format);
+ rv = vprintf(format, ap);
+ va_end(ap);
+
+ return rv;
+}
Index: src/lib/librumpuser/rumpuser_dl.c
diff -u /dev/null src/lib/librumpuser/rumpuser_dl.c:1.1
--- /dev/null Fri Feb 26 18:54:21 2010
+++ src/lib/librumpuser/rumpuser_dl.c Fri Feb 26 18:54:20 2010
@@ -0,0 +1,413 @@
+/* $NetBSD: rumpuser_dl.c,v 1.1 2010/02/26 18:54:20 pooka Exp $ */
+
+/*
+ * Copyright (c) 2009 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.
+ */
+
+/*
+ * Load all module link sets and feed symbol table to the kernel.
+ * Called during rump bootstrap.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: rumpuser_dl.c,v 1.1 2010/02/26 18:54:20 pooka Exp $");
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <assert.h>
+#include <dlfcn.h>
+#include <elf.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <link.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rump/rumpuser.h>
+
+#if defined(__ELF__) && (defined(__NetBSD__) || defined(__FreeBSD__) \
+ || (defined(__sun__) && defined(__svr4__)))
+static size_t symtabsize = 0, strtabsize = 0;
+static size_t symtaboff = 0, strtaboff = 0;
+static uint8_t *symtab = NULL;
+static char *strtab = NULL;
+static unsigned char eident;
+
+static void *
+reservespace(void *store, size_t *storesize,
+ size_t storeoff, size_t required)
+{
+ size_t chunk, newsize;
+
+ assert(storeoff <= *storesize);
+ chunk = *storesize - storeoff;
+
+ if (chunk >= required)
+ return store;
+
+ newsize = *storesize + ((size_t)required - chunk);
+ store = realloc(store, newsize);
+ if (store == NULL) {
+ return NULL;
+ }
+ *((uint8_t *)store + storeoff) = '\0';
+ *storesize = newsize;
+
+ return store;
+}
+
+/*
+ * Macros to make handling elf32/64 in the code a little saner.
+ */
+
+#define EHDR_GETMEMBER(base, thevar, result) \
+do { \
+ if (eident == ELFCLASS32) { \
+ Elf32_Ehdr *ehdr = base; \
+ /*LINTED*/ \
+ result = ehdr->thevar; \
+ } else { \
+ Elf64_Ehdr *ehdr = base; \
+ /*LINTED*/ \
+ result = ehdr->thevar; \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define SHDRn_GETMEMBER(base, n, thevar, result) \
+do { \
+ if (eident == ELFCLASS32) { \
+ Elf32_Shdr *shdr = base; \
+ /*LINTED*/ \
+ result = shdr[n].thevar; \
+ } else { \
+ Elf64_Shdr *shdr = base; \
+ /*LINTED*/ \
+ result = shdr[n].thevar; \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define DYNn_GETMEMBER(base, n, thevar, result) \
+do { \
+ if (eident == ELFCLASS32) { \
+ Elf32_Dyn *dyn = base; \
+ /*LINTED*/ \
+ result = dyn[n].thevar; \
+ } else { \
+ Elf64_Dyn *dyn = base; \
+ /*LINTED*/ \
+ result = dyn[n].thevar; \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define SYMn_GETMEMBER(base, n, thevar, result) \
+do { \
+ if (eident == ELFCLASS32) { \
+ Elf32_Sym *sym = base; \
+ /*LINTED*/ \
+ result = sym[n].thevar; \
+ } else { \
+ Elf64_Sym *sym = base; \
+ /*LINTED*/ \
+ result = sym[n].thevar; \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define SYMn_SETMEMBER(base, n, thevar, value) \
+do { \
+ if (eident == ELFCLASS32) { \
+ Elf32_Sym *sym = base; \
+ /*LINTED*/ \
+ sym[n].thevar = value; \
+ } else { \
+ Elf64_Sym *sym = base; \
+ /*LINTED*/ \
+ sym[n].thevar = value; \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define SYM_GETSIZE() ((eident==ELFCLASS32)?sizeof(Elf32_Sym):sizeof(Elf64_Sym))
+
+static int
+getsymbols(struct link_map *map)
+{
+ void *libbase = map->l_addr;
+ int i = 0, fd;
+ char *str_base;
+ void *syms_base = NULL; /* XXXgcc */
+ size_t cursymsize, curstrsize;
+ void *shdr_base;
+ size_t shsize;
+ int shnum;
+ uint64_t shoff;
+ void *ed_base;
+ uint64_t ed_tag;
+ int sverrno;
+
+ if (memcmp(libbase, ELFMAG, SELFMAG) != 0)
+ return ENOEXEC;
+ eident = *(unsigned char *)(map->l_addr + EI_CLASS);
+ if (eident != ELFCLASS32 && eident != ELFCLASS64)
+ return ENOEXEC;
+
+ /* read the section headers from disk to determine size of dynsym */
+ fd = open(map->l_name, O_RDONLY);
+ if (fd == -1) {
+ sverrno = errno;
+ fprintf(stderr, "open %s failed\n", map->l_name);
+ return sverrno;
+ }
+
+ EHDR_GETMEMBER(libbase, e_shnum, shnum);
+ EHDR_GETMEMBER(libbase, e_shentsize, shsize);
+ EHDR_GETMEMBER(libbase, e_shoff, shoff);
+ shdr_base = malloc(shnum * shsize);
+ if (pread(fd, shdr_base, shnum * shsize, (off_t)shoff)
+ != (ssize_t)(shnum*shsize)){
+ sverrno = errno;
+ fprintf(stderr, "read section headers for %s failed\n",
+ map->l_name);
+ free(shdr_base);
+ close(fd);
+ return sverrno;
+ }
+ cursymsize = (size_t)-1;
+ for (i = 1; i <= shnum; i++) {
+ int shtype;
+
+ SHDRn_GETMEMBER(shdr_base, i, sh_type, shtype);
+ if (shtype != SHT_DYNSYM)
+ continue;
+ SHDRn_GETMEMBER(shdr_base, i, sh_size, cursymsize);
+ break;
+ }
+ free(shdr_base);
+ close(fd);
+ if (cursymsize == (size_t)-1) {
+ fprintf(stderr, "could not find dynsym size from %s\n",
+ map->l_name);
+ return ENOEXEC;
+ }
+
+ /* find symtab, strtab and strtab size */
+ str_base = NULL;
+ curstrsize = (size_t)-1;
+ ed_base = map->l_ld;
+ i = 0;
+ DYNn_GETMEMBER(ed_base, i, d_tag, ed_tag);
+ while (ed_tag != DT_NULL) {
+ uintptr_t edptr;
+ size_t edval;
+
+ switch (ed_tag) {
+ case DT_SYMTAB:
+ DYNn_GETMEMBER(ed_base, i, d_un.d_ptr, edptr);
+ syms_base = map->l_addr + edptr;
+ break;
+ case DT_STRTAB:
+ DYNn_GETMEMBER(ed_base, i, d_un.d_ptr, edptr);
+ str_base = map->l_addr + edptr;
+ break;
+ case DT_STRSZ:
+ DYNn_GETMEMBER(ed_base, i, d_un.d_val, edval);
+ curstrsize = edval;
+ break;
+ default:
+ break;
+ }
+ i++;
+ DYNn_GETMEMBER(ed_base, i, d_tag, ed_tag);
+ } while (ed_tag != DT_NULL);
+
+ if (str_base == NULL || syms_base == NULL || curstrsize == (size_t)-1) {
+ fprintf(stderr, "could not find strtab, symtab or strtab size "
+ "in %s\n", map->l_name);
+ return ENOEXEC;
+ }
+
+ /*
+ * Make sure we have enough space for the contents of the symbol
+ * and string tables we are currently processing. The total used
+ * space will be smaller due to undefined symbols we are not
+ * interested in.
+ */
+ symtab = reservespace(symtab, &symtabsize, symtaboff, cursymsize);
+ strtab = reservespace(strtab, &strtabsize, strtaboff, curstrsize);
+ if (symtab == NULL || strtab == NULL) {
+ fprintf(stderr, "failed to reserve memory");
+ return ENOMEM;
+ }
+
+ /* iterate over all symbols in current symtab */
+ for (i = 0; i * SYM_GETSIZE() < cursymsize; i++) {
+ char *cursymname;
+ int shndx, name;
+ uintptr_t value;
+ void *csym;
+
+ SYMn_GETMEMBER(syms_base, i, st_shndx, shndx);
+ SYMn_GETMEMBER(syms_base, i, st_value, value);
+ if (shndx == SHN_UNDEF || value == 0)
+ continue;
+
+ /* get symbol name */
+ SYMn_GETMEMBER(syms_base, i, st_name, name);
+ cursymname = name + str_base;
+ memcpy(symtab + symtaboff,
+ (uint8_t *)syms_base + i*SYM_GETSIZE(), SYM_GETSIZE());
+
+ /*
+ * set name to point at new strtab, offset symbol value
+ * with lib base address.
+ */
+ csym = symtab + symtaboff;
+ SYMn_SETMEMBER(csym, 0, st_name, strtaboff);
+ SYMn_GETMEMBER(csym, 0, st_value, value);
+ SYMn_SETMEMBER(csym, 0, st_value,(intptr_t)(value+map->l_addr));
+ symtaboff += SYM_GETSIZE();
+
+ strcpy(strtab + strtaboff, cursymname);
+ strtaboff += strlen(cursymname)+1;
+ }
+
+ return 0;
+}
+
+static int
+process(const char *soname, rump_modinit_fn domodinit)
+{
+ void *handle;
+ struct modinfo **mi, **mi_end;
+ int loaded = 0;
+
+ if (strstr(soname, "librump") == NULL)
+ return 0;
+
+ handle = dlopen(soname, RTLD_LAZY);
+ if (handle == NULL)
+ return 0;
+
+ mi = dlsym(handle, "__start_link_set_modules");
+ if (!mi)
+ goto out;
+ mi_end = dlsym(handle, "__stop_link_set_modules");
+ if (!mi_end)
+ goto out;
+
+ for (; mi < mi_end; mi++)
+ if (domodinit(*mi, NULL) == 0)
+ loaded = 1;
+ assert(mi == mi_end);
+
+ out:
+ dlclose(handle);
+ return loaded;
+}
+
+/*
+ * Get the linkmap from the dynlinker. Try to load kernel modules
+ * from all objects in the linkmap.
+ */
+void
+rumpuser_dl_bootstrap(rump_modinit_fn domodinit,
+ rump_symload_fn symload)
+{
+ struct link_map *map, *origmap;
+ int couldload;
+ int error;
+
+ if (dlinfo(RTLD_SELF, RTLD_DI_LINKMAP, &origmap) == -1) {
+ fprintf(stderr, "warning: rumpuser module bootstrap "
+ "failed: %s\n", dlerror());
+ return;
+ }
+ /*
+ * Process last->first because that's the most probable
+ * order for dependencies
+ */
+ for (; origmap->l_next; origmap = origmap->l_next)
+ continue;
+
+ /*
+ * Build symbol table to hand to the rump kernel. Do this by
+ * iterating over all rump libraries and collecting symbol
+ * addresses and relocation info.
+ */
+ error = 0;
+ for (map = origmap; map && !error; map = map->l_prev) {
+ if (map->l_addr == NULL)
+ continue;
+ if (strstr(map->l_name, "librump") != NULL)
+ error = getsymbols(map);
+ }
+
+ if (error == 0) {
+ void *trimmedsym, *trimmedstr;
+
+ /*
+ * Allocate optimum-sized memory for storing tables
+ * and feed to kernel. If memory allocation fails,
+ * just give the ones with extra context (although
+ * I'm pretty sure we'll die moments later due to
+ * memory running out).
+ */
+ if ((trimmedsym = malloc(symtaboff)) != NULL) {
+ memcpy(trimmedsym, symtab, symtaboff);
+ } else {
+ trimmedsym = symtab;
+ symtab = NULL;
+ }
+ if ((trimmedstr = malloc(strtaboff)) != NULL) {
+ memcpy(trimmedstr, strtab, strtaboff);
+ } else {
+ trimmedstr = strtab;
+ strtab = NULL;
+ }
+ symload(trimmedsym, symtaboff, trimmedstr, strtaboff);
+ }
+ free(symtab);
+ free(strtab);
+
+ /*
+ * Next, load modules from dynlibs.
+ */
+ do {
+ couldload = 0;
+ map = origmap;
+ for (; map; map = map->l_prev)
+ if (process(map->l_name, domodinit))
+ couldload = 1;
+ } while (couldload);
+}
+#else
+void
+rumpuser_dl_bootstrap(rump_modinit_fn domodinit,
+ rump_symload_fn symload)
+{
+
+ fprintf(stderr, "Warning, dlinfo() unsupported on host?\n");
+}
+#endif
Index: src/lib/librumpuser/rumpuser_int.h
diff -u /dev/null src/lib/librumpuser/rumpuser_int.h:1.1
--- /dev/null Fri Feb 26 18:54:21 2010
+++ src/lib/librumpuser/rumpuser_int.h Fri Feb 26 18:54:20 2010
@@ -0,0 +1,61 @@
+/* $NetBSD: rumpuser_int.h,v 1.1 2010/02/26 18:54:20 pooka Exp $ */
+
+/*
+ * Copyright (c) 2008 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 <rump/rumpuser.h>
+
+extern kernel_lockfn rumpuser__klock;
+extern kernel_unlockfn rumpuser__kunlock;
+extern int rumpuser__wantthreads;
+
+#define KLOCK_WRAP(a) \
+do { \
+ int nlocks; \
+ rumpuser__kunlock(0, &nlocks); \
+ a; \
+ rumpuser__klock(nlocks); \
+} while (/*CONSTCOND*/0)
+
+#define DOCALL(rvtype, call) \
+ rvtype rv; \
+ rv = call; \
+ if (rv == -1) \
+ *error = errno; \
+ else \
+ *error = 0; \
+ return rv;
+
+#define DOCALL_KLOCK(rvtype, call) \
+ rvtype rv; \
+ int nlocks; \
+ rumpuser__kunlock(0, &nlocks); \
+ rv = call; \
+ rumpuser__klock(nlocks); \
+ if (rv == -1) \
+ *error = errno; \
+ else \
+ *error = 0; \
+ return rv;
Index: src/lib/librumpuser/rumpuser_net.c
diff -u /dev/null src/lib/librumpuser/rumpuser_net.c:1.1
--- /dev/null Fri Feb 26 18:54:21 2010
+++ src/lib/librumpuser/rumpuser_net.c Fri Feb 26 18:54:20 2010
@@ -0,0 +1,125 @@
+/* $NetBSD: rumpuser_net.c,v 1.1 2010/02/26 18:54:20 pooka Exp $ */
+
+/*
+ * Copyright (c) 2008 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 <sys/cdefs.h>
+#if !defined(lint)
+__RCSID("$NetBSD: rumpuser_net.c,v 1.1 2010/02/26 18:54:20 pooka Exp $");
+#endif /* !lint */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <errno.h>
+
+#include <rump/rumpuser.h>
+
+#include "rumpuser_int.h"
+
+int
+rumpuser_net_socket(int domain, int type, int proto, int *error)
+{
+
+ DOCALL_KLOCK(int, (socket(domain, type, proto)));
+}
+
+int
+rumpuser_net_sendmsg(int s, const struct msghdr *msg, int flags, int *error)
+{
+
+ DOCALL_KLOCK(ssize_t, (sendmsg(s, msg, flags)));
+}
+
+int
+rumpuser_net_recvmsg(int s, struct msghdr *msg, int flags, int *error)
+{
+
+ DOCALL_KLOCK(ssize_t, (recvmsg(s, msg, flags)));
+}
+
+int
+rumpuser_net_connect(int s, const struct sockaddr *name, int len, int *error)
+{
+
+ DOCALL_KLOCK(int, (connect(s, name, (socklen_t)len)));
+}
+
+int
+rumpuser_net_bind(int s, const struct sockaddr *name, int len, int *error)
+{
+
+ DOCALL_KLOCK(int, (bind(s, name, (socklen_t)len)));
+}
+
+int
+rumpuser_net_accept(int s, struct sockaddr *name, int *lenp, int *error)
+{
+
+ DOCALL_KLOCK(int, (accept(s, name, (socklen_t *)lenp)));
+}
+
+int
+rumpuser_net_listen(int s, int backlog, int *error)
+{
+
+ DOCALL_KLOCK(int, (listen(s, backlog)));
+}
+
+int
+rumpuser_net_getname(int s, struct sockaddr *so, int *lenp,
+ enum rumpuser_getnametype which, int *error)
+{
+ socklen_t slen = *lenp;
+ int rv;
+
+ if (which == RUMPUSER_SOCKNAME)
+ rv = getsockname(s, so, &slen);
+ else
+ rv = getpeername(s, so, &slen);
+
+ *lenp = slen;
+ if (rv == -1)
+ *error = errno;
+ else
+ *error = 0;
+
+ return rv;
+}
+
+int
+rumpuser_net_setsockopt(int s, int level, int name,
+ const void *data, int dlen, int *error)
+{
+ socklen_t slen = dlen;
+ int rv;
+
+ rv = setsockopt(s, level, name, data, slen);
+ if (rv == -1)
+ *error = errno;
+ else
+ *error = 0;
+ return rv;
+}
Index: src/lib/librumpuser/rumpuser_pth.c
diff -u /dev/null src/lib/librumpuser/rumpuser_pth.c:1.1
--- /dev/null Fri Feb 26 18:54:21 2010
+++ src/lib/librumpuser/rumpuser_pth.c Fri Feb 26 18:54:20 2010
@@ -0,0 +1,526 @@
+/* $NetBSD: rumpuser_pth.c,v 1.1 2010/02/26 18:54:20 pooka Exp $ */
+
+/*
+ * 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 <sys/cdefs.h>
+#if !defined(lint)
+__RCSID("$NetBSD: rumpuser_pth.c,v 1.1 2010/02/26 18:54:20 pooka Exp $");
+#endif /* !lint */
+
+#ifdef __linux__
+#define _XOPEN_SOURCE 500
+#define _BSD_SOURCE
+#define _FILE_OFFSET_BITS 64
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include <rump/rumpuser.h>
+
+#include "rumpuser_int.h"
+
+static pthread_key_t curlwpkey;
+
+#define NOFAIL(a) do {if (!(a)) abort();} while (/*CONSTCOND*/0)
+#define NOFAIL_ERRNO(a) \
+do { \
+ int fail_rv = (a); \
+ if (fail_rv) { \
+ printf("panic: rumpuser fatal failure %d (%s)\n", \
+ fail_rv, strerror(fail_rv)); \
+ abort(); \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define RUMTX_INCRECURSION(mtx) ((mtx)->recursion++)
+#define RUMTX_DECRECURSION(mtx) ((mtx)->recursion--)
+struct rumpuser_mtx {
+ pthread_mutex_t pthmtx;
+ pthread_t owner;
+ unsigned recursion;
+};
+
+#define RURW_AMWRITER(rw) (pthread_equal(rw->writer, pthread_self()) \
+ && rw->readers == -1)
+#define RURW_HASREAD(rw) (rw->readers > 0)
+
+#define RURW_SETWRITE(rw) \
+do { \
+ assert(rw->readers == 0); \
+ rw->writer = pthread_self(); \
+ rw->readers = -1; \
+} while (/*CONSTCOND*/0)
+#define RURW_CLRWRITE(rw) \
+do { \
+ assert(rw->readers == -1 && RURW_AMWRITER(rw)); \
+ rw->readers = 0; \
+} while (/*CONSTCOND*/0)
+#define RURW_INCREAD(rw) \
+do { \
+ pthread_spin_lock(&rw->spin); \
+ assert(rw->readers >= 0); \
+ ++(rw)->readers; \
+ pthread_spin_unlock(&rw->spin); \
+} while (/*CONSTCOND*/0)
+#define RURW_DECREAD(rw) \
+do { \
+ pthread_spin_lock(&rw->spin); \
+ assert(rw->readers > 0); \
+ --(rw)->readers; \
+ pthread_spin_unlock(&rw->spin); \
+} while (/*CONSTCOND*/0)
+
+struct rumpuser_rw {
+ pthread_rwlock_t pthrw;
+ pthread_spinlock_t spin;
+ int readers;
+ pthread_t writer;
+};
+
+struct rumpuser_cv {
+ pthread_cond_t pthcv;
+ int nwaiters;
+};
+
+struct rumpuser_mtx rumpuser_aio_mtx;
+struct rumpuser_cv rumpuser_aio_cv;
+int rumpuser_aio_head, rumpuser_aio_tail;
+struct rumpuser_aio rumpuser_aios[N_AIOS];
+
+kernel_lockfn rumpuser__klock;
+kernel_unlockfn rumpuser__kunlock;
+int rumpuser__wantthreads;
+
+void
+/*ARGSUSED*/
+rumpuser_biothread(void *arg)
+{
+ struct rumpuser_aio *rua;
+ rump_biodone_fn biodone = arg;
+ ssize_t rv;
+ int error, dummy;
+
+ /* unschedule from CPU. we reschedule before running the interrupt */
+ rumpuser__kunlock(0, &dummy);
+ assert(dummy == 0);
+
+ NOFAIL_ERRNO(pthread_mutex_lock(&rumpuser_aio_mtx.pthmtx));
+ for (;;) {
+ while (rumpuser_aio_head == rumpuser_aio_tail) {
+ NOFAIL_ERRNO(pthread_cond_wait(&rumpuser_aio_cv.pthcv,
+ &rumpuser_aio_mtx.pthmtx));
+ }
+
+ rua = &rumpuser_aios[rumpuser_aio_tail];
+ assert(rua->rua_bp != NULL);
+ pthread_mutex_unlock(&rumpuser_aio_mtx.pthmtx);
+
+ if (rua->rua_op & RUA_OP_READ) {
+ error = 0;
+ rv = pread(rua->rua_fd, rua->rua_data,
+ rua->rua_dlen, rua->rua_off);
+ if (rv < 0) {
+ rv = 0;
+ error = errno;
+ }
+ } else {
+ error = 0;
+ rv = pwrite(rua->rua_fd, rua->rua_data,
+ rua->rua_dlen, rua->rua_off);
+ if (rv < 0) {
+ rv = 0;
+ error = errno;
+ } else if (rua->rua_op & RUA_OP_SYNC) {
+#ifdef __NetBSD__
+ fsync_range(rua->rua_fd, FDATASYNC,
+ rua->rua_off, rua->rua_dlen);
+#else
+ fsync(rua->rua_fd);
+#endif
+ }
+ }
+ rumpuser__klock(0);
+ biodone(rua->rua_bp, (size_t)rv, error);
+ rumpuser__kunlock(0, &dummy);
+
+ rua->rua_bp = NULL;
+
+ NOFAIL_ERRNO(pthread_mutex_lock(&rumpuser_aio_mtx.pthmtx));
+ rumpuser_aio_tail = (rumpuser_aio_tail+1) % N_AIOS;
+ pthread_cond_signal(&rumpuser_aio_cv.pthcv);
+ }
+
+ /*NOTREACHED*/
+ fprintf(stderr, "error: rumpuser_biothread reached unreachable\n");
+ abort();
+}
+
+void
+rumpuser_thrinit(kernel_lockfn lockfn, kernel_unlockfn unlockfn, int threads)
+{
+
+ pthread_mutex_init(&rumpuser_aio_mtx.pthmtx, NULL);
+ pthread_cond_init(&rumpuser_aio_cv.pthcv, NULL);
+
+ pthread_key_create(&curlwpkey, NULL);
+
+ rumpuser__klock = lockfn;
+ rumpuser__kunlock = unlockfn;
+ rumpuser__wantthreads = threads;
+}
+
+#if 0
+void
+rumpuser__thrdestroy(void)
+{
+
+ pthread_key_delete(curlwpkey);
+}
+#endif
+
+int
+rumpuser_thread_create(void *(*f)(void *), void *arg, const char *thrname)
+{
+ pthread_t ptid;
+ int rv;
+
+ rv = pthread_create(&ptid, NULL, f, arg);
+#ifdef __NetBSD__
+ if (rv == 0 && thrname)
+ pthread_setname_np(ptid, thrname, NULL);
+#endif
+
+ return rv;
+}
+
+__dead void
+rumpuser_thread_exit(void)
+{
+
+ pthread_exit(NULL);
+}
+
+void
+rumpuser_mutex_init(struct rumpuser_mtx **mtx)
+{
+ pthread_mutexattr_t att;
+
+ NOFAIL(*mtx = malloc(sizeof(struct rumpuser_mtx)));
+
+ pthread_mutexattr_init(&att);
+ pthread_mutexattr_settype(&att, PTHREAD_MUTEX_ERRORCHECK);
+ NOFAIL_ERRNO(pthread_mutex_init(&((*mtx)->pthmtx), &att));
+ pthread_mutexattr_destroy(&att);
+
+ (*mtx)->owner = NULL;
+ (*mtx)->recursion = 0;
+}
+
+void
+rumpuser_mutex_recursive_init(struct rumpuser_mtx **mtx)
+{
+ pthread_mutexattr_t mattr;
+
+ pthread_mutexattr_init(&mattr);
+ pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE);
+
+ NOFAIL(*mtx = malloc(sizeof(struct rumpuser_mtx)));
+ NOFAIL_ERRNO(pthread_mutex_init(&((*mtx)->pthmtx), &mattr));
+ (*mtx)->owner = NULL;
+ (*mtx)->recursion = 0;
+
+ pthread_mutexattr_destroy(&mattr);
+}
+
+static void
+mtxenter(struct rumpuser_mtx *mtx)
+{
+
+ if (mtx->recursion++ == 0) {
+ assert(mtx->owner == NULL);
+ mtx->owner = pthread_self();
+ } else {
+ assert(pthread_equal(mtx->owner, pthread_self()));
+ }
+}
+
+static void
+mtxexit(struct rumpuser_mtx *mtx)
+{
+
+ assert(mtx->owner != NULL);
+ if (--mtx->recursion == 0)
+ mtx->owner = NULL;
+}
+
+void
+rumpuser_mutex_enter(struct rumpuser_mtx *mtx)
+{
+
+ if (pthread_mutex_trylock(&mtx->pthmtx) != 0)
+ KLOCK_WRAP(NOFAIL_ERRNO(pthread_mutex_lock(&mtx->pthmtx)));
+ mtxenter(mtx);
+}
+
+void
+rumpuser_mutex_enter_nowrap(struct rumpuser_mtx *mtx)
+{
+
+ NOFAIL_ERRNO(pthread_mutex_lock(&mtx->pthmtx));
+ mtxenter(mtx);
+}
+
+int
+rumpuser_mutex_tryenter(struct rumpuser_mtx *mtx)
+{
+ int rv;
+
+ rv = pthread_mutex_trylock(&mtx->pthmtx);
+ if (rv == 0) {
+ mtxenter(mtx);
+ }
+
+ return rv == 0;
+}
+
+void
+rumpuser_mutex_exit(struct rumpuser_mtx *mtx)
+{
+
+ mtxexit(mtx);
+ NOFAIL_ERRNO(pthread_mutex_unlock(&mtx->pthmtx));
+}
+
+void
+rumpuser_mutex_destroy(struct rumpuser_mtx *mtx)
+{
+
+ NOFAIL_ERRNO(pthread_mutex_destroy(&mtx->pthmtx));
+ free(mtx);
+}
+
+int
+rumpuser_mutex_held(struct rumpuser_mtx *mtx)
+{
+
+ return mtx->recursion && pthread_equal(mtx->owner, pthread_self());
+}
+
+void
+rumpuser_rw_init(struct rumpuser_rw **rw)
+{
+
+ NOFAIL(*rw = malloc(sizeof(struct rumpuser_rw)));
+ NOFAIL_ERRNO(pthread_rwlock_init(&((*rw)->pthrw), NULL));
+ NOFAIL_ERRNO(pthread_spin_init(&((*rw)->spin), PTHREAD_PROCESS_SHARED));
+ (*rw)->readers = 0;
+ (*rw)->writer = NULL;
+}
+
+void
+rumpuser_rw_enter(struct rumpuser_rw *rw, int iswrite)
+{
+
+ if (iswrite) {
+ if (pthread_rwlock_trywrlock(&rw->pthrw) != 0)
+ KLOCK_WRAP(NOFAIL_ERRNO(
+ pthread_rwlock_wrlock(&rw->pthrw)));
+ RURW_SETWRITE(rw);
+ } else {
+ if (pthread_rwlock_tryrdlock(&rw->pthrw) != 0)
+ KLOCK_WRAP(NOFAIL_ERRNO(
+ pthread_rwlock_rdlock(&rw->pthrw)));
+ RURW_INCREAD(rw);
+ }
+}
+
+int
+rumpuser_rw_tryenter(struct rumpuser_rw *rw, int iswrite)
+{
+ int rv;
+
+ if (iswrite) {
+ rv = pthread_rwlock_trywrlock(&rw->pthrw);
+ if (rv == 0)
+ RURW_SETWRITE(rw);
+ } else {
+ rv = pthread_rwlock_tryrdlock(&rw->pthrw);
+ if (rv == 0)
+ RURW_INCREAD(rw);
+ }
+
+ return rv == 0;
+}
+
+void
+rumpuser_rw_exit(struct rumpuser_rw *rw)
+{
+
+ if (RURW_HASREAD(rw))
+ RURW_DECREAD(rw);
+ else
+ RURW_CLRWRITE(rw);
+ NOFAIL_ERRNO(pthread_rwlock_unlock(&rw->pthrw));
+}
+
+void
+rumpuser_rw_destroy(struct rumpuser_rw *rw)
+{
+
+ NOFAIL_ERRNO(pthread_rwlock_destroy(&rw->pthrw));
+ NOFAIL_ERRNO(pthread_spin_destroy(&rw->spin));
+ free(rw);
+}
+
+int
+rumpuser_rw_held(struct rumpuser_rw *rw)
+{
+
+ return rw->readers != 0;
+}
+
+int
+rumpuser_rw_rdheld(struct rumpuser_rw *rw)
+{
+
+ return RURW_HASREAD(rw);
+}
+
+int
+rumpuser_rw_wrheld(struct rumpuser_rw *rw)
+{
+
+ return RURW_AMWRITER(rw);
+}
+
+void
+rumpuser_cv_init(struct rumpuser_cv **cv)
+{
+
+ NOFAIL(*cv = malloc(sizeof(struct rumpuser_cv)));
+ NOFAIL_ERRNO(pthread_cond_init(&((*cv)->pthcv), NULL));
+ (*cv)->nwaiters = 0;
+}
+
+void
+rumpuser_cv_destroy(struct rumpuser_cv *cv)
+{
+
+ NOFAIL_ERRNO(pthread_cond_destroy(&cv->pthcv));
+ free(cv);
+}
+
+void
+rumpuser_cv_wait(struct rumpuser_cv *cv, struct rumpuser_mtx *mtx)
+{
+
+ cv->nwaiters++;
+ assert(mtx->recursion == 1);
+ mtxexit(mtx);
+ KLOCK_WRAP(NOFAIL_ERRNO(pthread_cond_wait(&cv->pthcv, &mtx->pthmtx)));
+ mtxenter(mtx);
+ cv->nwaiters--;
+}
+
+void
+rumpuser_cv_wait_nowrap(struct rumpuser_cv *cv, struct rumpuser_mtx *mtx)
+{
+
+ cv->nwaiters++;
+ assert(mtx->recursion == 1);
+ mtxexit(mtx);
+ NOFAIL_ERRNO(pthread_cond_wait(&cv->pthcv, &mtx->pthmtx));
+ mtxenter(mtx);
+ cv->nwaiters--;
+}
+
+int
+rumpuser_cv_timedwait(struct rumpuser_cv *cv, struct rumpuser_mtx *mtx,
+ int64_t sec, int64_t nsec)
+{
+ struct timespec ts;
+ int rv;
+
+ /* LINTED */
+ ts.tv_sec = sec; ts.tv_nsec = nsec;
+
+ cv->nwaiters++;
+ mtxexit(mtx);
+ KLOCK_WRAP(rv = pthread_cond_timedwait(&cv->pthcv, &mtx->pthmtx, &ts));
+ mtxenter(mtx);
+ cv->nwaiters--;
+ if (rv != 0 && rv != ETIMEDOUT)
+ abort();
+
+ return rv == ETIMEDOUT;
+}
+
+void
+rumpuser_cv_signal(struct rumpuser_cv *cv)
+{
+
+ NOFAIL_ERRNO(pthread_cond_signal(&cv->pthcv));
+}
+
+void
+rumpuser_cv_broadcast(struct rumpuser_cv *cv)
+{
+
+ NOFAIL_ERRNO(pthread_cond_broadcast(&cv->pthcv));
+}
+
+int
+rumpuser_cv_has_waiters(struct rumpuser_cv *cv)
+{
+
+ return cv->nwaiters;
+}
+
+/*
+ * curlwp
+ */
+
+void
+rumpuser_set_curlwp(struct lwp *l)
+{
+
+ assert(pthread_getspecific(curlwpkey) == NULL || l == NULL);
+ pthread_setspecific(curlwpkey, l);
+}
+
+struct lwp *
+rumpuser_get_curlwp(void)
+{
+
+ return pthread_getspecific(curlwpkey);
+}
Index: src/lib/librumpuser/rumpuser_pth_dummy.c
diff -u /dev/null src/lib/librumpuser/rumpuser_pth_dummy.c:1.1
--- /dev/null Fri Feb 26 18:54:21 2010
+++ src/lib/librumpuser/rumpuser_pth_dummy.c Fri Feb 26 18:54:20 2010
@@ -0,0 +1,296 @@
+/* $NetBSD: rumpuser_pth_dummy.c,v 1.1 2010/02/26 18:54:20 pooka Exp $ */
+
+/*
+ * Copyright (c) 2009 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 <sys/cdefs.h>
+#if !defined(lint)
+__RCSID("$NetBSD: rumpuser_pth_dummy.c,v 1.1 2010/02/26 18:54:20 pooka Exp $");
+#endif /* !lint */
+
+#include <sys/time.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <rump/rumpuser.h>
+
+#include "rumpuser_int.h"
+
+struct rumpuser_cv {};
+
+struct rumpuser_mtx {
+ int v;
+};
+
+struct rumpuser_rw {
+ int v;
+};
+
+struct rumpuser_mtx rumpuser_aio_mtx;
+struct rumpuser_cv rumpuser_aio_cv;
+int rumpuser_aio_head, rumpuser_aio_tail;
+struct rumpuser_aio rumpuser_aios[N_AIOS];
+
+void donada(int);
+/*ARGSUSED*/
+void donada(int arg) {}
+void dounnada(int, int *);
+/*ARGSUSED*/
+void dounnada(int arg, int *ap) {}
+kernel_lockfn rumpuser__klock = donada;
+kernel_unlockfn rumpuser__kunlock = dounnada;
+
+/*ARGSUSED*/
+void
+rumpuser_thrinit(kernel_lockfn lockfn, kernel_unlockfn unlockfn, int threads)
+{
+
+}
+
+/*ARGSUSED*/
+void
+rumpuser_biothread(void *arg)
+{
+
+ fprintf(stderr, "rumpuser: threads not available\n");
+ abort();
+}
+
+/*ARGSUSED*/
+int
+rumpuser_thread_create(void *(*f)(void *), void *arg, const char *thrname)
+{
+
+ fprintf(stderr, "rumpuser: threads not available\n");
+ abort();
+ return 0;
+}
+
+void
+rumpuser_thread_exit(void)
+{
+
+}
+
+void
+rumpuser_mutex_init(struct rumpuser_mtx **mtx)
+{
+
+ *mtx = calloc(1, sizeof(struct rumpuser_mtx));
+}
+
+void
+rumpuser_mutex_recursive_init(struct rumpuser_mtx **mtx)
+{
+
+ rumpuser_mutex_init(mtx);
+}
+
+void
+rumpuser_mutex_enter(struct rumpuser_mtx *mtx)
+{
+
+ mtx->v++;
+}
+
+int
+rumpuser_mutex_tryenter(struct rumpuser_mtx *mtx)
+{
+
+ mtx->v++;
+ return 1;
+}
+
+void
+rumpuser_mutex_exit(struct rumpuser_mtx *mtx)
+{
+
+ mtx->v--;
+}
+
+void
+rumpuser_mutex_destroy(struct rumpuser_mtx *mtx)
+{
+
+ free(mtx);
+}
+
+int
+rumpuser_mutex_held(struct rumpuser_mtx *mtx)
+{
+
+ return mtx->v;
+}
+
+void
+rumpuser_rw_init(struct rumpuser_rw **rw)
+{
+
+ *rw = calloc(1, sizeof(struct rumpuser_rw));
+}
+
+void
+rumpuser_rw_enter(struct rumpuser_rw *rw, int write)
+{
+
+ if (write) {
+ rw->v++;
+ assert(rw->v == 1);
+ } else {
+ assert(rw->v <= 0);
+ rw->v--;
+ }
+}
+
+int
+rumpuser_rw_tryenter(struct rumpuser_rw *rw, int write)
+{
+
+ rumpuser_rw_enter(rw, write);
+ return 1;
+}
+
+void
+rumpuser_rw_exit(struct rumpuser_rw *rw)
+{
+
+ if (rw->v > 0) {
+ assert(rw->v == 1);
+ rw->v--;
+ } else {
+ rw->v++;
+ }
+}
+
+void
+rumpuser_rw_destroy(struct rumpuser_rw *rw)
+{
+
+ free(rw);
+}
+
+int
+rumpuser_rw_held(struct rumpuser_rw *rw)
+{
+
+ return rw->v != 0;
+}
+
+int
+rumpuser_rw_rdheld(struct rumpuser_rw *rw)
+{
+
+ return rw->v < 0;
+}
+
+int
+rumpuser_rw_wrheld(struct rumpuser_rw *rw)
+{
+
+ return rw->v > 0;
+}
+
+/*ARGSUSED*/
+void
+rumpuser_cv_init(struct rumpuser_cv **cv)
+{
+
+}
+
+/*ARGSUSED*/
+void
+rumpuser_cv_destroy(struct rumpuser_cv *cv)
+{
+
+}
+
+/*ARGSUSED*/
+void
+rumpuser_cv_wait(struct rumpuser_cv *cv, struct rumpuser_mtx *mtx)
+{
+
+}
+
+/*ARGSUSED*/
+int
+rumpuser_cv_timedwait(struct rumpuser_cv *cv, struct rumpuser_mtx *mtx,
+ int64_t sec, int64_t nsec)
+{
+ struct timespec ts;
+
+ /*LINTED*/
+ ts.tv_sec = sec;
+ /*LINTED*/
+ ts.tv_nsec = nsec;
+
+ nanosleep(&ts, NULL);
+ return 0;
+}
+
+/*ARGSUSED*/
+void
+rumpuser_cv_signal(struct rumpuser_cv *cv)
+{
+
+}
+
+/*ARGSUSED*/
+void
+rumpuser_cv_broadcast(struct rumpuser_cv *cv)
+{
+
+}
+
+/*ARGSUSED*/
+int
+rumpuser_cv_has_waiters(struct rumpuser_cv *cv)
+{
+
+ return 0;
+}
+
+/*
+ * curlwp
+ */
+
+static struct lwp *curlwp;
+void
+rumpuser_set_curlwp(struct lwp *l)
+{
+
+ curlwp = l;
+}
+
+struct lwp *
+rumpuser_get_curlwp(void)
+{
+
+ return curlwp;
+}
Index: src/lib/librumpuser/shlib_version
diff -u /dev/null src/lib/librumpuser/shlib_version:1.1
--- /dev/null Fri Feb 26 18:54:21 2010
+++ src/lib/librumpuser/shlib_version Fri Feb 26 18:54:20 2010
@@ -0,0 +1,4 @@
+# $NetBSD: shlib_version,v 1.1 2010/02/26 18:54:20 pooka Exp $
+#
+major=0
+minor=0