Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
47a7e55049155fb49ffda80276f7639adb814a43
[simgrid.git] / src / simix / smx_context_sysv.c
1 /* $Id$ */
2
3 /* context_sysv - implementation of context switching with ucontextes from Sys V */
4
5 /* Copyright (c) 2004-2008 the SimGrid team. All right reserved */
6
7 /* This program is free software; you can redistribute it and/or modify it
8  * under the terms of the license (GNU LGPL) which comes with this package. */
9
10 #include "smx_context_private.h"
11 #include "context_sysv_config.h"        /* loads context system definitions */
12 #include "portable.h"
13 #include <ucontext.h>           /* context relative declarations */
14
15 /* lower this if you want to reduce the memory consumption  */
16 #define STACK_SIZE 128*1024
17
18 #ifdef HAVE_VALGRIND_VALGRIND_H
19 #  include <valgrind/valgrind.h>
20 #endif /* HAVE_VALGRIND_VALGRIND_H */
21
22 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_context);
23
24 typedef struct s_smx_ctx_sysv {
25   s_smx_ctx_base_t super;       /* Fields of super implementation */
26   ucontext_t uc;                /* the thread that execute the code */
27   char stack[STACK_SIZE];       /* the thread stack size */
28 #ifdef HAVE_VALGRIND_VALGRIND_H
29   unsigned int valgrind_stack_id;       /* the valgrind stack id */
30 #endif                          
31 } s_smx_ctx_sysv_t, *smx_ctx_sysv_t;
32
33 static smx_context_t 
34 smx_ctx_sysv_create_context(xbt_main_func_t code, int argc, char** argv,
35     void_f_pvoid_t cleanup_func, void* cleanup_arg);
36
37
38 static void smx_ctx_sysv_wrapper(void);
39
40 void SIMIX_ctx_sysv_factory_init(smx_context_factory_t *factory) {
41
42   smx_ctx_base_factory_init(factory);
43
44   (*factory)->create_context = smx_ctx_sysv_create_context;
45   /* Do not overload that method (*factory)->finalize */
46   (*factory)->free = smx_ctx_sysv_free;
47   (*factory)->stop = smx_ctx_sysv_stop;
48   (*factory)->suspend = smx_ctx_sysv_suspend;
49   (*factory)->resume = smx_ctx_sysv_resume;
50   (*factory)->name = "smx_sysv_context_factory";
51 }
52
53 smx_context_t
54 smx_ctx_sysv_create_context_sized(size_t size, xbt_main_func_t code, int argc, char** argv,
55     void_f_pvoid_t cleanup_func, void* cleanup_arg) {
56
57   smx_ctx_sysv_t context = (smx_ctx_sysv_t)smx_ctx_base_factory_create_context_sized
58       (size, code,argc,argv,cleanup_func,cleanup_arg);
59
60   /* If the user provided a function for the process then use it
61      otherwise is the context for maestro */
62   if(code){
63
64     xbt_assert2(getcontext(&(context->uc)) == 0,
65         "Error in context saving: %d (%s)", errno, strerror(errno));
66
67     context->uc.uc_link = NULL;
68
69     context->uc.uc_stack.ss_sp =
70         pth_skaddr_makecontext(context->stack, STACK_SIZE);
71
72     context->uc.uc_stack.ss_size =
73         pth_sksize_makecontext(context->stack, STACK_SIZE);
74
75 #ifdef HAVE_VALGRIND_VALGRIND_H
76     context->valgrind_stack_id =
77         VALGRIND_STACK_REGISTER(context->uc.uc_stack.ss_sp,
78             ((char *) context->uc.uc_stack.ss_sp) +
79             context->uc.uc_stack.ss_size);
80 #endif /* HAVE_VALGRIND_VALGRIND_H */
81
82     makecontext(&((smx_ctx_sysv_t)context)->uc, smx_ctx_sysv_wrapper, 0);
83   }
84
85   return (smx_context_t)context;
86
87 }
88
89 static smx_context_t
90 smx_ctx_sysv_create_context(xbt_main_func_t code, int argc, char** argv,
91     void_f_pvoid_t cleanup_func, void* cleanup_arg) {
92
93   return smx_ctx_sysv_create_context_sized(sizeof(s_smx_ctx_sysv_t),
94       code,argc,argv,cleanup_func,cleanup_arg);
95
96 }
97
98 void smx_ctx_sysv_free(smx_context_t context) {
99
100   if (context){
101
102 #ifdef HAVE_VALGRIND_VALGRIND_H
103     VALGRIND_STACK_DEREGISTER(((smx_ctx_sysv_t) context)->valgrind_stack_id);
104 #endif /* HAVE_VALGRIND_VALGRIND_H */
105
106   }
107   smx_ctx_base_free(context);
108 }
109
110 void smx_ctx_sysv_stop(smx_context_t context) {
111   smx_ctx_base_stop(context);
112
113   smx_ctx_sysv_suspend(context);
114 }
115
116 void smx_ctx_sysv_wrapper() {
117   /*FIXME: I would like to avoid accessing simix_global to get the current
118     context by passing it as an argument of the wrapper function. The problem
119     is that this function is called from smx_ctx_sysv_start, and uses
120     makecontext for calling it, and the stupid posix specification states that
121     all the arguments of the function should be int(32 bits), making it useless
122     in 64-bit architectures where pointers are 64 bit long.
123    */
124   smx_ctx_sysv_t context = 
125       (smx_ctx_sysv_t)simix_global->current_process->context;
126
127   (context->super.code) (context->super.argc, context->super.argv);
128
129   smx_ctx_sysv_stop((smx_context_t)context);
130 }
131
132 void smx_ctx_sysv_suspend(smx_context_t context) {
133   ucontext_t maestro_ctx = ((smx_ctx_sysv_t)simix_global->maestro_process->context)->uc;
134
135   int rv = swapcontext(&((smx_ctx_sysv_t) context)->uc, &maestro_ctx);
136
137   xbt_assert0((rv == 0), "Context swapping failure");
138 }
139
140 void smx_ctx_sysv_resume(smx_context_t new_context) {
141   smx_ctx_sysv_t maestro = (smx_ctx_sysv_t)simix_global->maestro_process->context;
142
143   int rv = swapcontext(&(maestro->uc), &((smx_ctx_sysv_t)new_context)->uc);
144
145   xbt_assert0((rv == 0), "Context swapping failure");
146 }