2 Parallel Programming - 2026/2027
20 #define SEND_BASIC_MESSAGE_PROBABILITY 50
21 #define BECOME_PASSIVE_PROBABILITY 30
23 #define WORK_TIME_MIN 500 // ms
24 #define WORK_TIME_MAX 1500 // ms
26 #define BASIC_MESSAGE 1 // basic message tag
28 // a process is either active or passive
29 typedef enum { ACTIVE
, PASSIVE
} process_state_t
;
32 typedef struct { int value
; } basic_message_t
;
34 static int pid
; // this process id
36 static bool is_initiator
= false;
37 static process_state_t state
= PASSIVE
;
40 Process with id ID becomes active.
42 static void basic_set_active(int id
)
46 trace("%d: is ACTIVE\n", id
);
48 control_become_active_hook(id
);
52 Process with id ID becomes passive.
54 static void basic_set_passive(int id
)
58 trace("%d: is PASSIVE\n", id
);
60 control_become_passive_hook(id
);
64 Active process with id ID becomes passive with probability
65 BECOME_PASSIVE_PROBABILITY.
67 static process_state_t
basic_new_state(int id
)
69 if (rand_ab(1, 100) <= BECOME_PASSIVE_PROBABILITY
)
70 basic_set_passive(id
);
76 Receive a basic message. The process is blocked until a message is
79 The contents of the message are stored at address PTR and the id of
80 the sender process is stored at PEER.
82 static void basic_receive_message(int id
, basic_message_t
*ptr
, int *peer
)
86 MPI_Recv(ptr
, sizeof(basic_message_t
), MPI_BYTE
, MPI_ANY_SOURCE
,
87 BASIC_MESSAGE
, MPI_COMM_WORLD
, &status
);
89 *peer
= status
.MPI_SOURCE
;
91 control_basic_receive_hook(id
, *peer
);
95 Receive a basic message, in case there is a pending message
98 If there is a pending message, the contents of the message are
99 stored at address PTR, the id of the sender process is stored at
100 PEER and return true.
102 Otherwise, return false.
104 static bool basic_receive_message_maybe(int id
, basic_message_t
*ptr
, int *peer
)
109 MPI_Iprobe(MPI_ANY_SOURCE
, BASIC_MESSAGE
, MPI_COMM_WORLD
, &flag
, &status
);
114 MPI_Recv(ptr
, sizeof(basic_message_t
), MPI_BYTE
, MPI_ANY_SOURCE
,
115 BASIC_MESSAGE
, MPI_COMM_WORLD
, &status
);
117 *peer
= status
.MPI_SOURCE
;
119 control_basic_receive_hook(id
, *peer
);
125 Send a basic message, with probability
126 SEND_BASIC_MESSAGE_PROBABILITY, to a random process.
128 PROCESSES is the total number of processes running the basic
131 static void basic_send_message_maybe(int id
, int processes
)
133 static int msg_no
= 0;
135 basic_message_t message
;
137 if (rand_ab(1, 100) > SEND_BASIC_MESSAGE_PROBABILITY
)
140 message
.value
= ++msg_no
;
142 // choose the process to send the message to
144 peer
= rand_ab(0, processes
- 1);
147 control_basic_send_hook(id
, peer
);
149 MPI_Send(&message
, sizeof(basic_message_t
), MPI_BYTE
, peer
, BASIC_MESSAGE
,
152 trace("%d: sent %d to %d\n", id
, message
.value
, peer
);
158 - An initiator process is initially active, a non-initiator process
159 is initially passive.
161 - While a process is active:
162 - It sends a message to some other process, with probability
163 SEND_BASIC_MESSAGE_PROBABILITY;
164 - It becomes passive with probability BECOME_PASSIVE_PROBABILITY.
166 - A passive process waits to be sent a message and the becomes
169 The arguments of the basic algorithm are the ID of the process, the
170 number of PROCESSES running the algorithm, and whether the process
173 void *basic_algorithm(void *_args
)
175 thread_args_t
*args
= _args
;
177 int processes
= args
->processes
;
178 bool initiator
= args
->initiator
;
180 basic_message_t message
;
184 is_initiator
= initiator
;
186 // tell the control algorithm that the basic algorithm has started;
187 // allows the synchronisation of both algorithms
188 control_basic_start_hook(id
);
194 // wait for a message
195 basic_receive_message(id
, &message
, &peer
);
197 trace("%d: got %d from %d\n", id
, message
.value
, peer
);
200 // process becomes active
201 basic_set_active(id
);
207 // may send a message to another process
208 basic_send_message_maybe(id
, processes
);
210 // may become passive
211 state
= basic_new_state(id
);
214 if (state
== PASSIVE
)
218 // wait for an incoming message
219 basic_receive_message(id
, &message
, &peer
);
221 trace("%d: got %d from %d\n", id
, message
.value
, peer
);
223 // process becomes active
224 basic_set_active(id
);
230 // see if there's an incoming message
231 if (basic_receive_message_maybe(id
, &message
, &peer
))
232 trace("%d: got %d from %d\n", id
, message
.value
, peer
);
235 // let some time go by
236 rand_sleep(WORK_TIME_MIN
, WORK_TIME_MAX
);