Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[mc] Cross-process MC/safety implementation
[simgrid.git] / src / mc / mc_client.c
1 /* Copyright (c) 2015. 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 <stdlib.h>
8 #include <errno.h>
9 #include <error.h>
10
11 #include <sys/types.h>
12 #include <sys/socket.h>
13
14 #include <xbt/log.h>
15 #include <xbt/sysdep.h>
16 #include <xbt/mmalloc.h>
17
18 #include "mc_protocol.h"
19 #include "mc_client.h"
20
21 // We won't need those once the separation MCer/MCed is complete:
22 #include "mc_mmalloc.h"
23 #include "mc_ignore.h"
24 #include "mc_model_checker.h"
25 #include "mc_private.h" // MC_deadlock_check()
26 #include "mc_smx.h"
27
28 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_client, mc, "MC client logic");
29
30 mc_client_t mc_client;
31
32 void MC_client_init(void)
33 {
34   if (mc_client) {
35     XBT_WARN("MC_client_init called more than once.");
36     return;
37   }
38
39   char* fd_env = getenv(MC_ENV_SOCKET_FD);
40   if (!fd_env)
41     xbt_die("MC socket not found");
42
43   int fd = atoi(fd_env);
44   XBT_DEBUG("Model-checked application found socket FD %i", fd);
45
46   int type;
47   socklen_t socklen = sizeof(type);
48   if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &socklen) != 0)
49     xbt_die("Could not check socket type");
50   if (type != SOCK_DGRAM)
51     xbt_die("Unexpected socket type %i", type);
52   XBT_DEBUG("Model-checked application found expected socket type");
53
54   mc_client = xbt_new0(s_mc_client_t, 1);
55   mc_client->fd = fd;
56   mc_client->active = 1;
57 }
58
59 void MC_client_hello(void)
60 {
61   if (MC_protocol_hello(mc_client->fd) != 0)
62     xbt_die("Could not say hello the MC server");
63 }
64
65 void MC_client_send_message(void* message, size_t size)
66 {
67   if (MC_protocol_send(mc_client->fd, message, size))
68     xbt_die("Could not send message %i", (int) ((mc_message_t)message)->type);
69 }
70
71 void MC_client_send_simple_message(int type)
72 {
73   if (MC_protocol_send_simple_message(mc_client->fd, type))
74     xbt_die("Could not send message %i", type);
75 }
76
77 void MC_client_handle_messages(void)
78 {
79   while (1) {
80     XBT_DEBUG("Waiting messages from model-checker");
81
82     char message_buffer[MC_MESSAGE_LENGTH];
83     size_t s;
84     if ((s = MC_receive_message(mc_client->fd, &message_buffer, sizeof(message_buffer), 0)) == -1)
85       xbt_die("Could not receive commands from the model-checker");
86
87     s_mc_message_t message;
88     if (s < sizeof(message))
89       xbt_die("Received message is too small");
90     memcpy(&message, message_buffer, sizeof(message));
91     switch (message.type) {
92
93     case MC_MESSAGE_DEADLOCK_CHECK:
94       {
95         int result = MC_deadlock_check();
96         s_mc_int_message_t answer;
97         answer.type = MC_MESSAGE_DEADLOCK_CHECK_REPLY;
98         answer.value = result;
99         if (MC_protocol_send(mc_client->fd, &answer, sizeof(answer)))
100           xbt_die("Could not send response");
101       }
102       break;
103
104     case MC_MESSAGE_CONTINUE:
105       return;
106
107     case MC_MESSAGE_SIMCALL_HANDLE:
108       {
109         s_mc_simcall_handle_message_t message;
110         if (s != sizeof(message))
111           xbt_die("Unexpected size for SIMCALL_HANDLE");
112         memcpy(&message, message_buffer, sizeof(message));
113         smx_process_t process = SIMIX_process_from_PID(message.pid);
114         if (!process)
115           xbt_die("Invalid pid %lu", (unsigned long) message.pid);
116         SIMIX_simcall_handle(&process->simcall, message.value);
117       }
118       return;
119
120     default:
121       xbt_die("%s received unexpected message %s (%i)",
122         MC_mode_name(mc_mode),
123         MC_message_type_name(message.type),
124         message.type
125       );
126     }
127   }
128 }
129
130 void MC_client_main_loop(void)
131 {
132   while (1) {
133     MC_protocol_send_simple_message(mc_client->fd, MC_MESSAGE_WAITING);
134     MC_client_handle_messages();
135     MC_wait_for_requests();
136   }
137 }