- Channel, for low-lewel message send/receive (currently a wrapper around a socket);
- Client, for the client-side logic.
--- /dev/null
+/* Copyright (c) 2015-2016. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <xbt/log.h>
+
+#include "src/mc/Channel.hpp"
+
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_Channel, mc, "MC interprocess communication");
+
+namespace simgrid {
+namespace mc {
+
+Channel::~Channel()
+{
+ if (this->socket_ >=0)
+ close(this->socket_);
+}
+
+int Channel::send(const void* message, size_t size) const
+{
+ XBT_DEBUG("Protocol [%s] send %s",
+ MC_mode_name(mc_mode),
+ MC_message_type_name(*(e_mc_message_type*) message));
+
+ while (::send(this->socket_, message, size, 0) == -1)
+ if (errno == EINTR)
+ continue;
+ else
+ return errno;
+ return 0;
+}
+
+ssize_t Channel::receive(void* message, size_t size, bool block) const
+{
+ int res = recv(this->socket_, message, size, block ? 0 : MSG_DONTWAIT);
+ if (res != -1)
+ XBT_DEBUG("Protocol [%s] received %s",
+ MC_mode_name(mc_mode),
+ MC_message_type_name(*(e_mc_message_type*) message));
+ return res;
+}
+
+}
+}
--- /dev/null
+/* Copyright (c) 2015-2016. The SimGrid Team.
+ * All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#ifndef SIMGRID_MC_CHANNEL_HPP
+#define SIMGRID_MC_CHANNEL_HPP
+
+#include <unistd.h>
+
+#include <type_traits>
+
+#include "src/mc/mc_protocol.h"
+
+namespace simgrid {
+namespace mc {
+
+class Channel {
+ int socket_ = -1;
+ template<class M>
+ static constexpr bool messageType()
+ {
+ return std::is_class<M>::value && std::is_trivial<M>::value;
+ }
+public:
+
+ Channel() {}
+ Channel(int sock) : socket_(sock) {}
+ ~Channel();
+
+ // No copy:
+ Channel(Channel const&) = delete;
+ Channel& operator=(Channel const&) = delete;
+
+ // Move:
+ Channel(Channel&& that) : socket_(that.socket_)
+ {
+ that.socket_ = -1;
+ }
+ Channel& operator=(Channel&& that)
+ {
+ this->socket_ = that.socket_;
+ that.socket_ = -1;
+ return *this;
+ }
+
+ // Send
+ int send(const void* message, size_t size) const;
+ int send(e_mc_message_type type) const
+ {
+ s_mc_message message = { type };
+ return this->send(&message, sizeof(message));
+ }
+ template<class M>
+ typename std::enable_if< messageType<M>(), int >::type
+ send(M const& m) const
+ {
+ return this->send(&m, sizeof(M));
+ }
+
+ // Receive
+ ssize_t receive(void* message, size_t size, bool block = true) const;
+ template<class M>
+ typename std::enable_if< messageType<M>(), ssize_t >::type
+ receive(M& m) const
+ {
+ return this->receive(&m, sizeof(M));
+ }
+
+ int getSocket() const
+ {
+ return socket_;
+ }
+
+};
+
+}
+}
+
+#endif
// Prepare data for poll:
struct pollfd* socket_pollfd = &fds_[SOCKET_FD_INDEX];
- socket_pollfd->fd = process_->socket();;
+ socket_pollfd->fd = process_->getChannel().getSocket();
socket_pollfd->events = POLLIN;
socket_pollfd->revents = 0;
void ModelChecker::resume(simgrid::mc::Process& process)
{
- int res = process.send_message(MC_MESSAGE_CONTINUE);
+ int res = process.getChannel().send(MC_MESSAGE_CONTINUE);
if (res)
throw simgrid::xbt::errno_error(res);
process.cache_flags = (mc_process_cache_flags_t) 0;
if (socket_pollfd->revents) {
if (socket_pollfd->revents & POLLIN) {
- ssize_t size = MC_receive_message(socket_pollfd->fd, buffer, sizeof(buffer), MSG_DONTWAIT);
+ ssize_t size = process_->getChannel().receive(buffer, sizeof(buffer), false);
if (size == -1 && errno != EAGAIN)
throw simgrid::xbt::errno_error(errno);
return handle_message(buffer, size);
m.type = MC_MESSAGE_SIMCALL_HANDLE;
m.pid = pid;
m.value = value;
- process.send_message(m);
+ process.getChannel().send(m);
process.cache_flags = (mc_process_cache_flags_t) 0;
while (process.running())
if (!this->handle_events())
// ***** Process
Process::Process(pid_t pid, int sockfd) :
- AddressSpace(this),pid_(pid), socket_(sockfd), running_(true)
+ AddressSpace(this), pid_(pid), channel_(sockfd), running_(true)
{}
void Process::init()
Process::~Process()
{
- if (this->socket_ >= 0 && close(this->socket_) < 0)
- xbt_die("Could not close communication socket");
-
- this->maestro_stack_start_ = nullptr;
- this->maestro_stack_end_ = nullptr;
-
if (this->memory_file >= 0)
close(this->memory_file);
unw_destroy_addr_space(this->unw_underlying_addr_space);
_UPT_destroy(this->unw_underlying_context);
}
- this->unw_underlying_context = nullptr;
- this->unw_underlying_addr_space = nullptr;
unw_destroy_addr_space(this->unw_addr_space);
- this->unw_addr_space = nullptr;
-
- this->cache_flags = MC_PROCESS_CACHE_FLAG_NONE;
if (this->clear_refs_fd_ >= 0)
close(this->clear_refs_fd_);
#include <xbt/dynar.h>
#include <xbt/mmalloc.h>
-#if HAVE_MC
#include "src/xbt/mmalloc/mmprivate.h"
-#endif
+#include "src/mc/Channel.hpp"
#include <simgrid/simix.h>
#include "src/simix/popping_private.h"
return this->heap_info.data();
}
+ Channel const& getChannel() const { return channel_; }
+ Channel& getChannel() { return channel_; }
+
std::vector<IgnoredRegion> const& ignored_regions() const
{
return ignored_regions_;
running_ = false;
}
- template<class M>
- typename std::enable_if< std::is_class<M>::value && std::is_trivial<M>::value, int >::type
- send_message(M const& m)
- {
- return MC_protocol_send(this->socket_, &m, sizeof(M));
- }
-
- int send_message(e_mc_message_type message_id)
- {
- return MC_protocol_send_simple_message(this->socket_, message_id);
- }
-
- template<class M>
- typename std::enable_if< std::is_class<M>::value && std::is_trivial<M>::value, ssize_t >::type
- receive_message(M& m)
- {
- return MC_receive_message(this->socket_, &m, sizeof(M), 0);
- }
-
void reset_soft_dirty();
void read_pagemap(uint64_t* pagemap, size_t start_page, size_t page_count);
void unignore_heap(void *address, size_t size);
void ignore_local_variable(const char *var_name, const char *frame_name);
- int socket() { return socket_; }
std::vector<simgrid::mc::SimixProcessInformation>& simix_processes();
std::vector<simgrid::mc::SimixProcessInformation>& old_simix_processes();
private:
pid_t pid_ = -1;
- int socket_ = -1;
+ Channel channel_;
bool running_ = false;
std::vector<simgrid::xbt::VmMap> memory_map_;
RemotePtr<void> maestro_stack_start_, maestro_stack_end_;
s_mc_restore_message message;
message.type = MC_MESSAGE_RESTORE;
message.index = snapshot->privatization_index;
- mc_model_checker->process().send_message(message);
+ mc_model_checker->process().getChannel().send(message);
}
#endif
}
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_client, mc, "MC client logic");
-extern "C" {
+namespace simgrid {
+namespace mc {
-mc_client_t mc_client;
+std::unique_ptr<Client> Client::client_;
-void MC_client_init(void)
+Client* Client::initialize()
{
- if (mc_mode != MC_MODE_NONE)
- return;
+ // We are not in MC mode:
+ // TODO, handle this more gracefully.
if (!getenv(MC_ENV_SOCKET_FD))
- return;
- mc_mode = MC_MODE_CLIENT;
+ return nullptr;
- if (mc_client) {
- XBT_WARN("MC_client_init called more than once.");
- return;
- }
+ // Do not break if we are called multiple times:
+ if (client_)
+ return client_.get();
+ // Check and set the mode:
+ if (mc_mode != MC_MODE_NONE)
+ abort();
+ mc_mode = MC_MODE_CLIENT;
+
+ // Fetch socket from MC_ENV_SOCKET_FD:
char* fd_env = std::getenv(MC_ENV_SOCKET_FD);
if (!fd_env)
- xbt_die("MC socket not found");
-
- int fd = xbt_str_parse_int(fd_env,bprintf("Variable %s should contain a number but contains '%%s'", MC_ENV_SOCKET_FD));
+ xbt_die("No MC socket passed in the environment");
+ int fd = xbt_str_parse_int(fd_env, bprintf("Variable %s should contain a number but contains '%%s'", MC_ENV_SOCKET_FD));
XBT_DEBUG("Model-checked application found socket FD %i", fd);
+ // Check the socket type/validity:
int type;
socklen_t socklen = sizeof(type);
if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &socklen) != 0)
xbt_die("Unexpected socket type %i", type);
XBT_DEBUG("Model-checked application found expected socket type");
- mc_client = xbt_new0(s_mc_client_t, 1);
- mc_client->fd = fd;
- mc_client->active = 1;
+ client_ = std::unique_ptr<Client>(new simgrid::mc::Client(fd));
- // Waiting for the model-checker:
+ // Wait for the model-checker:
if (ptrace(PTRACE_TRACEME, 0, nullptr, NULL) == -1 || raise(SIGSTOP) != 0)
xbt_die("Could not wait for the model-checker");
- MC_client_handle_messages();
-}
-void MC_client_send_message(void* message, size_t size)
-{
- if (MC_protocol_send(mc_client->fd, message, size))
- xbt_die("Could not send message %i", (int) ((mc_message_t)message)->type);
+ client_->handleMessages();
+ return client_.get();
}
-void MC_client_send_simple_message(e_mc_message_type type)
-{
- if (MC_protocol_send_simple_message(mc_client->fd, type))
- xbt_die("Could not send message %i", type);
-}
-
-void MC_client_handle_messages(void)
+void Client::handleMessages()
{
while (1) {
XBT_DEBUG("Waiting messages from model-checker");
char message_buffer[MC_MESSAGE_LENGTH];
ssize_t s;
- if ((s = MC_receive_message(mc_client->fd, &message_buffer, sizeof(message_buffer), 0)) < 0)
+
+ if ((s = channel_.receive(&message_buffer, sizeof(message_buffer))) < 0)
xbt_die("Could not receive commands from the model-checker");
s_mc_message_t message;
s_mc_int_message_t answer;
answer.type = MC_MESSAGE_DEADLOCK_CHECK_REPLY;
answer.value = result;
- if (MC_protocol_send(mc_client->fd, &answer, sizeof(answer)))
+ if (channel_.send(answer))
xbt_die("Could not send response");
}
break;
if (!process)
xbt_die("Invalid pid %lu", (unsigned long) message.pid);
SIMIX_simcall_handle(&process->simcall, message.value);
- MC_protocol_send_simple_message(mc_client->fd, MC_MESSAGE_WAITING);
+ if (channel_.send(MC_MESSAGE_WAITING))
+ xbt_die("Could not send MESSAGE_WAITING to model-checker");
}
break;
}
}
-void MC_client_main_loop(void)
+void Client::mainLoop(void)
{
while (1) {
- MC_protocol_send_simple_message(mc_client->fd, MC_MESSAGE_WAITING);
- MC_client_handle_messages();
+ if (channel_.send(MC_MESSAGE_WAITING))
+ xbt_die("Could not send WAITING mesage to model-checker");
+ this->handleMessages();
simgrid::mc::wait_for_requests();
}
}
}
+}
#include <cstddef>
+#include <memory>
+
#include <xbt/base.h>
+
#include "src/mc/mc_protocol.h"
+#include "src/mc/Channel.hpp"
+
+namespace simgrid {
+namespace mc {
+
+class XBT_PUBLIC() Client {
+private:
+ bool active_ = false;
+ Channel channel_;
+ static std::unique_ptr<Client> client_;
+public:
+ Client();
+ Client(int fd) : active_(true), channel_(fd) {}
+ void handleMessages();
+ Channel const& getChannel() const { return channel_; }
+ Channel& getChannel() { return channel_; }
+ void mainLoop(void);
+
+ // Singleton :/
+ // TODO, remove the singleton antipattern.
+ static Client* initialize();
+ static Client* get()
+ {
+ return client_.get();
+ }
+};
+
+}
+}
SG_BEGIN_DECL()
-typedef struct s_mc_client {
- int active;
- int fd;
-} s_mc_client_t, *mc_client_t;
-
-extern XBT_PRIVATE mc_client_t mc_client;
-
-XBT_PRIVATE void MC_client_init(void);
-XBT_PRIVATE void MC_client_handle_messages(void);
-XBT_PRIVATE void MC_client_send_message(void* message, std::size_t size);
-XBT_PRIVATE void MC_client_send_simple_message(e_mc_message_type type);
-
#if HAVE_MC
void MC_ignore(void* addr, std::size_t size);
#endif
-void MC_client_main_loop(void);
-
SG_END_DECL()
#endif
void MC_assert(int prop)
{
if (MC_is_active() && !prop) {
- MC_client_send_simple_message(MC_MESSAGE_ASSERTION_FAILED);
- MC_client_handle_messages();
+ if (simgrid::mc::Client::get()->getChannel().send(MC_MESSAGE_ASSERTION_FAILED))
+ xbt_die("Could not send assertion to model-checker");
+ simgrid::mc::Client::get()->handleMessages();
}
}
message.type = MC_MESSAGE_IGNORE_MEMORY;
message.addr = (std::uintptr_t) addr;
message.size = size;
- MC_client_send_message(&message, sizeof(message));
+ if (simgrid::mc::Client::get()->getChannel().send(message))
+ xbt_die("Could not send IGNORE_MEMORY mesage to model-checker");
}
void MC_automaton_new_propositional_symbol(const char *id, int(*fct)(void))
strncpy(message.name, name, sizeof(message.name));
message.callback = nullptr;
message.data = value;
- MC_client_send_message(&message, sizeof(message));
+ if (simgrid::mc::Client::get()->getChannel().send(message))
+ xbt_die("Could send REGISTER_SYMBOL message to model-checker");
}
if (mc_mode == MC_MODE_CLIENT)
// This will move somehwere else:
- MC_client_handle_messages();
+ simgrid::mc::Client::get()->handleMessages();
/* Create exploration stack */
mc_stack = xbt_fifo_new();
{
mc_mode = MC_MODE_CLIENT;
MC_init();
- MC_client_main_loop();
+ simgrid::mc::Client::get()->mainLoop();
}
void MC_exit(void)
{
if (mc_mode == MC_MODE_SERVER) {
int res;
- if ((res = mc_model_checker->process().send_message(MC_MESSAGE_DEADLOCK_CHECK)))
+ if ((res = mc_model_checker->process().getChannel().send(MC_MESSAGE_DEADLOCK_CHECK)))
xbt_die("Could not check deadlock state");
s_mc_int_message_t message;
- ssize_t s = mc_model_checker->process().receive_message(message);
+ ssize_t s = mc_model_checker->process().getChannel().receive(message);
if (s == -1)
xbt_die("Could not receive message");
if (s != sizeof(message) || message.type != MC_MESSAGE_DEADLOCK_CHECK_REPLY)
heap->heapinfo[message.block].busy_frag.ignore[message.fragment]++;
}
- if (MC_protocol_send(mc_client->fd, &message, sizeof(message)))
+ if (simgrid::mc::Client::get()->getChannel().send(message))
xbt_die("Could not send ignored region to MCer");
}
message.type = MC_MESSAGE_UNIGNORE_HEAP;
message.addr = (std::uintptr_t) address;
message.size = size;
- MC_client_send_message(&message, sizeof(message));
+ if (simgrid::mc::Client::get()->getChannel().send(message))
+ xbt_die("Could not send UNIGNORE_HEAP mesasge to model-checker");
}
void MC_ignore_global_variable(const char *name)
s_mc_stack_region_message_t message;
message.type = MC_MESSAGE_STACK_REGION;
message.stack_region = region;
- MC_client_send_message(&message, sizeof(message));
+ if (simgrid::mc::Client::get()->getChannel().send(message))
+ xbt_die("Coule not send STACK_REGION to model-checker");
}
}
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_protocol, mc, "Generic MC protocol logic");
-extern "C" {
-
-int MC_protocol_send(int socket, const void* message, std::size_t size)
-{
- XBT_DEBUG("Protocol [%s] send %s",
- MC_mode_name(mc_mode),
- MC_message_type_name(*(e_mc_message_type*) message));
-
- while (send(socket, message, size, 0) == -1)
- if (errno == EINTR)
- continue;
- else
- return errno;
- return 0;
-}
-
-int MC_protocol_send_simple_message(int socket, e_mc_message_type type)
-{
- s_mc_message_t message;
- message.type = type;
- return MC_protocol_send(socket, &message, sizeof(message));
-}
-
-ssize_t MC_receive_message(int socket, void* message, size_t size, int options)
-{
- int res = recv(socket, message, size, options);
- if (res != -1)
- XBT_DEBUG("Protocol [%s] received %s",
- MC_mode_name(mc_mode),
- MC_message_type_name(*(e_mc_message_type*) message));
- return res;
-}
-
const char* MC_message_type_name(e_mc_message_type type)
{
switch(type) {
return "?";
}
}
-
-}
int index;
} s_mc_restore_message_t, *mc_restore_message_t;
-XBT_PRIVATE int MC_protocol_send(int socket, const void* message, size_t size);
-XBT_PRIVATE int MC_protocol_send_simple_message(int socket, e_mc_message_type type);
-XBT_PRIVATE ssize_t MC_receive_message(int socket, void* message, size_t size, int options);
-
XBT_PRIVATE const char* MC_message_type_name(e_mc_message_type type);
XBT_PRIVATE const char* MC_mode_name(e_mc_mode_t mode);
#if HAVE_MC
// The communication initialization is done ASAP.
// We need to communicate initialization of the different layers to the model-checker.
- MC_client_init();
+ simgrid::mc::Client::initialize();
#endif
if (_sg_cfg_exit_asap)
src/mc/RemotePtr.hpp
src/mc/AddressSpace.hpp
src/mc/AddressSpace.cpp
+ src/mc/Channel.cpp
+ src/mc/Channel.hpp
src/mc/Frame.hpp
src/mc/Frame.cpp
src/mc/ModelChecker.hpp