- xbt_context_t res = NULL;
-
- res = xbt_new0(s_xbt_context_t,1);
-
- res->code = code;
- #ifdef CONTEXT_THREADS
- res->mutex = xbt_mutex_init();
- res->cond = xbt_thcond_init();
- #else
-
- xbt_assert2(getcontext(&(res->uc))==0,"Error in context saving: %d (%s)", errno, strerror(errno));
- res->uc.uc_link = NULL;
- /* res->uc.uc_link = &(current_context->uc); */
- /* WARNING : when this context is over, the current_context (i.e. the
- father), is awaken... Theorically, the wrapper should prevent using
- this feature. */
- res->uc.uc_stack.ss_sp = pth_skaddr_makecontext(res->stack,STACK_SIZE);
- res->uc.uc_stack.ss_size = pth_sksize_makecontext(res->stack,STACK_SIZE);
- #endif /* CONTEXT_THREADS or not */
-
- res->argc = argc;
- res->argv = argv;
- res->startup_func = startup_func;
- res->startup_arg = startup_arg;
- res->cleanup_func = cleanup_func;
- res->cleanup_arg = cleanup_arg;
- res->exception = xbt_new(ex_ctx_t,1);
- XBT_CTX_INITIALIZE(res->exception);
-
- xbt_swag_insert(res, context_living);
-
- return res;
+#ifdef CONTEXT_THREADS
+ /* create the process and start it */
+ context->thread = xbt_os_thread_create(context->name,__context_wrapper, context);
+
+ /* wait the starting of the newly created process */
+ xbt_os_sem_acquire(context->end);
+#else
+ makecontext(&(context->uc), (void (*)(void)) __context_wrapper, 1, context);
+#endif
+}
+
+/* Stops current context: calls user's cleanup function, kills os thread, and yields back to maestro */
+static void xbt_context_stop(int retvalue)
+{
+ DEBUG1("--------- %p is exiting ---------", current_context);
+
+ if (current_context->cleanup_func) {
+ DEBUG0("Calling cleanup function");
+ current_context->cleanup_func(current_context->cleanup_arg);
+ }
+
+ DEBUG0("Putting context in the to_destroy set");
+ xbt_swag_remove(current_context, context_living);
+ xbt_swag_insert(current_context, context_to_destroy);
+
+ DEBUG0("Yielding");
+
+#ifdef CONTEXT_THREADS
+ /* signal to the maestro that it has finished */
+ xbt_os_sem_release(current_context->end);
+ /* exit*/
+ xbt_os_thread_exit(NULL); /* We should provide return value in case other wants it */
+#else
+ __xbt_context_yield(current_context);
+#endif
+ THROW_IMPOSSIBLE;
+}
+
+
+
+/** Garbage collection
+ *
+ * Should be called some time to time to free the memory allocated for contexts
+ * that have finished executing their main functions.
+ */
+void xbt_context_empty_trash(void)
+{
+ xbt_context_t context = NULL;
+
+ DEBUG1("Emptying trashbin (%d contexts to free)",
+ xbt_swag_size(context_to_destroy));
+
+ while ((context = xbt_swag_extract(context_to_destroy)))
+ xbt_context_free(context);
+}
+
+/*********************/
+/* context switching */
+/*********************/
+
+static void __xbt_context_yield(xbt_context_t context)
+{
+ xbt_assert0(current_context, "You have to call context_init() first.");
+ xbt_assert0(context, "Invalid argument");
+
+ if (current_context == context) {
+ DEBUG1
+ ("--------- current_context (%p) is yielding back to maestro ---------",
+ context);
+ } else {
+ DEBUG2
+ ("--------- current_context (%p) is yielding to context(%p) ---------",
+ current_context, context);
+ }
+
+#ifdef CONTEXT_THREADS
+
+ if(current_context != init_context && !context->iwannadie)
+ {/* it's a process and it doesn't wants to die (xbt_context_yield()) */
+
+ /* save the current context */
+ xbt_context_t self = current_context;
+
+ /* update the current context to this context */
+ current_context = context;
+
+ /* yield itself */
+ yield(context);
+
+ /* restore the current context to the previously saved context */
+ current_context = self;
+ }
+ else
+ { /* maestro wants to schedule a process or a process wants to die (xbt_context_schedule() or xbt_context_kill())*/
+
+ /* save the current context */
+ xbt_context_t self = current_context;
+
+ /* update the current context */
+ current_context = context;
+
+ /* schedule the process associated with this context */
+ schedule(context);
+
+ /* restore the current context to the previously saved context */
+ current_context = self;
+ }
+
+#else /* use SUSv2 contexts */
+ VOIRP(current_context);
+ VOIRP(current_context->save);
+
+ VOIRP(context);
+ VOIRP(context->save);
+
+ int return_value = 0;
+
+ if (context->save == NULL) {
+ DEBUG1("[%p] **** Yielding to somebody else ****", current_context);
+ DEBUG2("Saving current_context value (%p) to context(%p)->save",
+ current_context, context);
+ context->save = current_context;
+ DEBUG1("current_context becomes context(%p) ", context);
+ current_context = context;
+ DEBUG1
+ ("Current position memorized (context->save). Jumping to context (%p)",
+ context);
+ return_value = swapcontext(&(context->save->uc), &(context->uc));
+ xbt_assert0((return_value == 0), "Context swapping failure");
+ DEBUG1("I am (%p). Coming back\n", context);
+ } else {
+ xbt_context_t old_context = context->save;
+
+ DEBUG1("[%p] **** Back ! ****", context);
+ DEBUG2("Setting current_context (%p) to context(%p)->save",
+ current_context, context);
+ current_context = context->save;
+ DEBUG1("Setting context(%p)->save to NULL", context);
+ context->save = NULL;
+ DEBUG2("Current position memorized (%p). Jumping to context (%p)",
+ context, old_context);
+ return_value = swapcontext(&(context->uc), &(old_context->uc));
+ xbt_assert0((return_value == 0), "Context swapping failure");
+ DEBUG1("I am (%p). Coming back\n", context);
+ }
+#endif
+
+ if (current_context->iwannadie)
+ xbt_context_stop(1);