Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
54a9fdf69d323c759ea584b2f42cf9b7c5659eaf
[simgrid.git] / src / simix / smx_context_ruby.c
1 /* $Id$ */
2
3 /* context_Ruby - implementation of context switching with ruby coroutines */
4
5 /* Copyright (c) 2010, 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 #include <ruby.h>
10 #include "private.h"
11 #include "xbt/function_types.h"
12 #include "xbt/sysdep.h"
13 #include "xbt/log.h"
14 #include "xbt/asserts.h"
15 #include "context_sysv_config.h"
16 #include "bindings/ruby/rb_msg_process.c"
17
18
19 typedef struct s_smx_ctx_ruby
20
21 {
22   SMX_CTX_BASE_T;
23   VALUE process;   // The  Ruby Process Instance 
24   //...
25 }s_smx_ctx_ruby_t,*smx_ctx_ruby_t;
26   
27 static smx_context_t
28 smx_ctx_ruby_create_context(xbt_main_func_t code,int argc,char** argv,
29                             void_f_pvoid_t cleanup_func,void *cleanup_arg);
30
31 static int smx_ctx_ruby_factory_finalize(smx_context_factory_t *factory);
32
33 static void smx_ctx_ruby_free(smx_context_t context);
34
35 static void smx_ctx_ruby_start(smx_context_t context);
36
37 static void smx_ctx_ruby_stop(smx_context_t context);
38
39 static void smx_ctx_ruby_suspend(smx_context_t context);
40
41 static void 
42   smx_ctx_ruby_resume(smx_context_t old_context,smx_context_t new_context);
43
44 static void smx_ctx_ruby_wrapper(void); 
45
46
47
48 void SIMIX_ctx_ruby_factory_init(smx_context_factory_t *factory)
49 {
50   
51  *factory = xbt_new0(s_smx_context_factory_t,1);
52  
53  (*factory)->create_context = smx_ctx_ruby_create_context;
54  (*factory)->finalize = smx_ctx_ruby_factory_finalize;
55  (*factory)->free = smx_ctx_ruby_free;
56  (*factory)->start = smx_ctx_ruby_start;
57  (*factory)->stop = smx_ctx_ruby_stop;
58  (*factory)->suspend = smx_ctx_ruby_suspend;
59  (*factory)->resume = smx_ctx_ruby_resume;
60  (*factory)->name = "smx_ruby_context_factory";
61   ruby_init();
62   ruby_init_loadpath();
63   #ifdef MY_DEBUG
64   printf("SIMIX_ctx_ruby_factory_init...Done\n");
65   #endif 
66 }
67   
68 static int smx_ctx_ruby_factory_finalize(smx_context_factory_t *factory)
69 {
70   
71  free(*factory);
72  *factory = NULL;
73  return 0;
74  
75 }
76
77 static smx_context_t 
78   smx_ctx_ruby_create_context(xbt_main_func_t code,int argc,char** argv,
79                               void_f_pvoid_t cleanup_func,void* cleanup_arg)
80 {
81   
82   smx_ctx_ruby_t context = xbt_new0(s_smx_ctx_ruby_t,1);
83   
84   /*if the user provided a function for the process , then use it 
85   Otherwise it's the context for maestro */
86   if( code )
87   {
88    context->cleanup_func = cleanup_func;
89    context->cleanup_arg = cleanup_arg;
90    context->process = (VALUE)code;
91    
92   #ifdef MY_DEBUG
93   printf("smx_ctx_ruby_create_context...Done\n");
94   #endif
95    
96   }
97   return (smx_context_t) context;
98   
99 }
100   
101 static void smx_ctx_ruby_free(smx_context_t context)
102 {
103  /* VALUE process;
104   if (context)
105   {
106    smx_ctx_ruby_t ctx_ruby = (smx_ctx_ruby_t) context;
107    
108    if (ctx_ruby->process){
109      // if the Ruby Process is Alive , Join it   
110    // if ( process_isAlive(ctx_ruby->process))
111     {
112       process = ctx_ruby->process;
113       ctx_ruby->process = Qnil;
114       process_join(process);
115     } 
116     
117   }
118   free(context);
119   context = NULL; 
120   }*/
121   free (context);
122   context = NULL;
123     #ifdef MY_DEBUG
124   printf("smx_ctx_ruby_free_context...Done\n");
125   #endif
126   
127 }
128
129 static void smx_ctx_ruby_start(smx_context_t context)
130 {
131    
132  /* Already Done .. Since a Ruby Process is launched within initialization
133  We Start it Within the Initializer ... We Use the Semaphore To Keep 
134  The Thread Alive Waitin' For Mutex Signal to Execute The Main*/
135  
136 }
137
138 static void smx_ctx_ruby_stop(smx_context_t context)
139 {
140   
141   
142   VALUE process = Qnil;
143   smx_ctx_ruby_t ctx_ruby,current;
144   
145   if ( context->cleanup_func)
146     (*(context->cleanup_func)) (context->cleanup_arg);
147   
148   ctx_ruby = (smx_ctx_ruby_t) context;
149   
150   // Well , Let's Do The Same as JNI Stoppin' Process
151   if ( simix_global->current_process->iwannadie )
152   {
153    if( ctx_ruby->process )
154    {
155     //if the Ruby Process still Alive ,let's Schedule it
156     if ( process_isAlive( ctx_ruby->process ) )
157     {
158      current = (smx_ctx_ruby_t)simix_global->current_process->context;
159      process_schedule(current->process); 
160      process = ctx_ruby->process;     
161      // interupt/kill The Ruby Process
162      process_kill(process);
163     }
164    }    
165   }else {
166    
167     process = ctx_ruby->process;
168     ctx_ruby->process = Qnil;
169     
170   }
171   #ifdef MY_DEBUG
172   printf("smx_ctx_ruby_stop...Done\n");
173   #endif
174 }
175
176 static void smx_ctx_ruby_suspend(smx_context_t context)
177 {
178
179 if (context)
180 {
181 smx_ctx_ruby_t ctx_ruby = (smx_ctx_ruby_t) context;
182   if (ctx_ruby->process)
183     process_unschedule( ctx_ruby->process ) ;
184 #ifdef MY_DEBUG
185   printf("smx_ctx_ruby_unschedule...Done\n");
186 #endif
187 }
188   
189   else
190     rb_raise(rb_eRuntimeError,"smx_ctx_ruby_suspend failed");
191   
192 }
193
194 static void smx_ctx_ruby_resume(smx_context_t old_context,smx_context_t new_context)
195 {
196   
197  smx_ctx_ruby_t ctx_ruby = (smx_ctx_ruby_t) new_context;
198  process_schedule(ctx_ruby->process);
199  
200   #ifdef MY_DEBUG
201     printf("smx_ctx_ruby_schedule...Done\n");
202   #endif
203  
204 }