[Sheepdog] [PATCH] remove coroutine code

MORITA Kazutaka morita.kazutaka at lab.ntt.co.jp
Tue Apr 10 19:13:41 CEST 2012


It was overkill to use coroutine for group_handler race conditions.

Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
---
 include/coroutine.h |   20 ---
 lib/Makefile.am     |    2 +-
 lib/coroutine.c     |  324 ---------------------------------------------------
 3 files changed, 1 insertions(+), 345 deletions(-)
 delete mode 100644 include/coroutine.h
 delete mode 100644 lib/coroutine.c

diff --git a/include/coroutine.h b/include/coroutine.h
deleted file mode 100644
index a69097f..0000000
--- a/include/coroutine.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef __COROUTINE__
-#define __COROUTINE__
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <unistd.h>
-
-#include "list.h"
-
-struct coroutine;
-
-typedef void coroutine_entry_func_t(void *opaque);
-
-struct coroutine *coroutine_create(coroutine_entry_func_t *entry);
-void coroutine_enter(struct coroutine *coroutine, void *opaque);
-void coroutine_yield(void);
-struct coroutine *coroutine_self(void);
-int in_coroutine(void);
-
-#endif
diff --git a/lib/Makefile.am b/lib/Makefile.am
index d9e8429..eda3c9a 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -4,4 +4,4 @@ INCLUDES                = -I$(top_builddir)/include -I$(top_srcdir)/include
 
 noinst_LIBRARIES	= libsheepdog.a
 
-libsheepdog_a_SOURCES	= event.c logger.c net.c util.c coroutine.c rbtree.c ring_buffer.c
+libsheepdog_a_SOURCES	= event.c logger.c net.c util.c rbtree.c ring_buffer.c
diff --git a/lib/coroutine.c b/lib/coroutine.c
deleted file mode 100644
index 3d79b40..0000000
--- a/lib/coroutine.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * Copyright (C) 2011 MORITA Kazutaka <morita.kazutaka at gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.0 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- *
- * This code is based on coroutine-ucontext.c and qemu-coroutine.c from QEMU:
- *   Copyright (C) 2006 Anthony Liguori <anthony at codemonkey.ws>
- *   Copyright (C) 2011 Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
- *   Copyright (C) 2011 Kevin Wolf <kwolf at redhat.com>
- */
-
-/* disable glibc's stack check for longjmp which doesn't work well
- * with our code */
-#ifdef _FORTIFY_SOURCE
-#undef _FORTIFY_SOURCE
-#endif
-
-#include <stdlib.h>
-#include <setjmp.h>
-#include <stdint.h>
-#include <ucontext.h>
-#include <errno.h>
-#include <assert.h>
-#include <arpa/inet.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <sys/socket.h>
-
-#include "util.h"
-#include "coroutine.h"
-#include "logger.h"
-
-enum co_action {
-	COROUTINE_YIELD = 1,
-	COROUTINE_TERMINATE = 2,
-};
-
-/* Maximum free pool size prevents holding too many freed coroutines */
-#ifdef COROUTINE_DEBUG
-#define POOL_MAX_SIZE   1
-#else
-#define POOL_MAX_SIZE   64
-#endif
-
-#define STACK_MAX_SIZE (1 << 20)  /* 1 MB */
-
-struct coroutine {
-	coroutine_entry_func_t *entry;
-	void *entry_arg;
-	struct coroutine *caller;
-	struct list_head pool_next;
-	struct list_head co_queue_next;
-};
-
-struct co_ucontext {
-	struct coroutine base;
-	void *stack;
-	jmp_buf env;
-};
-
-/**
- * Per-thread coroutine bookkeeping
- */
-__thread struct co_thread_state{
-	/** Currently executing coroutine */
-	struct coroutine *current;
-
-	/** Free list to speed up creation */
-	struct list_head pool;
-	unsigned int pool_size;
-
-	/** The default coroutine */
-	struct co_ucontext leader;
-} co_ts;
-
-static enum co_action coroutine_switch(struct coroutine *from,
-				       struct coroutine *to,
-				       enum co_action action);
-
-/*
- * va_args to makecontext() must be type 'int', so passing
- * the pointer we need may require several int args. This
- * union is a quick hack to let us do that
- */
-union cc_arg {
-	void *p;
-	int i[2];
-};
-
-static struct co_thread_state *coroutine_get_thread_state(void)
-{
-	struct co_thread_state *s = &co_ts;
-
-	if (!s->current) {
-		s->current = &s->leader.base;
-		INIT_LIST_HEAD(&s->pool);
-	}
-	return s;
-}
-
-static void coroutine_trampoline(int i0, int i1)
-{
-	union cc_arg arg;
-	struct co_ucontext *self;
-	struct coroutine *co;
-
-	arg.i[0] = i0;
-	arg.i[1] = i1;
-	self = arg.p;
-	co = &self->base;
-
-	/* Initialize longjmp environment and switch back the caller */
-	if (!setjmp(self->env))
-		longjmp(*(jmp_buf *)co->entry_arg, 1);
-
-	for (;;) {
-		co->entry(co->entry_arg);
-		coroutine_switch(co, co->caller, COROUTINE_TERMINATE);
-	}
-}
-
-#ifdef COROUTINE_DEBUG
-
-#define MAGIC_NUMBER 0x1234567890123456
-
-static void init_stack(struct co_ucontext *co)
-{
-	uint64_t *stack = co->stack;
-	int i;
-
-	for (i = 0; i < STACK_MAX_SIZE / sizeof(stack[0]); i++)
-		stack[i] = MAGIC_NUMBER;
-}
-
-static int get_stack_size(struct co_ucontext *co)
-{
-	uint64_t *stack = co->stack;
-	int i;
-
-	for (i = 0; i < STACK_MAX_SIZE / sizeof(stack[0]); i++)
-		if (stack[i] != MAGIC_NUMBER)
-			break;
-
-	if (i == 0)
-		panic("stack overflow\n");
-
-	return STACK_MAX_SIZE - i * sizeof(stack[0]);
-}
-
-#endif
-
-static struct coroutine *__coroutine_new(void)
-{
-	const size_t stack_size = STACK_MAX_SIZE;
-	struct co_ucontext *co;
-	ucontext_t old_uc, uc;
-	jmp_buf old_env;
-	union cc_arg arg = {0};
-
-	/* The ucontext functions preserve signal masks which incurs a
-	 * system call overhead.  setjmp()/longjmp() does not preserve
-	 * signal masks but only works on the current stack.  Since we
-	 * need a way to create and switch to a new stack, use the
-	 * ucontext functions for that but setjmp()/longjmp() for
-	 * everything else.
-	 */
-
-	if (getcontext(&uc) == -1)
-		abort();
-
-	co = zalloc(sizeof(*co));
-	if (!co)
-		abort();
-	co->stack = zalloc(stack_size);
-	if (!co->stack)
-		abort();
-#ifdef COROUTINE_DEBUG
-	init_stack(co);
-#endif
-	co->base.entry_arg = &old_env; /* stash away our jmp_buf */
-
-	uc.uc_link = &old_uc;
-	uc.uc_stack.ss_sp = co->stack;
-	uc.uc_stack.ss_size = stack_size;
-	uc.uc_stack.ss_flags = 0;
-
-	arg.p = co;
-
-	makecontext(&uc, (void (*)(void))coroutine_trampoline,
-		    2, arg.i[0], arg.i[1]);
-
-	/* swapcontext() in, longjmp() back out */
-	if (!setjmp(old_env))
-		swapcontext(&old_uc, &uc);
-
-	return &co->base;
-}
-
-static struct coroutine *coroutine_new(void)
-{
-	struct co_thread_state *s = coroutine_get_thread_state();
-	struct coroutine *co;
-
-	if (!list_empty(&s->pool)) {
-		co = list_first_entry(&s->pool, struct coroutine, pool_next);
-		list_del(&co->pool_next);
-		s->pool_size--;
-	} else
-		co = __coroutine_new();
-
-	return co;
-}
-
-static void coroutine_delete(struct coroutine *co_)
-{
-	struct co_thread_state *s = coroutine_get_thread_state();
-	struct co_ucontext *co = container_of(co_, struct co_ucontext, base);
-
-#ifdef COROUTINE_DEBUG
-	fprintf(stdout, "%d bytes are consumed\n", get_stack_size(co));
-#endif
-
-	if (s->pool_size < POOL_MAX_SIZE) {
-		list_add(&co->base.pool_next, &s->pool);
-		co->base.caller = NULL;
-		s->pool_size++;
-		return;
-	}
-
-	free(co->stack);
-	free(co);
-}
-
-static enum co_action coroutine_switch(struct coroutine *from_,
-				       struct coroutine *to_,
-				       enum co_action action)
-{
-	struct co_ucontext *from = container_of(from_, struct co_ucontext, base);
-	struct co_ucontext *to = container_of(to_, struct co_ucontext, base);
-	struct co_thread_state *s = coroutine_get_thread_state();
-	int ret;
-
-	s->current = to_;
-
-	ret = setjmp(from->env);
-	if (ret == 0)
-		longjmp(to->env, action);
-
-	return ret;
-}
-
-struct coroutine *coroutine_self(void)
-{
-	struct co_thread_state *s = coroutine_get_thread_state();
-
-	return s->current;
-}
-
-int in_coroutine(void)
-{
-	struct co_thread_state *s = &co_ts;
-
-	return s->current && s->current->caller;
-}
-
-
-struct coroutine *coroutine_create(coroutine_entry_func_t *entry)
-{
-	struct coroutine *co = coroutine_new();
-	co->entry = entry;
-	return co;
-}
-
-static void coroutine_swap(struct coroutine *from, struct coroutine *to)
-{
-	enum co_action ret;
-
-	ret = coroutine_switch(from, to, COROUTINE_YIELD);
-
-	switch (ret) {
-	case COROUTINE_YIELD:
-		return;
-	case COROUTINE_TERMINATE:
-		coroutine_delete(to);
-		return;
-	default:
-		abort();
-	}
-}
-
-void coroutine_enter(struct coroutine *co, void *opaque)
-{
-	struct coroutine *self = coroutine_self();
-
-	if (co->caller)
-		panic("Co-routine re-entered recursively\n");
-
-	co->caller = self;
-	co->entry_arg = opaque;
-	coroutine_swap(self, co);
-}
-
-void coroutine_yield(void)
-{
-	struct coroutine *self = coroutine_self();
-	struct coroutine *to = self->caller;
-
-	if (!to)
-		panic("Co-routine is yielding to no one\n");
-
-	self->caller = NULL;
-	coroutine_swap(self, to);
-}
-- 
1.7.2.5




More information about the sheepdog mailing list