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/d67092ad326f
branches:  trunk
changeset: 330489:d67092ad326f
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 d69ebd981262 -r d67092ad326f 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 d69ebd981262 -r d67092ad326f 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