Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[mc] Flag global variables in mc_ignore as belonging to the MCer
[simgrid.git] / src / mc / mc_base.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 <simgrid/simix.h>
8
9 #include "mc_base.h"
10 #include "../simix/smx_private.h"
11 #include "mc_record.h"
12
13 #ifdef HAVE_MC
14 #include "mc_process.h"
15 #include "mc_model_checker.h"
16 #endif
17
18 XBT_LOG_NEW_CATEGORY(mc, "All MC categories");
19
20 void MC_wait_for_requests(void)
21 {
22   smx_process_t process;
23   smx_simcall_t req;
24   unsigned int iter;
25
26   while (!xbt_dynar_is_empty(simix_global->process_to_run)) {
27     SIMIX_process_runall();
28     xbt_dynar_foreach(simix_global->process_that_ran, iter, process) {
29       req = &process->simcall;
30       if (req->call != SIMCALL_NONE && !MC_request_is_visible(req))
31         SIMIX_simcall_handle(req, 0);
32     }
33   }
34 }
35
36 int MC_request_is_enabled(smx_simcall_t req)
37 {
38   unsigned int index = 0;
39   smx_synchro_t act = 0;
40
41   switch (req->call) {
42   case SIMCALL_NONE:
43     return FALSE;
44
45   case SIMCALL_COMM_WAIT:
46     /* FIXME: check also that src and dst processes are not suspended */
47     act = simcall_comm_wait__get__comm(req);
48     if (simcall_comm_wait__get__timeout(req) >= 0) {
49       /* If it has a timeout it will be always be enabled, because even if the
50        * communication is not ready, it can timeout and won't block. */
51       if (_sg_mc_timeout == 1)
52         return TRUE;
53     } else {
54       /* On the other hand if it hasn't a timeout, check if the comm is ready.*/
55       if (act->comm.detached && act->comm.src_proc == NULL
56           && act->comm.type == SIMIX_COMM_READY)
57         return (act->comm.dst_proc != NULL);
58     }
59     return (act->comm.src_proc && act->comm.dst_proc);
60
61   case SIMCALL_COMM_WAITANY:
62     /* Check if it has at least one communication ready */
63     xbt_dynar_foreach(simcall_comm_waitany__get__comms(req), index, act)
64       if (act->comm.src_proc && act->comm.dst_proc)
65         return TRUE;
66     return FALSE;
67
68   default:
69     /* The rest of the requests are always enabled */
70     return TRUE;
71   }
72 }
73
74 int MC_request_is_visible(smx_simcall_t req)
75 {
76   return req->call == SIMCALL_COMM_ISEND
77       || req->call == SIMCALL_COMM_IRECV
78       || req->call == SIMCALL_COMM_WAIT
79       || req->call == SIMCALL_COMM_WAITANY
80       || req->call == SIMCALL_COMM_TEST
81       || req->call == SIMCALL_COMM_TESTANY
82       || req->call == SIMCALL_MC_RANDOM
83 #ifdef HAVE_MC
84       || req->call == SIMCALL_MC_SNAPSHOT
85       || req->call == SIMCALL_MC_COMPARE_SNAPSHOTS
86 #endif
87       ;
88 }
89
90 int MC_random(int min, int max)
91 {
92   /*FIXME: return mc_current_state->executed_transition->random.value; */
93   return simcall_mc_random(min, max);
94 }
95
96 static int prng_random(int min, int max)
97 {
98   unsigned long output_size = ((unsigned long) max - (unsigned long) min) + 1;
99   unsigned long input_size = (unsigned long) RAND_MAX + 1;
100   unsigned long reject_size = input_size % output_size;
101   unsigned long accept_size = input_size - reject_size; // module*accept_size
102
103   // Use rejection in order to avoid skew
104   long x;
105   do {
106 #ifndef _XBT_WIN32
107     x = random();
108 #else
109     x = rand();
110 #endif
111   } while( x >= accept_size );
112   return min + (x % output_size);
113 }
114
115 int simcall_HANDLER_mc_random(smx_simcall_t simcall, int min, int max)
116 {
117   if (!MC_is_active() && !MC_record_path){
118     return prng_random(min, max);
119   }
120
121   return simcall->mc_value;
122 }