/* 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 <dlfcn.h>
+#include <fcntl.h>
#include <spawn.h>
+#include <sys/sendfile.h>
+#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
-#include <dlfcn.h>
#include "mc/mc.h"
#include "private.h"
#include "src/mc/mc_replay.h"
#include "src/msg/msg_private.h"
#include "src/simix/smx_private.h"
+#include "src/surf/surf_interface.hpp"
#include "surf/surf.h"
#include "xbt/replay.hpp"
#include <xbt/config.hpp>
#endif
int smpirun = 0;
+ msg_bar_t finalization_barrier = nullptr;
if (process_count == 0){
process_count = SIMIX_process_count();
smpirun=1;
+ finalization_barrier = MSG_barrier_init(process_count);
}
smpi_universe_size = process_count;
process_data = new simgrid::smpi::Process*[process_count];
for (int i = 0; i < process_count; i++) {
- process_data[i] = new simgrid::smpi::Process(i);
+ process_data[i] = new simgrid::smpi::Process(i, finalization_barrier);
}
//if the process was launched through smpirun script we generate a global mpi_comm_world
//if not, we let MPI_COMM_NULL, and the comm world will be private to each mpi instance
group = new simgrid::smpi::Group(process_count);
MPI_COMM_WORLD = new simgrid::smpi::Comm(group, nullptr);
MPI_Attr_put(MPI_COMM_WORLD, MPI_UNIVERSE_SIZE, reinterpret_cast<void *>(process_count));
- msg_bar_t bar = MSG_barrier_init(process_count);
- for (int i = 0; i < process_count; i++) {
+ for (int i = 0; i < process_count; i++)
group->set_mapping(i, i);
- process_data[i]->set_finalization_barrier(bar);
- }
}
}
* configuration tools */
return 0;
}
- smpi_init_logs();
TRACE_global_init(&argc, argv);
- TRACE_add_start_function(TRACE_smpi_alloc);
- TRACE_add_end_function(TRACE_smpi_release);
SIMIX_global_init(&argc, argv);
MSG_init(&argc,argv);
SMPI_switch_data_segment = &smpi_switch_data_segment;
- smpi_init_options();
-
// parse the platform file: get the host list
SIMIX_create_environment(argv[1]);
SIMIX_comm_set_copy_data_callback(smpi_comm_copy_buffer_callback);
if (smpi_privatize_global_variables == SMPI_PRIVATIZE_DLOPEN) {
std::string executable_copy = executable;
- simix_global->default_function = [executable_copy](std::vector<std::string> args) {
- return std::function<void()>([executable_copy, args] {
+
+ // Prepare the copy of the binary (open the file and get its size)
+ // (fdin will remain open for the whole process execution. That's a sort of leak but we can live with it)
+ int fdin = open(executable_copy.c_str(), O_RDONLY);
+ xbt_assert(fdin >= 0, "Cannot read from %s", executable_copy.c_str());
+ struct stat fdin_stat;
+ fstat(fdin, &fdin_stat);
+ off_t fdin_size = fdin_stat.st_size;
+
+ simix_global->default_function = [executable_copy, fdin, fdin_size](std::vector<std::string> args) {
+ return std::function<void()>([executable_copy, fdin, fdin_size, args] {
// Copy the dynamic library:
std::string target_executable = executable_copy
+ "_" + std::to_string(getpid())
+ "_" + std::to_string(rank++) + ".so";
- // TODO, execute directly instead of relying on cp
- const char* command1 [] = {
- "cp", "--reflink=auto", "--", executable_copy.c_str(), target_executable.c_str(),
- nullptr
- };
- const char* command2 [] = {
- "cp", "--", executable_copy.c_str(), target_executable.c_str(),
- nullptr
- };
- if (execute_command(command1) != 0 && execute_command(command2) != 0)
- xbt_die("copy failed");
+
+ int fdout = open(target_executable.c_str(), O_WRONLY);
+ xbt_assert(fdout >= 0, "Cannot write into %s", target_executable.c_str());
+
+ sendfile(fdout, fdin, NULL, fdin_size);
+ close(fdout);
// Load the copy and resolve the entry point:
void* handle = dlopen(target_executable.c_str(), RTLD_LAZY | RTLD_LOCAL | RTLD_DEEPBIND);
if (!entry_point)
xbt_die("Could not resolve entry point");
- smpi_run_entry_point(entry_point, args);
+ smpi_run_entry_point(entry_point, args);
});
};
SIMIX_launch_application(argv[2]);
- smpi_global_init();
-
- smpi_check_options();
-
- if(smpi_privatize_global_variables == SMPI_PRIVATIZE_MMAP)
- smpi_initialize_global_memory_segments();
+ SMPI_init();
/* Clean IO before the run */
fflush(stdout);
return ret;
}
-// This function can be called from extern file, to initialize logs, options, and processes of smpi
-// without the need of smpirun
+// Called either directly from the user code, or from the code called by smpirun
void SMPI_init(){
smpi_init_logs();
smpi_init_options();
smpi_global_init();
smpi_check_options();
- if (TRACE_is_enabled() && TRACE_is_configured())
- TRACE_smpi_alloc();
+ TRACE_smpi_alloc();
+ simgrid::surf::surfExitCallbacks.connect(TRACE_smpi_release);
if(smpi_privatize_global_variables == SMPI_PRIVATIZE_MMAP)
smpi_initialize_global_memory_segments();
}