[Gluster-devel] swapcontest usage in syncio.c

Emmanuel Dreyfus manu at netbsd.org
Wed Aug 8 16:36:50 UTC 2012


On Wed, Aug 08, 2012 at 12:49:11PM +0000, Emmanuel Dreyfus wrote:
> The problem is caused by a non portable behavior of swapcontext(): on 
> Linux it remains in the same thread, on NetBSD it switches to the
> thread where getcontext()/makecontext() was run.

Is the attached patch resonable enough to be posted in gerrit?

-- 
Emmanuel Dreyfus
manu at netbsd.org
-------------- next part --------------
diff --git a/libglusterfs/src/syncop.c b/libglusterfs/src/syncop.c
index c84832d..5e7634a 100644
--- a/libglusterfs/src/syncop.c
+++ b/libglusterfs/src/syncop.c
@@ -15,6 +15,8 @@
 
 #include "syncop.h"
 
+static int syntask_newctx (struct synctask *);
+
 static void
 __run (struct synctask *task)
 {
@@ -82,6 +84,14 @@ __wait (struct synctask *task)
 void
 synctask_yield (struct synctask *task)
 {
+        if (task->stack == NULL) {
+                int ret;
+
+                ret = syntask_newctx (task);
+                if (ret != 0)
+                        return;
+        }
+
         if (swapcontext (&task->ctx, &task->proc->sched) < 0) {
                 gf_log ("syncop", GF_LOG_ERROR,
                         "swapcontext failed (%s)", strerror (errno));
@@ -164,6 +174,33 @@ synctask_done (struct synctask *task)
 }
 
 
+static int
+syntask_newctx (struct synctask *newtask)
+{
+        if (getcontext (&newtask->ctx) < 0) {
+                gf_log ("syncop", GF_LOG_ERROR,
+                        "getcontext failed (%s)",
+                        strerror (errno));
+                goto err;
+        }
+
+        newtask->stack = CALLOC (1, newtask->env->stacksize);
+        if (!newtask->stack) {
+                gf_log ("syncop", GF_LOG_ERROR,
+                        "out of memory for stack");
+                goto err;
+        }
+
+        newtask->ctx.uc_stack.ss_sp   = newtask->stack;
+        newtask->ctx.uc_stack.ss_size = newtask->env->stacksize;
+
+        makecontext (&newtask->ctx, (void *) synctask_wrap, 2, newtask);
+
+        return 0;
+err:
+        return -1;
+}
+
 int
 synctask_new (struct syncenv *env, synctask_fn_t fn, synctask_cbk_t cbk,
               call_frame_t *frame, void *opaque)
@@ -195,25 +232,6 @@ synctask_new (struct syncenv *env, synctask_fn_t fn, synctask_cbk_t cbk,
 
         INIT_LIST_HEAD (&newtask->all_tasks);
 
-        if (getcontext (&newtask->ctx) < 0) {
-                gf_log ("syncop", GF_LOG_ERROR,
-                        "getcontext failed (%s)",
-                        strerror (errno));
-                goto err;
-        }
-
-        newtask->stack = CALLOC (1, env->stacksize);
-        if (!newtask->stack) {
-                gf_log ("syncop", GF_LOG_ERROR,
-                        "out of memory for stack");
-                goto err;
-        }
-
-        newtask->ctx.uc_stack.ss_sp   = newtask->stack;
-        newtask->ctx.uc_stack.ss_size = env->stacksize;
-
-        makecontext (&newtask->ctx, (void *) synctask_wrap, 2, newtask);
-
 	newtask->state = SYNCTASK_INIT;
 
         newtask->slept = 1;
@@ -292,6 +310,14 @@ synctask_switchto (struct synctask *task)
         task->woken = 0;
         task->slept = 0;
 
+        if (task->stack == NULL) {
+                int ret;
+
+                ret = syntask_newctx (task);
+                if (ret != 0)
+                        return;
+        }
+
         if (swapcontext (&task->proc->sched, &task->ctx) < 0) {
                 gf_log ("syncop", GF_LOG_ERROR,
                         "swapcontext failed (%s)", strerror (errno));


More information about the Gluster-devel mailing list