Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
cc79209a32d0ad90a1c4fd5a65a7db144c46ef5d
[simgrid.git] / src / xbt / context.c
1 /*      $Id$     */
2
3 /* a fast and simple context switching library                              */
4
5 /* Copyright (c) 2004 Arnaud Legrand.                                       */
6 /* Copyright (c) 2004 Martin Quinson.                                       */
7 /* All rights reserved.                                                     */
8
9 /* This program is free software; you can redistribute it and/or modify it
10  * under the terms of the license (GNU LGPL) which comes with this package. */
11
12 #include "portable.h"
13 #include "context_private.h"
14 #include "xbt/error.h"
15 #include "xbt/dynar.h"
16 #include "gras_config.h"
17 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(context, xbt, "Context");
18
19 #define WARNING(format, ...) (fprintf(stderr, "[%s , %s : %d] ", __FILE__, __FUNCTION__, __LINE__),\
20                               fprintf(stderr, format, ## __VA_ARGS__), \
21                               fprintf(stderr, "\n"))
22 #define VOIRP(expr) WARNING("  {" #expr " = %p }", expr)
23
24 #ifndef HAVE_UCONTEXT_H
25 /* don't want to play with conditional compilation in automake tonight, sorry.
26    include directly the c file from here when needed. */
27 # include "context_win32.c" 
28 #endif
29
30 static xbt_context_t current_context = NULL;
31 static xbt_context_t init_context = NULL;
32 static xbt_swag_t context_to_destroy = NULL;
33 static xbt_swag_t context_living = NULL;
34
35 static void xbt_context_destroy(xbt_context_t context)
36 {
37   xbt_free(context);
38
39   return;
40 }
41
42 void xbt_context_init(void)
43 {
44   if(!current_context) {
45     current_context = init_context = xbt_new0(s_xbt_context_t,1);
46     context_to_destroy = xbt_swag_new(xbt_swag_offset(*current_context,hookup));
47     context_living = xbt_swag_new(xbt_swag_offset(*current_context,hookup));
48     xbt_swag_insert(init_context, context_living);
49   }
50 }
51
52 void xbt_context_empty_trash(void)
53 {
54   xbt_context_t context=NULL;
55
56   while((context=xbt_swag_extract(context_to_destroy)))
57     xbt_context_destroy(context);
58 }
59
60 static void *__context_wrapper(void *c)
61 {
62   xbt_context_t context = c;
63   int i;
64
65 /*   msg_global->current_process = process; */
66
67   /*  WARNING("Calling the main function"); */
68   /*   xbt_context_yield(context); */
69   (context->code) (context->argc,context->argv);
70
71   for(i=0;i<context->argc; i++) 
72     if(context->argv[i]) xbt_free(context->argv[i]);
73   if(context->argv) xbt_free(context->argv);
74
75   xbt_swag_remove(context, context_living);
76   xbt_swag_insert(context, context_to_destroy);
77
78   xbt_context_yield(context);
79
80   return NULL;
81 }
82
83 void xbt_context_start(xbt_context_t context) 
84 {
85 /*   xbt_fifo_insert(msg_global->process, process); */
86 /*   xbt_fifo_insert(msg_global->process_to_run, process); */
87
88   makecontext (&(context->uc), (void (*) (void)) __context_wrapper,
89                1, context);
90   return;
91 }
92
93 xbt_context_t xbt_context_new(xbt_context_function_t code,
94                          int argc, char *argv[])
95 {
96   xbt_context_t res = NULL;
97
98   res = xbt_new0(s_xbt_context_t,1);
99
100   xbt_assert0(getcontext(&(res->uc))==0,"Error in context saving.");
101
102   res->code = code;
103   res->uc.uc_link = NULL;
104 /*   res->uc.uc_link = &(current_context->uc); */
105   /* WARNING : when this context is over, the current_context (i.e. the 
106      father), is awaken... Theorically, the wrapper should prevent using 
107      this feature. */
108   res->uc.uc_stack.ss_sp = res->stack;
109   res->uc.uc_stack.ss_size = STACK_SIZE;
110
111   xbt_swag_insert(res, context_living);
112
113   return res;
114 }
115
116 void xbt_context_yield(xbt_context_t context)
117 {
118   int return_value = 0;
119
120   xbt_assert0(current_context,"You have to call context_init() first.");
121   
122 /*   WARNING("--------- current_context (%p) is yielding to context(%p) ---------",current_context,context); */
123 /*   VOIRP(current_context); */
124 /*   if(current_context) VOIRP(current_context->save); */
125 /*   VOIRP(context); */
126 /*   if(context) VOIRP(context->save); */
127
128   if (context) {
129     if(context->save==NULL) {
130 /*       WARNING("**** Yielding to somebody else ****"); */
131 /*       WARNING("Saving current_context value (%p) to context(%p)->save",current_context,context); */
132       context->save = current_context ;
133 /*       WARNING("current_context becomes  context(%p) ",context); */
134       current_context = context ;
135 /*       WARNING("Current position memorized (context->save). Jumping to context (%p)",context); */
136       return_value = swapcontext (&(context->save->uc), &(context->uc));
137       xbt_assert0((return_value==0),"Context swapping failure");
138 /*       WARNING("I am (%p). Coming back\n",context); */
139     } else {
140       xbt_context_t old_context = context->save ;
141 /*       WARNING("**** Back ! ****"); */
142 /*       WARNING("Setting current_context (%p) to context(%p)->save",current_context,context); */
143       current_context = context->save ;
144 /*       WARNING("Setting context(%p)->save to NULL",context); */
145       context->save = NULL ;
146 /*       WARNING("Current position memorized (%p). Jumping to context (%p)",context,old_context); */
147       return_value = swapcontext (&(context->uc), &(old_context->uc));
148       xbt_assert0((return_value==0),"Context swapping failure");
149 /*       WARNING("I am (%p). Coming back\n",context); */
150     }
151   }
152
153   return;
154 }
155
156 void xbt_context_exit(void) {
157   xbt_context_t context=NULL;
158
159   xbt_context_empty_trash();
160   xbt_swag_free(context_to_destroy);
161
162   while((context=xbt_swag_extract(context_living)))
163     xbt_context_destroy(context);
164
165   xbt_swag_free(context_living);
166
167   init_context = current_context = NULL ;
168 }