Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
1f3abcec74d22459be188862ee74be028f02a791
[simgrid.git] / src / mc / mc_state.c
1 /* Copyright (c) 2008-2014. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #include "../simix/smx_private.h"
8 #include "xbt/fifo.h"
9 #include "mc_state.h"
10 #include "mc_request.h"
11 #include "mc_private.h"
12 #include "mc_comm_pattern.h"
13
14 static void copy_incomplete_communications_pattern(mc_state_t state) {
15   int i;
16   xbt_dynar_t incomplete_process_comms;
17   mc_comm_pattern_t comm;
18   unsigned int cursor;
19   state->incomplete_comm_pattern = xbt_dynar_new(sizeof(xbt_dynar_t), xbt_dynar_free_voidp);
20   for (i=0; i<simix_process_maxpid; i++) {
21     incomplete_process_comms = xbt_dynar_get_as(incomplete_communications_pattern, i, xbt_dynar_t);
22     xbt_dynar_t incomplete_process_comms_copy = xbt_dynar_new(sizeof(mc_comm_pattern_t), comm_pattern_free_voidp);
23     xbt_dynar_foreach(incomplete_process_comms, cursor, comm) {
24       mc_comm_pattern_t copy_comm = xbt_new0(s_mc_comm_pattern_t, 1);
25       copy_comm->index = comm->index;
26       copy_comm->type = comm->type;
27       copy_comm->comm = comm->comm;
28       copy_comm->rdv = strdup(comm->rdv);
29       copy_comm->data_size = -1;
30       copy_comm->data = NULL;
31       if(comm->type == SIMIX_COMM_SEND){
32         copy_comm->src_proc = comm->src_proc;
33         copy_comm->src_host = comm->src_host;
34         if (comm->data != NULL) {
35           copy_comm->data_size = comm->data_size;
36           copy_comm->data = xbt_malloc0(comm->data_size);
37           memcpy(copy_comm->data, comm->data, comm->data_size);
38         }
39       }else{
40         copy_comm->dst_proc = comm->dst_proc;
41         copy_comm->dst_host = comm->dst_host;
42       }
43       xbt_dynar_push(incomplete_process_comms_copy, &copy_comm);
44     }
45     xbt_dynar_insert_at(state->incomplete_comm_pattern, i, &incomplete_process_comms_copy);
46   }
47 }
48
49 static void copy_index_communications_pattern(mc_state_t state) {
50
51   state->index_comm = xbt_dynar_new(sizeof(unsigned int), NULL);
52   mc_list_comm_pattern_t list_process_comm;
53   unsigned int cursor;
54   xbt_dynar_foreach(initial_communications_pattern, cursor, list_process_comm){
55     xbt_dynar_push_as(state->index_comm, unsigned int, list_process_comm->index_comm);
56   }
57 }
58
59 /**
60  * \brief Creates a state data structure used by the exploration algorithm
61  */
62 mc_state_t MC_state_new()
63 {
64   mc_state_t state = NULL;
65
66   state = xbt_new0(s_mc_state_t, 1);
67   state->max_pid = simix_process_maxpid;
68   state->proc_status = xbt_new0(s_mc_procstate_t, state->max_pid);
69   state->system_state = NULL;
70   state->num = ++mc_stats->expanded_states;
71
72   return state;
73 }
74
75 /**
76  * \brief Deletes a state data structure
77  * \param trans The state to be deleted
78  */
79 void MC_state_delete(mc_state_t state)
80 {
81   if (state->system_state)
82     MC_free_snapshot(state->system_state);
83   xbt_free(state->proc_status);
84   xbt_free(state);
85 }
86
87 void MC_state_interleave_process(mc_state_t state, smx_process_t process)
88 {
89   state->proc_status[process->pid].state = MC_INTERLEAVE;
90   state->proc_status[process->pid].interleave_count = 0;
91 }
92
93 void MC_state_remove_interleave_process(mc_state_t state, smx_process_t process)
94 {
95   if (state->proc_status[process->pid].state == MC_INTERLEAVE)
96     state->proc_status[process->pid].state = MC_DONE;
97 }
98
99 unsigned int MC_state_interleave_size(mc_state_t state)
100 {
101   unsigned int i, size = 0;
102
103   for (i = 0; i < state->max_pid; i++) {
104     if ((state->proc_status[i].state == MC_INTERLEAVE)
105         || (state->proc_status[i].state == MC_MORE_INTERLEAVE))
106       size++;
107   }
108
109   return size;
110 }
111
112 int MC_state_process_is_done(mc_state_t state, smx_process_t process)
113 {
114   return state->proc_status[process->pid].state == MC_DONE ? TRUE : FALSE;
115 }
116
117 void MC_state_set_executed_request(mc_state_t state, smx_simcall_t req,
118                                    int value)
119 {
120   state->executed_req = *req;
121   state->req_num = value;
122   smx_process_t process = NULL;
123   mc_procstate_t procstate = NULL;
124
125   /* The waitany and testany request are transformed into a wait or test request over the
126    * corresponding communication action so it can be treated later by the dependence
127    * function. */
128   switch (req->call) {
129   case SIMCALL_COMM_WAITANY:
130     state->internal_req.call = SIMCALL_COMM_WAIT;
131     state->internal_req.issuer = req->issuer;
132     state->internal_comm =
133         *xbt_dynar_get_as(simcall_comm_waitany__get__comms(req), value,
134                           smx_synchro_t);
135     simcall_comm_wait__set__comm(&state->internal_req, &state->internal_comm);
136     simcall_comm_wait__set__timeout(&state->internal_req, 0);
137     break;
138
139   case SIMCALL_COMM_TESTANY:
140     state->internal_req.call = SIMCALL_COMM_TEST;
141     state->internal_req.issuer = req->issuer;
142
143     if (value > 0)
144       state->internal_comm =
145           *xbt_dynar_get_as(simcall_comm_testany__get__comms(req), value,
146                             smx_synchro_t);
147
148     simcall_comm_test__set__comm(&state->internal_req, &state->internal_comm);
149     simcall_comm_test__set__result(&state->internal_req, value);
150     break;
151
152   case SIMCALL_COMM_WAIT:
153     state->internal_req = *req;
154     state->internal_comm = *(simcall_comm_wait__get__comm(req));
155     simcall_comm_wait__set__comm(&state->executed_req, &state->internal_comm);
156     simcall_comm_wait__set__comm(&state->internal_req, &state->internal_comm);
157     break;
158
159   case SIMCALL_COMM_TEST:
160     state->internal_req = *req;
161     state->internal_comm = *simcall_comm_test__get__comm(req);
162     simcall_comm_test__set__comm(&state->executed_req, &state->internal_comm);
163     simcall_comm_test__set__comm(&state->internal_req, &state->internal_comm);
164     break;
165
166   case SIMCALL_MC_RANDOM:
167     state->internal_req = *req;
168     if (value != simcall_mc_random__get__max(req)) {
169       xbt_swag_foreach(process, simix_global->process_list) {
170         procstate = &state->proc_status[process->pid];
171         if (process->pid == req->issuer->pid) {
172           procstate->state = MC_MORE_INTERLEAVE;
173           break;
174         }
175       }
176     }
177     break;
178
179   default:
180     state->internal_req = *req;
181     break;
182   }
183 }
184
185 smx_simcall_t MC_state_get_executed_request(mc_state_t state, int *value)
186 {
187   *value = state->req_num;
188   return &state->executed_req;
189 }
190
191 smx_simcall_t MC_state_get_internal_request(mc_state_t state)
192 {
193   return &state->internal_req;
194 }
195
196 smx_simcall_t MC_state_get_request(mc_state_t state, int *value)
197 {
198   smx_process_t process = NULL;
199   mc_procstate_t procstate = NULL;
200   unsigned int start_count;
201   smx_synchro_t act = NULL;
202
203   xbt_swag_foreach(process, simix_global->process_list) {
204     procstate = &state->proc_status[process->pid];
205
206     if (procstate->state == MC_INTERLEAVE
207         || procstate->state == MC_MORE_INTERLEAVE) {
208       if (MC_process_is_enabled(process)) {
209         switch (process->simcall.call) {
210         case SIMCALL_COMM_WAITANY:
211           *value = -1;
212           while (procstate->interleave_count <
213                  xbt_dynar_length(simcall_comm_waitany__get__comms
214                                   (&process->simcall))) {
215             if (MC_request_is_enabled_by_idx
216                 (&process->simcall, procstate->interleave_count++)) {
217               *value = procstate->interleave_count - 1;
218               break;
219             }
220           }
221
222           if (procstate->interleave_count >=
223               xbt_dynar_length(simcall_comm_waitany__get__comms
224                                (&process->simcall)))
225             procstate->state = MC_DONE;
226
227           if (*value != -1)
228             return &process->simcall;
229
230           break;
231
232         case SIMCALL_COMM_TESTANY:
233           start_count = procstate->interleave_count;
234           *value = -1;
235           while (procstate->interleave_count <
236                  xbt_dynar_length(simcall_comm_testany__get__comms
237                                   (&process->simcall))) {
238             if (MC_request_is_enabled_by_idx
239                 (&process->simcall, procstate->interleave_count++)) {
240               *value = procstate->interleave_count - 1;
241               break;
242             }
243           }
244
245           if (procstate->interleave_count >=
246               xbt_dynar_length(simcall_comm_testany__get__comms
247                                (&process->simcall)))
248             procstate->state = MC_DONE;
249
250           if (*value != -1 || start_count == 0)
251             return &process->simcall;
252
253           break;
254
255         case SIMCALL_COMM_WAIT:
256           act = simcall_comm_wait__get__comm(&process->simcall);
257           if (act->comm.src_proc && act->comm.dst_proc) {
258             *value = 0;
259           } else {
260             if (act->comm.src_proc == NULL && act->comm.type == SIMIX_COMM_READY
261                 && act->comm.detached == 1)
262               *value = 0;
263             else
264               *value = -1;
265           }
266           procstate->state = MC_DONE;
267           return &process->simcall;
268
269           break;
270
271         case SIMCALL_MC_RANDOM:
272           if (procstate->state == MC_INTERLEAVE)
273             *value = 0;
274           else {
275             if (state->req_num < simcall_mc_random__get__max(&process->simcall))
276               *value = state->req_num + 1;
277           }
278           procstate->state = MC_DONE;
279           return &process->simcall;
280           break;
281
282         default:
283           procstate->state = MC_DONE;
284           *value = 0;
285           return &process->simcall;
286           break;
287         }
288       }
289     }
290   }
291
292   return NULL;
293 }