Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src Add a fiber based implementation of librumpuser in addition ...
details: https://anonhg.NetBSD.org/src/rev/2b7165b226f4
branches: trunk
changeset: 797250:2b7165b226f4
user: justin <justin%NetBSD.org@localhost>
date: Fri Jul 11 20:26:31 2014 +0000
description:
Add a fiber based implementation of librumpuser in addition to the
default pthreads based version.
Discussed with pooka@
diffstat:
lib/librumpuser/Makefile | 33 +-
lib/librumpuser/rumpfiber.c | 1041 +++++++++++++++++++++++++++++++++++++++
lib/librumpuser/rumpfiber.h | 77 ++
lib/librumpuser/rumpfiber_bio.c | 65 ++
lib/librumpuser/rumpfiber_sp.c | 108 ++++
sys/rump/README.compileopts | 18 +-
6 files changed, 1335 insertions(+), 7 deletions(-)
diffs (truncated from 1405 to 300 lines):
diff -r caa708df6951 -r 2b7165b226f4 lib/librumpuser/Makefile
--- a/lib/librumpuser/Makefile Fri Jul 11 19:40:52 2014 +0000
+++ b/lib/librumpuser/Makefile Fri Jul 11 20:26:31 2014 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.19 2014/07/09 23:41:40 justin Exp $
+# $NetBSD: Makefile,v 1.20 2014/07/11 20:26:31 justin Exp $
#
.include <bsd.own.mk>
@@ -8,8 +8,13 @@
# 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,15 +22,32 @@
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
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
@@ -34,5 +56,4 @@
CPPFLAGS+= -D_REENTRANT
-
.include <bsd.lib.mk>
diff -r caa708df6951 -r 2b7165b226f4 lib/librumpuser/rumpfiber.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/librumpuser/rumpfiber.c Fri Jul 11 20:26:31 2014 +0000
@@ -0,0 +1,1041 @@
+/*
+ * 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.1 2014/07/11 20:26:31 justin 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)
Home |
Main Index |
Thread Index |
Old Index