1 /* context_sysv - context switching with ucontextes from System V */
3 /* Copyright (c) 2009, 2010. The SimGrid Team.
4 * All rights reserved. */
6 /* This program is free software; you can redistribute it and/or modify it
7 * under the terms of the license (GNU LGPL) which comes with this package. */
11 #include "smx_context_sysv_private.h"
13 #ifdef HAVE_VALGRIND_VALGRIND_H
14 # include <valgrind/valgrind.h>
15 #endif /* HAVE_VALGRIND_VALGRIND_H */
18 #include "win32_ucontext.h"
19 #include "win32_ucontext.c"
24 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_context);
27 smx_ctx_sysv_create_context(xbt_main_func_t code, int argc, char **argv,
28 void_f_pvoid_t cleanup_func,
32 static void smx_ctx_sysv_wrapper(void);
34 void SIMIX_ctx_sysv_factory_init(smx_context_factory_t * factory)
37 smx_ctx_base_factory_init(factory);
39 (*factory)->create_context = smx_ctx_sysv_create_context;
40 /* Do not overload that method (*factory)->finalize */
41 (*factory)->free = smx_ctx_sysv_free;
42 (*factory)->stop = smx_ctx_sysv_stop;
43 (*factory)->suspend = smx_ctx_sysv_suspend;
44 (*factory)->resume = smx_ctx_sysv_resume;
45 (*factory)->name = "smx_sysv_context_factory";
49 smx_ctx_sysv_create_context_sized(size_t size, xbt_main_func_t code,
50 int argc, char **argv,
51 void_f_pvoid_t cleanup_func,
55 smx_ctx_sysv_t context =
56 (smx_ctx_sysv_t) smx_ctx_base_factory_create_context_sized(size,
63 /* If the user provided a function for the process then use it
64 otherwise is the context for maestro */
67 xbt_assert2(getcontext(&(context->uc)) == 0,
68 "Error in context saving: %d (%s)", errno,
71 context->uc.uc_link = NULL;
73 context->uc.uc_stack.ss_sp =
74 pth_skaddr_makecontext(context->stack, CONTEXT_STACK_SIZE);
76 context->uc.uc_stack.ss_size =
77 pth_sksize_makecontext(context->stack, CONTEXT_STACK_SIZE);
79 #ifdef HAVE_VALGRIND_VALGRIND_H
80 context->valgrind_stack_id =
81 VALGRIND_STACK_REGISTER(context->uc.uc_stack.ss_sp,
82 ((char *) context->uc.uc_stack.ss_sp) +
83 context->uc.uc_stack.ss_size);
84 #endif /* HAVE_VALGRIND_VALGRIND_H */
86 makecontext(&((smx_ctx_sysv_t) context)->uc, smx_ctx_sysv_wrapper, 0);
89 return (smx_context_t) context;
94 smx_ctx_sysv_create_context(xbt_main_func_t code, int argc, char **argv,
95 void_f_pvoid_t cleanup_func, void *cleanup_arg)
98 return smx_ctx_sysv_create_context_sized(sizeof(s_smx_ctx_sysv_t),
99 code, argc, argv, cleanup_func,
104 void smx_ctx_sysv_free(smx_context_t context)
109 #ifdef HAVE_VALGRIND_VALGRIND_H
110 VALGRIND_STACK_DEREGISTER(((smx_ctx_sysv_t)
111 context)->valgrind_stack_id);
112 #endif /* HAVE_VALGRIND_VALGRIND_H */
115 smx_ctx_base_free(context);
118 void smx_ctx_sysv_stop(smx_context_t context)
120 smx_ctx_base_stop(context);
122 smx_ctx_sysv_suspend(context);
125 void smx_ctx_sysv_wrapper()
127 /*FIXME: I would like to avoid accessing simix_global to get the current
128 context by passing it as an argument of the wrapper function. The problem
129 is that this function is called from smx_ctx_sysv_start, and uses
130 makecontext for calling it, and the stupid posix specification states that
131 all the arguments of the function should be int(32 bits), making it useless
132 in 64-bit architectures where pointers are 64 bit long.
134 smx_ctx_sysv_t context =
135 (smx_ctx_sysv_t) simix_global->current_process->context;
137 (context->super.code) (context->super.argc, context->super.argv);
139 smx_ctx_sysv_stop((smx_context_t) context);
142 void smx_ctx_sysv_suspend(smx_context_t context)
144 ucontext_t maestro_ctx =
145 ((smx_ctx_sysv_t) simix_global->maestro_process->context)->uc;
147 int rv = swapcontext(&((smx_ctx_sysv_t) context)->uc, &maestro_ctx);
149 xbt_assert0((rv == 0), "Context swapping failure");
152 void smx_ctx_sysv_resume(smx_context_t new_context)
154 smx_ctx_sysv_t maestro =
155 (smx_ctx_sysv_t) simix_global->maestro_process->context;
158 swapcontext(&(maestro->uc), &((smx_ctx_sysv_t) new_context)->uc);
160 xbt_assert0((rv == 0), "Context swapping failure");