Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of scm.gforge.inria.fr:/gitroot/simgrid/simgrid
[simgrid.git] / src / mc / mc_client.cpp
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 <cstdlib>
8 #include <cerrno>
9
10 #include <sys/types.h>
11 #include <sys/ptrace.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 "src/mc/mc_protocol.h"
19 #include "src/mc/mc_client.h"
20
21 // We won't need those once the separation MCer/MCed is complete:
22 #include "src/mc/mc_mmalloc.h"
23 #include "src/mc/mc_ignore.h"
24 #include "src/mc/mc_private.h" // MC_deadlock_check()
25 #include "src/mc/mc_smx.h"
26
27 extern "C" {
28
29 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_client, mc, "MC client logic");
30
31 mc_client_t mc_client;
32
33 void MC_client_init(void)
34 {
35   if (mc_mode != MC_MODE_NONE)
36     return;
37   if (!getenv(MC_ENV_SOCKET_FD))
38     return;
39   mc_mode = MC_MODE_CLIENT;
40
41   if (mc_client) {
42     XBT_WARN("MC_client_init called more than once.");
43     return;
44   }
45
46   char* fd_env = std::getenv(MC_ENV_SOCKET_FD);
47   if (!fd_env)
48     xbt_die("MC socket not found");
49
50   int fd = xbt_str_parse_int(fd_env,bprintf("Variable %s should contain a number but contains '%%s'", MC_ENV_SOCKET_FD));
51   XBT_DEBUG("Model-checked application found socket FD %i", fd);
52
53   int type;
54   socklen_t socklen = sizeof(type);
55   if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &socklen) != 0)
56     xbt_die("Could not check socket type");
57   if (type != SOCK_DGRAM)
58     xbt_die("Unexpected socket type %i", type);
59   XBT_DEBUG("Model-checked application found expected socket type");
60
61   mc_client = xbt_new0(s_mc_client_t, 1);
62   mc_client->fd = fd;
63   mc_client->active = 1;
64
65   // Waiting for the model-checker:
66   if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) == -1 || raise(SIGSTOP) != 0)
67     xbt_die("Could not wait for the model-checker");
68   MC_client_handle_messages();
69 }
70
71 void MC_client_send_message(void* message, size_t size)
72 {
73   if (MC_protocol_send(mc_client->fd, message, size))
74     xbt_die("Could not send message %i", (int) ((mc_message_t)message)->type);
75 }
76
77 void MC_client_send_simple_message(e_mc_message_type type)
78 {
79   if (MC_protocol_send_simple_message(mc_client->fd, type))
80     xbt_die("Could not send message %i", type);
81 }
82
83 void MC_client_handle_messages(void)
84 {
85   while (1) {
86     XBT_DEBUG("Waiting messages from model-checker");
87
88     char message_buffer[MC_MESSAGE_LENGTH];
89     ssize_t s;
90     if ((s = MC_receive_message(mc_client->fd, &message_buffer, sizeof(message_buffer), 0)) < 0)
91       xbt_die("Could not receive commands from the model-checker");
92
93     s_mc_message_t message;
94     if ((size_t) s < sizeof(message))
95       xbt_die("Received message is too small");
96     memcpy(&message, message_buffer, sizeof(message));
97     switch (message.type) {
98
99     case MC_MESSAGE_DEADLOCK_CHECK:
100       {
101         int result = MC_deadlock_check();
102         s_mc_int_message_t answer;
103         answer.type = MC_MESSAGE_DEADLOCK_CHECK_REPLY;
104         answer.value = result;
105         if (MC_protocol_send(mc_client->fd, &answer, sizeof(answer)))
106           xbt_die("Could not send response");
107       }
108       break;
109
110     case MC_MESSAGE_CONTINUE:
111       return;
112
113     case MC_MESSAGE_SIMCALL_HANDLE:
114       {
115         s_mc_simcall_handle_message_t message;
116         if (s != sizeof(message))
117           xbt_die("Unexpected size for SIMCALL_HANDLE");
118         memcpy(&message, message_buffer, sizeof(message));
119         smx_process_t process = SIMIX_process_from_PID(message.pid);
120         if (!process)
121           xbt_die("Invalid pid %lu", (unsigned long) message.pid);
122         SIMIX_simcall_handle(&process->simcall, message.value);
123         MC_protocol_send_simple_message(mc_client->fd, MC_MESSAGE_WAITING);
124       }
125       break;
126
127     case MC_MESSAGE_RESTORE:
128       {
129         s_mc_restore_message_t message;
130         if (s != sizeof(message))
131           xbt_die("Unexpected size for SIMCALL_HANDLE");
132         memcpy(&message, message_buffer, sizeof(message));
133         smpi_really_switch_data_segment(message.index);
134       }
135       break;
136
137     default:
138       xbt_die("%s received unexpected message %s (%i)",
139         MC_mode_name(mc_mode),
140         MC_message_type_name(message.type),
141         message.type
142       );
143     }
144   }
145 }
146
147 void MC_client_main_loop(void)
148 {
149   while (1) {
150     MC_protocol_send_simple_message(mc_client->fd, MC_MESSAGE_WAITING);
151     MC_client_handle_messages();
152     MC_wait_for_requests();
153   }
154 }
155
156 }