Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Do not request status if not requested by caller.
[simgrid.git] / src / simix / smx_context_sysv.c
1 /* context_sysv - context switching with ucontextes from System V           */
2
3 /* Copyright (c) 2009, 2010. The SimGrid Team.
4  * All rights reserved.                                                     */
5
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. */
8
9
10
11 #include "smx_context_sysv_private.h"
12
13 #ifdef HAVE_VALGRIND_VALGRIND_H
14 #  include <valgrind/valgrind.h>
15 #endif                          /* HAVE_VALGRIND_VALGRIND_H */
16
17 #ifdef _XBT_WIN32
18 #include "win32_ucontext.h"
19 #include "win32_ucontext.c"
20 #else
21 #include "ucontext.h"
22 #endif
23
24 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_context);
25
26 static smx_context_t
27 smx_ctx_sysv_create_context(xbt_main_func_t code, int argc, char **argv,
28                             void_f_pvoid_t cleanup_func,
29                             void *cleanup_arg);
30
31
32 static void smx_ctx_sysv_wrapper(void);
33
34 void SIMIX_ctx_sysv_factory_init(smx_context_factory_t * factory)
35 {
36
37   smx_ctx_base_factory_init(factory);
38
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";
46 }
47
48 smx_context_t
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,
52                                   void *cleanup_arg)
53 {
54
55   smx_ctx_sysv_t context =
56       (smx_ctx_sysv_t) smx_ctx_base_factory_create_context_sized(size,
57                                                                  code,
58                                                                  argc,
59                                                                  argv,
60                                                                  cleanup_func,
61                                                                  cleanup_arg);
62
63   /* If the user provided a function for the process then use it
64      otherwise is the context for maestro */
65   if (code) {
66
67     xbt_assert2(getcontext(&(context->uc)) == 0,
68                 "Error in context saving: %d (%s)", errno,
69                 strerror(errno));
70
71     context->uc.uc_link = NULL;
72
73     context->uc.uc_stack.ss_sp =
74         pth_skaddr_makecontext(context->stack, CONTEXT_STACK_SIZE);
75
76     context->uc.uc_stack.ss_size =
77         pth_sksize_makecontext(context->stack, CONTEXT_STACK_SIZE);
78
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 */
85
86     makecontext(&((smx_ctx_sysv_t) context)->uc, smx_ctx_sysv_wrapper, 0);
87   }
88
89   return (smx_context_t) context;
90
91 }
92
93 static smx_context_t
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)
96 {
97
98   return smx_ctx_sysv_create_context_sized(sizeof(s_smx_ctx_sysv_t),
99                                            code, argc, argv, cleanup_func,
100                                            cleanup_arg);
101
102 }
103
104 void smx_ctx_sysv_free(smx_context_t context)
105 {
106
107   if (context) {
108
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 */
113
114   }
115   smx_ctx_base_free(context);
116 }
117
118 void smx_ctx_sysv_stop(smx_context_t context)
119 {
120   smx_ctx_base_stop(context);
121
122   smx_ctx_sysv_suspend(context);
123 }
124
125 void smx_ctx_sysv_wrapper()
126 {
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.
133    */
134   smx_ctx_sysv_t context =
135       (smx_ctx_sysv_t) simix_global->current_process->context;
136
137   (context->super.code) (context->super.argc, context->super.argv);
138
139   smx_ctx_sysv_stop((smx_context_t) context);
140 }
141
142 void smx_ctx_sysv_suspend(smx_context_t context)
143 {
144   ucontext_t maestro_ctx =
145       ((smx_ctx_sysv_t) simix_global->maestro_process->context)->uc;
146
147   int rv = swapcontext(&((smx_ctx_sysv_t) context)->uc, &maestro_ctx);
148
149   xbt_assert0((rv == 0), "Context swapping failure");
150 }
151
152 void smx_ctx_sysv_resume(smx_context_t new_context)
153 {
154   smx_ctx_sysv_t maestro =
155       (smx_ctx_sysv_t) simix_global->maestro_process->context;
156
157   int rv =
158       swapcontext(&(maestro->uc), &((smx_ctx_sysv_t) new_context)->uc);
159
160   xbt_assert0((rv == 0), "Context swapping failure");
161 }