Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of git+ssh://scm.gforge.inria.fr//gitroot/simgrid/simgrid
[simgrid.git] / src / simix / smx_context_raw.c
1 /* context_raw - fast context switching inspired from System V ucontexts   */
2
3 /* Copyright (c) 2009-2014. 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 #include <math.h>
9 #include "smx_private.h"
10 #include "xbt/parmap.h"
11 #include "xbt/dynar.h"
12 #include "mc/mc.h"
13
14 typedef char * raw_stack_t;
15 typedef void (*rawctx_entry_point_t)(void *);
16
17 typedef struct s_smx_ctx_raw {
18   s_smx_ctx_base_t super;         /* Fields of super implementation */
19   char *malloced_stack;           /* malloced area containing the stack */
20   raw_stack_t stack_top;          /* pointer to stack top (within previous area) */
21 #ifdef TIME_BENCH_PER_SR
22   unsigned int thread;            /* Just for measuring purposes */
23 #endif
24 } s_smx_ctx_raw_t, *smx_ctx_raw_t;
25
26 #ifdef CONTEXT_THREADS
27 static xbt_parmap_t raw_parmap;
28 static smx_ctx_raw_t* raw_workers_context;    /* space to save the worker context in each thread */
29 static unsigned long raw_threads_working;     /* number of threads that have started their work */
30 static xbt_os_thread_key_t raw_worker_id_key; /* thread-specific storage for the thread id */
31 #endif
32
33 #ifdef ADAPTIVE_THRESHOLD
34 #define SCHED_ROUND_LIMIT 5
35 xbt_os_timer_t round_time;
36 double par_time,seq_time;
37 double par_ratio,seq_ratio;
38 int reached_seq_limit, reached_par_limit;
39 static unsigned int par_proc_that_ran = 0,seq_proc_that_ran = 0;  /* Counters of processes that have run in SCHED_ROUND_LIMIT scheduling rounds */
40 static unsigned int seq_sched_round=0, par_sched_round=0; /* Amount of SR that ran serial/parallel*/
41 /*Varables used to calculate running variance and mean*/
42 double prev_avg_par_proc=0,prev_avg_seq_proc=0;
43 double delta=0;
44 double s_par_proc=0,s_seq_proc=0; /*Standard deviation of number of processes computed in par/seq during the current simulation*/
45 double avg_par_proc=0,sd_par_proc=0;
46 double avg_seq_proc=0,sd_seq_proc=0;
47 double par_window=4294967296,seq_window=0; /*par_window is initially 1<<32*/
48 #endif
49
50 static unsigned long raw_process_index = 0;   /* index of the next process to run in the
51                                                * list of runnable processes */
52 static smx_ctx_raw_t raw_maestro_context;
53
54 extern raw_stack_t raw_makecontext(char* malloced_stack, int stack_size,
55                                    rawctx_entry_point_t entry_point, void* arg);
56 extern void raw_swapcontext(raw_stack_t* old, raw_stack_t new);
57
58 #if PROCESSOR_x86_64
59 __asm__ (
60 #if defined(APPLE)
61    ".text\n"
62    ".globl _raw_makecontext\n"
63    "_raw_makecontext:\n"
64 #elif defined(_WIN32)
65    ".text\n"
66    ".globl raw_makecontext\n"
67    "raw_makecontext:\n"
68 #else
69    ".text\n"
70    ".globl raw_makecontext\n"
71    ".type raw_makecontext,@function\n"
72    "raw_makecontext:\n"/* Calling convention sets the arguments in rdi, rsi, rdx and rcx, respectively */
73 #endif
74    "   mov %rdi,%rax\n"      /* stack */
75    "   add %rsi,%rax\n"      /* size  */
76    "   andq $-16, %rax\n"    /* align stack */
77    "   movq $0,   -8(%rax)\n" /* @return for func */
78    "   mov %rdx,-16(%rax)\n" /* func */
79    "   mov %rcx,-24(%rax)\n" /* arg/rdi */
80    "   movq $0,  -32(%rax)\n" /* rsi */
81    "   movq $0,  -40(%rax)\n" /* rdx */
82    "   movq $0,  -48(%rax)\n" /* rcx */
83    "   movq $0,  -56(%rax)\n" /* r8  */
84    "   movq $0,  -64(%rax)\n" /* r9  */
85    "   movq $0,  -72(%rax)\n" /* rbp */
86    "   movq $0,  -80(%rax)\n" /* rbx */
87    "   movq $0,  -88(%rax)\n" /* r12 */
88    "   movq $0,  -96(%rax)\n" /* r13 */
89    "   movq $0, -104(%rax)\n" /* r14 */
90    "   movq $0, -112(%rax)\n" /* r15 */
91    "   sub $112,%rax\n"
92    "   ret\n"
93 );
94
95 __asm__ (
96 #if defined(APPLE)
97    ".text\n"
98    ".globl _raw_swapcontext\n"
99    "_raw_swapcontext:\n"
100 #elif defined(_WIN32)
101    ".text\n"
102    ".globl raw_swapcontext\n"
103    "raw_swapcontext:\n"
104 #else
105    ".text\n"
106    ".globl raw_swapcontext\n"
107    ".type raw_swapcontext,@function\n"
108    "raw_swapcontext:\n" /* Calling convention sets the arguments in rdi and rsi, respectively */
109 #endif
110    "   push %rdi\n"
111    "   push %rsi\n"
112    "   push %rdx\n"
113    "   push %rcx\n"
114    "   push %r8\n"
115    "   push %r9\n"
116    "   push %rbp\n"
117    "   push %rbx\n"
118    "   push %r12\n"
119    "   push %r13\n"
120    "   push %r14\n"
121    "   push %r15\n"
122    "   mov %rsp,(%rdi)\n" /* old */
123    "   mov %rsi,%rsp\n" /* new */
124    "   pop %r15\n"
125    "   pop %r14\n"
126    "   pop %r13\n"
127    "   pop %r12\n"
128    "   pop %rbx\n"
129    "   pop %rbp\n"
130    "   pop %r9\n"
131    "   pop %r8\n"
132    "   pop %rcx\n"
133    "   pop %rdx\n"
134    "   pop %rsi\n"
135    "   pop %rdi\n"
136    "   ret\n"
137 );
138 #elif PROCESSOR_i686
139 __asm__ (
140 #if defined(APPLE) || defined(_WIN32)
141    ".text\n"
142    ".globl _raw_makecontext\n"
143    "_raw_makecontext:\n"
144 #else
145    ".text\n"
146    ".globl raw_makecontext\n"
147    ".type raw_makecontext,@function\n"
148    "raw_makecontext:\n"
149 #endif
150    "   movl 4(%esp),%eax\n"   /* stack */
151    "   addl 8(%esp),%eax\n"   /* size  */
152    "   andl $-16, %eax\n"     /* align stack */
153    "   movl 12(%esp),%ecx\n"  /* func  */
154    "   movl 16(%esp),%edx\n"  /* arg   */
155    "   movl %edx, -4(%eax)\n"
156    "   movl $0,   -8(%eax)\n" /* @return for func */
157    "   movl %ecx,-12(%eax)\n"
158    "   movl $0,  -16(%eax)\n" /* ebp */
159    "   movl $0,  -20(%eax)\n" /* ebx */
160    "   movl $0,  -24(%eax)\n" /* esi */
161    "   movl $0,  -28(%eax)\n" /* edi */
162    "   subl $28,%eax\n"
163    "   retl\n"
164 );
165
166 __asm__ (
167 #if defined(APPLE) || defined(_WIN32)
168    ".text\n"
169    ".globl _raw_swapcontext\n"
170    "_raw_swapcontext:\n"
171 #else
172    ".text\n"
173    ".globl raw_swapcontext\n"
174    ".type raw_swapcontext,@function\n"
175    "raw_swapcontext:\n"
176 #endif
177    "   movl 4(%esp),%eax\n" /* old */
178    "   movl 8(%esp),%edx\n" /* new */
179    "   pushl %ebp\n"
180    "   pushl %ebx\n"
181    "   pushl %esi\n"
182    "   pushl %edi\n"
183    "   movl %esp,(%eax)\n"
184    "   movl %edx,%esp\n"
185    "   popl %edi\n"
186    "   popl %esi\n"
187    "   popl %ebx\n"
188    "   popl %ebp\n"
189    "   retl\n"
190 );
191 #else
192
193
194 /* If you implement raw contexts for other processors, don't forget to
195    update the definition of HAVE_RAWCTX in buildtools/Cmake/CompleteInFiles.cmake */
196
197 raw_stack_t raw_makecontext(char* malloced_stack, int stack_size,
198                             rawctx_entry_point_t entry_point, void* arg) {
199    THROW_UNIMPLEMENTED;
200 }
201
202 void raw_swapcontext(raw_stack_t* old, raw_stack_t new) {
203    THROW_UNIMPLEMENTED;
204 }
205
206 #endif
207
208 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_context);
209
210 #ifdef TIME_BENCH_PER_SR
211 #include "xbt/xbt_os_time.h"
212 #define NUM_THREADS 4
213 static xbt_os_timer_t timer;
214 static double time_thread_sr[NUM_THREADS];
215 static double time_thread_ssr[NUM_THREADS];
216 static double time_wasted_sr = 0;
217 static double time_wasted_ssr = 0;
218 static unsigned int sr_count = 0;
219 static unsigned int ssr_count = 0;
220 static char new_sr = 0;
221 #endif
222
223 #ifdef TIME_BENCH_ENTIRE_SRS
224 static unsigned int sr_count = 0;
225 static xbt_os_timer_t timer;
226 #endif
227
228 static void smx_ctx_raw_wrapper(smx_ctx_raw_t context);
229 static int smx_ctx_raw_factory_finalize(smx_context_factory_t *factory);
230 static smx_context_t smx_ctx_raw_create_context(xbt_main_func_t code, int argc,
231     char **argv, void_pfn_smxprocess_t cleanup_func, smx_process_t process);
232 static void smx_ctx_raw_free(smx_context_t context);
233 static void smx_ctx_raw_wrapper(smx_ctx_raw_t context);
234 static void smx_ctx_raw_stop(smx_context_t context);
235 static void smx_ctx_raw_suspend_serial(smx_context_t context);
236 static void smx_ctx_raw_resume_serial(smx_process_t first_process);
237 #ifdef TIME_BENCH_PER_SR
238 static void smx_ctx_raw_runall_serial(xbt_dynar_t processes);
239 void smx_ctx_raw_new_sr(void);
240 #else
241 static void smx_ctx_raw_runall_serial(void);
242 #endif
243 static void smx_ctx_raw_suspend_parallel(smx_context_t context);
244 static void smx_ctx_raw_resume_parallel(smx_process_t first_process);
245 static void smx_ctx_raw_runall_parallel(void);
246 static void smx_ctx_raw_runall(void);
247
248 /**
249  * \brief Initializes the raw context factory.
250  * \param factory where to initialize the factory
251  */
252 void SIMIX_ctx_raw_factory_init(smx_context_factory_t *factory)
253 {
254
255   XBT_VERB("Using raw contexts. Because the glibc is just not good enough for us.");
256   smx_ctx_base_factory_init(factory);
257
258   (*factory)->finalize  = smx_ctx_raw_factory_finalize;
259   (*factory)->create_context = smx_ctx_raw_create_context;
260   /* Do not overload that method (*factory)->finalize */
261   (*factory)->free = smx_ctx_raw_free;
262   (*factory)->stop = smx_ctx_raw_stop;
263   (*factory)->name = "smx_raw_context_factory";
264
265   if (SIMIX_context_is_parallel()) {
266 #ifdef CONTEXT_THREADS
267     int nthreads = SIMIX_context_get_nthreads();
268     xbt_os_thread_key_create(&raw_worker_id_key);
269     raw_parmap = xbt_parmap_new(nthreads, SIMIX_context_get_parallel_mode());
270     raw_workers_context = xbt_new(smx_ctx_raw_t, nthreads);
271     raw_maestro_context=NULL;
272
273 #endif
274     if (SIMIX_context_get_parallel_threshold() > 1) {
275       /* choose dynamically */
276       (*factory)->runall = smx_ctx_raw_runall;
277       (*factory)->suspend = NULL;
278     }
279     else {
280       /* always parallel */
281       (*factory)->runall = smx_ctx_raw_runall_parallel;
282       (*factory)->suspend = smx_ctx_raw_suspend_parallel;
283     }
284   }
285   else {
286     /* always serial */
287     (*factory)->runall = smx_ctx_raw_runall_serial;
288     (*factory)->suspend = smx_ctx_raw_suspend_serial;
289   }
290 #ifdef TIME_BENCH_ENTIRE_SRS
291   (*factory)->runall = smx_ctx_raw_runall;
292   (*factory)->suspend = NULL;
293   timer = xbt_os_timer_new();
294 #endif  
295
296 #ifdef ADAPTIVE_THRESHOLD
297   round_time = xbt_os_timer_new(); 
298   reached_seq_limit = 0;
299   reached_par_limit = 0;
300 #endif
301
302 #ifdef TIME_BENCH_PER_SR
303   timer = xbt_os_timer_new();
304 #endif
305 }
306
307 /**
308  * \brief Finalizes the raw context factory.
309  * \param factory the raw context factory
310  */
311 static int smx_ctx_raw_factory_finalize(smx_context_factory_t *factory)
312 {
313 #ifdef TIME_BENCH_PER_SR
314   XBT_VERB("Total wasted time in %u SR: %f", sr_count, time_wasted_sr);
315   XBT_VERB("Total wasted time in %u SSR: %f", ssr_count, time_wasted_ssr);
316 #endif
317
318 #ifdef CONTEXT_THREADS
319   if (raw_parmap)
320     xbt_parmap_destroy(raw_parmap);
321   xbt_free(raw_workers_context);
322 #endif
323   return smx_ctx_base_factory_finalize(factory);
324 }
325
326 /**
327  * \brief Creates a new raw context.
328  * \param code main function of this context or NULL to create the maestro
329  * context
330  * \param argc argument number
331  * \param argv arguments to pass to the main function
332  * \param cleanup_func a function to call to free the user data when the
333  * context finished
334  * \param process SIMIX process
335  */
336 static smx_context_t
337 smx_ctx_raw_create_context(xbt_main_func_t code, int argc, char **argv,
338                            void_pfn_smxprocess_t cleanup_func,
339                            smx_process_t process)
340 {
341
342   smx_ctx_raw_t context =
343       (smx_ctx_raw_t) smx_ctx_base_factory_create_context_sized(
344           sizeof(s_smx_ctx_raw_t),
345           code,
346           argc,
347           argv,
348           cleanup_func,
349           process);
350
351   /* if the user provided a function for the process then use it,
352      otherwise it is the context for maestro */
353      if (code) {
354        context->malloced_stack = SIMIX_context_stack_new();
355        context->stack_top =
356            raw_makecontext(context->malloced_stack,
357                            smx_context_usable_stack_size,
358                            (void_f_pvoid_t)smx_ctx_raw_wrapper, context);
359
360      } else {
361        if(process != NULL && raw_maestro_context==NULL)
362          raw_maestro_context = context;
363
364        if(MC_is_active())
365          MC_ignore_heap(&(raw_maestro_context->stack_top), sizeof(raw_maestro_context->stack_top));
366
367      }
368
369      return (smx_context_t) context;
370 }
371
372 /**
373  * \brief Destroys a raw context.
374  * \param context a raw context
375  */
376 static void smx_ctx_raw_free(smx_context_t context)
377 {
378   if (context) {
379     SIMIX_context_stack_delete(((smx_ctx_raw_t) context)->malloced_stack);
380   }
381   smx_ctx_base_free(context);
382 }
383
384 /**
385  * \brief Wrapper for the main function of a context.
386  * \param context a raw context
387  */
388 static void smx_ctx_raw_wrapper(smx_ctx_raw_t context)
389 {
390   (context->super.code) (context->super.argc, context->super.argv);
391
392   smx_ctx_raw_stop((smx_context_t) context);
393 }
394
395 /**
396  * \brief Stops a raw context.
397  *
398  * This function is called when the main function of the context if finished.
399  *
400  * \param context the current context
401  */
402 static void smx_ctx_raw_stop(smx_context_t context)
403 {
404   smx_ctx_base_stop(context);
405   simix_global->context_factory->suspend(context);
406 }
407
408 /**
409  * \brief Suspends a running context and resumes another one or returns to
410  * maestro.
411  * \param context the current context
412  */
413 static void smx_ctx_raw_suspend_serial(smx_context_t context)
414 {
415   /* determine the next context */
416   smx_context_t next_context;
417   unsigned long int i; 
418 #ifdef TIME_BENCH_PER_SR
419   i = ++raw_process_index;
420 #else
421   i = raw_process_index++;
422 #endif
423   if (i < xbt_dynar_length(simix_global->process_to_run)) {
424     /* execute the next process */
425     XBT_DEBUG("Run next process");
426     next_context = xbt_dynar_get_as(
427         simix_global->process_to_run, i, smx_process_t)->context;
428   }
429   else {
430     /* all processes were run, return to maestro */
431     XBT_DEBUG("No more process to run");
432     next_context = (smx_context_t) raw_maestro_context;
433   }
434   SIMIX_context_set_current(next_context);
435   raw_swapcontext(&((smx_ctx_raw_t) context)->stack_top,
436       ((smx_ctx_raw_t) next_context)->stack_top);
437 }
438
439 /**
440  * \brief Resumes sequentially all processes ready to run.
441  * \param first_process the first process to resume
442  */
443 static void smx_ctx_raw_resume_serial(smx_process_t first_process)
444 {
445   smx_ctx_raw_t context = (smx_ctx_raw_t) first_process->context;
446   SIMIX_context_set_current((smx_context_t) context);
447   raw_swapcontext(&raw_maestro_context->stack_top,
448       ((smx_ctx_raw_t) context)->stack_top);
449 }
450
451 #ifdef TIME_BENCH_PER_SR
452 static void smx_ctx_raw_runall_serial(xbt_dynar_t processes)
453 {
454   smx_process_t process;
455   unsigned int cursor;
456   double elapsed = 0;
457   double tmax = 0;
458   unsigned long num_proc = xbt_dynar_length(simix_global->process_to_run);
459   unsigned int t=0;
460   unsigned int data_size = (num_proc / NUM_THREADS) + ((num_proc % NUM_THREADS) ? 1 : 0);
461
462   ssr_count++;
463   time_thread_ssr[0] = 0;
464   xbt_dynar_foreach(processes, cursor, process){ 
465         XBT_VERB("Schedule item %u of %lu",cursor,num_proc);
466         if(cursor >= t * data_size + data_size){
467           if(time_thread_ssr[t] > tmax)
468             tmax = time_thread_ssr[t];
469           t++;
470           time_thread_ssr[t] = 0;
471         }
472
473         if(new_sr){
474           ((smx_ctx_raw_t)process->context)->thread = t;
475           time_thread_sr[t] = 0;
476         }
477
478         xbt_os_cputimer_start(timer);
479         smx_ctx_raw_resume_serial(process);
480         xbt_os_cputimer_stop(timer);
481         elapsed = xbt_os_timer_elapsed(timer);
482         time_thread_ssr[t] += elapsed;
483         time_thread_sr[((smx_ctx_raw_t)process->context)->thread] += elapsed;
484   }
485
486   if(new_sr)
487     new_sr = FALSE;
488
489   if(time_thread_ssr[t] > tmax)
490     tmax = time_thread_ssr[t];
491
492   for(cursor=0; cursor <= t; cursor++){
493     XBT_VERB("Time SSR thread %u = %f (max %f)", cursor, time_thread_ssr[cursor], tmax);
494     time_wasted_ssr += tmax - time_thread_ssr[cursor];
495   }
496 }
497
498 void smx_ctx_raw_new_sr(void)
499 {
500   int i;
501   double tmax = 0;
502   new_sr = TRUE;
503   sr_count++;
504   for(i=0; i < NUM_THREADS; i++){
505     if(time_thread_sr[i] > tmax)
506       tmax = time_thread_sr[i];
507   }
508
509   for(i=0; i < NUM_THREADS; i++){
510     XBT_CRITICAL("Time SR thread %u = %f (max %f)", i, time_thread_sr[i], tmax);
511     time_wasted_sr += tmax - time_thread_sr[i];
512   }
513
514   XBT_CRITICAL("Total time SR %u = %f, %d", sr_count, tmax, xbt_dynar_length(simix_global->process_that_ran));
515   XBT_CRITICAL("New scheduling round");
516 }
517 #else
518 /**
519  * \brief Resumes sequentially all processes ready to run.
520  */
521 static void smx_ctx_raw_runall_serial(void)
522 {
523   smx_process_t first_process =
524       xbt_dynar_get_as(simix_global->process_to_run, 0, smx_process_t);
525   raw_process_index = 1;
526
527   /* execute the first process */
528   smx_ctx_raw_resume_serial(first_process);
529 }
530 #endif
531
532 /**
533  * \brief Suspends a running context and resumes another one or returns to
534  * the main function of the current worker thread.
535  * \param context the context of the current worker thread
536  */
537 static void smx_ctx_raw_suspend_parallel(smx_context_t context)
538 {
539 #ifdef CONTEXT_THREADS
540   /* determine the next context */
541   smx_process_t next_work = xbt_parmap_next(raw_parmap);
542   smx_context_t next_context;
543   raw_stack_t next_stack;
544
545   if (next_work != NULL) {
546     /* there is a next process to resume */
547     XBT_DEBUG("Run next process");
548     next_context = next_work->context;
549     next_stack = ((smx_ctx_raw_t) next_context)->stack_top;
550   }
551   else {
552     /* all processes were run, go to the barrier */
553     XBT_DEBUG("No more processes to run");
554
555     unsigned long worker_id =
556         (unsigned long) xbt_os_thread_get_specific(raw_worker_id_key);
557
558     next_context = (smx_context_t)raw_workers_context[worker_id];
559     XBT_DEBUG("Restoring worker stack %lu (working threads = %lu)",
560         worker_id, raw_threads_working);
561     next_stack = ((smx_ctx_raw_t)next_context)->stack_top;
562   }
563
564   SIMIX_context_set_current(next_context);
565   raw_swapcontext(&((smx_ctx_raw_t) context)->stack_top, next_stack);
566 #endif
567 }
568
569 /**
570  * \brief Resumes sequentially in the current worker thread the processes ready
571  * to run.
572  * \param first_process the first process to resume
573  */
574 static void smx_ctx_raw_resume_parallel(smx_process_t first_process)
575 {
576 #ifdef CONTEXT_THREADS
577   unsigned long worker_id = __sync_fetch_and_add(&raw_threads_working, 1);
578   xbt_os_thread_set_specific(raw_worker_id_key, (void*) worker_id);
579   smx_ctx_raw_t worker_context = (smx_ctx_raw_t)SIMIX_context_self();
580   raw_workers_context[worker_id] = worker_context;
581   XBT_DEBUG("Saving worker stack %lu", worker_id);
582   raw_stack_t* worker_stack = &(worker_context)->stack_top;
583
584
585   smx_context_t context = first_process->context;
586   SIMIX_context_set_current(context);
587   raw_swapcontext(worker_stack, ((smx_ctx_raw_t) context)->stack_top);
588 #endif
589 }
590
591 /**
592  * \brief Resumes in parallel all processes ready to run.
593  */
594 static void smx_ctx_raw_runall_parallel(void)
595 {
596 #ifdef CONTEXT_THREADS
597   raw_threads_working = 0;
598   xbt_parmap_apply(raw_parmap, (void_f_pvoid_t) smx_ctx_raw_resume_parallel,
599       simix_global->process_to_run);
600 #else
601   xbt_die("You asked for a parallel execution, but you don't have any threads.");
602 #endif
603 }
604
605 /**
606  * \brief Resumes all processes ready to run.
607  */
608 #ifdef ADAPTIVE_THRESHOLD
609 static void smx_ctx_raw_runall(void)
610 {
611   unsigned long nb_processes = xbt_dynar_length(simix_global->process_to_run);
612   unsigned long threshold = SIMIX_context_get_parallel_threshold();
613   reached_seq_limit = (seq_sched_round % SCHED_ROUND_LIMIT == 0); 
614   reached_par_limit = (par_sched_round % SCHED_ROUND_LIMIT == 0);
615
616   if(reached_seq_limit && reached_par_limit){
617     par_ratio = (par_proc_that_ran != 0) ? (par_time / (double)par_proc_that_ran) : 0;
618     seq_ratio = (seq_proc_that_ran != 0) ? (seq_time / (double)seq_proc_that_ran) : 0; 
619     if(seq_ratio > par_ratio){
620         if(nb_processes < avg_par_proc) {
621           threshold = (threshold>2) ? threshold - 1 : threshold ;
622           SIMIX_context_set_parallel_threshold(threshold);
623         }
624     } else {
625         if(nb_processes > avg_seq_proc){
626           SIMIX_context_set_parallel_threshold(threshold+1);
627         }
628     }
629   }
630
631   //XBT_CRITICAL("Thres: %d.", SIMIX_context_get_parallel_threshold());
632
633   if (nb_processes >= SIMIX_context_get_parallel_threshold()) {
634     simix_global->context_factory->suspend = smx_ctx_raw_suspend_parallel;
635     if(nb_processes < par_window){ 
636       par_sched_round++;
637       xbt_os_cputimer_start(round_time);
638       smx_ctx_raw_runall_parallel();
639       xbt_os_cputimer_stop(round_time);
640       par_time += xbt_os_timer_elapsed(round_time);
641
642       prev_avg_par_proc = avg_par_proc;
643       delta = (nb_processes-avg_par_proc);
644       avg_par_proc = (par_sched_round==1) ? nb_processes : avg_par_proc + delta / (double) par_sched_round;
645
646       if(par_sched_round>=2){
647         s_par_proc = sd_par_proc + (nb_processes - prev_avg_par_proc)*delta; 
648         sd_par_proc = sqrt(s_par_proc/(par_sched_round-1));
649         par_window = avg_par_proc + sd_par_proc;
650       }else{
651         sd_par_proc = 0;
652       }
653
654       par_proc_that_ran += nb_processes;
655     } else{
656       smx_ctx_raw_runall_parallel();
657     }
658   } else {
659     simix_global->context_factory->suspend = smx_ctx_raw_suspend_serial;
660     if(nb_processes > seq_window){ 
661       seq_sched_round++;
662       xbt_os_cputimer_start(round_time);
663       smx_ctx_raw_runall_serial();
664       xbt_os_cputimer_stop(round_time);
665       seq_time += xbt_os_timer_elapsed(round_time);
666
667       prev_avg_seq_proc = avg_seq_proc;
668       delta = (nb_processes-avg_seq_proc);
669       avg_seq_proc = (seq_sched_round==1) ? nb_processes : avg_seq_proc + delta / (double) seq_sched_round;
670
671       if(seq_sched_round>=2){
672         s_seq_proc = sd_seq_proc + (nb_processes - prev_avg_seq_proc)*delta; 
673         sd_seq_proc = sqrt(s_seq_proc/(seq_sched_round-1));
674         seq_window = avg_seq_proc - sd_seq_proc;
675       } else {
676         sd_seq_proc = 0;
677       }
678
679       seq_proc_that_ran += nb_processes;
680     } else {
681       smx_ctx_raw_runall_serial();
682     }
683   }
684 }
685
686 #else
687
688 static void smx_ctx_raw_runall(void)
689 {
690 #ifdef TIME_BENCH_ENTIRE_SRS
691   sr_count++;
692   timer = xbt_os_timer_new();
693   double elapsed = 0;
694 #endif
695   unsigned long nb_processes = xbt_dynar_length(simix_global->process_to_run);
696   if (SIMIX_context_is_parallel() && SIMIX_context_get_parallel_threshold()<nb_processes) {
697         XBT_DEBUG("Runall // %lu", nb_processes);
698         simix_global->context_factory->suspend = smx_ctx_raw_suspend_parallel;
699
700      #ifdef TIME_BENCH_ENTIRE_SRS
701         xbt_os_cputimer_start(timer);
702      #endif
703
704         smx_ctx_raw_runall_parallel();
705
706      #ifdef TIME_BENCH_ENTIRE_SRS
707         xbt_os_cputimer_stop(timer);
708         elapsed = xbt_os_timer_elapsed(timer);
709      #endif
710     } else {
711         XBT_DEBUG("Runall serial %lu", nb_processes);
712         simix_global->context_factory->suspend = smx_ctx_raw_suspend_serial;
713
714       #ifdef TIME_BENCH_PER_SR
715         smx_ctx_raw_runall_serial(simix_global->process_to_run);
716       #else
717
718         #ifdef TIME_BENCH_ENTIRE_SRS
719           xbt_os_cputimer_start(timer);
720         #endif
721
722         smx_ctx_raw_runall_serial();
723
724         #ifdef TIME_BENCH_ENTIRE_SRS
725           xbt_os_cputimer_stop(timer);
726           elapsed = xbt_os_timer_elapsed(timer);
727         #endif
728       #endif
729     }
730
731 #ifdef TIME_BENCH_ENTIRE_SRS
732   XBT_CRITICAL("Total time SR %u = %f, %d", sr_count, elapsed, nb_processes);
733 #endif
734 }
735 #endif