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));