doc/doxygen/logcategories.doc
doc/simgrid_modules.map
doc/javadoc
+doc/example_lists/
### Specific of project
.settings/
.csettings/
- Comm.detach(): start and forget about asynchronous emission
- this_actor::send(mailbox) is now mailbox->put()
+ SURF
+ - Unused option network/sender-gap is removed.
+
+ MSG
+ - Deprecate MSG_task_isend_with_matching(): This unused feature
+ really complicates our internals. Will be removed in v3.20.
+
SimGrid (3.16) Released June 22. 2017.
The Blooming Spring Release: developments are budding.
SMPI
- New algorithm to privatize globals: dlopen, with dynamic loading tricks
- New option: smpi/keep-temps to not cleanup temp files
- - New option : smpi/shared-malloc-blocksize . Relevant only when global shared
+ - New option : smpi/shared-malloc-blocksize . Relevant only when global shared
mallocs mode is used, allows to change the size of the fake file used
(default 1MB), to potentially limit the number of mappings for large runs.
- Support for sparse privatized malloc with SMPI_PARTIAL_SHARED_MALLOC()
MSG
- New: MSG_process_yield(). Stop and yield to other processes.
- - New: MSG_process_daemon(). Daemon processes are automatically killed
+ - New: MSG_process_daemon(). Daemon processes are automatically killed
when the last non-daemon process terminates
- New: MSG_process_ref/unref(). Fiddle with the process refcounting.
- Renamed MSG_energy_plugin_init() -> MSG_host_energy_plugin_init()
- Kill the obscure NativeException. Nobody want to survive the issues
it denotes, so use JniException that is a RuntimeException (not to
be caught explicitly).
- - Partial bug fix in initialization. SimGrid flags on command line were
- consumed at C level but stayed in the original Java String[] args.
+ - Partial bug fix in initialization. SimGrid flags on command line were
+ consumed at C level but stayed in the original Java String[] args.
This could mess users' args[i] if SG flags were not put at the end of
the command line.
- The SimGrid flags are now removed from the Java arguments. However,
+ The SimGrid flags are now removed from the Java arguments. However,
the number of arguments REMAINS UNCHANGED. It is then UNSAFE to test
- if args.length is greater than the number of YOUR OWN ARGUMENTS.
+ if args.length is greater than the number of YOUR OWN ARGUMENTS.
It might be if you have --log or --cfg flags in the command line.
- Fix numerous memleaks all around the place. In particular, around VMs.
SimDag
- Backwards Compatibility breaks
- - The SD_route_get_list and SD_route_get_size functions have been removed.
- They are replaced by the unique
+ - The SD_route_get_list and SD_route_get_size functions have been removed.
+ They are replaced by the unique
void sg_host_route(sg_host_t src, sg_host_t dst, xbt_dynar_t links)
- The route from src to dst is built in the links dynar whose size can
+ The route from src to dst is built in the links dynar whose size can
be obtained with xbt_dynar_length.
- The SD_route_bandwidth and SD_route_latency functions have been replaced by
- sg_host_route_bandwidth and sg_host_route_latency.
+ sg_host_route_bandwidth and sg_host_route_latency.
Macros ensure the backwards compatibility, but you should fix your code
SMPI
- - Major C++ rewrite ongoing (SMPI used to be C compiled in C++).
+ - Major C++ rewrite ongoing (SMPI used to be C compiled in C++).
This can break codes using SMPI internals (from private.h instead of the public smpi.h).
- - Bump our claim of support from MPI 1.1 to MPI 2.2.
+ - Bump our claim of support from MPI 1.1 to MPI 2.2.
We don't support 100% of it, but it should be enough. Contact us if not.
- - MPI_Win_lock/unlock, MPI_Get_accumulate support added (as for all RMA, implementation is
+ - MPI_Win_lock/unlock, MPI_Get_accumulate support added (as for all RMA, implementation is
naive and probably inaccurate)
- New algorithm for SMPI_SHARED_MALLOC: global, where all blocks are
mapped onto a unique small file using some system magic.
SMPI
* Privatization now works on FreeBSD
-
+
* Privatization is now activated by default in smpirun
You can turn it off with -no-privatize if something goes wrong.
* Call-location tracing for SMPI.
- You can add the exact location (filename / linenumber) of an MPI call to
- your trace files and slow down or speed up the simulation between two
+ You can add the exact location (filename / linenumber) of an MPI call to
+ your trace files and slow down or speed up the simulation between two
consecutive calls by using an adjustment file (see the documentation).
* Fixed computation of timings for MPI_Send, MPI_Recv & possibly also others
* smpi/cpu-threshold:-1 should become smpi/simulate-computation:no
smpi/running-power is renamed to smpi/host-speed
- * smpi/grow-injected-times option to enable or disable multiplication of the
- timings injected in MPI_Iprobe, or MPI_Test. Enabled by default, which can
+ * smpi/grow-injected-times option to enable or disable multiplication of the
+ timings injected in MPI_Iprobe, or MPI_Test. Enabled by default, which can
make simulation less precise (but also much faster).
* smpirun script should be (much) faster for large deployments.
- Ignored parameter of vm_create: core_nb, disk_path and disk_size.
- Unimplemented save/restore methods
* MSG_as_router_get_property_value() was redundent with
- MSG_environment_as_get_property_value().
+ MSG_environment_as_get_property_value().
- Removed MSG_as_router_*propert*() functions
- Added MSG_environment_as_set_property_value() for consistency
- * xbt heterogeneous dictionnaries (created with xbt_dict_new()).
- Well, they are still there for now, but deprecated with a warning.
+ * xbt heterogeneous dictionnaries (created with xbt_dict_new()).
+ Well, they are still there for now, but deprecated with a warning.
Please switch to xbt_dict_new_homogeneous() before this is removed
for real.
* Task affinity. Its intended behavior (that was very badly tested
would have hoped here.
* xbt_os_sem_get_value: unused internally, deprecated on OS X El Capitan
* Option network/coordinates is now useless and should be dropped.
-
- Storage:
+
+ Storage:
* Added option storage/max_file_descriptors to allow more than 1024 files opened
SURF:
XML:
* Add Exa- and Peta- units such as EiB, EB, Eib, Eb for size, and
- EiBps, EBps, Eibps, Ebps for bandwidth.
+ EiBps, EBps, Eibps, Ebps for bandwidth.
They may become useful to some lucky ones.
-
+
Java:
* New functions: msg.Comm.waitAll() and msg.Comm.waitAny()
* ex/app_tokenring: new example, very similar to the MSG Token Ring
* ex/async_waitAll: new example, on asynchronous communications
MSG:
- * Memory usage should be decreased for simulations with a large number
+ * Memory usage should be decreased for simulations with a large number
of processes. This also helps for SMPI.
SimGrid (3.13) stable; urgency=low
The Half Release, a.k.a. the Zealous Easter Trim.
-
+
- We removed half of the lines, that were mostly experimental cruft.
v3.12 lasted 286000 lines of code, v3.13 is only 142000 lines
(not counting blanks and comments -- according to openhub.net)
- The internals are now compiled in C++ (and will soon be clean C++)
- - We removed 75 klines of XML, 12 klines of Java, 5 klines of cmake,
+ - We removed 75 klines of XML, 12 klines of Java, 5 klines of cmake,
59 klines of C, etc. We added only 29 klines of C++ in replacement.
-
+
* Backwards Compatibility breaks
- Removed Lua simulation bindings (switch to C or Java for that).
Lua can still be used to describe platforms
way, with filter function.
- MSG_task_listen_from_host
- MSG_mailbox_get_count_host_waiting_tasks
- - MSG_mailbox_put_with_timeout was removed.
+ - MSG_mailbox_put_with_timeout was removed.
Please use MSG_task_send_with_timeout instead.
- - In SimDag
- - the SD_application_reinit function was removed. It has been a noop for a while.
- - The ACCESS_MODE of SD_workstation has been removed. This feature was not really usable and should soon be
+ - In SimDag
+ - the SD_application_reinit function was removed. It has been a noop for a while.
+ - The ACCESS_MODE of SD_workstation has been removed. This feature was not really usable and should soon be
replaced by a more flexible mechanism.
- The following functions thus do not exist anymore
- SD_workstation_get_access_mode
- SD_route_get_communication_time => SG_route_get_latency() + amount / SD_route_get_bandwidth()
- SD_workstation_get_computation_time => amount / sg_host_speed()
- In Java
- - VM.setBound(int load) is now VM.setBound(double bound) to meet the MSG semantics.
+ - VM.setBound(int load) is now VM.setBound(double bound) to meet the MSG semantics.
Use VM.getSpeed()*load/100 for the legacy behavior.
- In CMake
- option enable_tracing was removed. It was not doing anything for a while.
And the same in bits: 'Tibps', 'Gibps', 'Mibps', 'Kibps', 'Tbps', 'Gbps', 'Mbps', 'kbps', 'bps'
- latency. Default: 's' second. Also defined:
'w' week, 'd' day, 'h' hour, 'm' minute, 'ms' millisecond, 'us' microsecond, 'ns' nanosecond, 'ps' picosecond
-
+
* bin/simgrid_update_xml can upgrade your files automatically (won't convert unit-less values)
tools/sg_xml_unit_converter.py may help (but it's just a warning and will probably ever be).
MSG
* The examples were completely reorganized (in C and Java), for your browsing pleasure.
- * Kill all deprecated functions (the ones you had when declaring MSG_DEPRECATED).
+ * Kill all deprecated functions (the ones you had when declaring MSG_DEPRECATED).
They were deprecated since a few years, and probably did not even compile anymore.
SimDag
- * The API has been profoundly modified to directly use the core objects instead of redefining its own.
+ * The API has been profoundly modified to directly use the core objects instead of redefining its own.
SD_Workstation_t and SD_link_t are now sg_host_t and sg_link_t respectively.
- Some functions have also been renamed for consistency. Backward compatibility is maintained, but users are
- encouraged to update their codes. A list of the modified functions can be found at the end of
+ Some functions have also been renamed for consistency. Backward compatibility is maintained, but users are
+ encouraged to update their codes. A list of the modified functions can be found at the end of
include/simgrid/simdag.h
Simix
* refactoring and cleanup of the code;
* ongoing process to cleanly separate the model-checking algorithms
from the code model-checking support.
-
+
-- Wed Apr 27 21:00:53 CEST 2016 Da SimGrid team <simgrid-devel@lists.gforge.inria.fr>
SimGrid (3.12) stable; urgency=low
@CMAKE_HOME_DIRECTORY@/include/simgrid \
@CMAKE_HOME_DIRECTORY@/include/simgrid/s4u \
@CMAKE_HOME_DIRECTORY@/src/include/surf \
+ @CMAKE_HOME_DIRECTORY@/src/include/xbt \
@CMAKE_HOME_DIRECTORY@/src/msg/ \
@CMAKE_HOME_DIRECTORY@/src/kernel/ \
@CMAKE_HOME_DIRECTORY@/src/kernel/activity/ \
- \c network/maxmin-selective-update: \ref options_model_optim
- \c network/model: \ref options_model_select
- \c network/optim: \ref options_model_optim
-- \c network/sender_gap: \ref options_model_network_sendergap
- \c network/TCP-gamma: \ref options_model_network_gamma
- \c network/weight-S: \ref options_model_network_coefs
Note that with the default host model this option is activated by default.
-\subsubsection options_model_network_sendergap Simulating sender gap
-
-(this configuration item is experimental and may change or disapear)
-
-It is possible to specify a timing gap between consecutive emission on
-the same network card through the \b network/sender-gap item. This
-is still under investigation as of writting, and the default value is
-to wait 10 microseconds (1e-5 seconds) between emissions.
-
\subsubsection options_model_network_asyncsend Simulating asyncronous send
(this configuration item is experimental and may change or disapear)
-/* Copyright (c) 2006-2014, 2016. The SimGrid Team.
+/* Copyright (c) 2006-2014, 2016-2017. The SimGrid Team.
* All rights reserved. */
/* This program is free software; you can redistribute it and/or modify it
public static final int MESSAGE_SIZE = 1; /* Information message size */
public static final int MAXIMUM_PEERS = 50; /* Max number of peers sent by the tracker to clients */
public static final int TRACKER_QUERY_INTERVAL = 1000; /* Interval of time where the peer should send a request to the tracker */
- public static final double TRACKER_COMM_SIZE = 0.01; /* Communication size for a task to the tracker */
+ public static final double TRACKER_COMM_SIZE = 1; /* Communication size for a task to the tracker */
public static final int GET_PEERS_TIMEOUT = 10000; /* Timeout for the get peers data */
public static final int TIMEOUT_MESSAGE = 10;
public static final int TRACKER_RECEIVE_TIMEOUT = 10;
set_target_properties(network-ns3 PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/network-ns3)
endif()
-add_executable (bittorrent app-bittorrent/bittorrent.c app-bittorrent/messages.c app-bittorrent/peer.c app-bittorrent/tracker.c app-bittorrent/connection.c)
-target_link_libraries(bittorrent simgrid)
-set_target_properties(bittorrent PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/app-bittorrent)
-foreach (file bittorrent connection messages peer tracker)
- set(examples_src ${examples_src} ${CMAKE_CURRENT_SOURCE_DIR}/app-bittorrent/${file}.c ${CMAKE_CURRENT_SOURCE_DIR}/app-bittorrent/${file}.h)
-endforeach()
-
add_executable (chainsend app-chainsend/chainsend.c app-chainsend/iterator.c app-chainsend/common.c app-chainsend/messages.c app-chainsend/broadcaster.c app-chainsend/peer.c)
target_link_libraries(chainsend simgrid)
set_target_properties(chainsend PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/app-chainsend)
set(examples_src ${examples_src} ${CMAKE_CURRENT_SOURCE_DIR}/dht-kademlia/${file}.c ${CMAKE_CURRENT_SOURCE_DIR}/dht-kademlia/${file}.h)
endforeach()
-foreach (file app-bittorrent app-chainsend app-masterworker app-pingpong async-wait
+foreach (file app-chainsend app-masterworker app-pingpong async-wait
async-waitall async-waitany dht-kademlia dht-pastry io-remote platform-properties process-yield
task-priority)
set(xml_files ${xml_files} ${CMAKE_CURRENT_SOURCE_DIR}/${file}/${file}_d.xml)
endforeach()
set(txt_files ${txt_files} ${CMAKE_CURRENT_SOURCE_DIR}/README.doc PARENT_SCOPE)
-set(bin_files ${bin_files} ${CMAKE_CURRENT_SOURCE_DIR}/app-bittorrent/generate.py
- ${CMAKE_CURRENT_SOURCE_DIR}/dht-kademlia/generate.py
+set(bin_files ${bin_files} ${CMAKE_CURRENT_SOURCE_DIR}/dht-kademlia/generate.py
${CMAKE_CURRENT_SOURCE_DIR}/dht-pastry/generate.py PARENT_SCOPE)
set(examples_src ${examples_src} ${CMAKE_CURRENT_SOURCE_DIR}/app-chainsend/chainsend.c
${CMAKE_CURRENT_SOURCE_DIR}/dht-kademlia/common.h
${CMAKE_CURRENT_SOURCE_DIR}/network-ns3/network-ns3.c PARENT_SCOPE)
-set(tesh_files ${tesh_files} ${CMAKE_CURRENT_SOURCE_DIR}/app-bittorrent/app-bittorrent.tesh
- ${CMAKE_CURRENT_SOURCE_DIR}/app-chainsend/app-chainsend.tesh
+set(tesh_files ${tesh_files} ${CMAKE_CURRENT_SOURCE_DIR}/app-chainsend/app-chainsend.tesh
${CMAKE_CURRENT_SOURCE_DIR}/dht-kademlia/dht-kademlia.tesh
${CMAKE_CURRENT_SOURCE_DIR}/app-masterworker/app-masterworker-multicore.tesh
${CMAKE_CURRENT_SOURCE_DIR}/app-masterworker/app-masterworker-vivaldi.tesh
${CMAKE_CURRENT_SOURCE_DIR}/process-startkilltime/start_d.xml
${CMAKE_CURRENT_SOURCE_DIR}/process-startkilltime/start_kill_d.xml PARENT_SCOPE)
-foreach(x app-bittorrent app-chainsend app-masterworker app-pingpong app-token-ring
+foreach(x app-chainsend app-masterworker app-pingpong app-token-ring
async-wait async-waitall async-waitany cloud-capping cloud-masterworker cloud-migration cloud-simple
cloud-two-tasks dht-pastry dht-kademlia platform-failures io-file io-remote io-storage task-priority
process-create process-daemon process-join process-kill process-migration process-startkilltime process-suspend process-yield
ADD_TESH(msg-trace-${x} --setenv bindir=${CMAKE_BINARY_DIR}/examples/msg/trace-${x} --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/platforms --cd ${CMAKE_HOME_DIRECTORY}/examples/msg/trace-${x} trace-${x}.tesh)
endforeach()
-ADD_TESH_FACTORIES(msg-app-bittorrent-parallel "thread;ucontext;raw" --cfg contexts/nthreads:4 ${CONTEXTS_SYNCHRO} --setenv bindir=${CMAKE_BINARY_DIR}/examples/msg/app-bittorrent --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/platforms --cd ${CMAKE_HOME_DIRECTORY}/examples/msg/app-bittorrent app-bittorrent.tesh)
ADD_TESH_FACTORIES(msg-dht-kademlia-parallel "thread;ucontext;raw" --cfg contexts/nthreads:4 ${CONTEXTS_SYNCHRO} --setenv bindir=${CMAKE_BINARY_DIR}/examples/msg/dht-kademlia --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/platforms --cd ${CMAKE_HOME_DIRECTORY}/examples/msg/dht-kademlia dht-kademlia.tesh)
ADD_TESH_FACTORIES(msg-energy-pstate-ptask "thread;ucontext;raw;boost" --cfg host/model:ptask_L07 --log xbt_cfg.threshold:critical --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/msg --cd ${CMAKE_BINARY_DIR}/examples/msg ${CMAKE_HOME_DIRECTORY}/examples/msg/energy-pstate/energy-pstate.tesh)
ADD_TESH_FACTORIES(msg-energy-consumption-ptask "thread;ucontext;raw;boost" --cfg host/model:ptask_L07 --log xbt_cfg.threshold:critical --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/msg --cd ${CMAKE_BINARY_DIR}/examples/msg ${CMAKE_HOME_DIRECTORY}/examples/msg/energy-consumption/energy-consumption.tesh)
+++ /dev/null
-/* Copyright (c) 2012-2014. 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 "messages.h"
-#include "bittorrent.h"
-
-XBT_LOG_NEW_DEFAULT_CATEGORY(msg_messages, "Messages specific for the message factory");
-
-#define BITS_TO_BYTES(x) ((x / 8) + (x % 8) ? 1 : 0)
-
-/** @brief Build a new empty message
- * @param type type of the message
- * @param issuer_host_name hostname of the issuer, for debugging purposes
- * @param mailbox mailbox where the peer should answer
- * @param peer_id id of the issuer
- * @param size message size in bytes
- */
-msg_task_t task_message_new(e_message_type type, const char *issuer_host_name, const char *mailbox, int peer_id,
- int size)
-{
- message_t message = xbt_new(s_message_t, 1);
- message->issuer_host_name = issuer_host_name;
- message->peer_id = peer_id;
- message->mailbox = mailbox;
- message->type = type;
- msg_task_t task = MSG_task_create(NULL, 0, size, message);
- XBT_DEBUG("type: %d size: %d", (int) type, size);
- return task;
-}
-
-/** Builds a message containing an index. */
-msg_task_t task_message_index_new(e_message_type type, const char *issuer_host_name, const char *mailbox, int peer_id,
- int index, int varsize)
-{
- msg_task_t task = task_message_new(type, issuer_host_name, mailbox, peer_id, task_message_size(type) + varsize);
- message_t message = MSG_task_get_data(task);
- message->index = index;
- return task;
-}
-
-msg_task_t task_message_bitfield_new(const char *issuer_host_name, const char *mailbox, int peer_id,
- unsigned int bitfield, int bitfield_size)
-{
- msg_task_t task = task_message_new(MESSAGE_BITFIELD, issuer_host_name, mailbox, peer_id,
- task_message_size(MESSAGE_BITFIELD) + BITS_TO_BYTES(bitfield_size));
- message_t message = MSG_task_get_data(task);
- message->bitfield = bitfield;
- return task;
-}
-
-msg_task_t task_message_request_new(const char *issuer_host_name, const char *mailbox, int peer_id, int index,
- int block_index, int block_length)
-{
- msg_task_t task = task_message_index_new(MESSAGE_REQUEST, issuer_host_name, mailbox, peer_id, index, 0);
- message_t message = MSG_task_get_data(task);
- message->block_index = block_index;
- message->block_length = block_length;
- return task;
-}
-
-msg_task_t task_message_piece_new(const char *issuer_host_name, const char *mailbox, int peer_id, int index,
- int block_index, int block_length, int block_size)
-{
- msg_task_t task = task_message_index_new(MESSAGE_PIECE, issuer_host_name, mailbox, peer_id, index,
- block_length * block_size);
- message_t message = MSG_task_get_data(task);
- message->block_index = block_index;
- message->block_length = block_length;
- return task;
-}
-
-void task_message_free(void *task)
-{
- message_t message = MSG_task_get_data(task);
- xbt_free(message);
- MSG_task_destroy(task);
-}
-
-int task_message_size(e_message_type type)
-{
- int size = 0;
- switch (type) {
- case MESSAGE_HANDSHAKE:
- size = MESSAGE_HANDSHAKE_SIZE;
- break;
- case MESSAGE_CHOKE:
- size = MESSAGE_CHOKE_SIZE;
- break;
- case MESSAGE_UNCHOKE:
- size = MESSAGE_UNCHOKE_SIZE;
- break;
- case MESSAGE_INTERESTED:
- case MESSAGE_NOTINTERESTED:
- size = MESSAGE_INTERESTED_SIZE;
- break;
- case MESSAGE_HAVE:
- size = MESSAGE_HAVE_SIZE;
- break;
- case MESSAGE_BITFIELD:
- size = MESSAGE_BITFIELD_SIZE;
- break;
- case MESSAGE_REQUEST:
- size = MESSAGE_REQUEST_SIZE;
- break;
- case MESSAGE_PIECE:
- size = MESSAGE_PIECE_SIZE;
- break;
- case MESSAGE_CANCEL:
- size = MESSAGE_CANCEL_SIZE;
- break;
- default:
- THROW_IMPOSSIBLE;
- }
- return size;
-}
+++ /dev/null
-/* Copyright (c) 2012-2014. 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 BITTORRENT_TRACKER_H_
-#define BITTORRENT_TRACKER_H_
-#include <xbt/dynar.h>
-#include "bittorrent.h"
-/**
- * Tracker main function
- */
-int tracker(int argc, char *argv[]);
-/**
- * Task types exchanged between a node and the tracker
- */
-typedef enum {
- TRACKER_TASK_QUERY,
- TRACKER_TASK_ANSWER
-} e_tracker_task_type_t;
-/**
- * Tasks exchanged between a tracker and peers.
- */
-typedef struct s_tracker_task_data {
- e_tracker_task_type_t type; //type of the task
- const char *mailbox; //mailbox where the tracker should answer
- const char *issuer_host_name; //hostname, for debug purposes
- //Query data
- int peer_id; //peer id
- int uploaded; //how much the peer has already uploaded
- int downloaded; //how much the peer has downloaded
- int left; //how much the peer has left
- //Answer data
- int interval; //how often the peer should contact the tracker (unused for now)
- xbt_dynar_t peers; //the peer list the peer has asked for.
-} s_tracker_task_data_t;
-typedef s_tracker_task_data_t *tracker_task_data_t;
-
-tracker_task_data_t tracker_task_data_new(const char *issuer_host_name, const char *mailbox, int peer_id,
- int uploaded, int downloaded, int left);
-void tracker_task_data_free(tracker_task_data_t task);
-
-int is_in_list(xbt_dynar_t peers, int id);
-#endif /* BITTORRENT_TRACKER_H */
XBT_INFO(" Property: %s old value: %s", exist, value);
XBT_INFO("== Trying to modify a host property");
- MSG_host_set_property_value(thehost, exist, xbt_strdup("250"));
+ MSG_host_set_property_value(thehost, exist, (char*)"250");
/* Test if we have changed the value */
value = MSG_host_get_property_value(thehost, exist);
XBT_INFO(" Property: %s old value: %s", exist, value);
/* Restore the value for the next test */
- MSG_host_set_property_value(thehost, exist, xbt_strdup("180"));
+ MSG_host_set_property_value(thehost, exist, (char*)"180");
+
+ xbt_dict_free(&props);
}
static int alice(int argc, char *argv[]) { /* Dump what we have on the current host */
value = MSG_process_get_property_value(MSG_process_self(), noexist);
xbt_assert(!value, "The property is defined (it shouldnt)");
+ xbt_dict_free(&props);
return 0;
}
> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'viva/uncategorized' to 'categories.uncat.plist'
$ $SG_TEST_EXENV cat categories.cat.plist
-> node = ("HOST","LINK");
-> edge = ("0-LINK4-LINK4","0-HOST1-LINK4","0-LINK4-HOST1");
+> node = ("LINK","HOST");
+> edge = ("0-LINK4-LINK4","0-LINK4-HOST1","0-HOST1-LINK4");
>
> host = {
> type = "square";
> size = "power";
-> values = ("pdata","pcompute","pfinalize","prequest");
+> values = ("pcompute","pdata","pfinalize","prequest");
> };
> link = {
> type = "rhombus";
> size = "bandwidth";
-> values = ("bdata","bcompute","bfinalize","brequest");
+> values = ("bcompute","bdata","bfinalize","brequest");
> };
$ $SG_TEST_EXENV cat categories.uncat.plist
-> node = ("HOST","LINK");
-> edge = ("0-LINK4-LINK4","0-HOST1-LINK4","0-LINK4-HOST1");
+> node = ("LINK","HOST");
+> edge = ("0-LINK4-LINK4","0-LINK4-HOST1","0-HOST1-LINK4");
>
> host = {
> type = "square";
> [0.004078] [msg_test/INFO] HDD_utilization
> [0.004078] [msg_test/INFO] Declared link variables:
> [0.004078] [msg_test/INFO] Node types in the trace:
-> [0.004078] [msg_test/INFO] LINK
> [0.004078] [msg_test/INFO] HOST
+> [0.004078] [msg_test/INFO] LINK
> [0.004078] [msg_test/INFO] Node types in the trace:
-> [0.004078] [msg_test/INFO] 0-LINK3-LINK3
> [0.004078] [msg_test/INFO] 0-HOST1-LINK3
> [0.004078] [msg_test/INFO] 0-LINK3-HOST1
+> [0.004078] [msg_test/INFO] 0-LINK3-LINK3
$ rm -f viva_graph.plist
> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'viva/categorized' to 'trace-masterworker.cat.plist'
> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'viva/uncategorized' to 'trace-masterworker.uncat.plist'
> [4.214821] [msg_trace_masterworker/INFO] Declared tracing categories:
-> [4.214821] [msg_trace_masterworker/INFO] request
+> [4.214821] [msg_trace_masterworker/INFO] compute
> [4.214821] [msg_trace_masterworker/INFO] finalize
> [4.214821] [msg_trace_masterworker/INFO] report
-> [4.214821] [msg_trace_masterworker/INFO] compute
+> [4.214821] [msg_trace_masterworker/INFO] request
> [4.214821] [msg_trace_masterworker/INFO] Declared marks:
> [4.214821] [msg_trace_masterworker/INFO] msmark
> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'viva/categorized' to 'trace-masterworker.cat.plist'
> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'viva/uncategorized' to 'trace-masterworker.uncat.plist'
> [4.214821] [msg_trace_masterworker/INFO] Declared tracing categories:
-> [4.214821] [msg_trace_masterworker/INFO] request
+> [4.214821] [msg_trace_masterworker/INFO] compute
> [4.214821] [msg_trace_masterworker/INFO] finalize
> [4.214821] [msg_trace_masterworker/INFO] report
-> [4.214821] [msg_trace_masterworker/INFO] compute
+> [4.214821] [msg_trace_masterworker/INFO] request
> [4.214821] [msg_trace_masterworker/INFO] Declared marks:
> [4.214821] [msg_trace_masterworker/INFO] msmark
> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'viva/categorized' to 'trace-masterworker.cat.plist'
> [0.000000] [xbt_cfg/INFO] Configuration change: Set 'viva/uncategorized' to 'trace-masterworker.uncat.plist'
> [4.214821] [msg_trace_masterworker/INFO] Declared tracing categories:
-> [4.214821] [msg_trace_masterworker/INFO] request
+> [4.214821] [msg_trace_masterworker/INFO] compute
> [4.214821] [msg_trace_masterworker/INFO] finalize
> [4.214821] [msg_trace_masterworker/INFO] report
-> [4.214821] [msg_trace_masterworker/INFO] compute
+> [4.214821] [msg_trace_masterworker/INFO] request
> [4.214821] [msg_trace_masterworker/INFO] Declared marks:
> [4.214821] [msg_trace_masterworker/INFO] msmark
$ $SG_TEST_EXENV cat trace-masterworker.uncat.plist
-> node = ("HOST","LINK");
+> node = ("LINK","HOST");
> edge = ("0-LINK13-LINK13","0-LINK13-HOST1","0-HOST1-LINK13");
->
+>
> host = {
> type = "square";
> size = "power";
> };
$ $SG_TEST_EXENV cat trace-masterworker.cat.plist
-> node = ("HOST","LINK");
+> node = ("LINK","HOST");
> edge = ("0-LINK13-LINK13","0-LINK13-HOST1","0-HOST1-LINK13");
->
+>
> host = {
> type = "square";
> size = "power";
-> values = ("pcompute","preport","pfinalize","prequest");
+> values = ("pcompute","pfinalize","preport","prequest");
> };
> link = {
> type = "rhombus";
> size = "bandwidth";
-> values = ("bcompute","breport","bfinalize","brequest");
+> values = ("bcompute","bfinalize","breport","brequest");
> };
$ rm -rf trace-masterworker.trace trace-masterworker.cat.plist trace-masterworker.uncat.plist
endforeach()
set(examples_src ${examples_src} ${CMAKE_CURRENT_SOURCE_DIR}/dht-chord/s4u_dht-chord.hpp)
+add_executable (s4u_bittorrent app-bittorrent/s4u_bittorrent.cpp app-bittorrent/s4u_peer.cpp
+ app-bittorrent/s4u_tracker.cpp)
+target_link_libraries(s4u_bittorrent simgrid)
+set_target_properties(s4u_bittorrent PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/app-bittorrent)
+foreach (file s4u_bittorrent s4u_peer s4u_tracker)
+ set(examples_src ${examples_src} ${CMAKE_CURRENT_SOURCE_DIR}/app-bittorrent/${file}.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/app-bittorrent/${file}.hpp)
+endforeach()
+
set(examples_src ${examples_src} PARENT_SCOPE)
-set(tesh_files ${tesh_files} ${CMAKE_CURRENT_SOURCE_DIR}/dht-chord/s4u_dht-chord.tesh PARENT_SCOPE)
+set(tesh_files ${tesh_files} ${CMAKE_CURRENT_SOURCE_DIR}/app-bittorrent/s4u_app-bittorrent.tesh
+ ${CMAKE_CURRENT_SOURCE_DIR}/dht-chord/s4u_dht-chord.tesh PARENT_SCOPE)
set(xml_files ${xml_files} ${CMAKE_CURRENT_SOURCE_DIR}/actions-comm/s4u_actions-comm_split_d.xml
${CMAKE_CURRENT_SOURCE_DIR}/actions-comm/s4u_actions-comm_d.xml
${CMAKE_CURRENT_SOURCE_DIR}/actions-storage/s4u_actions-storage_d.xml
${CMAKE_CURRENT_SOURCE_DIR}/actor-create/s4u_actor-create_d.xml
+ ${CMAKE_CURRENT_SOURCE_DIR}/app-bittorrent/s4u_app-bittorrent_d.xml
${CMAKE_CURRENT_SOURCE_DIR}/app-masterworker/s4u_app-masterworker_d.xml
${CMAKE_CURRENT_SOURCE_DIR}/dht-chord/s4u_dht-chord_d.xml PARENT_SCOPE)
set(txt_files ${txt_files} ${CMAKE_CURRENT_SOURCE_DIR}/actions-comm/s4u_actions-comm_split_p0.txt
${CMAKE_CURRENT_SOURCE_DIR}/README.doc PARENT_SCOPE)
foreach(example actions-comm actions-storage actor-create actor-daemon actor-kill actor-migration actor-suspend
- app-masterworker app-pingpong app-token-ring dht-chord plugin-hostload io mutex )
+ app-bittorrent app-masterworker app-pingpong app-token-ring dht-chord plugin-hostload io mutex )
ADD_TESH_FACTORIES(s4u-${example} "thread;ucontext;raw;boost" --setenv bindir=${CMAKE_CURRENT_BINARY_DIR}/${example} --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/platforms --cd ${CMAKE_HOME_DIRECTORY}/examples/s4u/${example} s4u_${example}.tesh)
endforeach()
}
}
-static simgrid::s4u::File* get_file_descriptor(const char* file_name)
+static simgrid::s4u::File* get_file_descriptor(std::string file_name)
{
std::string full_name = simgrid::s4u::this_actor::getName() + ":" + file_name;
/* My actions */
static void open(const char* const* action)
{
- const char* file_name = action[2];
+ std::string file_name = action[2];
double clock = simgrid::s4u::Engine::getClock();
std::string full_name = simgrid::s4u::this_actor::getName() + ":" + file_name;
- ACT_DEBUG("Entering Open: %s (filename: %s)", NAME, file_name);
+ ACT_DEBUG("Entering Open: %s (filename: %s)", NAME, file_name.c_str());
simgrid::s4u::File* file = new simgrid::s4u::File(file_name, NULL);
opened_files.insert({full_name, file});
static void read(const char* const* action)
{
- const char* file_name = action[2];
+ std::string file_name = action[2];
sg_size_t size = std::stoul(action[3]);
double clock = simgrid::s4u::Engine::getClock();
static void close(const char* const* action)
{
- const char* file_name = action[2];
+ std::string file_name = action[2];
double clock = simgrid::s4u::Engine::getClock();
simgrid::s4u::File* file = get_file_descriptor(file_name);
- ACT_DEBUG("Entering Close: %s (filename: %s)", NAME, file_name);
+ ACT_DEBUG("Entering Close: %s (filename: %s)", NAME, file_name.c_str());
delete file;
log_action(action, simgrid::s4u::Engine::getClock() - clock);
--- /dev/null
+#! ./tesh
+
+p Testing the Bittorrent implementation with MSG
+
+! timeout 10
+! output sort 19
+$ $SG_TEST_EXENV ${bindir:=.}/s4u_bittorrent ${srcdir:=.}/cluster.xml ${srcdir:=.}/../s4u/app-bittorrent/s4u_app-bittorrent_d.xml "--log=root.fmt:[%12.6r]%e(%i:%P@%h)%e%m%n"
+> [ 0.000000] (1:tracker@node-0.acme.org) Tracker launched.
+> [ 0.000000] (2:peer@node-1.acme.org) Hi, I'm joining the network with id 2
+> [ 0.000000] (3:peer@node-2.acme.org) Hi, I'm joining the network with id 3
+> [ 0.000000] (4:peer@node-3.acme.org) Hi, I'm joining the network with id 4
+> [ 0.000000] (5:peer@node-4.acme.org) Hi, I'm joining the network with id 5
+> [ 0.000000] (6:peer@node-5.acme.org) Hi, I'm joining the network with id 6
+> [ 0.000000] (7:peer@node-6.acme.org) Hi, I'm joining the network with id 7
+> [ 0.000000] (8:peer@node-7.acme.org) Hi, I'm joining the network with id 8
+> [ 3000.000000] (1:tracker@node-0.acme.org) Tracker is leaving
+> [ 5000.007806] (2:peer@node-1.acme.org) Here is my current status: 1111111111
+> [ 5000.007806] (3:peer@node-2.acme.org) Here is my current status: 1111111111
+> [ 5000.007806] (4:peer@node-3.acme.org) Here is my current status: 1111111111
+> [ 5000.007806] (5:peer@node-4.acme.org) Here is my current status: 1111111111
+> [ 5000.007806] (6:peer@node-5.acme.org) Here is my current status: 1111111111
+> [ 5000.007806] (7:peer@node-6.acme.org) Here is my current status: 1111111111
+> [ 5000.007806] (8:peer@node-7.acme.org) Here is my current status: 1111111111
--- /dev/null
+/* Copyright (c) 2012-2017. 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 "s4u_bittorrent.hpp"
+#include "s4u_peer.hpp"
+#include "s4u_tracker.hpp"
+
+simgrid::xbt::Extension<simgrid::s4u::Host, HostBittorrent> HostBittorrent::EXTENSION_ID;
+
+int main(int argc, char* argv[])
+{
+ simgrid::s4u::Engine* e = new simgrid::s4u::Engine(&argc, argv);
+
+ /* Check the arguments */
+ xbt_assert(argc > 2, "Usage: %s platform_file deployment_file", argv[0]);
+
+ e->loadPlatform(argv[1]);
+
+ HostBittorrent::EXTENSION_ID = simgrid::s4u::Host::extension_create<HostBittorrent>();
+
+ std::vector<simgrid::s4u::Host*> list;
+ simgrid::s4u::Engine::getInstance()->getHostList(&list);
+ for (auto host : list)
+ host->extension_set(new HostBittorrent(host));
+
+ e->registerFunction<Tracker>("tracker");
+ e->registerFunction<Peer>("peer");
+ e->loadDeployment(argv[2]);
+
+ e->run();
+
+ delete e;
+ return 0;
+}
--- /dev/null
+/* Copyright (c) 2012-2014, 2016-2017. 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 BITTORRENT_BITTORRENT_HPP_
+#define BITTORRENT_BITTORRENT_HPP_
+
+#include <simgrid/s4u.hpp>
+#include <xbt/RngStream.h>
+
+#define MAILBOX_SIZE 40
+#define TRACKER_MAILBOX "tracker_mailbox"
+/** Max number of peers sent by the tracker to clients */
+#define MAXIMUM_PEERS 50
+/** Interval of time where the peer should send a request to the tracker */
+#define TRACKER_QUERY_INTERVAL 1000
+/** Communication size for a task to the tracker */
+#define TRACKER_COMM_SIZE 1
+#define GET_PEERS_TIMEOUT 10000
+#define TIMEOUT_MESSAGE 10
+#define TRACKER_RECEIVE_TIMEOUT 10
+/** Number of peers that can be unchocked at a given time */
+#define MAX_UNCHOKED_PEERS 4
+/** Interval between each update of the choked peers */
+#define UPDATE_CHOKED_INTERVAL 30
+/** Number of pieces the peer asks for simultaneously */
+#define MAX_PIECES 1
+
+/** Message sizes
+ * Sizes based on report by A. Legout et al, Understanding BitTorrent: An Experimental Perspective
+ * http://hal.inria.fr/inria-00000156/en
+ */
+#define MESSAGE_HANDSHAKE_SIZE 68
+#define MESSAGE_CHOKE_SIZE 5
+#define MESSAGE_UNCHOKE_SIZE 5
+#define MESSAGE_INTERESTED_SIZE 5
+#define MESSAGE_NOTINTERESTED_SIZE 5
+#define MESSAGE_HAVE_SIZE 9
+#define MESSAGE_BITFIELD_SIZE 5
+#define MESSAGE_REQUEST_SIZE 17
+#define MESSAGE_PIECE_SIZE 13
+#define MESSAGE_CANCEL_SIZE 17
+
+/** Types of messages exchanged between two peers. */
+typedef enum {
+ MESSAGE_HANDSHAKE,
+ MESSAGE_CHOKE,
+ MESSAGE_UNCHOKE,
+ MESSAGE_INTERESTED,
+ MESSAGE_NOTINTERESTED,
+ MESSAGE_HAVE,
+ MESSAGE_BITFIELD,
+ MESSAGE_REQUEST,
+ MESSAGE_PIECE,
+ MESSAGE_CANCEL
+} e_message_type;
+
+class Message {
+public:
+ e_message_type type;
+ int peer_id;
+ simgrid::s4u::MailboxPtr return_mailbox;
+ unsigned int bitfield = 0U;
+ int piece = 0;
+ int block_index = 0;
+ int block_length = 0;
+ Message(e_message_type type, int peer_id, simgrid::s4u::MailboxPtr return_mailbox)
+ : type(type), peer_id(peer_id), return_mailbox(return_mailbox){};
+ Message(e_message_type type, int peer_id, unsigned int bitfield, simgrid::s4u::MailboxPtr return_mailbox)
+ : type(type), peer_id(peer_id), return_mailbox(return_mailbox), bitfield(bitfield){};
+ Message(e_message_type type, int peer_id, simgrid::s4u::MailboxPtr return_mailbox, int piece, int block_index,
+ int block_length)
+ : type(type)
+ , peer_id(peer_id)
+ , return_mailbox(return_mailbox)
+ , piece(piece)
+ , block_index(block_index)
+ , block_length(block_length){};
+ Message(e_message_type type, int peer_id, simgrid::s4u::MailboxPtr return_mailbox, int piece)
+ : type(type), peer_id(peer_id), return_mailbox(return_mailbox), piece(piece){};
+ ~Message() = default;
+};
+
+class HostBittorrent {
+ RngStream stream_;
+ simgrid::s4u::Host* host = nullptr;
+
+public:
+ static simgrid::xbt::Extension<simgrid::s4u::Host, HostBittorrent> EXTENSION_ID;
+
+ explicit HostBittorrent(simgrid::s4u::Host* ptr) : host(ptr)
+ {
+ std::string descr = std::string("RngSream<") + host->getCname() + ">";
+ stream_ = RngStream_CreateStream(descr.c_str());
+ }
+
+ ~HostBittorrent() { RngStream_DeleteStream(&stream_); };
+
+ RngStream getStream() { return stream_; };
+};
+
+#endif /* BITTORRENT_BITTORRENT_HPP_ */
--- /dev/null
+/* Copyright (c) 2012-2017. 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 <climits>
+#include <xbt/ex.hpp>
+
+#include "s4u_peer.hpp"
+#include "s4u_tracker.hpp"
+
+XBT_LOG_NEW_DEFAULT_CATEGORY(s4u_bt_peer, "Messages specific for the peers");
+
+/*
+ * User parameters for transferred file data. For the test, the default values are :
+ * File size: 10 pieces * 5 blocks/piece * 16384 bytes/block = 819200 bytes
+ */
+#define FILE_PIECES 10UL
+#define PIECES_BLOCKS 5UL
+#define BLOCK_SIZE 16384
+
+/** Number of blocks asked by each request */
+#define BLOCKS_REQUESTED 2
+
+#define ENABLE_END_GAME_MODE 1
+#define SLEEP_DURATION 1
+#define BITS_TO_BYTES(x) (((x) / 8 + (x) % 8) ? 1 : 0)
+
+Peer::Peer(std::vector<std::string> args)
+{
+ // Check arguments
+ xbt_assert(args.size() == 3 || args.size() == 4, "Wrong number of arguments");
+ try {
+ id = std::stoi(args[1]);
+ mailbox_ = simgrid::s4u::Mailbox::byName(std::to_string(id));
+ } catch (std::invalid_argument& ia) {
+ throw std::invalid_argument(std::string("Invalid ID:") + args[1].c_str());
+ }
+
+ try {
+ deadline = std::stod(args[2]);
+ } catch (std::invalid_argument& ia) {
+ throw std::invalid_argument(std::string("Invalid deadline:") + args[2].c_str());
+ }
+ xbt_assert(deadline > 0, "Wrong deadline supplied");
+
+ stream = simgrid::s4u::this_actor::getHost()->extension<HostBittorrent>()->getStream();
+
+ if (args.size() == 4 && args[3] == "1") {
+ bitfield_ = (1U << FILE_PIECES) - 1U;
+ bitfield_blocks = (1ULL << (FILE_PIECES * PIECES_BLOCKS)) - 1ULL;
+ }
+ pieces_count = new short[FILE_PIECES]{0};
+
+ XBT_INFO("Hi, I'm joining the network with id %d", id);
+}
+
+Peer::~Peer()
+{
+ for (auto peer : connected_peers)
+ delete peer.second;
+ delete[] pieces_count;
+}
+
+/** Peer main function */
+void Peer::operator()()
+{
+ // Getting peer data from the tracker.
+ if (getPeersFromTracker()) {
+ XBT_DEBUG("Got %zu peers from the tracker. Current status is: %s", connected_peers.size(), getStatus().c_str());
+ begin_receive_time = simgrid::s4u::Engine::getClock();
+ mailbox_->setReceiver(simgrid::s4u::Actor::self());
+ if (hasFinished()) {
+ sendHandshakeToAllPeers();
+ } else {
+ leech();
+ }
+ seed();
+ } else {
+ XBT_INFO("Couldn't contact the tracker.");
+ }
+
+ XBT_INFO("Here is my current status: %s", getStatus().c_str());
+}
+
+bool Peer::getPeersFromTracker()
+{
+ simgrid::s4u::MailboxPtr tracker_mailbox = simgrid::s4u::Mailbox::byName(TRACKER_MAILBOX);
+ // Build the task to send to the tracker
+ TrackerQuery* peer_request = new TrackerQuery(id, mailbox_);
+ try {
+ XBT_DEBUG("Sending a peer request to the tracker.");
+ tracker_mailbox->put(peer_request, TRACKER_COMM_SIZE, GET_PEERS_TIMEOUT);
+ } catch (xbt_ex& e) {
+ if (e.category == timeout_error) {
+ XBT_DEBUG("Timeout expired when requesting peers to tracker");
+ delete peer_request;
+ return false;
+ }
+ }
+
+ try {
+ TrackerAnswer* answer = static_cast<TrackerAnswer*>(mailbox_->get(GET_PEERS_TIMEOUT));
+ // Add the peers the tracker gave us to our peer list.
+ for (auto peer_id : *answer->getPeers())
+ if (id != peer_id)
+ connected_peers[peer_id] = new Connection(peer_id);
+ delete answer;
+ } catch (xbt_ex& e) {
+ if (e.category == timeout_error) {
+ XBT_DEBUG("Timeout expired when requesting peers to tracker");
+ return false;
+ }
+ }
+ return true;
+}
+
+void Peer::sendHandshakeToAllPeers()
+{
+ for (auto kv : connected_peers) {
+ Connection* remote_peer = kv.second;
+ Message* handshake = new Message(MESSAGE_HANDSHAKE, id, mailbox_);
+ remote_peer->mailbox_->put_init(handshake, MESSAGE_HANDSHAKE_SIZE)->detach();
+ XBT_DEBUG("Sending a HANDSHAKE to %d", remote_peer->id);
+ }
+}
+
+void Peer::sendMessage(simgrid::s4u::MailboxPtr mailbox, e_message_type type, uint64_t size)
+{
+ const char* type_names[6] = {"HANDSHAKE", "CHOKE", "UNCHOKE", "INTERESTED", "NOTINTERESTED", "CANCEL"};
+ XBT_DEBUG("Sending %s to %s", type_names[type], mailbox->getName());
+ mailbox->put_init(new Message(type, id, bitfield_, mailbox_), size)->detach();
+}
+
+void Peer::sendBitfield(simgrid::s4u::MailboxPtr mailbox)
+{
+ XBT_DEBUG("Sending a BITFIELD to %s", mailbox->getName());
+ mailbox
+ ->put_init(new Message(MESSAGE_BITFIELD, id, bitfield_, mailbox_),
+ MESSAGE_BITFIELD_SIZE + BITS_TO_BYTES(FILE_PIECES))
+ ->detach();
+}
+
+void Peer::sendPiece(simgrid::s4u::MailboxPtr mailbox, unsigned int piece, int block_index, int block_length)
+{
+ xbt_assert(not hasNotPiece(piece), "Tried to send a unavailable piece.");
+ XBT_DEBUG("Sending the PIECE %u (%d,%d) to %s", piece, block_index, block_length, mailbox->getName());
+ mailbox->put_init(new Message(MESSAGE_PIECE, id, mailbox_, piece, block_index, block_length), BLOCK_SIZE)->detach();
+}
+
+void Peer::sendHaveToAllPeers(unsigned int piece)
+{
+ XBT_DEBUG("Sending HAVE message to all my peers");
+ for (auto kv : connected_peers) {
+ Connection* remote_peer = kv.second;
+ remote_peer->mailbox_->put_init(new Message(MESSAGE_HAVE, id, mailbox_, piece), MESSAGE_HAVE_SIZE)->detach();
+ }
+}
+
+void Peer::sendRequestTo(Connection* remote_peer, unsigned int piece)
+{
+ remote_peer->current_piece = piece;
+ xbt_assert(remote_peer->hasPiece(piece));
+ int block_index = getFirstMissingBlockFrom(piece);
+ if (block_index != -1) {
+ int block_length = MIN(BLOCKS_REQUESTED, PIECES_BLOCKS - block_index);
+ XBT_DEBUG("Sending a REQUEST to %s for piece %u (%d,%d)", remote_peer->mailbox_->getName(), piece, block_index,
+ block_length);
+ remote_peer->mailbox_
+ ->put_init(new Message(MESSAGE_REQUEST, id, mailbox_, piece, block_index, block_length), MESSAGE_REQUEST_SIZE)
+ ->detach();
+ }
+}
+
+std::string Peer::getStatus()
+{
+ std::string res = std::string("");
+ for (int i = FILE_PIECES - 1; i >= 0; i--)
+ res = std::string((bitfield_ & (1U << i)) ? "1" : "0") + res;
+ return res;
+}
+
+bool Peer::hasFinished()
+{
+ return bitfield_ == (1U << FILE_PIECES) - 1U;
+}
+
+/** Indicates if the remote peer has a piece not stored by the local peer */
+bool Peer::isInterestedBy(Connection* remote_peer)
+{
+ return remote_peer->bitfield & (bitfield_ ^ ((1 << FILE_PIECES) - 1));
+}
+
+bool Peer::isInterestedByFree(Connection* remote_peer)
+{
+ for (unsigned int i = 0; i < FILE_PIECES; i++)
+ if (hasNotPiece(i) && remote_peer->hasPiece(i) && isNotDownloadingPiece(i))
+ return true;
+ return false;
+}
+
+void Peer::updatePiecesCountFromBitfield(unsigned int bitfield)
+{
+ for (unsigned int i = 0; i < FILE_PIECES; i++)
+ if (bitfield & (1U << i))
+ pieces_count[i]++;
+}
+
+unsigned int Peer::countPieces(unsigned int bitfield)
+{
+ unsigned int count = 0U;
+ unsigned int n = bitfield;
+ while (n) {
+ count += n & 1U;
+ n >>= 1U;
+ }
+ return count;
+}
+
+int Peer::nbInterestedPeers()
+{
+ int nb = 0;
+ for (auto kv : connected_peers)
+ if (kv.second->interested)
+ nb++;
+ return nb;
+}
+
+void Peer::leech()
+{
+ double next_choked_update = simgrid::s4u::Engine::getClock() + UPDATE_CHOKED_INTERVAL;
+ XBT_DEBUG("Start downloading.");
+
+ /* Send a "handshake" message to all the peers it got (since it couldn't have gotten more than 50 peers) */
+ sendHandshakeToAllPeers();
+ XBT_DEBUG("Starting main leech loop listening on mailbox: %s", mailbox_->getName());
+
+ void* data = nullptr;
+ while (simgrid::s4u::Engine::getClock() < deadline && countPieces(bitfield_) < FILE_PIECES) {
+ if (comm_received == nullptr) {
+ comm_received = mailbox_->get_async(&data);
+ }
+ if (comm_received->test()) {
+ message = static_cast<Message*>(data);
+ handleMessage();
+ delete message;
+ comm_received = nullptr;
+ } else {
+ // We don't execute the choke algorithm if we don't already have a piece
+ if (simgrid::s4u::Engine::getClock() >= next_choked_update && countPieces(bitfield_) > 0) {
+ updateChokedPeers();
+ next_choked_update += UPDATE_CHOKED_INTERVAL;
+ } else {
+ simgrid::s4u::this_actor::sleep_for(SLEEP_DURATION);
+ }
+ }
+ }
+ if (hasFinished())
+ XBT_DEBUG("%d becomes a seeder", id);
+}
+
+void Peer::seed()
+{
+ double next_choked_update = simgrid::s4u::Engine::getClock() + UPDATE_CHOKED_INTERVAL;
+ XBT_DEBUG("Start seeding.");
+ // start the main seed loop
+ void* data = nullptr;
+ while (simgrid::s4u::Engine::getClock() < deadline) {
+ if (comm_received == nullptr) {
+ comm_received = mailbox_->get_async(&data);
+ }
+ if (comm_received->test()) {
+ message = static_cast<Message*>(data);
+ handleMessage();
+ delete message;
+ comm_received = nullptr;
+ } else {
+ if (simgrid::s4u::Engine::getClock() >= next_choked_update) {
+ updateChokedPeers();
+ // TODO: Change the choked peer algorithm when seeding.
+ next_choked_update += UPDATE_CHOKED_INTERVAL;
+ } else {
+ simgrid::s4u::this_actor::sleep_for(SLEEP_DURATION);
+ }
+ }
+ }
+}
+
+void Peer::updateActivePeersSet(Connection* remote_peer)
+{
+ if (remote_peer->interested && not remote_peer->choked_upload)
+ active_peers.insert(remote_peer);
+ else
+ active_peers.erase(remote_peer);
+}
+
+void Peer::handleMessage()
+{
+ const char* type_names[10] = {"HANDSHAKE", "CHOKE", "UNCHOKE", "INTERESTED", "NOTINTERESTED",
+ "HAVE", "BITFIELD", "REQUEST", "PIECE", "CANCEL"};
+
+ XBT_DEBUG("Received a %s message from %s", type_names[message->type], message->return_mailbox->getName());
+
+ auto known_peer = connected_peers.find(message->peer_id);
+ Connection* remote_peer = (known_peer == connected_peers.end()) ? nullptr : known_peer->second;
+ xbt_assert(remote_peer != nullptr || message->type == MESSAGE_HANDSHAKE,
+ "The impossible did happened: A not-in-our-list peer sent us a message.");
+
+ switch (message->type) {
+ case MESSAGE_HANDSHAKE:
+ // Check if the peer is in our connection list.
+ if (remote_peer == nullptr) {
+ XBT_DEBUG("This peer %d was unknown, answer to its handshake", message->peer_id);
+ connected_peers[message->peer_id] = new Connection(message->peer_id);
+ sendMessage(message->return_mailbox, MESSAGE_HANDSHAKE, MESSAGE_HANDSHAKE_SIZE);
+ }
+ // Send our bitfield to the peer
+ sendBitfield(message->return_mailbox);
+ break;
+ case MESSAGE_BITFIELD:
+ // Update the pieces list
+ updatePiecesCountFromBitfield(message->bitfield);
+ // Store the bitfield
+ remote_peer->bitfield = message->bitfield;
+ xbt_assert(not remote_peer->am_interested, "Should not be interested at first");
+ if (isInterestedBy(remote_peer)) {
+ remote_peer->am_interested = true;
+ sendMessage(message->return_mailbox, MESSAGE_INTERESTED, MESSAGE_INTERESTED_SIZE);
+ }
+ break;
+ case MESSAGE_INTERESTED:
+ // Update the interested state of the peer.
+ remote_peer->interested = true;
+ updateActivePeersSet(remote_peer);
+ break;
+ case MESSAGE_NOTINTERESTED:
+ remote_peer->interested = false;
+ updateActivePeersSet(remote_peer);
+ break;
+ case MESSAGE_UNCHOKE:
+ xbt_assert(remote_peer->choked_download);
+ remote_peer->choked_download = false;
+ // Send requests to the peer, since it has unchoked us
+ if (remote_peer->am_interested)
+ requestNewPieceTo(remote_peer);
+ break;
+ case MESSAGE_CHOKE:
+ xbt_assert(not remote_peer->choked_download);
+ remote_peer->choked_download = true;
+ if (remote_peer->current_piece != -1)
+ removeCurrentPiece(remote_peer, remote_peer->current_piece);
+ break;
+ case MESSAGE_HAVE:
+ XBT_DEBUG("\t for piece %d", message->piece);
+ xbt_assert((message->piece >= 0 && static_cast<unsigned int>(message->piece) < FILE_PIECES),
+ "Wrong HAVE message received");
+ remote_peer->bitfield = remote_peer->bitfield | (1U << static_cast<unsigned int>(message->piece));
+ pieces_count[message->piece]++;
+ // If the piece is in our pieces, we tell the peer that we are interested.
+ if (not remote_peer->am_interested && hasNotPiece(message->piece)) {
+ remote_peer->am_interested = true;
+ sendMessage(message->return_mailbox, MESSAGE_INTERESTED, MESSAGE_INTERESTED_SIZE);
+ if (not remote_peer->choked_download)
+ requestNewPieceTo(remote_peer);
+ }
+ break;
+ case MESSAGE_REQUEST:
+ xbt_assert(remote_peer->interested);
+ xbt_assert((message->piece >= 0 && static_cast<unsigned int>(message->piece) < FILE_PIECES),
+ "Wrong HAVE message received");
+ if (not remote_peer->choked_upload) {
+ XBT_DEBUG("\t for piece %d (%d,%d)", message->piece, message->block_index,
+ message->block_index + message->block_length);
+ if (not hasNotPiece(message->piece)) {
+ sendPiece(message->return_mailbox, message->piece, message->block_index, message->block_length);
+ }
+ } else {
+ XBT_DEBUG("\t for piece %d but he is choked.", message->peer_id);
+ }
+ break;
+ case MESSAGE_PIECE:
+ XBT_DEBUG(" \t for piece %d (%d,%d)", message->piece, message->block_index,
+ message->block_index + message->block_length);
+ xbt_assert(not remote_peer->choked_download);
+ xbt_assert(remote_peer->am_interested || ENABLE_END_GAME_MODE,
+ "Can't received a piece if I'm not interested without end-game mode!"
+ "piece (%d) bitfield (%u) remote bitfield (%u)",
+ message->piece, bitfield_, remote_peer->bitfield);
+ xbt_assert(not remote_peer->choked_download, "Can't received a piece if I'm choked !");
+ xbt_assert((message->piece >= 0 && static_cast<unsigned int>(message->piece) < FILE_PIECES),
+ "Wrong piece received");
+ // TODO: Execute a computation.
+ if (hasNotPiece(static_cast<unsigned int>(message->piece))) {
+ updateBitfieldBlocks(message->piece, message->block_index, message->block_length);
+ if (hasCompletedPiece(static_cast<unsigned int>(message->piece))) {
+ // Removing the piece from our piece list
+ removeCurrentPiece(remote_peer, message->piece);
+ // Setting the fact that we have the piece
+ bitfield_ = bitfield_ | (1U << static_cast<unsigned int>(message->piece));
+ XBT_DEBUG("My status is now %s", getStatus().c_str());
+ // Sending the information to all the peers we are connected to
+ sendHaveToAllPeers(message->piece);
+ // sending UNINTERESTED to peers that do not have what we want.
+ updateInterestedAfterReceive();
+ } else { // piece not completed
+ sendRequestTo(remote_peer, message->piece); // ask for the next block
+ }
+ } else {
+ XBT_DEBUG("However, we already have it");
+ xbt_assert(ENABLE_END_GAME_MODE, "Should not happen because we don't use end game mode !");
+ requestNewPieceTo(remote_peer);
+ }
+ break;
+ case MESSAGE_CANCEL:
+ break;
+ default:
+ THROW_IMPOSSIBLE;
+ }
+ // Update the peer speed.
+ if (remote_peer) {
+ remote_peer->addSpeedValue(1.0 / (simgrid::s4u::Engine::getClock() - begin_receive_time));
+ }
+ begin_receive_time = simgrid::s4u::Engine::getClock();
+}
+
+/** Selects the appropriate piece to download and requests it to the remote_peer */
+void Peer::requestNewPieceTo(Connection* remote_peer)
+{
+ int piece = selectPieceToDownload(remote_peer);
+ if (piece != -1) {
+ current_pieces |= (1U << (unsigned int)piece);
+ sendRequestTo(remote_peer, piece);
+ }
+}
+
+void Peer::removeCurrentPiece(Connection* remote_peer, unsigned int current_piece)
+{
+ current_pieces &= ~(1U << current_piece);
+ remote_peer->current_piece = -1;
+}
+
+/** @brief Return the piece to be downloaded
+ * There are two cases (as described in "Bittorrent Architecture Protocol", Ryan Toole :
+ * If a piece is partially downloaded, this piece will be selected prioritarily
+ * If the peer has strictly less than 4 pieces, he chooses a piece at random.
+ * If the peer has more than pieces, he downloads the pieces that are the less replicated (rarest policy).
+ * If all pieces have been downloaded or requested, we select a random requested piece (endgame mode).
+ * @param remote_peer: information about the connection
+ * @return the piece to download if possible. -1 otherwise
+ */
+int Peer::selectPieceToDownload(Connection* remote_peer)
+{
+ int piece = partiallyDownloadedPiece(remote_peer);
+ // strict priority policy
+ if (piece != -1)
+ return piece;
+
+ // end game mode
+ if (countPieces(current_pieces) >= (FILE_PIECES - countPieces(bitfield_)) && isInterestedBy(remote_peer)) {
+#if ENABLE_END_GAME_MODE == 0
+ return -1;
+#endif
+ int nb_interesting_pieces = 0;
+ // compute the number of interesting pieces
+ for (unsigned int i = 0; i < FILE_PIECES; i++)
+ if (hasNotPiece(i) && remote_peer->hasPiece(i))
+ nb_interesting_pieces++;
+
+ xbt_assert(nb_interesting_pieces != 0);
+ // get a random interesting piece
+ int random_piece_index = RngStream_RandInt(stream, 0, nb_interesting_pieces - 1);
+ int current_index = 0;
+ for (unsigned int i = 0; i < FILE_PIECES; i++) {
+ if (hasNotPiece(i) && remote_peer->hasPiece(i)) {
+ if (random_piece_index == current_index) {
+ piece = i;
+ break;
+ }
+ current_index++;
+ }
+ }
+ xbt_assert(piece != -1);
+ return piece;
+ }
+ // Random first policy
+ if (countPieces(bitfield_) < 4 && isInterestedByFree(remote_peer)) {
+ int nb_interesting_pieces = 0;
+ // compute the number of interesting pieces
+ for (unsigned int i = 0; i < FILE_PIECES; i++)
+ if (hasNotPiece(i) && remote_peer->hasPiece(i) && isNotDownloadingPiece(i))
+ nb_interesting_pieces++;
+ xbt_assert(nb_interesting_pieces != 0);
+ // get a random interesting piece
+ int random_piece_index = RngStream_RandInt(stream, 0, nb_interesting_pieces - 1);
+ int current_index = 0;
+ for (unsigned int i = 0; i < FILE_PIECES; i++) {
+ if (hasNotPiece(i) && remote_peer->hasPiece(i) && isNotDownloadingPiece(i)) {
+ if (random_piece_index == current_index) {
+ piece = i;
+ break;
+ }
+ current_index++;
+ }
+ }
+ xbt_assert(piece != -1);
+ return piece;
+ } else { // Rarest first policy
+ short min = SHRT_MAX;
+ int nb_min_pieces = 0;
+ int current_index = 0;
+ // compute the smallest number of copies of available pieces
+ for (unsigned int i = 0; i < FILE_PIECES; i++) {
+ if (pieces_count[i] < min && hasNotPiece(i) && remote_peer->hasPiece(i) && isNotDownloadingPiece(i))
+ min = pieces_count[i];
+ }
+
+ xbt_assert(min != SHRT_MAX || not isInterestedByFree(remote_peer));
+ // compute the number of rarest pieces
+ for (unsigned int i = 0; i < FILE_PIECES; i++)
+ if (pieces_count[i] == min && hasNotPiece(i) && remote_peer->hasPiece(i) && isNotDownloadingPiece(i))
+ nb_min_pieces++;
+
+ xbt_assert(nb_min_pieces != 0 || not isInterestedByFree(remote_peer));
+ // get a random rarest piece
+ int random_rarest_index = RngStream_RandInt(stream, 0, nb_min_pieces - 1);
+ for (unsigned int i = 0; i < FILE_PIECES; i++)
+ if (pieces_count[i] == min && hasNotPiece(i) && remote_peer->hasPiece(i) && isNotDownloadingPiece(i)) {
+ if (random_rarest_index == current_index) {
+ piece = i;
+ break;
+ }
+ current_index++;
+ }
+
+ xbt_assert(piece != -1 || not isInterestedByFree(remote_peer));
+ return piece;
+ }
+}
+
+void Peer::updateChokedPeers()
+{
+ if (nbInterestedPeers() == 0)
+ return;
+ XBT_DEBUG("(%d) update_choked peers %zu active peers", id, active_peers.size());
+ // update the current round
+ round_ = (round_ + 1) % 3;
+ Connection* chosen_peer = nullptr;
+ // select first active peer and remove it from the set
+ Connection* choked_peer = *(active_peers.begin());
+ active_peers.erase(choked_peer);
+
+ /**If we are currently seeding, we unchoke the peer which has been unchoked the last time.*/
+ if (hasFinished()) {
+ Connection* remote_peer;
+ double unchoke_time = simgrid::s4u::Engine::getClock() + 1;
+ for (auto kv : connected_peers) {
+ remote_peer = kv.second;
+ if (remote_peer->last_unchoke < unchoke_time && remote_peer->interested && remote_peer->choked_upload) {
+ unchoke_time = remote_peer->last_unchoke;
+ chosen_peer = remote_peer;
+ }
+ }
+ } else {
+ // Random optimistic unchoking
+ if (round_ == 0) {
+ int j = 0;
+ do {
+ // We choose a random peer to unchoke.
+ std::unordered_map<int, Connection*>::iterator chosen_peer_it = connected_peers.begin();
+ std::advance(chosen_peer_it, RngStream_RandInt(stream, 0, connected_peers.size() - 1));
+ chosen_peer = chosen_peer_it->second;
+ if (chosen_peer == nullptr)
+ THROWF(unknown_error, 0, "A peer should have be selected at this point");
+ else if (not chosen_peer->interested || not chosen_peer->choked_upload)
+ chosen_peer = nullptr;
+ else
+ XBT_DEBUG("Nothing to do, keep going");
+ j++;
+ } while (chosen_peer == nullptr && j < MAXIMUM_PEERS);
+ } else {
+ // Use the "fastest download" policy.
+ double fastest_speed = 0.0;
+ for (auto kv : connected_peers) {
+ Connection* remote_peer = kv.second;
+ if (remote_peer->peer_speed > fastest_speed && remote_peer->choked_upload && remote_peer->interested) {
+ chosen_peer = remote_peer;
+ fastest_speed = remote_peer->peer_speed;
+ }
+ }
+ }
+ }
+
+ if (chosen_peer != nullptr)
+ XBT_DEBUG("(%d) update_choked peers unchoked (%d) ; int (%d) ; choked (%d) ", id, chosen_peer->id,
+ chosen_peer->interested, chosen_peer->choked_upload);
+
+ if (choked_peer != chosen_peer) {
+ if (choked_peer != nullptr) {
+ xbt_assert(not choked_peer->choked_upload, "Tries to choked a choked peer");
+ choked_peer->choked_upload = true;
+ updateActivePeersSet(choked_peer);
+ XBT_DEBUG("(%d) Sending a CHOKE to %d", id, choked_peer->id);
+ sendMessage(choked_peer->mailbox_, MESSAGE_CHOKE, MESSAGE_CHOKE_SIZE);
+ }
+ if (chosen_peer != nullptr) {
+ xbt_assert((chosen_peer->choked_upload), "Tries to unchoked an unchoked peer");
+ chosen_peer->choked_upload = false;
+ active_peers.insert(chosen_peer);
+ chosen_peer->last_unchoke = simgrid::s4u::Engine::getClock();
+ XBT_DEBUG("(%d) Sending a UNCHOKE to %d", id, chosen_peer->id);
+ updateActivePeersSet(chosen_peer);
+ sendMessage(chosen_peer->mailbox_, MESSAGE_UNCHOKE, MESSAGE_UNCHOKE_SIZE);
+ }
+ }
+}
+
+/** @brief Update "interested" state of peers: send "not interested" to peers that don't have any more pieces we want.*/
+void Peer::updateInterestedAfterReceive()
+{
+ for (auto kv : connected_peers) {
+ Connection* remote_peer = kv.second;
+ if (remote_peer->am_interested) {
+ bool interested = false;
+ // Check if the peer still has a piece we want.
+ for (unsigned int i = 0; i < FILE_PIECES; i++)
+ if (hasNotPiece(i) && remote_peer->hasPiece(i)) {
+ interested = true;
+ break;
+ }
+
+ if (not interested) { // no more piece to download from connection
+ remote_peer->am_interested = false;
+ sendMessage(remote_peer->mailbox_, MESSAGE_NOTINTERESTED, MESSAGE_NOTINTERESTED_SIZE);
+ }
+ }
+ }
+}
+
+void Peer::updateBitfieldBlocks(int piece, int block_index, int block_length)
+{
+ xbt_assert((piece >= 0 && static_cast<unsigned int>(piece) <= FILE_PIECES), "Wrong piece.");
+ xbt_assert((block_index >= 0 && static_cast<unsigned int>(block_index) <= PIECES_BLOCKS), "Wrong block : %d.",
+ block_index);
+ for (int i = block_index; i < (block_index + block_length); i++)
+ bitfield_blocks |= (1ULL << static_cast<unsigned int>(piece * PIECES_BLOCKS + i));
+}
+
+bool Peer::hasCompletedPiece(unsigned int piece)
+{
+ for (unsigned int i = 0; i < PIECES_BLOCKS; i++)
+ if (not(bitfield_blocks & 1ULL << (piece * PIECES_BLOCKS + i)))
+ return false;
+ return true;
+}
+
+int Peer::getFirstMissingBlockFrom(int piece)
+{
+ for (unsigned int i = 0; i < PIECES_BLOCKS; i++)
+ if (not(bitfield_blocks & 1ULL << (piece * PIECES_BLOCKS + i)))
+ return i;
+ return -1;
+}
+
+/** Returns a piece that is partially downloaded and stored by the remote peer if any -1 otherwise. */
+int Peer::partiallyDownloadedPiece(Connection* remote_peer)
+{
+ for (unsigned int i = 0; i < FILE_PIECES; i++)
+ if (hasNotPiece(i) && remote_peer->hasPiece(i) && isNotDownloadingPiece(i) && getFirstMissingBlockFrom(i) > 0)
+ return i;
+ return -1;
+}
--- /dev/null
+/* Copyright (c) 2012-2017. 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 BITTORRENT_PEER_HPP
+#define BITTORRENT_PEER_HPP
+#include "s4u_bittorrent.hpp"
+#include <set>
+#include <unordered_map>
+
+class Connection {
+public:
+ int id; // Peer id
+ simgrid::s4u::MailboxPtr mailbox_;
+ unsigned int bitfield = 0U; // Fields
+ // int messages_count;
+ double peer_speed = 0;
+ double last_unchoke = 0;
+ int current_piece = -1;
+ bool am_interested = false; // Indicates if we are interested in something the peer has
+ bool interested = false; // Indicates if the peer is interested in one of our pieces
+ bool choked_upload = true; // Indicates if the peer is choked for the current peer
+ bool choked_download = true; // Indicates if the peer has choked the current peer
+
+ explicit Connection(int id) : id(id), mailbox_(simgrid::s4u::Mailbox::byName(std::to_string(id))){};
+ ~Connection() = default;
+ void addSpeedValue(double speed) { peer_speed = peer_speed * 0.6 + speed * 0.4; }
+ bool hasPiece(unsigned int piece) { return bitfield & 1U << piece; }
+};
+
+class Peer {
+ int id;
+ double deadline;
+ RngStream stream;
+ simgrid::s4u::MailboxPtr mailbox_;
+ std::unordered_map<int, Connection*> connected_peers;
+ std::set<Connection*> active_peers; // active peers list
+
+ unsigned int bitfield_ = 0; // list of pieces the peer has.
+ unsigned long long bitfield_blocks = 0; // list of blocks the peer has.
+ short* pieces_count = nullptr; // number of peers that have each piece.
+ unsigned int current_pieces = 0; // current pieces the peer is downloading
+ double begin_receive_time = 0; // time when the receiving communication has begun, useful for calculating host speed.
+ int round_ = 0; // current round for the chocking algorithm.
+
+ simgrid::s4u::CommPtr comm_received = nullptr; // current comm
+ Message* message = nullptr; // current message being received
+public:
+ explicit Peer(std::vector<std::string> args);
+ Peer(const Peer&) = delete;
+ ~Peer();
+ void operator()();
+
+ std::string getStatus();
+ bool hasFinished();
+ int nbInterestedPeers();
+ bool isInterestedBy(Connection* remote_peer);
+ bool isInterestedByFree(Connection* remote_peer);
+ void updateActivePeersSet(Connection* remote_peer);
+ void updateInterestedAfterReceive();
+ void updateChokedPeers();
+
+ bool hasNotPiece(unsigned int piece) { return not(bitfield_ & 1U << piece); }
+ bool hasCompletedPiece(unsigned int piece);
+ unsigned int countPieces(unsigned int bitfield);
+ /** Check that a piece is not currently being download by the peer. */
+ bool isNotDownloadingPiece(unsigned int piece) { return not(current_pieces & 1U << piece); }
+ int partiallyDownloadedPiece(Connection* remote_peer);
+ void updatePiecesCountFromBitfield(unsigned int bitfield);
+ void removeCurrentPiece(Connection* remote_peer, unsigned int current_piece);
+ void updateBitfieldBlocks(int piece, int block_index, int block_length);
+ int getFirstMissingBlockFrom(int piece);
+ int selectPieceToDownload(Connection* remote_peer);
+ void requestNewPieceTo(Connection* remote_peer);
+
+ bool getPeersFromTracker();
+ void sendMessage(simgrid::s4u::MailboxPtr mailbox, e_message_type type, uint64_t size);
+ void sendBitfield(simgrid::s4u::MailboxPtr mailbox);
+ void sendPiece(simgrid::s4u::MailboxPtr mailbox, unsigned int piece, int block_index, int block_length);
+ void sendHandshakeToAllPeers();
+ void sendHaveToAllPeers(unsigned int piece);
+ void sendRequestTo(Connection* remote_peer, unsigned int piece);
+
+ void handleMessage();
+ void leech();
+ void seed();
+};
+
+#endif /* BITTORRENT_PEER_HPP */
--- /dev/null
+/* Copyright (c) 2012-2017. 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 "s4u_tracker.hpp"
+#include <xbt/RngStream.h>
+
+XBT_LOG_NEW_DEFAULT_CATEGORY(s4u_bt_tracker, "Messages specific for the tracker");
+
+Tracker::Tracker(std::vector<std::string> args)
+{
+ // Checking arguments
+ xbt_assert(args.size() == 2, "Wrong number of arguments for the tracker.");
+ // Retrieving end time
+ try {
+ deadline = std::stod(args[1]);
+ } catch (std::invalid_argument& ia) {
+ throw std::invalid_argument(std::string("Invalid deadline:") + args[1].c_str());
+ }
+ xbt_assert(deadline > 0, "Wrong deadline supplied");
+
+ stream = simgrid::s4u::this_actor::getHost()->extension<HostBittorrent>()->getStream();
+
+ mailbox = simgrid::s4u::Mailbox::byName(TRACKER_MAILBOX);
+
+ XBT_INFO("Tracker launched.");
+}
+
+void Tracker::operator()()
+{
+ simgrid::s4u::CommPtr comm = nullptr;
+ while (simgrid::s4u::Engine::getClock() < deadline) {
+ void* received;
+ if (comm == nullptr)
+ comm = mailbox->get_async(&received);
+ if (comm->test()) {
+ // Retrieve the data sent by the peer.
+ TrackerQuery* tq = static_cast<TrackerQuery*>(received);
+
+ // Add the peer to our peer list, if not already known.
+ if (known_peers.find(tq->getPeerId()) == known_peers.end()) {
+ known_peers.insert(tq->getPeerId());
+ }
+
+ // Sending back peers to the requesting peer
+ TrackerAnswer* ta = new TrackerAnswer(TRACKER_QUERY_INTERVAL);
+ std::set<int>::iterator next_peer;
+ int nb_known_peers = known_peers.size();
+ int max_tries = MIN(MAXIMUM_PEERS, nb_known_peers);
+ int tried = 0;
+ while (tried < max_tries) {
+ do {
+ next_peer = known_peers.begin();
+ std::advance(next_peer, RngStream_RandInt(stream, 0, nb_known_peers - 1));
+ } while (ta->getPeers()->find(*next_peer) != ta->getPeers()->end());
+ ta->addPeer(*next_peer);
+ tried++;
+ }
+ tq->getReturnMailbox()->put_init(ta, TRACKER_COMM_SIZE)->detach();
+
+ delete tq;
+ comm = nullptr;
+ } else {
+ simgrid::s4u::this_actor::sleep_for(1);
+ }
+ }
+ XBT_INFO("Tracker is leaving");
+}
--- /dev/null
+/* Copyright (c) 2012-2014, 2017. 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 BITTORRENT_TRACKER_HPP_
+#define BITTORRENT_TRACKER_HPP_
+
+#include "s4u_bittorrent.hpp"
+#include <set>
+
+class TrackerQuery {
+ int peer_id; // peer id
+ simgrid::s4u::MailboxPtr return_mailbox;
+public:
+ explicit TrackerQuery(int peer_id, simgrid::s4u::MailboxPtr return_mailbox)
+ : peer_id(peer_id), return_mailbox(return_mailbox){};
+ ~TrackerQuery() = default;
+ int getPeerId() { return peer_id; }
+ simgrid::s4u::MailboxPtr getReturnMailbox() { return return_mailbox; }
+};
+
+class TrackerAnswer {
+ XBT_ATTRIB_UNUSED int interval; // how often the peer should contact the tracker (unused for now)
+ std::set<int>* peers; // the peer list the peer has asked for.
+public:
+ explicit TrackerAnswer(int interval) : interval(interval) { peers = new std::set<int>; }
+ TrackerAnswer(const TrackerAnswer&) = delete;
+ ~TrackerAnswer() { delete peers; };
+ void addPeer(int peer) { peers->insert(peer); }
+ std::set<int>* getPeers() { return peers; }
+};
+
+class Tracker {
+ double deadline;
+ RngStream stream;
+ simgrid::s4u::MailboxPtr mailbox;
+ std::set<int> known_peers;
+
+public:
+ explicit Tracker(std::vector<std::string> args);
+ void operator()();
+};
+
+#endif /* BITTORRENT_TRACKER_HPP */
XBT_INFO("Sending \"%s\" (of %ld) to mailbox \"%s\"", (std::string("Task_") + std::to_string(i)).c_str(),
number_of_tasks, mailbox->getName());
- /* - Send the task to the @ref worker */
- char* payload = bprintf("%f", comp_size);
- mailbox->put(payload, comm_size);
+ /* - Send the computation amount to the @ref worker */
+ mailbox->put(static_cast<void*>(&comp_size), comm_size);
}
XBT_INFO("All tasks have been dispatched. Let's tell everybody the computation is over.");
for (int i = 0; i < workers_count; i++) {
/* - Eventually tell all the workers to stop by sending a "finalize" task */
mailbox = simgrid::s4u::Mailbox::byName(std::string("worker-") + std::to_string(i % workers_count));
- mailbox->put(xbt_strdup("finalize"), 0);
+ double finalize = -1;
+ mailbox->put(static_cast<void*>(&finalize), 0);
}
+ simgrid::s4u::this_actor::sleep_for(.1); // Grace time to ensure everyone finishes.
}
};
void operator()()
{
while (1) { /* The worker waits in an infinite loop for tasks sent by the \ref master */
- char* res = static_cast<char*>(mailbox->get());
- xbt_assert(res != nullptr, "MSG_task_get failed");
-
- if (strcmp(res, "finalize") == 0) { /* - Exit if 'finalize' is received */
- xbt_free(res);
+ double* comp_size = static_cast<double*>(mailbox->get());
+ xbt_assert(comp_size != nullptr, "MSG_task_get failed");
+ if (*comp_size < 0) { /* - Exit if 'finalize' is received */
+ XBT_INFO("I'm done. See you!");
break;
}
/* - Otherwise, process the task */
- double comp_size = std::stod(res);
- xbt_free(res);
- simgrid::s4u::this_actor::execute(comp_size);
+ simgrid::s4u::this_actor::execute(*comp_size);
}
- XBT_INFO("I'm done. See you!");
}
};
> [ 4.057541] (worker@Jupiter) I'm done. See you!
> [ 4.083249] (worker@Fafard) I'm done. See you!
> [ 4.931805] (worker@Ginette) I'm done. See you!
-> [ 5.094868] (maestro@) Simulation time 5.09487
> [ 5.094868] (worker@Bourassa) I'm done. See you!
+> [ 5.194868] (maestro@) Simulation time 5.19487
XBT_INFO("Storage info on %s:", simgrid::s4u::Host::current()->getCname());
for (const auto&kv : mounts) {
- const char* mountpoint = kv.first.c_str();
+ std::string mountpoint = kv.first;
simgrid::s4u::Storage* storage = kv.second;
// Retrieve disk's information
sg_size_t used_size = storage->getSizeUsed();
sg_size_t size = storage->getSize();
- XBT_INFO(" %s (%s) Used: %llu; Free: %llu; Total: %llu.", storage->getName(), mountpoint, used_size, free_size,
- size);
+ XBT_INFO(" %s (%s) Used: %llu; Free: %llu; Total: %llu.", storage->getName(), mountpoint.c_str(), used_size,
+ free_size, size);
}
}
show_info(mounts);
// Open an non-existing file to create it
- const char* filename = "/home/tmp/data.txt";
+ std::string filename = "/home/tmp/data.txt";
simgrid::s4u::File* file = new simgrid::s4u::File(filename, nullptr);
sg_size_t write = file->write(200000); // Write 200,000 bytes
- XBT_INFO("Create a %llu bytes file named '%s' on /sd1", write, filename);
+ XBT_INFO("Create a %llu bytes file named '%s' on /sd1", write, filename.c_str());
// check that sizes have changed
show_info(mounts);
const sg_size_t file_size = file->size();
file->seek(0);
const sg_size_t read = file->read(file_size);
- XBT_INFO("Read %llu bytes on %s", read, filename);
+ XBT_INFO("Read %llu bytes on %s", read, filename.c_str());
// Now write 100,000 bytes in tmp/data.txt
write = file->write(100000); // Write 100,000 bytes
- XBT_INFO("Write %llu bytes on %s", write, filename);
+ XBT_INFO("Write %llu bytes on %s", write, filename.c_str());
simgrid::s4u::Storage* storage = simgrid::s4u::Storage::byName("Disk4");
// Now rename file from ./tmp/data.txt to ./tmp/simgrid.readme
- const char *newpath = "/home/tmp/simgrid.readme";
- XBT_INFO("Move '%s' to '%s'", file->getPath(), newpath);
+ std::string newpath = "/home/tmp/simgrid.readme";
+ XBT_INFO("Move '%s' to '%s'", file->getPath(), newpath.c_str());
file->move(newpath);
// Test attaching some user data to the file
file->setUserdata(xbt_strdup("777"));
- XBT_INFO("User data attached to the file: %s", (char*)file->getUserdata());
+ XBT_INFO("User data attached to the file: %s", static_cast<char*>(file->getUserdata()));
xbt_free(file->getUserdata());
// Close the file
// Now attach some user data to disk1
XBT_INFO("Get/set data for storage element: %s", storage->getName());
- XBT_INFO(" Uninitialized storage data: '%s'", (char*)storage->getUserdata());
+ XBT_INFO(" Uninitialized storage data: '%s'", static_cast<char*>(storage->getUserdata()));
storage->setUserdata(xbt_strdup("Some user data"));
- XBT_INFO(" Set and get data: '%s'", (char*)storage->getUserdata());
+ XBT_INFO(" Set and get data: '%s'", static_cast<char*>(storage->getUserdata()));
xbt_free(storage->getUserdata());
}
> [0.016600] node-1.acme.org compute 42000000000.000000 # 1@task1
> [0.016600] node-10.acme.org compute 42000000000.000000 # 2@task2
> [42.033200] node-11.acme.org compute 42000000000.000000 # 3@task1
+> [0.000000] node-0.acme.org send node-1.acme.org 1000000.000000 # root_i1_1@task1
+> [0.016600] node-1.acme.org recv node-0.acme.org 1000000.000000 # root_i1_1@task1
> [0.000000] node-0.acme.org send node-10.acme.org 1000000.000000 # root_i2_2@task2
> [0.016600] node-10.acme.org recv node-0.acme.org 1000000.000000 # root_i2_2@task2
> [42.016600] node-1.acme.org send node-11.acme.org 1000000.000000 # 1@task1_o1_3@task1
> [42.033200] node-11.acme.org recv node-10.acme.org 1000000.000000 # 2@task2_o2_3@task1
> [84.033200] node-11.acme.org send node-0.acme.org 4167312.000000 # 3@task1_o3_end
> [84.067138] node-0.acme.org recv node-11.acme.org 4167312.000000 # 3@task1_o3_end
-> [0.000000] node-0.acme.org send node-1.acme.org 1000000.000000 # root_i1_1@task1
-> [0.016600] node-1.acme.org recv node-0.acme.org 1000000.000000 # root_i1_1@task1
> [84.067138] node-0.acme.org compute 0.000000 # end
$ cmake -E remove -f ${srcdir:=.}/dax.dot ${srcdir:=.}/daxload/smalldax.trace
/* Print the properties of 'host1' */
- xbt_dict_foreach(props, cursor, key, data) {
+ xbt_dict_foreach (props, cursor, key, data)
XBT_INFO("\tProperty: %s has value: %s", key, data);
- }
/* Try to get a property that does not exist */
value = sg_host_get_property_value(h1, noexist);
XBT_INFO("\tProperty: %s has value: %s", noexist, value?value:"Undefined (NULL)");
+ xbt_dict_free(&props);
+
/* Get the property list of 'host2' */
XBT_INFO("Property list for host %s", name2);
props = sg_host_get_properties(h2);
/* Print the properties of 'host2' */
- xbt_dict_foreach(props, cursor, key, data) {
+ xbt_dict_foreach (props, cursor, key, data)
XBT_INFO("\tProperty: %s on host: %s", key, data);
- }
+
+ xbt_dict_free(&props);
/* Modify an existing property test. First check it exists */
XBT_INFO("Modify an existing property");
-/* Copyright (c) 2004-2015. The SimGrid Team.
- * All rights reserved. */
+/* Copyright (c) 2004-2017. 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. */
XBT_PUBLIC(msg_comm_t) MSG_task_isend(msg_task_t task, const char *alias);
XBT_PUBLIC(msg_comm_t) MSG_task_isend_bounded(msg_task_t task, const char *alias, double maxrate);
XBT_PUBLIC(msg_comm_t)
-MSG_task_isend_with_matching(msg_task_t task, const char* alias, int (*match_fun)(void*, void*, void*),
- void* match_data);
+XBT_ATTRIB_DEPRECATED_v320(
+ "This function will be removed from SimGrid v3.20. If you really need this function, please speak up quickly.")
+ MSG_task_isend_with_matching(msg_task_t task, const char* alias, int (*match_fun)(void*, void*, void*),
+ void* match_data);
XBT_PUBLIC(void) MSG_task_dsend(msg_task_t task, const char *alias, void_f_pvoid_t cleanup);
XBT_PUBLIC(void) MSG_task_dsend_bounded(msg_task_t task, const char *alias, void_f_pvoid_t cleanup, double maxrate);
/* Used only by the bindings -- unclean pimple, please ignore if you're not writing a binding */
XBT_PUBLIC(smx_context_t) MSG_process_get_smx_ctx(msg_process_t process);
-/* Functions renamed in 3.14 */
-#define MSG_mailbox_get_head(m) MSG_mailbox_front(m)
-
SG_END_DECL()
#ifdef __cplusplus
simgrid::s4u::NetZone* getNetzoneByNameOrNull(const char* name);
/** @brief Retrieve the netcard of the given name (or nullptr if not found) */
- simgrid::kernel::routing::NetPoint* getNetpointByNameOrNull(const char* name);
+ simgrid::kernel::routing::NetPoint* getNetpointByNameOrNull(std::string name);
void getNetpointList(std::vector<simgrid::kernel::routing::NetPoint*> * list);
void netpointRegister(simgrid::kernel::routing::NetPoint * card);
void netpointUnregister(simgrid::kernel::routing::NetPoint * card);
XBT_PUBLIC_CLASS File
{
public:
- File(const char* fullpath, void* userdata);
- File(const char* fullpath, sg_host_t host, void* userdata);
+ File(std::string fullpath, void* userdata);
+ File(std::string fullpath, sg_host_t host, void* userdata);
~File();
/** Retrieves the path to the file */
- const char* getPath() { return path_; }
+ const char* getPath() { return path_.c_str(); }
/** Simulates a local read action. Returns the size of data actually read */
sg_size_t read(sg_size_t size);
/** Retrieves the current file position */
sg_size_t tell();
- /** Rename a file
- *
- * WARNING: It is forbidden to move the file to another mount point */
- void move(const char* fullpath);
+ /** Rename a file. WARNING: It is forbidden to move the file to another mount point */
+ void move(std::string fullpath);
/** Remove a file from disk */
int unlink();
- const char* storage_type;
- const char* storageId;
+ std::string storage_type;
+ std::string storageId;
std::string mount_point;
int desc_id = 0;
private:
surf_file_t pimpl_ = nullptr;
- const char* path_ = nullptr;
- void* userdata_ = nullptr;
+ std::string path_;
+ void* userdata_ = nullptr;
};
}
} // namespace simgrid::s4u
#include <unordered_map>
#include "xbt/Extendable.hpp"
-#include "xbt/dict.h"
#include "xbt/signal.hpp"
#include "xbt/string.hpp"
#include "xbt/swag.h"
protected:
friend simgrid::kernel::routing::NetZoneImpl;
- explicit NetZone(NetZone * father, const char* name);
+ explicit NetZone(NetZone * father, std::string name);
virtual ~NetZone();
public:
/** @brief Seal your netzone once you're done adding content, and before routing stuff through it */
virtual void seal();
- char* getCname();
+ const char* getCname();
NetZone* getFather();
std::vector<NetZone*>* getChildren(); // Sub netzones
std::unordered_map<std::string, std::string> properties_;
NetZone* father_ = nullptr;
- char* name_ = nullptr;
+ std::string name_;
bool sealed_ = false; // We cannot add more content when sealed
explicit Storage(surf::StorageImpl * pimpl) : pimpl_(pimpl) {}
virtual ~Storage() = default;
/** Retrieve a Storage by its name. It must exist in the platform file */
- static Storage* byName(const char* name);
+ static Storage* byName(std::string name);
const char* getName();
const char* getType();
Host* getHost();
virtual ~VirtualMachine();
public:
+ void start();
bool isMigrating();
void getParameters(vm_params_t params);
SG_BEGIN_DECL()
-XBT_PUBLIC(xbt_dynar_t) SIMIX_process_get_runnable();
XBT_PUBLIC(smx_actor_t) SIMIX_process_from_PID(aid_t PID);
-XBT_PUBLIC(xbt_dynar_t) SIMIX_processes_as_dynar();
/* parallelism */
XBT_PUBLIC(int) SIMIX_context_is_parallel();
simcall_process_create(const char* name, xbt_main_func_t code, void* data, sg_host_t host, int argc, char** argv,
std::map<std::string, std::string>* properties);
-XBT_PUBLIC(void) simcall_process_kill(smx_actor_t process);
XBT_PUBLIC(void) simcall_process_killall(int reset_pid);
XBT_PUBLIC(void) SIMIX_process_throw(smx_actor_t process, xbt_errcat_t cat, int value, const char *msg);
-/* Copyright (c) 2007-2010, 2012-2015. The SimGrid Team.
+/* Copyright (c) 2007-2010, 2012-2017. The SimGrid Team.
* All rights reserved. */
/* This program is free software; you can redistribute it and/or modify it
return result.get();
}
+XBT_PUBLIC(const std::vector<smx_actor_t>&) process_get_runnable();
XBT_PUBLIC(void) set_maestro(std::function<void()> code);
XBT_PUBLIC(void) create_maestro(std::function<void()> code);
--- /dev/null
+/* Copyright (c) 2015-2017. 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 XBT_ALGORITHM_HPP
+#define XBT_ALGORITHM_HPP
+
+namespace simgrid {
+namespace xbt {
+
+/** @brief Sorts the elements of the sequence [first, last) according to their color assuming elements can have only
+ * three colors. Since there are only three colors, it is linear and much faster than a classical sort. See for
+ * example http://en.wikipedia.org/wiki/Dutch_national_flag_problem
+ *
+ * \param first forward iterators to the initial position of the sequence to partition.
+ * \param last forward iterators to the final position of the sequence to partition.
+ * \param color the color function that accepts an element in the range as argument, and returns a value of 0, 1, or 2.
+ *
+ * At the end of the call, elements with color 0 are at the beginning of the range, elements with color 2 are at the end
+ * and elements with color 1 are in the middle.
+ */
+template <class ForwardIterator, class ColorFunction>
+void three_way_partition(ForwardIterator first, ForwardIterator last, ColorFunction color)
+{
+ ForwardIterator iter = first;
+ while (iter < last) {
+ int c = color(*iter);
+ if (c == 1) {
+ ++iter;
+ } else if (c == 0) {
+ if (iter != first)
+ std::swap(*iter, *first);
+ ++iter;
+ ++first;
+ } else { // c == 2
+ --last;
+ if (iter != last)
+ std::swap(*iter, *last);
+ }
+ }
+}
+}
+}
+
+#endif
XBT_PUBLIC(int) xbt_dynar_member(xbt_dynar_t const dynar, void *elem);
XBT_PUBLIC(void) xbt_dynar_sort(xbt_dynar_t const dynar, int_f_cpvoid_cpvoid_t compar_fn);
XBT_PUBLIC(xbt_dynar_t) xbt_dynar_sort_strings(xbt_dynar_t dynar);
-XBT_PUBLIC(void) xbt_dynar_three_way_partition(xbt_dynar_t const dynar, int_f_pvoid_t color);
XBT_PUBLIC(int) xbt_dynar_compare(xbt_dynar_t d1, xbt_dynar_t d2, int(*compar)(const void *, const void *));
XBT_PUBLIC(void *) xbt_dynar_to_array (xbt_dynar_t dynar);
-/* Copyright (c) 2004-2007, 2009-2015. The SimGrid Team.
+/* Copyright (c) 2004-2007, 2009-2017. 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_XBT_DYNAR_HPP
-#define SIMGRId_XBT_DYNAR_HPP
+#ifndef SIMGRID_XBT_DYNAR_HPP
+#define SIMGRID_XBT_DYNAR_HPP
#include <boost/range/iterator_range.hpp>
#include <xbt/asserts.h>
/* function_type.h - classical types for pointer to function */
-/* Copyright (c) 2006-2007, 2009-2010, 2012-2015. The SimGrid Team.
- * All rights reserved. */
+/* Copyright (c) 2006-2017. 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. */
typedef void *(*pvoid_f_pvoid_t) (void *);
typedef void (*void_f_void_t) (void);
-typedef int (*int_f_pvoid_t) (void*);
-
typedef int (*int_f_pvoid_pvoid_t) (void *, void *);
typedef int (*int_f_cpvoid_cpvoid_t) (const void *, const void *);
/* A thread pool. */
-/* Copyright (c) 2007, 2009-2014. The SimGrid Team.
+/* Copyright (c) 2007, 2009-2014, 2016-2017. The SimGrid Team.
* All rights reserved. */
/* This program is free software; you can redistribute it and/or modify it
#ifndef XBT_PARMAP_H
#define XBT_PARMAP_H
-#include "xbt/misc.h" /* SG_BEGIN_DECL */
-#include "xbt/function_types.h"
-#include "xbt/dynar.h"
-
-SG_BEGIN_DECL()
-
/** \addtogroup XBT_parmap
* \ingroup XBT_misc
* \brief Parallel map.
*
- * A function is applied to all elements of a dynar in parallel with n worker threads.
- * The worker threads are persistent until the destruction of the parmap.
+ * A function is applied to all elements of a std::vector in parallel with n worker threads. The worker threads are
+ * persistent until the destruction of the parmap.
*
- * If there are more than n elements in the dynar, the worker threads are allowed to fetch themselves remaining work
- * with xbt_parmap_next() and execute it.
+ * If there are more than n elements in the vector, the worker threads are allowed to fetch themselves remaining work
+ * with method next() and execute it.
*
* \{
*/
-/** \brief Parallel map data type (opaque type) */
-typedef struct s_xbt_parmap *xbt_parmap_t;
-
/** \brief Synchronization mode of the worker threads of a parmap. */
typedef enum {
XBT_PARMAP_POSIX, /**< use POSIX synchronization primitives */
XBT_PARMAP_DEFAULT /**< futex if available, posix otherwise */
} e_xbt_parmap_mode_t;
-XBT_PUBLIC(xbt_parmap_t) xbt_parmap_new(unsigned int num_workers, e_xbt_parmap_mode_t mode);
-XBT_PUBLIC(void) xbt_parmap_destroy(xbt_parmap_t parmap);
-XBT_PUBLIC(void) xbt_parmap_apply(xbt_parmap_t parmap, void_f_pvoid_t fun, xbt_dynar_t data);
-XBT_PUBLIC(void*) xbt_parmap_next(xbt_parmap_t parmap);
-
/** \} */
-SG_END_DECL()
-
#endif
void JavaContextFactory::run_all()
{
- xbt_dynar_t processes = SIMIX_process_get_runnable();
- smx_actor_t process;
- unsigned int cursor;
- xbt_dynar_foreach(processes, cursor, process) {
+ for (smx_actor_t process : simgrid::simix::process_get_runnable()) {
static_cast<JavaContext*>(process->context)->resume();
}
}
#include "jmsg.h"
#include <simgrid/msg.h>
+#include <string>
+
XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(java);
SG_BEGIN_DECL()
}
if (not comm) {
- jxbt_throw_null(env, bprintf("comm is null"));
+ jxbt_throw_null(env, "comm is null");
return JNI_FALSE;
}
JNIEXPORT void JNICALL Java_org_simgrid_msg_Comm_waitCompletion(JNIEnv *env, jobject jcomm, jdouble timeout) {
msg_comm_t comm = (msg_comm_t) (uintptr_t) env->GetLongField(jcomm, jcomm_field_Comm_bind);
if (not comm) {
- jxbt_throw_null(env, bprintf("comm is null"));
+ jxbt_throw_null(env, "comm is null");
return;
}
comms[i] = (msg_comm_t) (uintptr_t) env->GetLongField(jcomm, jcomm_field_Comm_bind);
if (not comms[i]) {
- jxbt_throw_null(env, bprintf("comm at rank %d is null", i));
+ jxbt_throw_null(env, std::string("comm at rank ") + std::to_string(i) + " is null");
return nullptr;
}
#include "simgrid/plugins/energy.h"
#include "simgrid/s4u/Host.hpp"
+#include "simgrid/s4u/Storage.hpp"
#include "jmsg.h"
#include "jmsg_host.h"
/* get the C string from the java string */
if (jname == nullptr) {
- jxbt_throw_null(env,bprintf("No host can have a null name"));
+ jxbt_throw_null(env, "No host can have a null name");
return nullptr;
}
const char *name = env->GetStringUTFChars(jname, 0);
int index = 0;
jobjectArray jtable;
- xbt_dict_t dict = MSG_host_get_mounted_storage_list(host);
- int count = xbt_dict_length(dict);
+ std::unordered_map<std::string, msg_storage_t> mounted_storages = host->getMountedStorages();
+ int count = mounted_storages.size();
jclass cls = env->FindClass("org/simgrid/msg/Storage");
jtable = env->NewObjectArray((jsize) count, cls, nullptr);
return nullptr;
}
- xbt_dict_cursor_t cursor=nullptr;
- const char* mount_name;
- const char* storage_name;
-
- xbt_dict_foreach(dict,cursor,mount_name,storage_name) {
- jname = env->NewStringUTF(storage_name);
+ for (auto elm : mounted_storages) {
+ jname = env->NewStringUTF(elm.second->getName());
jstorage = Java_org_simgrid_msg_Storage_getByName(env,cls,jname);
env->SetObjectArrayElement(jtable, index, jstorage);
index++;
}
- xbt_dict_free(&dict);
return jtable;
}
msg_process_t process = MSG_process_from_PID(pid);
if (not process) {
- jxbt_throw_process_not_found(env, bprintf("PID = %d",static_cast<int>(pid)));
+ jxbt_throw_process_not_found(env, std::string("PID = ") + std::to_string(static_cast<int>(pid)));
return nullptr;
}
/* try to suspend the process */
msg_error_t rv = MSG_process_suspend(process);
- jxbt_check_res("MSG_process_suspend()", rv, MSG_OK, bprintf("unexpected error , please report this bug"));
+ jxbt_check_res("MSG_process_suspend()", rv, MSG_OK, "unexpected error , please report this bug");
}
JNIEXPORT void JNICALL Java_org_simgrid_msg_Process_resume(JNIEnv * env, jobject jprocess)
/* try to resume the process */
msg_error_t res = MSG_process_resume(process);
- jxbt_check_res("MSG_process_resume()", res, MSG_OK, bprintf("unexpected error , please report this bug"));
+ jxbt_check_res("MSG_process_resume()", res, MSG_OK, "unexpected error , please report this bug");
}
JNIEXPORT void
/* get the C string from the java string */
if (jname == nullptr) {
- jxbt_throw_null(env,bprintf("No host can have a null name"));
+ jxbt_throw_null(env, "No host can have a null name");
return nullptr;
}
const char *name = env->GetStringUTFChars(jname, 0);
msg_error_t rv = MSG_task_cancel(ptask);
- jxbt_check_res("MSG_task_cancel()", rv, MSG_OK, bprintf("unexpected error , please report this bug"));
+ jxbt_check_res("MSG_task_cancel()", rv, MSG_OK, "unexpected error , please report this bug");
}
JNIEXPORT void JNICALL Java_org_simgrid_msg_Task_execute(JNIEnv * env, jobject jtask)
/* get the C string from the java string */
if (jname == nullptr) {
- jxbt_throw_null(env, bprintf("No VM can have a null name"));
+ jxbt_throw_null(env, "No VM can have a null name");
return nullptr;
}
const char* name = env->GetStringUTFChars(jname, 0);
-/* Copyright (c) 2010, 2012-2017. The SimGrid Team.
- * All rights reserved. */
+/* Copyright (c) 2010-2017. 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 "src/surf/surf_private.h"
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
-#include <simgrid/host.h>
+#include <simgrid/s4u/Host.hpp>
#include <string>
#include <vector>
}
sg_platf_new_link(&link);
- routing_cluster_add_backbone(simgrid::surf::LinkImpl::byName(link.id.c_str()));
+ routing_cluster_add_backbone(simgrid::surf::LinkImpl::byName(link.id));
return 0;
}
int console_add_host___link(lua_State *L) {
- s_sg_platf_host_link_cbarg_t hostlink;
- memset(&hostlink,0,sizeof(hostlink));
+ HostLinkCreationArgs hostlink;
int type;
- lua_ensure(lua_istable(L, -1),
- "Bad Arguments to create host_link in Lua. Should be a table with named arguments.");
+ lua_ensure(lua_istable(L, -1), "Bad Arguments to create host_link in Lua. Should be a table with named arguments.");
lua_pushstring(L, "id");
type = lua_gettable(L, -2);
hostlink.link_down = lua_tostring(L, -1);
lua_pop(L, 1);
- XBT_DEBUG("Create a host_link for host %s", hostlink.id);
+ XBT_DEBUG("Create a host_link for host %s", hostlink.id.c_str());
sg_platf_new_hostlink(&hostlink);
return 0;
* add Router to AS components
*/
int console_add_router(lua_State* L) {
- lua_ensure(lua_istable(L, -1),
- "Bad Arguments to create router, Should be a table with named arguments");
+ lua_ensure(lua_istable(L, -1), "Bad Arguments to create router, Should be a table with named arguments");
lua_pushstring(L, "id");
int type = lua_gettable(L, -2);
// Several names separated by , \t\r\n
for (auto name : names) {
if (name.length() > 0) {
- simgrid::surf::LinkImpl* link = simgrid::surf::LinkImpl::byName(name.c_str());
+ simgrid::surf::LinkImpl* link = simgrid::surf::LinkImpl::byName(name);
route.link_list->push_back(link);
}
}
// Several names separated by , \t\r\n
for (auto name : names) {
if (name.length() > 0) {
- simgrid::surf::LinkImpl* link = simgrid::surf::LinkImpl::byName(name.c_str());
+ simgrid::surf::LinkImpl* link = simgrid::surf::LinkImpl::byName(name);
ASroute.link_list->push_back(link);
}
}
}
int console_AS_open(lua_State *L) {
- const char *id;
- const char *mode;
- int type;
-
XBT_DEBUG("Opening AS");
lua_ensure(lua_istable(L, 1), "Bad Arguments to AS_open, Should be a table with named arguments");
lua_pushstring(L, "id");
- type = lua_gettable(L, -2);
+ int type = lua_gettable(L, -2);
lua_ensure(type == LUA_TSTRING, "Attribute 'id' must be specified for any AS and must be a string.");
- id = lua_tostring(L, -1);
+ const char* id = lua_tostring(L, -1);
lua_pop(L, 1);
lua_pushstring(L, "mode");
lua_gettable(L, -2);
- mode = lua_tostring(L, -1);
+ const char* mode = lua_tostring(L, -1);
lua_pop(L, 1);
int mode_int = A_surfxml_AS_routing_None;
mode_int = A_surfxml_AS_routing_None;
else xbt_die("Don't have the model name '%s'",mode);
- s_sg_platf_AS_cbarg_t AS;
+ ZoneCreationArgs AS;
AS.id = id;
AS.routing = mode_int;
- simgrid::s4u::NetZone* new_as = sg_platf_new_AS_begin(&AS);
+ simgrid::s4u::NetZone* new_as = sg_platf_new_Zone_begin(&AS);
/* Build a Lua representation of the new AS on the stack */
lua_newtable(L);
}
int console_AS_seal(lua_State *L) {
XBT_DEBUG("Sealing AS");
- sg_platf_new_AS_seal();
+ sg_platf_new_Zone_seal();
return 0;
}
int console_host_set_property(lua_State *L) {
- const char* name ="";
- const char* prop_id = "";
- const char* prop_value = "";
lua_ensure(lua_istable(L, -1), "Bad Arguments to create link, Should be a table with named arguments");
// get Host id
lua_pushstring(L, "host");
lua_gettable(L, -2);
- name = lua_tostring(L, -1);
+ const char* name = lua_tostring(L, -1);
lua_pop(L, 1);
// get prop Name
lua_pushstring(L, "prop");
lua_gettable(L, -2);
- prop_id = lua_tostring(L, -1);
+ const char* prop_id = lua_tostring(L, -1);
lua_pop(L, 1);
//get args
lua_pushstring(L,"value");
lua_gettable(L, -2);
- prop_value = lua_tostring(L,-1);
+ const char* prop_value = lua_tostring(L, -1);
lua_pop(L, 1);
sg_host_t host = sg_host_by_name(name);
lua_ensure(host, "no host '%s' found",name);
- xbt_dict_t props = sg_host_get_properties(host);
- xbt_dict_set(props,prop_id,xbt_strdup(prop_value),nullptr);
+ host->setProperty(prop_id, prop_value);
return 0;
}
XBT_PUBLIC(int) TRACE_end ();
XBT_PUBLIC(void) TRACE_global_init();
XBT_PUBLIC(void) TRACE_help(int detailed);
-XBT_PUBLIC(void) TRACE_surf_resource_utilization_alloc();
-XBT_PUBLIC(void) TRACE_surf_resource_utilization_release();
SG_END_DECL()
/* user-visible parameters */
extern XBT_PRIVATE double sg_tcp_gamma;
-extern XBT_PRIVATE double sg_sender_gap;
extern XBT_PRIVATE double sg_latency_factor;
extern XBT_PRIVATE double sg_bandwidth_factor;
extern XBT_PRIVATE double sg_weight_S_parameter;
/********** Tracing **********/
/* from surf_instr.c */
void TRACE_surf_action(surf_action_t surf_action, const char *category);
-void TRACE_surf_alloc();
-void TRACE_surf_release();
/* instr_routing.c */
void instr_routing_define_callbacks ();
--- /dev/null
+/* A thread pool (C++ version). */
+
+/* Copyright (c) 2004-2017 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 XBT_PARMAP_HPP
+#define XBT_PARMAP_HPP
+
+#include "src/internal_config.h" // HAVE_FUTEX_H
+#include "src/kernel/context/Context.hpp"
+#include <atomic>
+#include <boost/optional.hpp>
+#include <simgrid/simix.h>
+#include <vector>
+#include <xbt/log.h>
+#include <xbt/parmap.h>
+#include <xbt/xbt_os_thread.h>
+
+#if HAVE_FUTEX_H
+#include <limits>
+#include <linux/futex.h>
+#include <sys/syscall.h>
+#endif
+
+XBT_LOG_EXTERNAL_CATEGORY(xbt_parmap);
+
+namespace simgrid {
+namespace xbt {
+
+/** \addtogroup XBT_parmap
+ * \ingroup XBT_misc
+ * \brief Parallel map class
+ * \{
+ */
+template <typename T> class Parmap {
+public:
+ Parmap(unsigned num_workers, e_xbt_parmap_mode_t mode);
+ Parmap(const Parmap&) = delete;
+ ~Parmap();
+ void apply(void (*fun)(T), const std::vector<T>& data);
+ boost::optional<T> next();
+
+private:
+ enum Flag { PARMAP_WORK, PARMAP_DESTROY };
+
+ /**
+ * \brief Thread data transmission structure
+ */
+ class ThreadData {
+ public:
+ ThreadData(Parmap<T>& parmap, int id) : parmap(parmap), worker_id(id) {}
+ Parmap<T>& parmap;
+ int worker_id;
+ };
+
+ /**
+ * \brief Synchronization object (different specializations).
+ */
+ class Synchro {
+ public:
+ explicit Synchro(Parmap<T>& parmap) : parmap(parmap) {}
+ virtual ~Synchro() {}
+ /**
+ * \brief Wakes all workers and waits for them to finish the tasks.
+ *
+ * This function is called by the controller thread.
+ */
+ virtual void master_signal() = 0;
+ /**
+ * \brief Starts the parmap: waits for all workers to be ready and returns.
+ *
+ * This function is called by the controller thread.
+ */
+ virtual void master_wait() = 0;
+ /**
+ * \brief Ends the parmap: wakes the controller thread when all workers terminate.
+ *
+ * This function is called by all worker threads when they end (not including the controller).
+ */
+ virtual void worker_signal() = 0;
+ /**
+ * \brief Waits for some work to process.
+ *
+ * This function is called by each worker thread (not including the controller) when it has no more work to do.
+ *
+ * \param round the expected round number
+ */
+ virtual void worker_wait(unsigned) = 0;
+
+ protected:
+ Parmap<T>& parmap;
+ };
+
+ class PosixSynchro : public Synchro {
+ public:
+ explicit PosixSynchro(Parmap<T>& parmap);
+ ~PosixSynchro();
+ void master_signal();
+ void master_wait();
+ void worker_signal();
+ void worker_wait(unsigned round);
+
+ private:
+ xbt_os_cond_t ready_cond;
+ xbt_os_mutex_t ready_mutex;
+ xbt_os_cond_t done_cond;
+ xbt_os_mutex_t done_mutex;
+ };
+
+#if HAVE_FUTEX_H
+ class FutexSynchro : public Synchro {
+ public:
+ explicit FutexSynchro(Parmap<T>& parmap) : Synchro(parmap) {}
+ void master_signal();
+ void master_wait();
+ void worker_signal();
+ void worker_wait(unsigned);
+
+ private:
+ static void futex_wait(unsigned* uaddr, unsigned val);
+ static void futex_wake(unsigned* uaddr, unsigned val);
+ };
+#endif
+
+ class BusyWaitSynchro : public Synchro {
+ public:
+ explicit BusyWaitSynchro(Parmap<T>& parmap) : Synchro(parmap) {}
+ void master_signal();
+ void master_wait();
+ void worker_signal();
+ void worker_wait(unsigned);
+ };
+
+ static void* worker_main(void* arg);
+ Synchro* new_synchro(e_xbt_parmap_mode_t mode);
+ void work();
+
+ Flag status; /**< is the parmap active or being destroyed? */
+ unsigned work_round; /**< index of the current round */
+ xbt_os_thread_t* workers; /**< worker thread handlers */
+ unsigned num_workers; /**< total number of worker threads including the controller */
+ Synchro* synchro; /**< synchronization object */
+
+ unsigned thread_counter = 0; /**< number of workers that have done the work */
+ void (*fun)(const T) = nullptr; /**< function to run in parallel on each element of data */
+ const std::vector<T>* data = nullptr; /**< parameters to pass to fun in parallel */
+ std::atomic<unsigned> index; /**< index of the next element of data to pick */
+};
+
+/**
+ * \brief Creates a parallel map object
+ * \param num_workers number of worker threads to create
+ * \param mode how to synchronize the worker threads
+ */
+template <typename T> Parmap<T>::Parmap(unsigned num_workers, e_xbt_parmap_mode_t mode)
+{
+ XBT_CDEBUG(xbt_parmap, "Create new parmap (%u workers)", num_workers);
+
+ /* Initialize the thread pool data structure */
+ this->status = PARMAP_WORK;
+ this->work_round = 0;
+ this->workers = new xbt_os_thread_t[num_workers];
+ this->num_workers = num_workers;
+ this->synchro = new_synchro(mode);
+
+ /* Create the pool of worker threads */
+ this->workers[0] = nullptr;
+#if HAVE_PTHREAD_SETAFFINITY
+ int core_bind = 0;
+#endif
+ for (unsigned i = 1; i < num_workers; i++) {
+ ThreadData* data = new ThreadData(*this, i);
+ this->workers[i] = xbt_os_thread_create(nullptr, worker_main, data, nullptr);
+#if HAVE_PTHREAD_SETAFFINITY
+ xbt_os_thread_bind(this->workers[i], core_bind);
+ if (core_bind != xbt_os_get_numcores() - 1)
+ core_bind++;
+ else
+ core_bind = 0;
+#endif
+ }
+}
+
+/**
+ * \brief Destroys a parmap
+ */
+template <typename T> Parmap<T>::~Parmap()
+{
+ status = PARMAP_DESTROY;
+ synchro->master_signal();
+
+ for (unsigned i = 1; i < num_workers; i++)
+ xbt_os_thread_join(workers[i], nullptr);
+
+ delete[] workers;
+ delete synchro;
+}
+
+/**
+ * \brief Applies a list of tasks in parallel.
+ * \param fun the function to call in parallel
+ * \param data each element of this vector will be passed as an argument to fun
+ */
+template <typename T> void Parmap<T>::apply(void (*fun)(T), const std::vector<T>& data)
+{
+ /* Assign resources to worker threads (we are maestro here)*/
+ this->fun = fun;
+ this->data = &data;
+ this->index = 0;
+ this->synchro->master_signal(); // maestro runs futex_wait to wake all the minions (the working threads)
+ this->work(); // maestro works with its minions
+ this->synchro->master_wait(); // When there is no more work to do, then maestro waits for the last minion to stop
+ XBT_CDEBUG(xbt_parmap, "Job done"); // ... and proceeds
+}
+
+/**
+ * \brief Returns a next task to process.
+ *
+ * Worker threads call this function to get more work.
+ *
+ * \return the next task to process, or throws a std::out_of_range exception if there is no more work
+ */
+template <typename T> boost::optional<T> Parmap<T>::next()
+{
+ unsigned index = this->index++;
+ if (index < this->data->size())
+ return (*this->data)[index];
+ else
+ return boost::none;
+}
+
+/**
+ * \brief Main work loop: applies fun to elements in turn.
+ */
+template <typename T> void Parmap<T>::work()
+{
+ unsigned index = this->index++;
+ unsigned length = this->data->size();
+ while (index < length) {
+ this->fun((*this->data)[index]);
+ index = this->index++;
+ }
+}
+
+/**
+ * Get a synchronization object for given mode.
+ * \param mode the synchronization mode
+ */
+template <typename T> typename Parmap<T>::Synchro* Parmap<T>::new_synchro(e_xbt_parmap_mode_t mode)
+{
+ if (mode == XBT_PARMAP_DEFAULT) {
+#if HAVE_FUTEX_H
+ mode = XBT_PARMAP_FUTEX;
+#else
+ mode = XBT_PARMAP_POSIX;
+#endif
+ }
+ Synchro* res;
+ switch (mode) {
+ case XBT_PARMAP_POSIX:
+ res = new PosixSynchro(*this);
+ break;
+ case XBT_PARMAP_FUTEX:
+#if HAVE_FUTEX_H
+ res = new FutexSynchro(*this);
+#else
+ xbt_die("Fute is not available on this OS.");
+#endif
+ break;
+ case XBT_PARMAP_BUSY_WAIT:
+ res = new BusyWaitSynchro(*this);
+ break;
+ default:
+ THROW_IMPOSSIBLE;
+ }
+ return res;
+}
+
+/**
+ * \brief Main function of a worker thread.
+ */
+template <typename T> void* Parmap<T>::worker_main(void* arg)
+{
+ ThreadData* data = static_cast<ThreadData*>(arg);
+ Parmap<T>& parmap = data->parmap;
+ unsigned round = 0;
+ smx_context_t context = SIMIX_context_new(std::function<void()>(), nullptr, nullptr);
+ SIMIX_context_set_current(context);
+
+ XBT_CDEBUG(xbt_parmap, "New worker thread created");
+
+ /* Worker's main loop */
+ while (1) {
+ round++;
+ parmap.synchro->worker_wait(round);
+ if (parmap.status == PARMAP_DESTROY)
+ break;
+
+ XBT_CDEBUG(xbt_parmap, "Worker %d got a job", data->worker_id);
+ parmap.work();
+ parmap.synchro->worker_signal();
+ XBT_CDEBUG(xbt_parmap, "Worker %d has finished", data->worker_id);
+ }
+ /* We are destroying the parmap */
+ delete context;
+ delete data;
+ return nullptr;
+}
+
+template <typename T> Parmap<T>::PosixSynchro::PosixSynchro(Parmap<T>& parmap) : Synchro(parmap)
+{
+ ready_cond = xbt_os_cond_init();
+ ready_mutex = xbt_os_mutex_init();
+ done_cond = xbt_os_cond_init();
+ done_mutex = xbt_os_mutex_init();
+}
+
+template <typename T> Parmap<T>::PosixSynchro::~PosixSynchro()
+{
+ xbt_os_cond_destroy(ready_cond);
+ xbt_os_mutex_destroy(ready_mutex);
+ xbt_os_cond_destroy(done_cond);
+ xbt_os_mutex_destroy(done_mutex);
+}
+
+template <typename T> void Parmap<T>::PosixSynchro::master_signal()
+{
+ xbt_os_mutex_acquire(ready_mutex);
+ this->parmap.thread_counter = 1;
+ this->parmap.work_round++;
+ /* wake all workers */
+ xbt_os_cond_broadcast(ready_cond);
+ xbt_os_mutex_release(ready_mutex);
+}
+
+template <typename T> void Parmap<T>::PosixSynchro::master_wait()
+{
+ xbt_os_mutex_acquire(done_mutex);
+ if (this->parmap.thread_counter < this->parmap.num_workers) {
+ /* wait for all workers to be ready */
+ xbt_os_cond_wait(done_cond, done_mutex);
+ }
+ xbt_os_mutex_release(done_mutex);
+}
+
+template <typename T> void Parmap<T>::PosixSynchro::worker_signal()
+{
+ xbt_os_mutex_acquire(done_mutex);
+ this->parmap.thread_counter++;
+ if (this->parmap.thread_counter == this->parmap.num_workers) {
+ /* all workers have finished, wake the controller */
+ xbt_os_cond_signal(done_cond);
+ }
+ xbt_os_mutex_release(done_mutex);
+}
+
+template <typename T> void Parmap<T>::PosixSynchro::worker_wait(unsigned round)
+{
+ xbt_os_mutex_acquire(ready_mutex);
+ /* wait for more work */
+ if (this->parmap.work_round != round) {
+ xbt_os_cond_wait(ready_cond, ready_mutex);
+ }
+ xbt_os_mutex_release(ready_mutex);
+}
+
+#if HAVE_FUTEX_H
+template <typename T> inline void Parmap<T>::FutexSynchro::futex_wait(unsigned* uaddr, unsigned val)
+{
+ XBT_CVERB(xbt_parmap, "Waiting on futex %p", uaddr);
+ syscall(SYS_futex, uaddr, FUTEX_WAIT_PRIVATE, val, nullptr, nullptr, 0);
+}
+
+template <typename T> inline void Parmap<T>::FutexSynchro::futex_wake(unsigned* uaddr, unsigned val)
+{
+ XBT_CVERB(xbt_parmap, "Waking futex %p", uaddr);
+ syscall(SYS_futex, uaddr, FUTEX_WAKE_PRIVATE, val, nullptr, nullptr, 0);
+}
+
+template <typename T> void Parmap<T>::FutexSynchro::master_signal()
+{
+ this->parmap.thread_counter = 1;
+ __sync_add_and_fetch(&this->parmap.work_round, 1);
+ /* wake all workers */
+ futex_wake(&this->parmap.work_round, std::numeric_limits<int>::max());
+}
+
+template <typename T> void Parmap<T>::FutexSynchro::master_wait()
+{
+ unsigned count = this->parmap.thread_counter;
+ while (count < this->parmap.num_workers) {
+ /* wait for all workers to be ready */
+ futex_wait(&this->parmap.thread_counter, count);
+ count = this->parmap.thread_counter;
+ }
+}
+
+template <typename T> void Parmap<T>::FutexSynchro::worker_signal()
+{
+ unsigned count = __sync_add_and_fetch(&this->parmap.thread_counter, 1);
+ if (count == this->parmap.num_workers) {
+ /* all workers have finished, wake the controller */
+ futex_wake(&this->parmap.thread_counter, std::numeric_limits<int>::max());
+ }
+}
+
+template <typename T> void Parmap<T>::FutexSynchro::worker_wait(unsigned round)
+{
+ unsigned work_round = this->parmap.work_round;
+ /* wait for more work */
+ while (work_round != round) {
+ futex_wait(&this->parmap.work_round, work_round);
+ work_round = this->parmap.work_round;
+ }
+}
+#endif
+
+template <typename T> void Parmap<T>::BusyWaitSynchro::master_signal()
+{
+ this->parmap.thread_counter = 1;
+ __sync_add_and_fetch(&this->parmap.work_round, 1);
+}
+
+template <typename T> void Parmap<T>::BusyWaitSynchro::master_wait()
+{
+ while (this->parmap.thread_counter < this->parmap.num_workers) {
+ xbt_os_thread_yield();
+ }
+}
+
+template <typename T> void Parmap<T>::BusyWaitSynchro::worker_signal()
+{
+ __sync_add_and_fetch(&this->parmap.thread_counter, 1);
+}
+
+template <typename T> void Parmap<T>::BusyWaitSynchro::worker_wait(unsigned round)
+{
+ /* wait for more work */
+ while (this->parmap.work_round != round) {
+ xbt_os_thread_yield();
+ }
+}
+
+/** \} */
+}
+}
+
+#endif
-/* Copyright (c) 2010-2015. The SimGrid Team.
- * All rights reserved. */
+/* Copyright (c) 2010-2017. 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 "src/instr/instr_private.h"
#include "surf/surf.h"
+#include <string>
#include <vector>
XBT_LOG_NEW_CATEGORY(instr, "Logging the behavior of the tracing system (used for Visualization/Analysis of simulations)");
}
trace_active = 1;
XBT_DEBUG("Tracing is on");
-
- /* other trace initialization */
- created_categories = xbt_dict_new_homogeneous(xbt_free_f);
- declared_marks = xbt_dict_new_homogeneous(xbt_free_f);
- user_host_variables = xbt_dict_new_homogeneous(xbt_free_f);
- user_vm_variables = xbt_dict_new_homogeneous(xbt_free_f);
- user_link_variables = xbt_dict_new_homogeneous(xbt_free_f);
}
return 0;
}
PJ_container_release();
rootType = nullptr;
- xbt_dict_free(&user_link_variables);
- xbt_dict_free(&user_host_variables);
- xbt_dict_free(&user_vm_variables);
- xbt_dict_free(&declared_marks);
- xbt_dict_free(&created_categories);
-
/* close the trace files */
const char* format = xbt_cfg_get_string(OPT_TRACING_FORMAT);
XBT_DEBUG("Tracing format %s\n", format);
xbt_dynar_free (&types);
}
-static void output_categories (const char *name, xbt_dynar_t cats, FILE *file)
+static void output_categories(const char* name, FILE* file)
{
- unsigned int i;
+ unsigned int i = created_categories.size();
fprintf (file, " values = (");
- for (i = xbt_dynar_length(cats); i > 0; i--) {
- char *cat = *(static_cast<char**>(xbt_dynar_get_ptr(cats, i - 1)));
- fprintf (file, "\"%s%s\"", name, cat);
- if (i - 1 > 0){
+ for (auto cat : created_categories) {
+ --i;
+ fprintf(file, "\"%s%s\"", name, cat.c_str());
+ if (i > 0) {
fprintf (file, ",");
}else{
fprintf (file, ");\n");
}
}
- xbt_dynar_free (&cats);
}
static void uncat_configuration (FILE *file)
" host = {\n"
" type = \"square\";\n"
" size = \"power\";\n");
- output_categories ("p", TRACE_get_categories(), file);
+ output_categories("p", file);
fprintf (file,
" };\n"
" link = {\n"
" type = \"rhombus\";\n"
" size = \"bandwidth\";\n");
- output_categories ("b", TRACE_get_categories(), file);
+ output_categories("b", file);
fprintf (file, " };\n");
//close
}
{
if (output && strlen(output) > 0){
//check if we do have categories declared
- if (xbt_dict_is_empty(created_categories)){
+ if (created_categories.empty()) {
XBT_INFO("No categories declared, ignoring generation of %s graph configuration", name);
return;
}
#include "src/surf/network_interface.hpp"
#include "src/surf/surf_private.h"
#include "surf/surf.h"
+#include <algorithm>
typedef enum {
INSTR_US_DECLARE,
XBT_LOG_NEW_DEFAULT_SUBCATEGORY (instr_api, instr, "API");
-xbt_dict_t created_categories = nullptr;
-xbt_dict_t declared_marks = nullptr;
-xbt_dict_t user_host_variables = nullptr;
-xbt_dict_t user_vm_variables = nullptr;
-xbt_dict_t user_link_variables = nullptr;
-extern xbt_dict_t trivaNodeTypes;
-extern xbt_dict_t trivaEdgeTypes;
+std::set<std::string> created_categories;
+std::set<std::string> declared_marks;
+std::set<std::string> user_host_variables;
+std::set<std::string> user_vm_variables;
+std::set<std::string> user_link_variables;
+extern std::set<std::string> trivaNodeTypes;
+extern std::set<std::string> trivaEdgeTypes;
-static xbt_dynar_t instr_dict_to_dynar (xbt_dict_t filter)
+static xbt_dynar_t instr_set_to_dynar(std::set<std::string>* filter)
{
if (not TRACE_is_enabled() || not TRACE_needs_platform())
return nullptr;
xbt_dynar_t ret = xbt_dynar_new (sizeof(char*), &xbt_free_ref);
- xbt_dict_cursor_t cursor = nullptr;
- char *name;
- char *value;
- xbt_dict_foreach(filter, cursor, name, value) {
- xbt_dynar_push_as (ret, char*, xbt_strdup(name));
- }
+ for (auto name : *filter)
+ xbt_dynar_push_as(ret, char*, xbt_strdup(name.c_str()));
+
return ret;
}
return;
//check if category is already created
- if (xbt_dict_get_or_null(created_categories, category) != nullptr)
+ if (created_categories.find(category) != created_categories.end())
return;
-
- xbt_dict_set (created_categories, category, xbt_strdup("1"), nullptr);
+ else
+ created_categories.insert(category);
//define final_color
char final_color[INSTR_DEFAULT_STR_SIZE];
{
if (not TRACE_is_enabled() || not TRACE_categorized())
return nullptr;
-
- return instr_dict_to_dynar (created_categories);
+ return instr_set_to_dynar(&created_categories);
}
/** \ingroup TRACE_mark
THROWF (tracing_error, 1, "mark_type is nullptr");
//check if mark_type is already declared
- if (xbt_dict_get_or_null(declared_marks, mark_type) != nullptr) {
+ if (declared_marks.find(mark_type) != declared_marks.end()) {
THROWF (tracing_error, 1, "mark_type with name (%s) is already declared", mark_type);
}
XBT_DEBUG("MARK,declare %s", mark_type);
PJ_type_event_new(mark_type, PJ_type_get_root());
- xbt_dict_set (declared_marks, mark_type, xbt_strdup("1"), nullptr);
+ declared_marks.insert(mark_type);
}
/** \ingroup TRACE_mark
if (not TRACE_is_enabled())
return nullptr;
- return instr_dict_to_dynar (declared_marks);
+ return instr_set_to_dynar(&declared_marks);
}
-static void instr_user_variable(double time, const char *resource, const char *variable, const char *father_type,
- double value, InstrUserVariable what, const char *color, xbt_dict_t filter)
+static void instr_user_variable(double time, const char* resource, const char* variable, const char* father_type,
+ double value, InstrUserVariable what, const char* color, std::set<std::string>* filter)
{
/* safe switches. tracing has to be activated and if platform is not traced, we don't allow user variables */
if (not TRACE_is_enabled() || not TRACE_needs_platform())
return;
//check if variable is already declared
- char *created = (char*)xbt_dict_get_or_null(filter, variable);
+ auto created = filter->find(variable);
if (what == INSTR_US_DECLARE){
- if (not created) { // not declared yet
- xbt_dict_set (filter, variable, xbt_strdup("1"), nullptr);
+ if (created == filter->end()) { // not declared yet
+ filter->insert(variable);
instr_new_user_variable_type (father_type, variable, color);
}
}else{
- if (created) { // declared, let's work
+ if (created != filter->end()) { // declared, let's work
char valuestr[100];
snprintf(valuestr, 100, "%g", value);
container_t container = PJ_container_get(resource);
std::vector<simgrid::surf::LinkImpl*> route;
simgrid::kernel::routing::NetZoneImpl::getGlobalRoute(src_elm, dst_elm, &route, nullptr);
for (auto link : route)
- instr_user_variable(time, link->cname(), variable, father_type, value, what, nullptr, user_link_variables);
+ instr_user_variable(time, link->cname(), variable, father_type, value, what, nullptr, &user_link_variables);
}
/** \ingroup TRACE_API
*/
void TRACE_vm_variable_declare (const char *variable)
{
- instr_user_variable(0, nullptr, variable, "MSG_VM", 0, INSTR_US_DECLARE, nullptr, user_vm_variables);
+ instr_user_variable(0, nullptr, variable, "MSG_VM", 0, INSTR_US_DECLARE, nullptr, &user_vm_variables);
}
/** \ingroup TRACE_user_variables
*/
void TRACE_vm_variable_declare_with_color (const char *variable, const char *color)
{
- instr_user_variable(0, nullptr, variable, "MSG_VM", 0, INSTR_US_DECLARE, color, user_vm_variables);
+ instr_user_variable(0, nullptr, variable, "MSG_VM", 0, INSTR_US_DECLARE, color, &user_vm_variables);
}
/** \ingroup TRACE_user_variables
*/
void TRACE_vm_variable_set_with_time (double time, const char *vm, const char *variable, double value)
{
- instr_user_variable(time, vm, variable, "MSG_VM", value, INSTR_US_SET, nullptr, user_vm_variables);
+ instr_user_variable(time, vm, variable, "MSG_VM", value, INSTR_US_SET, nullptr, &user_vm_variables);
}
/** \ingroup TRACE_user_variables
*/
void TRACE_vm_variable_add_with_time (double time, const char *vm, const char *variable, double value)
{
- instr_user_variable(time, vm, variable, "MSG_VM", value, INSTR_US_ADD, nullptr, user_vm_variables);
+ instr_user_variable(time, vm, variable, "MSG_VM", value, INSTR_US_ADD, nullptr, &user_vm_variables);
}
/** \ingroup TRACE_user_variables
*/
void TRACE_vm_variable_sub_with_time (double time, const char *vm, const char *variable, double value)
{
- instr_user_variable(time, vm, variable, "MSG_VM", value, INSTR_US_SUB, nullptr, user_vm_variables);
+ instr_user_variable(time, vm, variable, "MSG_VM", value, INSTR_US_SUB, nullptr, &user_vm_variables);
}
/* for host variables */
*/
void TRACE_host_variable_declare (const char *variable)
{
- instr_user_variable(0, nullptr, variable, "HOST", 0, INSTR_US_DECLARE, nullptr, user_host_variables);
+ instr_user_variable(0, nullptr, variable, "HOST", 0, INSTR_US_DECLARE, nullptr, &user_host_variables);
}
/** \ingroup TRACE_user_variables
*/
void TRACE_host_variable_declare_with_color (const char *variable, const char *color)
{
- instr_user_variable(0, nullptr, variable, "HOST", 0, INSTR_US_DECLARE, color, user_host_variables);
+ instr_user_variable(0, nullptr, variable, "HOST", 0, INSTR_US_DECLARE, color, &user_host_variables);
}
/** \ingroup TRACE_user_variables
*/
void TRACE_host_variable_set_with_time (double time, const char *host, const char *variable, double value)
{
- instr_user_variable(time, host, variable, "HOST", value, INSTR_US_SET, nullptr, user_host_variables);
+ instr_user_variable(time, host, variable, "HOST", value, INSTR_US_SET, nullptr, &user_host_variables);
}
/** \ingroup TRACE_user_variables
*/
void TRACE_host_variable_add_with_time (double time, const char *host, const char *variable, double value)
{
- instr_user_variable(time, host, variable, "HOST", value, INSTR_US_ADD, nullptr, user_host_variables);
+ instr_user_variable(time, host, variable, "HOST", value, INSTR_US_ADD, nullptr, &user_host_variables);
}
/** \ingroup TRACE_user_variables
*/
void TRACE_host_variable_sub_with_time (double time, const char *host, const char *variable, double value)
{
- instr_user_variable(time, host, variable, "HOST", value, INSTR_US_SUB, nullptr, user_host_variables);
+ instr_user_variable(time, host, variable, "HOST", value, INSTR_US_SUB, nullptr, &user_host_variables);
}
/** \ingroup TRACE_user_variables
*/
xbt_dynar_t TRACE_get_host_variables ()
{
- return instr_dict_to_dynar (user_host_variables);
+ return instr_set_to_dynar(&user_host_variables);
}
/* for link variables */
*/
void TRACE_link_variable_declare (const char *variable)
{
- instr_user_variable (0, nullptr, variable, "LINK", 0, INSTR_US_DECLARE, nullptr, user_link_variables);
+ instr_user_variable(0, nullptr, variable, "LINK", 0, INSTR_US_DECLARE, nullptr, &user_link_variables);
}
/** \ingroup TRACE_user_variables
*/
void TRACE_link_variable_declare_with_color (const char *variable, const char *color)
{
- instr_user_variable (0, nullptr, variable, "LINK", 0, INSTR_US_DECLARE, color, user_link_variables);
+ instr_user_variable(0, nullptr, variable, "LINK", 0, INSTR_US_DECLARE, color, &user_link_variables);
}
/** \ingroup TRACE_user_variables
*/
void TRACE_link_variable_set_with_time (double time, const char *link, const char *variable, double value)
{
- instr_user_variable (time, link, variable, "LINK", value, INSTR_US_SET, nullptr, user_link_variables);
+ instr_user_variable(time, link, variable, "LINK", value, INSTR_US_SET, nullptr, &user_link_variables);
}
/** \ingroup TRACE_user_variables
*/
void TRACE_link_variable_add_with_time (double time, const char *link, const char *variable, double value)
{
- instr_user_variable (time, link, variable, "LINK", value, INSTR_US_ADD, nullptr, user_link_variables);
+ instr_user_variable(time, link, variable, "LINK", value, INSTR_US_ADD, nullptr, &user_link_variables);
}
/** \ingroup TRACE_user_variables
*/
void TRACE_link_variable_sub_with_time (double time, const char *link, const char *variable, double value)
{
- instr_user_variable (time, link, variable, "LINK", value, INSTR_US_SUB, nullptr, user_link_variables);
+ instr_user_variable(time, link, variable, "LINK", value, INSTR_US_SUB, nullptr, &user_link_variables);
}
/* for link variables, but with src and dst used for get_route */
*/
xbt_dynar_t TRACE_get_link_variables ()
{
- return instr_dict_to_dynar (user_link_variables);
+ return instr_set_to_dynar(&user_link_variables);
}
/** \ingroup TRACE_user_variables
*/
xbt_dynar_t TRACE_get_node_types ()
{
- return instr_dict_to_dynar (trivaNodeTypes);
+ return instr_set_to_dynar(&trivaNodeTypes);
}
/** \ingroup TRACE_API
*/
xbt_dynar_t TRACE_get_edge_types ()
{
- return instr_dict_to_dynar (trivaEdgeTypes);
+ return instr_set_to_dynar(&trivaEdgeTypes);
}
static container_t rootContainer = nullptr; /* the root container */
static xbt_dict_t allContainers = nullptr; /* all created containers indexed by name */
-xbt_dict_t trivaNodeTypes = nullptr; /* all host types defined */
-xbt_dict_t trivaEdgeTypes = nullptr; /* all link types defined */
+std::set<std::string> trivaNodeTypes; /* all host types defined */
+std::set<std::string> trivaEdgeTypes; /* all link types defined */
long long int instr_new_paje_id ()
{
void PJ_container_alloc ()
{
allContainers = xbt_dict_new_homogeneous(nullptr);
- trivaNodeTypes = xbt_dict_new_homogeneous(xbt_free_f);
- trivaEdgeTypes = xbt_dict_new_homogeneous(xbt_free_f);
}
void PJ_container_release ()
{
xbt_dict_free (&allContainers);
- xbt_dict_free (&trivaNodeTypes);
- xbt_dict_free (&trivaEdgeTypes);
}
void PJ_container_set_root (container_t root)
//register NODE types for triva configuration
if (newContainer->kind == INSTR_HOST || newContainer->kind == INSTR_LINK || newContainer->kind == INSTR_ROUTER) {
- xbt_dict_set (trivaNodeTypes, newContainer->type->name, xbt_strdup("1"), nullptr);
+ trivaNodeTypes.insert(newContainer->type->name);
}
return newContainer;
}
#include <xbt/base.h>
-#include "simgrid/instr.h"
#include "instr/instr_interface.h"
-#include "src/internal_config.h"
+#include "simgrid/instr.h"
#include "simgrid_config.h"
+#include "src/internal_config.h"
+#include <set>
SG_BEGIN_DECL()
};
-
-extern XBT_PRIVATE xbt_dict_t created_categories;
-extern XBT_PRIVATE xbt_dict_t declared_marks;
-extern XBT_PRIVATE xbt_dict_t user_host_variables;
-extern XBT_PRIVATE xbt_dict_t user_vm_variables;
-extern XBT_PRIVATE xbt_dict_t user_link_variables;
+extern XBT_PRIVATE std::set<std::string> created_categories;
+extern XBT_PRIVATE std::set<std::string> declared_marks;
+extern XBT_PRIVATE std::set<std::string> user_host_variables;
+extern XBT_PRIVATE std::set<std::string> user_vm_variables;
+extern XBT_PRIVATE std::set<std::string> user_link_variables;
extern XBT_PRIVATE double TRACE_last_timestamp_to_dump;
/* instr_paje_header.c */
XBT_PUBLIC(void) TRACE_surf_resource_utilization_alloc();
/* instr_paje.c */
-extern XBT_PRIVATE xbt_dict_t trivaNodeTypes;
-extern XBT_PRIVATE xbt_dict_t trivaEdgeTypes;
+extern XBT_PRIVATE std::set<std::string> trivaNodeTypes;
+extern XBT_PRIVATE std::set<std::string> trivaEdgeTypes;
XBT_PRIVATE long long int instr_new_paje_id ();
XBT_PRIVATE void PJ_container_alloc ();
XBT_PRIVATE void PJ_container_release ();
-/* Copyright (c) 2010-2015. The SimGrid Team.
+/* Copyright (c) 2010-2017. 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 "src/instr/instr_private.h"
+#include <string>
+#include <unordered_map>
XBT_LOG_NEW_DEFAULT_SUBCATEGORY (instr_resource, instr, "tracing (un)-categorized resource utilization");
//to check if variables were previously set to 0, otherwise paje won't simulate them
-static xbt_dict_t platform_variables;
+static std::unordered_map<std::string, std::string> platform_variables;
//used by all methods
static void __TRACE_surf_check_variable_set_to_zero(double now, const char *variable, const char *resource)
*/
// create a key considering the resource and variable
- int n = strlen(variable)+strlen(resource)+1;
- char *key = (char*)xbt_malloc(n*sizeof(char));
- snprintf (key, n, "%s%s", resource, variable);
+ std::string key = std::string(resource) + variable;
// check if key exists: if it doesn't, set the variable to zero and mark this in the dict
- if (not xbt_dict_get_or_null(platform_variables, key)) {
+ if (platform_variables.find(key) == platform_variables.end()) {
container_t container = PJ_container_get (resource);
type_t type = PJ_type_get (variable, container->type);
new SetVariableEvent (now, container, type, 0);
- xbt_dict_set(platform_variables, key, (char*)"", nullptr);
+ platform_variables[key] = std::string("");
}
- xbt_free(key);
}
static void instr_event (double now, double delta, type_t variable, container_t resource, double value)
instr_event (now, delta, type, container, value);
}
}
-
-void TRACE_surf_resource_utilization_alloc()
-{
- platform_variables = xbt_dict_new_homogeneous(nullptr);
-}
-
-void TRACE_surf_resource_utilization_release()
-{
- xbt_dict_free(&platform_variables);
-}
void Container::addChild(jed_container_t child)
{
- xbt_assert(this != nullptr);
xbt_assert(child != nullptr);
this->children.push_back(child);
child->parent = this;
std::vector<int> Container::getHierarchy()
{
- xbt_assert( this!= nullptr );
-
if(this->parent != nullptr ) {
if (not this->parent->children.empty()) {
void Container::print(FILE* jed_file)
{
- xbt_assert( this != nullptr );
fprintf(jed_file, " <res name=\"%s\">\n", this->name.c_str());
if (not this->children.empty()) {
for (auto child: this->children) {
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_mailbox, simix, "Mailbox implementation");
-static xbt_dict_t mailboxes = xbt_dict_new_homogeneous([](void* data) {
- delete static_cast<smx_mailbox_t>(data);
-});
+static std::map<std::string, smx_mailbox_t>* mailboxes = new std::map<std::string, smx_mailbox_t>;
void SIMIX_mailbox_exit()
{
- xbt_dict_free(&mailboxes);
+ for (auto elm : *mailboxes)
+ delete elm.second;
+ delete mailboxes;
}
/******************************************************************************/
/** @brief Returns the mailbox of that name, or nullptr */
MailboxImpl* MailboxImpl::byNameOrNull(const char* name)
{
- return static_cast<smx_mailbox_t>(xbt_dict_get_or_null(mailboxes, name));
+ auto mbox = mailboxes->find(name);
+ if (mbox != mailboxes->end())
+ return mbox->second;
+ else
+ return nullptr;
}
/** @brief Returns the mailbox of that name, newly created on need */
MailboxImpl* MailboxImpl::byNameOrCreate(const char* name)
{
xbt_assert(name, "Mailboxes must have a name");
/* two processes may have pushed the same mbox_create simcall at the same time */
- smx_mailbox_t mbox = static_cast<smx_mailbox_t>(xbt_dict_get_or_null(mailboxes, name));
- if (not mbox) {
- mbox = new MailboxImpl(name);
+ auto m = mailboxes->find(name);
+ if (m == mailboxes->end()) {
+ smx_mailbox_t mbox = new MailboxImpl(name);
XBT_DEBUG("Creating a mailbox at %p with name %s", mbox, name);
- xbt_dict_set(mailboxes, mbox->name_, mbox, nullptr);
- }
- return mbox;
+ (*mailboxes)[mbox->name_] = mbox;
+ return mbox;
+ } else
+ return m->second;
}
/** @brief set the receiver of the mailbox to allow eager sends
* \param actor The receiving dude
XBT_PRIVATE void SIMIX_context_mod_init();
XBT_PRIVATE void SIMIX_context_mod_exit();
-XBT_PRIVATE smx_context_t SIMIX_context_new(
- std::function<void()> code,
- void_pfn_smxprocess_t cleanup_func,
- smx_actor_t simix_process);
+XBT_PUBLIC(smx_context_t)
+SIMIX_context_new(std::function<void()> code, void_pfn_smxprocess_t cleanup_func, smx_actor_t simix_process);
#ifndef WIN32
XBT_PUBLIC_DATA(char sigsegv_stack[SIGSTKSZ]);
XBT_PRIVATE void *SIMIX_context_stack_new();
XBT_PRIVATE void SIMIX_context_stack_delete(void *stack);
-XBT_PRIVATE void SIMIX_context_set_current(smx_context_t context);
+XBT_PUBLIC(void) SIMIX_context_set_current(smx_context_t context);
XBT_PRIVATE smx_context_t SIMIX_context_get_current();
XBT_PUBLIC(int) SIMIX_process_get_maxpid();
-/* Copyright (c) 2015. The SimGrid Team. All rights reserved. */
+/* Copyright (c) 2015-2017. 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. */
// BoostContextFactory
-bool BoostContext::parallel_ = false;
-xbt_parmap_t BoostContext::parmap_ = nullptr;
-uintptr_t BoostContext::threads_working_ = 0;
+bool BoostContext::parallel_ = false;
+simgrid::xbt::Parmap<smx_actor_t>* BoostContext::parmap_ = nullptr;
+uintptr_t BoostContext::threads_working_ = 0;
xbt_os_thread_key_t BoostContext::worker_id_key_;
-unsigned long BoostContext::process_index_ = 0;
-BoostContext* BoostContext::maestro_context_ = nullptr;
+unsigned long BoostContext::process_index_ = 0;
+BoostContext* BoostContext::maestro_context_ = nullptr;
std::vector<BoostContext*> BoostContext::workers_context_;
BoostContextFactory::BoostContextFactory()
if (BoostContext::parallel_) {
#if HAVE_THREAD_CONTEXTS
int nthreads = SIMIX_context_get_nthreads();
- BoostContext::parmap_ = xbt_parmap_new(nthreads, SIMIX_context_get_parallel_mode());
+ BoostContext::parmap_ = new simgrid::xbt::Parmap<smx_actor_t>(nthreads, SIMIX_context_get_parallel_mode());
BoostContext::workers_context_.clear();
BoostContext::workers_context_.resize(nthreads, nullptr);
BoostContext::maestro_context_ = nullptr;
{
#if HAVE_THREAD_CONTEXTS
if (BoostContext::parmap_) {
- xbt_parmap_destroy(BoostContext::parmap_);
+ delete BoostContext::parmap_;
BoostContext::parmap_ = nullptr;
}
BoostContext::workers_context_.clear();
#if HAVE_THREAD_CONTEXTS
if (BoostContext::parallel_) {
BoostContext::threads_working_ = 0;
- xbt_parmap_apply(BoostContext::parmap_,
- [](void* arg) {
- smx_actor_t process = static_cast<smx_actor_t>(arg);
- BoostContext* context = static_cast<BoostContext*>(process->context);
- return context->resume();
- },
- simix_global->process_to_run);
+ BoostContext::parmap_->apply(
+ [](smx_actor_t process) {
+ BoostContext* context = static_cast<BoostContext*>(process->context);
+ return context->resume();
+ },
+ simix_global->process_to_run);
} else
#endif
{
- if (xbt_dynar_is_empty(simix_global->process_to_run))
+ if (simix_global->process_to_run.empty())
return;
- smx_actor_t first_process = xbt_dynar_get_as(simix_global->process_to_run, 0, smx_actor_t);
+ smx_actor_t first_process = simix_global->process_to_run.front();
BoostContext::process_index_ = 1;
/* execute the first process */
static_cast<BoostContext*>(first_process->context)->resume();
unsigned long int i = process_index_;
process_index_++;
- if (i < xbt_dynar_length(simix_global->process_to_run)) {
+ if (i < simix_global->process_to_run.size()) {
/* execute the next process */
XBT_DEBUG("Run next process");
- next_context =
- static_cast<BoostSerialContext*>(xbt_dynar_get_as(simix_global->process_to_run, i, smx_actor_t)->context);
+ next_context = static_cast<BoostSerialContext*>(simix_global->process_to_run[i]->context);
} else {
/* all processes were run, return to maestro */
XBT_DEBUG("No more process to run");
void BoostParallelContext::suspend()
{
- smx_actor_t next_work = static_cast<smx_actor_t>(xbt_parmap_next(parmap_));
- BoostParallelContext* next_context = nullptr;
-
- if (next_work != nullptr) {
+ boost::optional<smx_actor_t> next_work = parmap_->next();
+ BoostParallelContext* next_context;
+ if (next_work) {
XBT_DEBUG("Run next process");
- next_context = static_cast<BoostParallelContext*>(next_work->context);
+ next_context = static_cast<BoostParallelContext*>(next_work.get()->context);
} else {
XBT_DEBUG("No more processes to run");
uintptr_t worker_id = (uintptr_t)xbt_os_thread_get_specific(worker_id_key_);
-/* Copyright (c) 2015. The SimGrid Team. All rights reserved. */
+/* Copyright (c) 2015-2017. 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 <functional>
#include <vector>
-#include <xbt/parmap.h>
+#include <xbt/parmap.hpp>
#include <simgrid/simix.hpp>
class BoostContext : public Context {
protected: // static
static bool parallel_;
- static xbt_parmap_t parmap_;
+ static simgrid::xbt::Parmap<smx_actor_t>* parmap_;
static std::vector<BoostContext*> workers_context_;
static uintptr_t threads_working_;
static xbt_os_thread_key_t worker_id_key_;
#include "src/internal_config.h"
-#include "xbt/parmap.h"
+#include "xbt/parmap.hpp"
#include "src/simix/smx_private.h"
#include "mc/mc.h"
// ***** Loads of static stuff
#if HAVE_THREAD_CONTEXTS
-static xbt_parmap_t raw_parmap;
+static simgrid::xbt::Parmap<smx_actor_t>* raw_parmap;
static simgrid::kernel::context::RawContext** raw_workers_context; /* space to save the worker context in each thread */
static uintptr_t raw_threads_working; /* number of threads that have started their work */
static xbt_os_thread_key_t raw_worker_id_key; /* thread-specific storage for the thread id */
RawContextFactory::~RawContextFactory()
{
#if HAVE_THREAD_CONTEXTS
- if (raw_parmap)
- xbt_parmap_destroy(raw_parmap);
+ delete raw_parmap;
xbt_free(raw_workers_context);
#endif
}
void RawContextFactory::run_all_serial()
{
- if (xbt_dynar_is_empty(simix_global->process_to_run))
+ if (simix_global->process_to_run.empty())
return;
- smx_actor_t first_process =
- xbt_dynar_get_as(simix_global->process_to_run, 0, smx_actor_t);
+ smx_actor_t first_process = simix_global->process_to_run.front();
raw_process_index = 1;
static_cast<RawContext*>(first_process->context)->resume_serial();
}
#if HAVE_THREAD_CONTEXTS
raw_threads_working = 0;
if (raw_parmap == nullptr)
- raw_parmap = xbt_parmap_new(
- SIMIX_context_get_nthreads(), SIMIX_context_get_parallel_mode());
- xbt_parmap_apply(raw_parmap,
- [](void* arg) {
- smx_actor_t process = static_cast<smx_actor_t>(arg);
+ raw_parmap = new simgrid::xbt::Parmap<smx_actor_t>(SIMIX_context_get_nthreads(), SIMIX_context_get_parallel_mode());
+ raw_parmap->apply(
+ [](smx_actor_t process) {
RawContext* context = static_cast<RawContext*>(process->context);
context->resume_parallel();
},
RawContext* next_context = nullptr;
unsigned long int i = raw_process_index;
raw_process_index++;
- if (i < xbt_dynar_length(simix_global->process_to_run)) {
+ if (i < simix_global->process_to_run.size()) {
/* execute the next process */
XBT_DEBUG("Run next process");
- next_context = static_cast<RawContext*>(xbt_dynar_get_as(simix_global->process_to_run, i, smx_actor_t)->context);
+ next_context = static_cast<RawContext*>(simix_global->process_to_run[i]->context);
} else {
/* all processes were run, return to maestro */
XBT_DEBUG("No more process to run");
{
#if HAVE_THREAD_CONTEXTS
/* determine the next context */
- smx_actor_t next_work = static_cast<smx_actor_t>(xbt_parmap_next(raw_parmap));
- RawContext* next_context = nullptr;
-
- if (next_work != nullptr) {
+ boost::optional<smx_actor_t> next_work = raw_parmap->next();
+ RawContext* next_context;
+ if (next_work) {
/* there is a next process to resume */
XBT_DEBUG("Run next process");
- next_context = static_cast<RawContext*>(next_work->context);
+ next_context = static_cast<RawContext*>(next_work.get()->context);
} else {
/* all processes were run, go to the barrier */
XBT_DEBUG("No more processes to run");
/** @brief Resumes all processes ready to run. */
void RawContextFactory::run_all_adaptative()
{
- unsigned long nb_processes = xbt_dynar_length(simix_global->process_to_run);
+ unsigned long nb_processes = simix_global->process_to_run.size();
if (SIMIX_context_is_parallel() &&
static_cast<unsigned long>(SIMIX_context_get_parallel_threshold()) < nb_processes) {
raw_context_parallel = true;
{
if (smx_ctx_thread_sem == nullptr) {
// Serial execution
- smx_actor_t process;
- unsigned int cursor;
- xbt_dynar_foreach(simix_global->process_to_run, cursor, process) {
+ for (smx_actor_t process : simix_global->process_to_run) {
XBT_DEBUG("Handling %p",process);
ThreadContext* context = static_cast<ThreadContext*>(process->context);
xbt_os_sem_release(context->begin_);
}
} else {
// Parallel execution
- unsigned int index;
- smx_actor_t process;
- xbt_dynar_foreach(simix_global->process_to_run, index, process)
+ for (smx_actor_t process : simix_global->process_to_run)
xbt_os_sem_release(static_cast<ThreadContext*>(process->context)->begin_);
- xbt_dynar_foreach(simix_global->process_to_run, index, process)
- xbt_os_sem_acquire(static_cast<ThreadContext*>(process->context)->end_);
+ for (smx_actor_t process : simix_global->process_to_run)
+ xbt_os_sem_acquire(static_cast<ThreadContext*>(process->context)->end_);
}
}
#include <ucontext.h> /* context relative declarations */
-#include "src/simix/ActorImpl.hpp"
-#include "src/simix/smx_private.h"
-#include "xbt/parmap.h"
#include "mc/mc.h"
#include "src/mc/mc_ignore.h"
-
+#include "src/simix/ActorImpl.hpp"
+#include "src/simix/smx_private.h"
+#include "xbt/parmap.hpp"
/** Many integers are needed to store a pointer
*
}}}
#if HAVE_THREAD_CONTEXTS
-static xbt_parmap_t sysv_parmap;
+static simgrid::xbt::Parmap<smx_actor_t>* sysv_parmap;
static simgrid::kernel::context::ParallelUContext** sysv_workers_context; /* space to save the worker's context in each thread */
static uintptr_t sysv_threads_working; /* number of threads that have started their work */
static xbt_os_thread_key_t sysv_worker_id_key; /* thread-specific storage for the thread id */
UContextFactory::~UContextFactory()
{
#if HAVE_THREAD_CONTEXTS
- if (sysv_parmap)
- xbt_parmap_destroy(sysv_parmap);
+ delete sysv_parmap;
xbt_free(sysv_workers_context);
#endif
}
// with simix_global->context_factory (which might not be initialized
// when bootstrapping):
if (sysv_parmap == nullptr)
- sysv_parmap = xbt_parmap_new(
- SIMIX_context_get_nthreads(), SIMIX_context_get_parallel_mode());
-
- xbt_parmap_apply(sysv_parmap,
- [](void* arg) {
- smx_actor_t process = (smx_actor_t) arg;
- ParallelUContext* context = static_cast<ParallelUContext*>(process->context);
- context->resume();
- },
- simix_global->process_to_run);
+ sysv_parmap =
+ new simgrid::xbt::Parmap<smx_actor_t>(SIMIX_context_get_nthreads(), SIMIX_context_get_parallel_mode());
+
+ sysv_parmap->apply(
+ [](smx_actor_t process) {
+ ParallelUContext* context = static_cast<ParallelUContext*>(process->context);
+ context->resume();
+ },
+ simix_global->process_to_run);
#else
xbt_die("You asked for a parallel execution, but you don't have any threads.");
#endif
} else {
// Serial:
- if (xbt_dynar_is_empty(simix_global->process_to_run))
+ if (simix_global->process_to_run.empty())
return;
- smx_actor_t first_process = xbt_dynar_get_as(simix_global->process_to_run, 0, smx_actor_t);
+ smx_actor_t first_process = simix_global->process_to_run.front();
sysv_process_index = 1;
SerialUContext* context = static_cast<SerialUContext*>(first_process->context);
context->resume();
SerialUContext* next_context = nullptr;
unsigned long int i = sysv_process_index++;
- if (i < xbt_dynar_length(simix_global->process_to_run)) {
+ if (i < simix_global->process_to_run.size()) {
/* execute the next process */
XBT_DEBUG("Run next process");
- next_context = (SerialUContext*) xbt_dynar_get_as(
- simix_global->process_to_run,i, smx_actor_t)->context;
+ next_context = static_cast<SerialUContext*>(simix_global->process_to_run[i]->context);
} else {
/* all processes were run, return to maestro */
XBT_DEBUG("No more process to run");
- next_context = (SerialUContext*) sysv_maestro_context;
+ next_context = static_cast<SerialUContext*>(sysv_maestro_context);
}
SIMIX_context_set_current(next_context);
swapcontext(&this->uc_, &next_context->uc_);
void SerialUContext::resume()
{
SIMIX_context_set_current(this);
- swapcontext(&((SerialUContext*)sysv_maestro_context)->uc_, &this->uc_);
+ swapcontext(&static_cast<SerialUContext*>(sysv_maestro_context)->uc_, &this->uc_);
}
void ParallelUContext::stop()
// Store the number of my containing body in os-thread-specific area :
xbt_os_thread_set_specific(sysv_worker_id_key, (void*) worker_id);
// Get my current soul:
- ParallelUContext* worker_context = (ParallelUContext*) SIMIX_context_self();
+ ParallelUContext* worker_context = static_cast<ParallelUContext*>(SIMIX_context_self());
// Write down that this soul is hosted in that body (for now)
sysv_workers_context[worker_id] = worker_context;
// Retrieve the system-level info that fuels this soul:
- ucontext_t* worker_stack = &((ParallelUContext*) worker_context)->uc_;
+ ucontext_t* worker_stack = &worker_context->uc_;
// Write in simix that I switched my soul
SIMIX_context_set_current(this);
// Actually do that using the relevant library call:
#if HAVE_THREAD_CONTEXTS
/* determine the next context */
// Get the next soul to embody now:
- smx_actor_t next_work = (smx_actor_t) xbt_parmap_next(sysv_parmap);
- ParallelUContext* next_context = nullptr;
- // Will contain the next soul to run, either simulated or initial minion's one
- ucontext_t* next_stack;
-
- if (next_work != nullptr) {
+ boost::optional<smx_actor_t> next_work = sysv_parmap->next();
+ ParallelUContext* next_context;
+ if (next_work) {
// There is a next soul to embody (ie, a next process to resume)
XBT_DEBUG("Run next process");
- next_context = (ParallelUContext*) next_work->context;
+ next_context = static_cast<ParallelUContext*>(next_work.get()->context);
} else {
// All processes were run, go to the barrier
XBT_DEBUG("No more processes to run");
uintptr_t worker_id =
(uintptr_t) xbt_os_thread_get_specific(sysv_worker_id_key);
// Deduce the initial soul of that body
- next_context = (ParallelUContext*) sysv_workers_context[worker_id];
+ next_context = sysv_workers_context[worker_id];
// When given that soul, the body will wait for the next scheduling round
}
- next_stack = &next_context->uc_;
+ // Will contain the next soul to run, either simulated or initial minion's one
+ ucontext_t* next_stack = &next_context->uc_;
SIMIX_context_set_current(next_context);
// Get that next soul:
namespace simgrid {
namespace kernel {
namespace routing {
-ClusterZone::ClusterZone(NetZone* father, const char* name) : NetZoneImpl(father, name)
+ClusterZone::ClusterZone(NetZone* father, std::string name) : NetZoneImpl(father, name)
{
}
}
}
-void ClusterZone::create_links_for_node(sg_platf_cluster_cbarg_t cluster, int id, int /*rank*/, int position)
+void ClusterZone::create_links_for_node(ClusterCreationArgs* cluster, int id, int /*rank*/, int position)
{
- char* link_id = bprintf("%s_link_%d", cluster->id, id);
+ std::string link_id = cluster->id + "_link_" + std::to_string(id);
LinkCreationArgs link;
link.id = link_id;
surf::LinkImpl *linkUp;
surf::LinkImpl *linkDown;
if (link.policy == SURF_LINK_FULLDUPLEX) {
- char* tmp_link = bprintf("%s_UP", link_id);
- linkUp = surf::LinkImpl::byName(tmp_link);
- xbt_free(tmp_link);
- tmp_link = bprintf("%s_DOWN", link_id);
- linkDown = surf::LinkImpl::byName(tmp_link);
- xbt_free(tmp_link);
+ linkUp = surf::LinkImpl::byName(link_id + "_UP");
+ linkDown = surf::LinkImpl::byName(link_id + "_DOWN");
} else {
linkUp = surf::LinkImpl::byName(link_id);
linkDown = linkUp;
}
- xbt_free(link_id);
privateLinks_.insert({position, {linkUp, linkDown}});
}
}
class XBT_PRIVATE ClusterZone : public NetZoneImpl {
public:
- explicit ClusterZone(NetZone* father, const char* name);
+ explicit ClusterZone(NetZone* father, std::string name);
void getLocalRoute(NetPoint* src, NetPoint* dst, sg_platf_route_cbarg_t into, double* latency) override;
void getGraph(xbt_graph_t graph, xbt_dict_t nodes, xbt_dict_t edges) override;
- virtual void create_links_for_node(sg_platf_cluster_cbarg_t cluster, int id, int rank, int position);
- virtual void parse_specific_arguments(sg_platf_cluster_cbarg_t cluster)
+ virtual void create_links_for_node(ClusterCreationArgs* cluster, int id, int rank, int position);
+ virtual void parse_specific_arguments(ClusterCreationArgs* cluster)
{
/* this routing method does not require any specific argument */
}
/* Creation routing model functions */
-DijkstraZone::DijkstraZone(NetZone* father, const char* name, bool cached) : RoutedZone(father, name)
+DijkstraZone::DijkstraZone(NetZone* father, std::string name, bool cached) : RoutedZone(father, name)
{
if (cached)
routeCache_ = xbt_dict_new_homogeneous(&route_cache_elem_free);
*/
class XBT_PRIVATE DijkstraZone : public RoutedZone {
public:
- DijkstraZone(NetZone* father, const char* name, bool cached);
+ DijkstraZone(NetZone* father, std::string name, bool cached);
void seal() override;
~DijkstraZone() override;
namespace kernel {
namespace routing {
-DragonflyZone::DragonflyZone(NetZone* father, const char* name) : ClusterZone(father, name)
+DragonflyZone::DragonflyZone(NetZone* father, std::string name) : ClusterZone(father, name)
{
}
(*coords)[3] = rankId % numNodesPerBlade_;
}
-void DragonflyZone::parse_specific_arguments(sg_platf_cluster_cbarg_t cluster)
+void DragonflyZone::parse_specific_arguments(ClusterCreationArgs* cluster)
{
std::vector<std::string> parameters;
std::vector<std::string> tmp;
std::string tmpID;
if (this->cluster_->sharing_policy == SURF_LINK_FULLDUPLEX) {
tmpID = linkTemplate.id + "_UP";
- link = surf::LinkImpl::byName(tmpID.c_str());
+ link = surf::LinkImpl::byName(tmpID);
*linkup = link; // check link?
tmpID = linkTemplate.id + "_DOWN";
- link = surf::LinkImpl::byName(tmpID.c_str());
+ link = surf::LinkImpl::byName(tmpID);
*linkdown = link; // check link ?
} else {
- link = surf::LinkImpl::byName(linkTemplate.id.c_str());
+ link = surf::LinkImpl::byName(linkTemplate.id);
*linkup = link;
*linkdown = link;
}
*/
class XBT_PRIVATE DragonflyZone : public ClusterZone {
public:
- explicit DragonflyZone(NetZone* father, const char* name);
+ explicit DragonflyZone(NetZone* father, std::string name);
~DragonflyZone() override;
// void create_links_for_node(sg_platf_cluster_cbarg_t cluster, int id, int rank, int position) override;
void getLocalRoute(NetPoint* src, NetPoint* dst, sg_platf_route_cbarg_t into, double* latency) override;
- void parse_specific_arguments(sg_platf_cluster_cbarg_t cluster) override;
+ void parse_specific_arguments(ClusterCreationArgs* cluster) override;
void seal() override;
void generateRouters();
void generateLinks();
private:
void rankId_to_coords(int rankId, unsigned int (*coords)[4]);
- sg_platf_cluster_cbarg_t cluster_;
+ ClusterCreationArgs* cluster_;
unsigned int numNodesPerBlade_ = 0;
unsigned int numBladesPerChassis_ = 0;
unsigned int numChassisPerGroup_ = 0;
namespace kernel {
namespace routing {
-EmptyZone::EmptyZone(NetZone* father, const char* name) : NetZoneImpl(father, name)
+EmptyZone::EmptyZone(NetZone* father, std::string name) : NetZoneImpl(father, name)
{
}
class XBT_PRIVATE EmptyZone : public NetZoneImpl {
public:
- explicit EmptyZone(NetZone* father, const char* name);
+ explicit EmptyZone(NetZone* father, std::string name);
~EmptyZone() override;
void getLocalRoute(NetPoint* src, NetPoint* dst, sg_platf_route_cbarg_t into, double* latency) override
namespace kernel {
namespace routing {
-FatTreeZone::FatTreeZone(NetZone* father, const char* name) : ClusterZone(father, name)
+FatTreeZone::FatTreeZone(NetZone* father, std::string name) : ClusterZone(father, name)
{
XBT_DEBUG("Creating a new fat tree.");
}
this->nodesByLevel_[0] *= this->lowerLevelNodesNumber_[i];
if (this->nodesByLevel_[0] != this->nodes_.size()) {
- surf_parse_error("The number of provided nodes does not fit with the wanted topology."
- " Please check your platform description (We need %u nodes, we got %zu)",
- this->nodesByLevel_[0], this->nodes_.size());
+ surf_parse_error(std::string("The number of provided nodes does not fit with the wanted topology.") +
+ " Please check your platform description (We need " + std::to_string(this->nodesByLevel_[0]) +
+ "nodes, we got " + std::to_string(this->nodes_.size()));
return;
}
this->links_.push_back(newLink);
}
-void FatTreeZone::parse_specific_arguments(sg_platf_cluster_cbarg_t cluster)
+void FatTreeZone::parse_specific_arguments(ClusterCreationArgs* cluster)
{
std::vector<std::string> parameters;
std::vector<std::string> tmp;
file.close();
}
-FatTreeNode::FatTreeNode(sg_platf_cluster_cbarg_t cluster, int id, int level, int position)
+FatTreeNode::FatTreeNode(ClusterCreationArgs* cluster, int id, int level, int position)
: id(id), level(level), position(position)
{
LinkCreationArgs linkTemplate;
linkTemplate.policy = SURF_LINK_SHARED;
linkTemplate.id = "limiter_"+std::to_string(id);
sg_platf_new_link(&linkTemplate);
- this->limiterLink = surf::LinkImpl::byName(linkTemplate.id.c_str());
+ this->limiterLink = surf::LinkImpl::byName(linkTemplate.id);
}
if (cluster->loopback_bw || cluster->loopback_lat) {
linkTemplate.bandwidth = cluster->loopback_bw;
linkTemplate.policy = SURF_LINK_FATPIPE;
linkTemplate.id = "loopback_"+ std::to_string(id);
sg_platf_new_link(&linkTemplate);
- this->loopback = surf::LinkImpl::byName(linkTemplate.id.c_str());
+ this->loopback = surf::LinkImpl::byName(linkTemplate.id);
}
}
-FatTreeLink::FatTreeLink(sg_platf_cluster_cbarg_t cluster, FatTreeNode* downNode, FatTreeNode* upNode)
+FatTreeLink::FatTreeLink(ClusterCreationArgs* cluster, FatTreeNode* downNode, FatTreeNode* upNode)
: upNode(upNode), downNode(downNode)
{
static int uniqueId = 0;
if (cluster->sharing_policy == SURF_LINK_FULLDUPLEX) {
std::string tmpID = std::string(linkTemplate.id) + "_UP";
- this->upLink = surf::LinkImpl::byName(tmpID.c_str()); // check link?
+ this->upLink = surf::LinkImpl::byName(tmpID); // check link?
tmpID = std::string(linkTemplate.id) + "_DOWN";
- this->downLink = surf::LinkImpl::byName(tmpID.c_str()); // check link ?
+ this->downLink = surf::LinkImpl::byName(tmpID); // check link ?
} else {
- this->upLink = surf::LinkImpl::byName(linkTemplate.id.c_str());
+ this->upLink = surf::LinkImpl::byName(linkTemplate.id);
this->downLink = this->upLink;
}
uniqueId++;
* instead of passing by an upper level switch.
*/
surf::LinkImpl* loopback;
- FatTreeNode(sg_platf_cluster_cbarg_t cluster, int id, int level, int position);
+ FatTreeNode(ClusterCreationArgs* cluster, int id, int level, int position);
};
/** \brief Link in a fat tree (@ref FatTreeZone).
*/
class FatTreeLink {
public:
- FatTreeLink(sg_platf_cluster_cbarg_t cluster, FatTreeNode* source, FatTreeNode* destination);
+ FatTreeLink(ClusterCreationArgs* cluster, FatTreeNode* source, FatTreeNode* destination);
/** Link going up in the tree */
surf::LinkImpl* upLink;
/** Link going down in the tree */
*/
class XBT_PRIVATE FatTreeZone : public ClusterZone {
public:
- explicit FatTreeZone(NetZone* father, const char* name);
+ explicit FatTreeZone(NetZone* father, std::string name);
~FatTreeZone() override;
void getLocalRoute(NetPoint* src, NetPoint* dst, sg_platf_route_cbarg_t into, double* latency) override;
*
* It will also store the cluster for future use.
*/
- void parse_specific_arguments(sg_platf_cluster_cbarg_t cluster) override;
+ void parse_specific_arguments(ClusterCreationArgs* cluster) override;
void addProcessingNode(int id);
void generateDotFile(const std::string& filename = "fatTree.dot") const;
std::vector<FatTreeLink*> links_;
std::vector<unsigned int> nodesByLevel_;
- sg_platf_cluster_cbarg_t cluster_ = nullptr;
+ ClusterCreationArgs* cluster_ = nullptr;
void addLink(FatTreeNode* parent, unsigned int parentPort, FatTreeNode* child, unsigned int childPort);
int getLevelPosition(const unsigned int level);
namespace kernel {
namespace routing {
-FloydZone::FloydZone(NetZone* father, const char* name) : RoutedZone(father, name)
+FloydZone::FloydZone(NetZone* father, std::string name) : RoutedZone(father, name)
{
predecessorTable_ = nullptr;
costTable_ = nullptr;
*/
class XBT_PRIVATE FloydZone : public RoutedZone {
public:
- explicit FloydZone(NetZone* father, const char* name);
+ explicit FloydZone(NetZone* father, std::string name);
~FloydZone() override;
void getLocalRoute(NetPoint* src, NetPoint* dst, sg_platf_route_cbarg_t into, double* latency) override;
namespace simgrid {
namespace kernel {
namespace routing {
-FullZone::FullZone(NetZone* father, const char* name) : RoutedZone(father, name)
+FullZone::FullZone(NetZone* father, std::string name) : RoutedZone(father, name)
{
}
/** @ingroup ROUTING_API
* @brief NetZone with an explicit routing provided by the user
*
- * The full communication matrix is provided at creation, so this model
- * has the highest expressive power and the lowest computational requirements,
- * but also the highest memory requirements (both in platform file and in memory).
+ * The full communication matrix is provided at creation, so this model has the highest expressive power and the lowest
+ * computational requirements, but also the highest memory requirements (both in platform file and in memory).
*/
class XBT_PRIVATE FullZone : public RoutedZone {
public:
- explicit FullZone(NetZone* father, const char* name);
+ explicit FullZone(NetZone* father, std::string name);
void seal() override;
~FullZone() override;
std::vector<surf::LinkImpl*> links;
};
-NetZoneImpl::NetZoneImpl(NetZone* father, const char* name) : NetZone(father, name)
+NetZoneImpl::NetZoneImpl(NetZone* father, std::string name) : NetZone(father, name)
{
- xbt_assert(nullptr == simgrid::s4u::Engine::getInstance()->getNetpointByNameOrNull(name),
- "Refusing to create a second NetZone called '%s'.", name);
+ xbt_assert(nullptr == simgrid::s4u::Engine::getInstance()->getNetpointByNameOrNull(name.c_str()),
+ "Refusing to create a second NetZone called '%s'.", name.c_str());
netpoint_ = new NetPoint(name, NetPoint::Type::NetZone, static_cast<NetZoneImpl*>(father));
- XBT_DEBUG("NetZone '%s' created with the id '%u'", name, netpoint_->id());
+ XBT_DEBUG("NetZone '%s' created with the id '%u'", name.c_str(), netpoint_->id());
}
+
NetZoneImpl::~NetZoneImpl()
{
for (auto& kv : bypassRoutes_)
for (int i = 0; i < max; i++) {
if (i <= max_index_src && max <= max_index_dst) {
key = {path_src.at(i)->netpoint_, path_dst.at(max)->netpoint_};
- try {
- bypassedRoute = bypassRoutes_.at(key);
+ auto bpr = bypassRoutes_.find(key);
+ if (bpr != bypassRoutes_.end()) {
+ bypassedRoute = bpr->second;
break;
- } catch (std::out_of_range& unfound) {
- // Do nothing
}
}
if (max <= max_index_src && i <= max_index_dst) {
key = {path_src.at(max)->netpoint_, path_dst.at(i)->netpoint_};
- try {
- bypassedRoute = bypassRoutes_.at(key);
+ auto bpr = bypassRoutes_.find(key);
+ if (bpr != bypassRoutes_.end()) {
+ bypassedRoute = bpr->second;
break;
- } catch (std::out_of_range& unfound) {
- // Do nothing
}
}
}
if (max <= max_index_src && max <= max_index_dst) {
key = {path_src.at(max)->netpoint_, path_dst.at(max)->netpoint_};
- try {
- bypassedRoute = bypassRoutes_.at(key);
+ auto bpr = bypassRoutes_.find(key);
+ if (bpr != bypassRoutes_.end()) {
+ bypassedRoute = bpr->second;
break;
- } catch (std::out_of_range& unfound) {
- // Do nothing
}
}
}
friend simgrid::kernel::EngineImpl; // it destroys netRoot_
protected:
- explicit NetZoneImpl(NetZone * father, const char* name);
+ explicit NetZoneImpl(NetZone * father, std::string name);
virtual ~NetZoneImpl();
public:
namespace kernel {
namespace routing {
-RoutedZone::RoutedZone(NetZone* father, const char* name) : NetZoneImpl(father, name)
+RoutedZone::RoutedZone(NetZone* father, std::string name) : NetZoneImpl(father, name)
{
}
class XBT_PRIVATE RoutedZone : public NetZoneImpl {
public:
- explicit RoutedZone(NetZone* father, const char* name);
+ explicit RoutedZone(NetZone* father, std::string name);
void getGraph(xbt_graph_t graph, xbt_dict_t nodes, xbt_dict_t edges) override;
virtual sg_platf_route_cbarg_t newExtendedRoute(RoutingMode hierarchy, sg_platf_route_cbarg_t routearg,
namespace simgrid {
namespace kernel {
namespace routing {
-TorusZone::TorusZone(NetZone* father, const char* name) : ClusterZone(father, name)
+TorusZone::TorusZone(NetZone* father, std::string name) : ClusterZone(father, name)
{
}
-void TorusZone::create_links_for_node(sg_platf_cluster_cbarg_t cluster, int id, int rank, int position)
+void TorusZone::create_links_for_node(ClusterCreationArgs* cluster, int id, int rank, int position)
{
/* Create all links that exist in the torus. Each rank creates @a dimensions-1 links */
int dim_product = 1; // Needed to calculate the next neighbor_id
? rank - (current_dimension - 1) * dim_product
: rank + dim_product;
// name of neighbor is not right for non contiguous cluster radicals (as id != rank in this case)
- char* link_id = bprintf("%s_link_from_%i_to_%i", cluster->id, id, neighbor_rank_id);
+ std::string link_id =
+ std::string(cluster->id) + "_link_from_" + std::to_string(id) + "_to_" + std::to_string(neighbor_rank_id);
link.id = link_id;
link.bandwidth = cluster->bw;
link.latency = cluster->lat;
surf::LinkImpl* linkUp;
surf::LinkImpl* linkDown;
if (link.policy == SURF_LINK_FULLDUPLEX) {
- char* tmp_link = bprintf("%s_UP", link_id);
+ std::string tmp_link = link_id + "_UP";
linkUp = surf::LinkImpl::byName(tmp_link);
- free(tmp_link);
- tmp_link = bprintf("%s_DOWN", link_id);
+ tmp_link = link_id + "_DOWN";
linkDown = surf::LinkImpl::byName(tmp_link);
- free(tmp_link);
} else {
linkUp = surf::LinkImpl::byName(link_id);
linkDown = linkUp;
*/
privateLinks_.insert({position + j, {linkUp, linkDown}});
dim_product *= current_dimension;
- xbt_free(link_id);
}
rank++;
}
-void TorusZone::parse_specific_arguments(sg_platf_cluster_cbarg_t cluster)
+void TorusZone::parse_specific_arguments(ClusterCreationArgs* cluster)
{
std::vector<std::string> dimensions;
boost::split(dimensions, cluster->topo_parameters, boost::is_any_of(","));
if (not dimensions.empty()) {
/* We are in a torus cluster
- * Parse attribute dimensions="dim1,dim2,dim3,...,dimN" and safe it in a vector.
+ * Parse attribute dimensions="dim1,dim2,dim3,...,dimN" and save them into a vector.
* Additionally, we need to know how many ranks we have in total
*/
- for (auto group : dimensions) {
- dimensions_.push_back(surf_parse_get_int(group.c_str()));
- }
+ for (auto group : dimensions)
+ dimensions_.push_back(surf_parse_get_int(group));
linkCountPerNode_ = dimensions_.size();
}
unsigned int current_node = src->id();
unsigned int next_node = 0;
/*
- * Arrays that hold the coordinates of the current node and
- * the target; comparing the values at the i-th position of
- * both arrays, we can easily assess whether we need to route
- * into this dimension or not.
+ * Arrays that hold the coordinates of the current node andthe target; comparing the values at the i-th position of
+ * both arrays, we can easily assess whether we need to route into this dimension or not.
*/
unsigned int myCoords[4];
rankId_to_coords(src->id(), dimensions_, &myCoords);
unsigned int targetCoords[4];
rankId_to_coords(dst->id(), dimensions_, &targetCoords);
/*
- * linkOffset describes the offset where the link
- * we want to use is stored
- * (+1 is added because each node has a link from itself to itself,
- * which can only be the case if src->m_id == dst->m_id -- see above
- * for this special case)
+ * linkOffset describes the offset where the link we want to use is stored(+1 is added because each node has a link
+ * from itself to itself, which can only be the case if src->m_id == dst->m_id -- see above for this special case)
*/
int nodeOffset = (dimensions_.size() + 1) * src->id();
class XBT_PRIVATE TorusZone : public ClusterZone {
public:
- explicit TorusZone(NetZone* father, const char* name);
- void create_links_for_node(sg_platf_cluster_cbarg_t cluster, int id, int rank, int position) override;
+ explicit TorusZone(NetZone* father, std::string name);
+ void create_links_for_node(ClusterCreationArgs* cluster, int id, int rank, int position) override;
void getLocalRoute(NetPoint* src, NetPoint* dst, sg_platf_route_cbarg_t into, double* latency) override;
- void parse_specific_arguments(sg_platf_cluster_cbarg_t cluster) override;
+ void parse_specific_arguments(ClusterCreationArgs* cluster) override;
private:
std::vector<unsigned int> dimensions_;
(np->isNetZone() ? "Netzone" : (np->isHost() ? "Host" : "Router")), np->cname(), np);
return &coords->coords;
}
-VivaldiZone::VivaldiZone(NetZone* father, const char* name) : ClusterZone(father, name)
+
+VivaldiZone::VivaldiZone(NetZone* father, std::string name) : ClusterZone(father, name)
{
}
}
/* Retrieve the private links */
- try {
- std::pair<surf::LinkImpl*, surf::LinkImpl*> info = privateLinks_.at(src->id());
+ auto src_link = privateLinks_.find(src->id());
+ if (src_link != privateLinks_.end()) {
+ std::pair<surf::LinkImpl*, surf::LinkImpl*> info = src_link->second;
if (info.first) {
route->link_list->push_back(info.first);
if (lat)
*lat += info.first->latency();
}
- } catch (std::out_of_range& unfound) {
+ } else {
XBT_DEBUG("Source of private link (%u) doesn't exist", src->id());
}
- try {
- std::pair<surf::LinkImpl*, surf::LinkImpl*> info = privateLinks_.at(dst->id());
+ auto dst_link = privateLinks_.find(dst->id());
+ if (dst_link != privateLinks_.end()) {
+ std::pair<surf::LinkImpl*, surf::LinkImpl*> info = dst_link->second;
if (info.second) {
route->link_list->push_back(info.second);
if (lat)
*lat += info.second->latency();
}
- } catch (std::out_of_range& unfound) {
+ } else {
XBT_DEBUG("Destination of private link (%u) doesn't exist", dst->id());
}
class XBT_PRIVATE VivaldiZone : public ClusterZone {
public:
- explicit VivaldiZone(NetZone* father, const char* name);
+ explicit VivaldiZone(NetZone* father, std::string name);
void setPeerLink(NetPoint* netpoint, double bw_in, double bw_out, std::string coord);
void getLocalRoute(NetPoint* src, NetPoint* dst, sg_platf_route_cbarg_t into, double* latency) override;
-/* Copyright (c) 2004-2015. The SimGrid Team.
- * All rights reserved. */
+/* Copyright (c) 2004-2017. 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. */
-/* Copyright (c) 2004-2015. The SimGrid Team.
- * All rights reserved. */
+/* Copyright (c) 2004-2015. 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. */
class Location {
private:
void* memory_;
- int register_id_;
+ int register_id_ = 0;
+
public:
explicit Location(void* x) : memory_(x) {}
explicit Location(int register_id) : memory_(nullptr), register_id_(register_id) {}
#if SIMGRID_HAVE_MC
xbt_assert(mc_model_checker == nullptr, "This must be called from the client");
#endif
-
- smx_actor_t process;
- unsigned int iter;
-
- while (not xbt_dynar_is_empty(simix_global->process_to_run)) {
+ while (not simix_global->process_to_run.empty()) {
SIMIX_process_runall();
- xbt_dynar_foreach(simix_global->process_that_ran, iter, process) {
+ for (smx_actor_t process : simix_global->process_that_ran) {
smx_simcall_t req = &process->simcall;
if (req->call != SIMCALL_NONE && not simgrid::mc::request_is_visible(req))
SIMIX_simcall_handle(req, 0);
if (msg_global==nullptr)
return;
- TRACE_surf_resource_utilization_release();
TRACE_end();
delete msg_global;
msg_global = nullptr;
"\t\tStorage Id: '%s'\n"
"\t\tStorage Type: '%s'\n"
"\t\tFile Descriptor Id: %d",
- fd->getPath(), fd->size(), fd->mount_point.c_str(), fd->storageId, fd->storage_type, fd->desc_id);
+ fd->getPath(), fd->size(), fd->mount_point.c_str(), fd->storageId.c_str(), fd->storage_type.c_str(),
+ fd->desc_id);
}
/** \ingroup msg_file
#include "msg_private.h"
#include "simgrid/s4u/Host.hpp"
#include "src/simix/ActorImpl.hpp"
+#include "src/simix/smx_private.h"
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(msg_process, msg, "Logging specific to MSG (process)");
/** @brief returns a list of all currently existing processes */
xbt_dynar_t MSG_processes_as_dynar() {
- return SIMIX_processes_as_dynar();
+ xbt_dynar_t res = xbt_dynar_new(sizeof(smx_actor_t), nullptr);
+ for (auto kv : simix_global->process_list) {
+ smx_actor_t actor = kv.second;
+ xbt_dynar_push(res, &actor);
+ }
+ return res;
}
/** @brief Return the current number MSG processes. */
*/
void MSG_vm_start(msg_vm_t vm)
{
- simgrid::simix::kernelImmediate([vm]() {
- simgrid::vm::VmHostExt::ensureVmExtInstalled();
-
- simgrid::s4u::Host* pm = vm->pimpl_vm_->getPm();
- if (pm->extension<simgrid::vm::VmHostExt>() == nullptr)
- pm->extension_set(new simgrid::vm::VmHostExt());
-
- long pm_ramsize = pm->extension<simgrid::vm::VmHostExt>()->ramsize;
- int pm_overcommit = pm->extension<simgrid::vm::VmHostExt>()->overcommit;
- long vm_ramsize = vm->getRamsize();
-
- if (pm_ramsize && not pm_overcommit) { /* Only verify that we don't overcommit on need */
- /* Retrieve the memory occupied by the VMs on that host. Yep, we have to traverse all VMs of all hosts for that */
- long total_ramsize_of_vms = 0;
- for (simgrid::s4u::VirtualMachine* ws_vm : simgrid::vm::VirtualMachineImpl::allVms_)
- if (pm == ws_vm->pimpl_vm_->getPm())
- total_ramsize_of_vms += ws_vm->pimpl_vm_->getRamsize();
-
- if (vm_ramsize > pm_ramsize - total_ramsize_of_vms) {
- XBT_WARN("cannnot start %s@%s due to memory shortage: vm_ramsize %ld, free %ld, pm_ramsize %ld (bytes).",
- vm->getCname(), pm->getCname(), vm_ramsize, pm_ramsize - total_ramsize_of_vms, pm_ramsize);
- THROWF(vm_error, 0, "Memory shortage on host '%s', VM '%s' cannot be started", pm->getCname(), vm->getCname());
- }
- }
-
- vm->pimpl_vm_->setState(SURF_VM_STATE_RUNNING);
- });
-
+ vm->start();
if (TRACE_msg_vm_is_enabled()) {
container_t vm_container = PJ_container_get(vm->getCname());
type_t type = PJ_type_get("MSG_VM_STATE", vm_container->type);
*/
void MSG_vm_shutdown(msg_vm_t vm)
{
- smx_actor_t issuer=SIMIX_process_self();
+ smx_actor_t issuer = SIMIX_process_self();
simgrid::simix::kernelImmediate([vm, issuer]() { vm->pimpl_vm_->shutdown(issuer); });
- // Make sure that the processes in the VM are killed in this scheduling round before processing
- // (eg with the VM destroy)
+ // Make sure that processes in the VM are killed in this scheduling round before processing (eg with the VM destroy)
MSG_process_sleep(0.);
}
-static inline char *get_mig_process_tx_name(msg_vm_t vm, msg_host_t src_pm, msg_host_t dst_pm)
+static std::string get_mig_process_tx_name(msg_vm_t vm, msg_host_t src_pm, msg_host_t dst_pm)
{
- return bprintf("__pr_mig_tx:%s(%s-%s)", vm->getCname(), src_pm->getCname(), dst_pm->getCname());
+ return std::string("__pr_mig_tx:") + vm->getCname() + "(" + src_pm->getCname() + "-" + dst_pm->getCname() + ")";
}
-static inline char *get_mig_process_rx_name(msg_vm_t vm, msg_host_t src_pm, msg_host_t dst_pm)
+static std::string get_mig_process_rx_name(msg_vm_t vm, msg_host_t src_pm, msg_host_t dst_pm)
{
- return bprintf("__pr_mig_rx:%s(%s-%s)", vm->getCname(), src_pm->getCname(), dst_pm->getCname());
+ return std::string("__pr_mig_rx:") + vm->getCname() + "(" + src_pm->getCname() + "-" + dst_pm->getCname() + ")";
}
-static inline char *get_mig_task_name(msg_vm_t vm, msg_host_t src_pm, msg_host_t dst_pm, int stage)
+static std::string get_mig_task_name(msg_vm_t vm, msg_host_t src_pm, msg_host_t dst_pm, int stage)
{
- return bprintf("__task_mig_stage%d:%s(%s-%s)", stage, vm->getCname(), src_pm->getCname(), dst_pm->getCname());
+ return std::string("__task_mig_stage") + std::to_string(stage) + ":" + vm->getCname() + "(" + src_pm->getCname() +
+ "-" + dst_pm->getCname() + ")";
}
struct migration_session {
bool received_finalize = false;
- char *finalize_task_name = get_mig_task_name(ms->vm, ms->src_pm, ms->dst_pm, 3);
+ std::string finalize_task_name = get_mig_task_name(ms->vm, ms->src_pm, ms->dst_pm, 3);
while (not received_finalize) {
msg_task_t task = nullptr;
int ret = MSG_task_recv(&task, ms->mbox);
if (ret != MSG_OK) {
// An error occurred, clean the code and return
// The owner did not change, hence the task should be only destroyed on the other side
- xbt_free(finalize_task_name);
return 0;
}
- if (strcmp(task->name, finalize_task_name) == 0)
+ if (finalize_task_name == task->name)
received_finalize = 1;
MSG_task_destroy(task);
}
- xbt_free(finalize_task_name);
// Here Stage 1, 2 and 3 have been performed.
// Hence complete the migration
}
// Inform the SRC that the migration has been correctly performed
- char *task_name = get_mig_task_name(ms->vm, ms->src_pm, ms->dst_pm, 4);
- msg_task_t task = MSG_task_create(task_name, 0, 0, nullptr);
+ std::string task_name = get_mig_task_name(ms->vm, ms->src_pm, ms->dst_pm, 4);
+ msg_task_t task = MSG_task_create(task_name.c_str(), 0, 0, nullptr);
msg_error_t ret = MSG_task_send(task, ms->mbox_ctl);
// xbt_assert(ret == MSG_OK);
if(ret == MSG_HOST_FAILURE){
// The SRC has crashed, this is not a problem has the VM has been correctly migrated on the DST node
MSG_task_destroy(task);
}
- xbt_free(task_name);
XBT_DEBUG("mig: rx_done");
return 0;
int stage, int stage2_round, double mig_speed, double timeout)
{
sg_size_t sent = 0;
- char *task_name = get_mig_task_name(vm, src_pm, dst_pm, stage);
- msg_task_t task = MSG_task_create(task_name, 0, static_cast<double>(size), nullptr);
+ std::string task_name = get_mig_task_name(vm, src_pm, dst_pm, stage);
+ msg_task_t task = MSG_task_create(task_name.c_str(), 0, static_cast<double>(size), nullptr);
double clock_sta = MSG_get_clock();
else
ret = MSG_task_send(task, mbox);
- xbt_free(task_name);
-
if (ret == MSG_OK) {
sent = size;
} else if (ret == MSG_TIMEOUT) {
ms->mbox_ctl = bprintf("__mbox_mig_ctl:%s(%s-%s)", vm->getCname(), src_pm->getCname(), dst_pm->getCname());
ms->mbox = bprintf("__mbox_mig_src_dst:%s(%s-%s)", vm->getCname(), src_pm->getCname(), dst_pm->getCname());
- char *pr_rx_name = get_mig_process_rx_name(vm, src_pm, dst_pm);
- char *pr_tx_name = get_mig_process_tx_name(vm, src_pm, dst_pm);
+ std::string pr_rx_name = get_mig_process_rx_name(vm, src_pm, dst_pm);
+ std::string pr_tx_name = get_mig_process_tx_name(vm, src_pm, dst_pm);
- char** argv = xbt_new(char*, 2);
- argv[0] = pr_rx_name;
- argv[1] = nullptr;
- MSG_process_create_with_arguments(pr_rx_name, migration_rx_fun, ms, dst_pm, 1, argv);
+ MSG_process_create(pr_rx_name.c_str(), migration_rx_fun, ms, dst_pm);
- argv = xbt_new(char*, 2);
- argv[0] = pr_tx_name;
- argv[1] = nullptr;
- MSG_process_create_with_arguments(pr_tx_name, migration_tx_fun, ms, src_pm, 1, argv);
+ MSG_process_create(pr_tx_name.c_str(), migration_tx_fun, ms, src_pm);
/* wait until the migration have finished or on error has occurred */
XBT_DEBUG("wait for reception of the final ACK (i.e. migration has been correctly performed");
vm->getCname());
}
- char* expected_task_name = get_mig_task_name(vm, src_pm, dst_pm, 4);
- xbt_assert(strcmp(task->name, expected_task_name) == 0);
- xbt_free(expected_task_name);
+ xbt_assert(get_mig_task_name(vm, src_pm, dst_pm, 4) == task->name);
MSG_task_destroy(task);
}
#include "src/instr/instr_private.h"
#include "src/plugins/vm/VirtualMachineImpl.hpp"
+#include "src/plugins/vm/VmHostExt.hpp"
#include "src/simix/smx_host_private.h"
#include "src/surf/cpu_cas01.hpp"
pimpl_netpoint = nullptr;
}
+void VirtualMachine::start()
+{
+ simgrid::simix::kernelImmediate([this]() {
+ simgrid::vm::VmHostExt::ensureVmExtInstalled();
+
+ simgrid::s4u::Host* pm = this->pimpl_vm_->getPm();
+ if (pm->extension<simgrid::vm::VmHostExt>() == nullptr)
+ pm->extension_set(new simgrid::vm::VmHostExt());
+
+ long pm_ramsize = pm->extension<simgrid::vm::VmHostExt>()->ramsize;
+ int pm_overcommit = pm->extension<simgrid::vm::VmHostExt>()->overcommit;
+ long vm_ramsize = this->getRamsize();
+
+ if (pm_ramsize && not pm_overcommit) { /* Only verify that we don't overcommit on need */
+ /* Retrieve the memory occupied by the VMs on that host. Yep, we have to traverse all VMs of all hosts for that */
+ long total_ramsize_of_vms = 0;
+ for (simgrid::s4u::VirtualMachine* ws_vm : simgrid::vm::VirtualMachineImpl::allVms_)
+ if (pm == ws_vm->pimpl_vm_->getPm())
+ total_ramsize_of_vms += ws_vm->pimpl_vm_->getRamsize();
+
+ if (vm_ramsize > pm_ramsize - total_ramsize_of_vms) {
+ XBT_WARN("cannnot start %s@%s due to memory shortage: vm_ramsize %ld, free %ld, pm_ramsize %ld (bytes).",
+ this->getCname(), pm->getCname(), vm_ramsize, pm_ramsize - total_ramsize_of_vms, pm_ramsize);
+ THROWF(vm_error, 0, "Memory shortage on host '%s', VM '%s' cannot be started", pm->getCname(),
+ this->getCname());
+ }
+ }
+
+ this->pimpl_vm_->setState(SURF_VM_STATE_RUNNING);
+ });
+}
+
bool VirtualMachine::isMigrating()
{
return pimpl_vm_ && pimpl_vm_->isMigrating;
/** @brief Sets the params of that VM/PM */
void VirtualMachine::setParameters(vm_params_t params)
{
- simgrid::simix::kernelImmediate([&]() { pimpl_vm_->setParams(params); });
+ simgrid::simix::kernelImmediate([this, params] { pimpl_vm_->setParams(params); });
}
} // namespace simgrid
{
smx_actor_t process = SIMIX_process_from_PID(pid);
if(process != nullptr) {
- simcall_process_kill(process);
+ simgrid::simix::kernelImmediate([process] { SIMIX_process_kill(process, process); });
} else {
std::ostringstream oss;
oss << "kill: ("<< pid <<") - No such process" << std::endl;
}
void Actor::kill() {
- simcall_process_kill(pimpl_);
+ smx_actor_t process = SIMIX_process_self();
+ simgrid::simix::kernelImmediate(
+ [this, process] { SIMIX_process_kill(pimpl_, (pimpl_ == simix_global->maestro_process) ? pimpl_ : process); });
}
// ***** Static functions *****
void kill()
{
- simcall_process_kill(SIMIX_process_self());
+ smx_actor_t process = SIMIX_process_self();
+ simgrid::simix::kernelImmediate([process] { SIMIX_process_kill(process, process); });
}
void onExit(int_f_pvoid_pvoid_t fun, void* data)
}
/** @brief Retrieve the netpoint of the given name (or nullptr if not found) */
-simgrid::kernel::routing::NetPoint* Engine::getNetpointByNameOrNull(const char* name)
+simgrid::kernel::routing::NetPoint* Engine::getNetpointByNameOrNull(std::string name)
{
- try {
- return pimpl->netpoints_.at(name);
- } catch (std::out_of_range& unfound) {
- return nullptr;
- }
+ auto netp = pimpl->netpoints_.find(name);
+ return netp == pimpl->netpoints_.end() ? nullptr : netp->second;
}
+
/** @brief Fill the provided vector with all existing netpoints */
void Engine::getNetpointList(std::vector<simgrid::kernel::routing::NetPoint*>* list)
{
namespace simgrid {
namespace s4u {
-File::File(const char* fullpath, void* userdata) : File(fullpath, Host::current(), userdata){};
+File::File(std::string fullpath, void* userdata) : File(fullpath, Host::current(), userdata){};
-File::File(const char* fullpath, sg_host_t host, void* userdata) : path_(fullpath), userdata_(userdata)
+File::File(std::string fullpath, sg_host_t host, void* userdata) : path_(fullpath), userdata_(userdata)
{
// this cannot fail because we get a xbt_die if the mountpoint does not exist
Storage* st = nullptr;
size_t longest_prefix_length = 0;
std::string path;
- XBT_DEBUG("Search for storage name for '%s' on '%s'", fullpath, host->getCname());
+ XBT_DEBUG("Search for storage name for '%s' on '%s'", fullpath.c_str(), host->getCname());
for (auto mnt : host->getMountedStorages()) {
XBT_DEBUG("See '%s'", mnt.first.c_str());
- mount_point = std::string(fullpath).substr(0, mnt.first.size());
+ mount_point = fullpath.substr(0, mnt.first.length());
if (mount_point == mnt.first && mnt.first.length() > longest_prefix_length) {
/* The current mount name is found in the full path and is bigger than the previous*/
}
}
if (longest_prefix_length > 0) { /* Mount point found, split fullpath into mount_name and path+filename*/
- mount_point = std::string(fullpath).substr(0, longest_prefix_length);
- path = std::string(fullpath).substr(longest_prefix_length, strlen(fullpath));
+ mount_point = fullpath.substr(0, longest_prefix_length);
+ path = fullpath.substr(longest_prefix_length, fullpath.length());
} else
- xbt_die("Can't find mount point for '%s' on '%s'", fullpath, host->getCname());
+ xbt_die("Can't find mount point for '%s' on '%s'", fullpath.c_str(), host->getCname());
pimpl_ =
simgrid::simix::kernelImmediate([this, st, path] { return new simgrid::surf::FileImpl(st, path, mount_point); });
return simgrid::simix::kernelImmediate([this] { return pimpl_->tell(); });
}
-void File::move(const char* fullpath)
+void File::move(std::string fullpath)
{
simgrid::simix::kernelImmediate([this, fullpath] { pimpl_->move(fullpath); });
}
}
Host* Host::by_name_or_null(std::string name)
{
- try {
- return host_list.at(name);
- } catch (std::out_of_range& unfound) {
- return nullptr;
- }
+ auto host = host_list.find(name);
+ return host == host_list.end() ? nullptr : host->second;
}
Host *Host::current(){
}
void Mailbox::setReceiver(ActorPtr actor) {
- simix::kernelImmediate([this, actor]() {
- this->pimpl_->setReceiver(actor);
- });
+ simix::kernelImmediate([this, actor]() { this->pimpl_->setReceiver(actor); });
}
/** @brief get the receiver (process associated to the mailbox) */
simgrid::xbt::signal<void(NetZone&)> NetZone::onCreation;
simgrid::xbt::signal<void(NetZone&)> NetZone::onSeal;
-NetZone::NetZone(NetZone* father, const char* name) : father_(father), name_(xbt_strdup(name))
+NetZone::NetZone(NetZone* father, std::string name) : father_(father), name_(name)
{
children_ = new std::vector<NetZone*>();
}
for (auto nz : *children_)
delete nz;
delete children_;
- xbt_free(name_);
}
std::unordered_map<std::string, std::string>* NetZone::getProperties()
{
return children_;
}
-char* NetZone::getCname()
+const char* NetZone::getCname()
{
- return name_;
+ return name_.c_str();
}
NetZone* NetZone::getFather()
{
void NetZone::addRoute(sg_platf_route_cbarg_t /*route*/)
{
- xbt_die("NetZone '%s' does not accept new routes (wrong class).", name_);
+ xbt_die("NetZone '%s' does not accept new routes (wrong class).", name_.c_str());
}
}
}; // namespace simgrid::s4u
return res;
}
-Storage* Storage::byName(const char* name)
+Storage* Storage::byName(std::string name)
{
surf::StorageImpl* res = surf::StorageImpl::byName(name);
if (res == nullptr)
-/* Copyright (c) 2009-2016. The SimGrid Team.
+/* Copyright (c) 2009-2017. The SimGrid Team.
* All rights reserved. */
/* This program is free software; you can redistribute it and/or modify it
#include "xbt/log.h"
#include "xbt/misc.h"
#include "xbt/str.h"
-#include <unordered_map>
+#include <map>
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(sd_daxparse, sd, "Parsing DAX files");
static YY_BUFFER_STATE input_buffer;
static xbt_dynar_t result;
-static std::unordered_map<std::string, SD_task_t> jobs;
-static xbt_dict_t files;
+static std::map<std::string, SD_task_t> jobs;
+static std::map<std::string, SD_task_t> files;
static SD_task_t current_job;
static SD_task_t root_task;
static SD_task_t end_task;
*/
xbt_dynar_t SD_daxload(const char *filename)
{
- xbt_dict_cursor_t cursor;
SD_task_t file;
- char* name;
FILE* in_file = fopen(filename, "r");
xbt_assert(in_file, "Unable to open \"%s\"\n", filename);
input_buffer = dax__create_buffer(in_file, 10);
dax_lineno = 1;
result = xbt_dynar_new(sizeof(SD_task_t), dax_task_free);
- files = xbt_dict_new_homogeneous(&dax_task_free);
root_task = SD_task_create_comp_seq("root", nullptr, 0);
/* by design the root task is always SCHEDULABLE */
SD_task_set_state(root_task, SD_SCHEDULABLE);
* Files not consumed in the system are said to be consumed by end task (bottom of DAG).
*/
- xbt_dict_foreach(files, cursor, name, file) {
+ for (auto elm : files) {
+ file = elm.second;
SD_task_t newfile;
if (file->predecessors->empty()) {
for (SD_task_t it : *file->successors) {
xbt_dynar_push(result, &end_task);
/* Free previous copy of the files */
- xbt_dict_free(&files);
+ for (auto elm : files)
+ SD_task_destroy(elm.second);
unsigned int cpt;
xbt_dynar_foreach(result, cpt, file) {
if (SD_task_get_kind(file) == SD_TASK_COMM_E2E) {
bool is_input = (A_dax__uses_link == A_dax__uses_link_input);
XBT_DEBUG("See <uses file=%s %s>",A_dax__uses_file,(is_input?"in":"out"));
- SD_task_t file = static_cast<SD_task_t>(xbt_dict_get_or_null(files, A_dax__uses_file));
- if (file == nullptr) {
+ auto it = files.find(A_dax__uses_file);
+ SD_task_t file;
+ if (it == files.end()) {
file = SD_task_create_comm_e2e(A_dax__uses_file, nullptr, size);
sd_global->initial_tasks->erase(file);
- xbt_dict_set(files, A_dax__uses_file, file, nullptr);
+ files[A_dax__uses_file] = file;
} else {
+ file = it->second;
if (file->amount < size || file->amount > size) {
XBT_WARN("Ignore file %s size redefinition from %.0f to %.0f", A_dax__uses_file, SD_task_get_amount(file), size);
}
static SD_task_t current_child;
void STag_dax__child()
{
- try {
- current_child = jobs.at(A_dax__child_ref);
- } catch (std::out_of_range& unfound) {
+ auto job = jobs.find(A_dax__child_ref);
+ if (job != jobs.end()) {
+ current_child = job->second;
+ } else {
throw std::out_of_range(std::string("Parse error on line ") + std::to_string(dax_lineno) +
": Asked to add dependencies to the non-existent " + A_dax__child_ref + "task");
}
void STag_dax__parent()
{
- try {
- SD_task_t parent = jobs.at(A_dax__parent_ref);
+ auto job = jobs.find(A_dax__parent_ref);
+ if (job != jobs.end()) {
+ SD_task_t parent = job->second;
SD_task_dependency_add(nullptr, nullptr, parent, current_child);
XBT_DEBUG("Control-flow dependency from %s to %s", current_child->name, parent->name);
- } catch (std::out_of_range& unfound) {
+ } else {
throw std::out_of_range(std::string("Parse error on line ") + std::to_string(dax_lineno) +
": Asked to add a dependency from " + current_child->name + " to " + A_dax__parent_ref +
", but " + A_dax__parent_ref + " does not exist");
if ((performer != -1 && order != -1) && performer < static_cast<int>(sg_host_count())) {
/* required parameters are given and less performers than hosts are required */
XBT_DEBUG ("Task '%s' is scheduled on workstation '%d' in position '%d'", task->name, performer, order);
- try {
- computer = computers.at(char_performer);
- } catch (std::out_of_range& unfound) {
+ auto comp = computers.find(char_performer);
+ if (comp != computers.end()) {
+ computer = comp->second;
+ } else {
computer = new std::vector<SD_task_t>;
computers.insert({char_performer, computer});
}
-/* Copyright (c) 2006-2015. The SimGrid Team.
+/* Copyright (c) 2006-2017. The SimGrid Team.
* All rights reserved. */
/* This program is free software; you can redistribute it and/or modify it
class Global {
public:
explicit Global();
+ Global(const Global&) = delete;
~Global();
bool watch_point_reached; /* has a task just reached a watch point? */
std::set<SD_task_t> *initial_tasks;
/* The parameters of network models */
- // real default for "network/sender-gap" is set in network_smpi.cpp:
- sg_sender_gap = NAN;
- simgrid::config::bindFlag(sg_sender_gap, {"network/sender-gap", "network/sender_gap"},
- "Minimum gap between two overlapping sends");
-
sg_latency_factor = 13.01; // comes from the default LV08 network model
simgrid::config::bindFlag(sg_latency_factor, {"network/latency-factor", "network/latency_factor"},
"Correction factor to apply to the provided latency (default value set by network model)");
xbt_os_mutex_acquire(simix_global->mutex);
/* cancel non-blocking communications */
- smx_activity_t synchro = process->comms.front();
while (not process->comms.empty()) {
+ smx_activity_t synchro = process->comms.front();
+ process->comms.pop_front();
simgrid::kernel::activity::CommImplPtr comm =
boost::static_pointer_cast<simgrid::kernel::activity::CommImpl>(synchro);
} else {
xbt_die("Communication synchro %p is in my list but I'm not the sender nor the receiver", synchro.get());
}
- process->comms.pop_front();
- synchro = process->comms.front();
comm->cancel();
}
/* Now insert it in the global process list and in the process to run list */
simix_global->process_list[process->pid] = process;
XBT_DEBUG("Inserting %s(%s) in the to_run list", process->cname(), host->getCname());
- xbt_dynar_push_as(simix_global->process_to_run, smx_actor_t, process);
+ simix_global->process_to_run.push_back(process);
intrusive_ptr_add_ref(process);
/* Tracing the process creation */
/* Now insert it in the global process list and in the process to run list */
simix_global->process_list[process->pid] = process;
XBT_DEBUG("Inserting %s(%s) in the to_run list", process->cname(), host->getCname());
- xbt_dynar_push_as(simix_global->process_to_run, smx_actor_t, process);
+ simix_global->process_to_run.push_back(process);
/* Tracing the process creation */
TRACE_msg_process_create(process->cname(), process->pid, process->host);
{
SIMIX_context_runall();
- xbt_dynar_t tmp = simix_global->process_that_ran;
- simix_global->process_that_ran = simix_global->process_to_run;
- simix_global->process_to_run = tmp;
- xbt_dynar_reset(simix_global->process_to_run);
+ simix_global->process_to_run.swap(simix_global->process_that_ran);
+ simix_global->process_to_run.clear();
}
-void simcall_HANDLER_process_kill(smx_simcall_t simcall, smx_actor_t process) {
- SIMIX_process_kill(process, simcall->issuer);
-}
/**
* \brief Internal function to kill a SIMIX process.
*
process->waiting_synchro = nullptr;
}
- if (not xbt_dynar_member(simix_global->process_to_run, &(process)) && process != issuer) {
+ if (std::find(begin(simix_global->process_to_run), end(simix_global->process_to_run), process) ==
+ end(simix_global->process_to_run) &&
+ process != issuer) {
XBT_DEBUG("Inserting %s in the to_run list", process->name.c_str());
- xbt_dynar_push_as(simix_global->process_to_run, smx_actor_t, process);
+ simix_global->process_to_run.push_back(process);
}
}
boost::dynamic_pointer_cast<simgrid::kernel::activity::SleepImpl>(process->waiting_synchro);
if (sleep != nullptr) {
SIMIX_process_sleep_destroy(process->waiting_synchro);
- if (not xbt_dynar_member(simix_global->process_to_run, &(process)) && process != SIMIX_process_self()) {
+ if (std::find(begin(simix_global->process_to_run), end(simix_global->process_to_run), process) ==
+ end(simix_global->process_to_run) &&
+ process != SIMIX_process_self()) {
XBT_DEBUG("Inserting %s in the to_run list", process->name.c_str());
- xbt_dynar_push_as(simix_global->process_to_run, smx_actor_t, process);
+ simix_global->process_to_run.push_back(process);
}
}
}
/** @brief Returns the list of processes to run. */
-xbt_dynar_t SIMIX_process_get_runnable()
+const std::vector<smx_actor_t>& simgrid::simix::process_get_runnable()
{
return simix_global->process_to_run;
}
/** @brief Returns the process from PID. */
smx_actor_t SIMIX_process_from_PID(aid_t PID)
{
- try {
- return simix_global->process_list.at(PID);
- } catch (std::out_of_range& unfound) {
- return nullptr;
- }
-}
-
-/** @brief returns a dynar containing all currently existing processes */
-xbt_dynar_t SIMIX_processes_as_dynar() {
- xbt_dynar_t res = xbt_dynar_new(sizeof(smx_actor_t),nullptr);
- for (auto kv : simix_global->process_list) {
- smx_actor_t proc = kv.second;
- xbt_dynar_push(res,&proc);
- }
- return res;
+ auto process = simix_global->process_list.find(PID);
+ return process == simix_global->process_list.end() ? nullptr : process->second;
}
void SIMIX_process_on_exit_runall(smx_actor_t process) {
return (e_smx_state_t) simcall_BODY_execution_wait(execution);
}
-/**
- * \ingroup simix_process_management
- * \brief Kills a SIMIX process.
- *
- * This function simply kills a process.
- *
- * \param process poor victim
- */
-void simcall_process_kill(smx_actor_t process)
-{
- simcall_BODY_process_kill(process);
-}
-
/**
* \ingroup simix_process_management
* \brief Kills all SIMIX processes.
if (kill_time <= SIMIX_get_clock() || simix_global->kill_process_function == nullptr)
return;
XBT_DEBUG("Set kill time %f for process %s@%s", kill_time, process->cname(), process->host->getCname());
- process->kill_timer = SIMIX_timer_set(kill_time, [=] {
+ process->kill_timer = SIMIX_timer_set(kill_time, [process] {
simix_global->kill_process_function(process);
process->kill_timer=nullptr;
});
XBT_DEBUG("Answer simcall %s (%d) issued by %s (%p)", SIMIX_simcall_name(simcall->call), (int)simcall->call,
simcall->issuer->name.c_str(), simcall->issuer);
simcall->issuer->simcall.call = SIMCALL_NONE;
- xbt_assert(SIMIX_is_maestro(), "Ugh! This code path is reserved for maestro, but I'm '%s' on '%s'",
- SIMIX_process_self()->cname(), sg_host_get_name(SIMIX_process_self()->host));
/* This check should be useless and slows everyone. Reactivate if you see something weird in process scheduling. */
- // if (xbt_dynar_member(simix_global->process_to_run, &(simcall->issuer)))
+ // if (std::find(begin(simix_global->process_to_run), end(simix_global->process_to_run), simcall->issuer) !=
+ // end(simix_global->process_to_run))
// DIE_IMPOSSIBLE;
- xbt_dynar_push_as(simix_global->process_to_run, smx_actor_t, simcall->issuer);
+ simix_global->process_to_run.push_back(simcall->issuer);
}
}
*/
#include "src/simix/popping_private.h"
-static inline smx_actor_t simcall_process_kill__get__process(smx_simcall_t simcall)
-{
- return simgrid::simix::unmarshal<smx_actor_t>(simcall->args[0]);
-}
-static inline smx_actor_t simcall_process_kill__getraw__process(smx_simcall_t simcall)
-{
- return simgrid::simix::unmarshal_raw<smx_actor_t>(simcall->args[0]);
-}
-static inline void simcall_process_kill__set__process(smx_simcall_t simcall, smx_actor_t arg)
-{
- simgrid::simix::marshal<smx_actor_t>(simcall->args[0], arg);
-}
-
static inline int simcall_process_killall__get__reset_pid(smx_simcall_t simcall)
{
return simgrid::simix::unmarshal<int>(simcall->args[0]);
/* The prototype of all simcall handlers, automatically generated for you */
-XBT_PRIVATE void simcall_HANDLER_process_kill(smx_simcall_t simcall, smx_actor_t process);
XBT_PRIVATE void simcall_HANDLER_process_killall(smx_simcall_t simcall, int reset_pid);
XBT_PRIVATE void simcall_HANDLER_process_suspend(smx_simcall_t simcall, smx_actor_t process);
XBT_PRIVATE void simcall_HANDLER_process_join(smx_simcall_t simcall, smx_actor_t process, double timeout);
return simgrid::simix::unmarshal<R>(self->simcall.result);
}
-inline static void simcall_BODY_process_kill(smx_actor_t process) {
- /* Go to that function to follow the code flow through the simcall barrier */
- if (0) simcall_HANDLER_process_kill(&SIMIX_process_self()->simcall, process);
- return simcall<void, smx_actor_t>(SIMCALL_PROCESS_KILL, process);
- }
-
inline static void simcall_BODY_process_killall(int reset_pid) {
/* Go to that function to follow the code flow through the simcall barrier */
if (0) simcall_HANDLER_process_killall(&SIMIX_process_self()->simcall, reset_pid);
*/
typedef enum {
SIMCALL_NONE,
- SIMCALL_PROCESS_KILL,
SIMCALL_PROCESS_KILLALL,
SIMCALL_PROCESS_CLEANUP,
SIMCALL_PROCESS_SUSPEND,
/** @brief Simcalls' names (generated from src/simix/simcalls.in) */
const char* simcall_names[] = {
"SIMCALL_NONE",
- "SIMCALL_PROCESS_KILL",
"SIMCALL_PROCESS_KILLALL",
"SIMCALL_PROCESS_CLEANUP",
"SIMCALL_PROCESS_SUSPEND",
if (simcall->issuer->context->iwannadie && simcall->call != SIMCALL_PROCESS_CLEANUP)
return;
switch (simcall->call) {
-case SIMCALL_PROCESS_KILL:
- simcall_HANDLER_process_kill(simcall, simgrid::simix::unmarshal<smx_actor_t>(simcall->args[0]));
- SIMIX_simcall_answer(simcall);
- break;
-
case SIMCALL_PROCESS_KILLALL:
simcall_HANDLER_process_killall(simcall, simgrid::simix::unmarshal<int>(simcall->args[0]));
SIMIX_simcall_answer(simcall);
# Last but not the least, you should declare the new simix call in
# ./include/simgrid/simix.h (otherwise you will get a warning at compile time)
-void process_kill(smx_actor_t process);
void process_killall(int reset_pid);
void process_cleanup(smx_actor_t process) [[nohandler]];
void process_suspend(smx_actor_t process) [[block]];
#include <csignal> /* Signal handling */
#include <cstdlib>
+#include <xbt/algorithm.hpp>
#include <xbt/functional.hpp>
#include "simgrid/s4u/Engine.hpp"
simix_global = std::unique_ptr<simgrid::simix::Global>(new simgrid::simix::Global());
simgrid::simix::ActorImpl proc;
- simix_global->process_to_run = xbt_dynar_new(sizeof(smx_actor_t), nullptr);
- simix_global->process_that_ran = xbt_dynar_new(sizeof(smx_actor_t), nullptr);
simix_global->process_to_destroy = xbt_swag_new(xbt_swag_offset(proc, destroy_hookup));
simix_global->maestro_process = nullptr;
simix_global->create_process_function = &SIMIX_process_create;
smx_cleaned = 1;
XBT_DEBUG("SIMIX_clean called. Simulation's over.");
- if (not xbt_dynar_is_empty(simix_global->process_to_run) && SIMIX_get_clock() <= 0.0) {
+ if (not simix_global->process_to_run.empty() && SIMIX_get_clock() <= 0.0) {
XBT_CRITICAL(" ");
XBT_CRITICAL("The time is still 0, and you still have processes ready to run.");
XBT_CRITICAL("It seems that you forgot to run the simulation that you setup.");
xbt_heap_free(simix_timers);
simix_timers = nullptr;
/* Free the remaining data structures */
- xbt_dynar_free(&simix_global->process_to_run);
- xbt_dynar_free(&simix_global->process_that_ran);
+ simix_global->process_to_run.clear();
+ simix_global->process_that_ran.clear();
xbt_swag_free(simix_global->process_to_destroy);
simix_global->process_list.clear();
simix_global->process_to_destroy = nullptr;
}
}
-static int process_syscall_color(void *p)
-{
- switch ((*(smx_actor_t *)p)->simcall.call) {
- case SIMCALL_NONE:
- case SIMCALL_PROCESS_KILL:
- return 2;
- // case SIMCALL_PROCESS_RESUME:
- // return 1;
- default:
- return 0;
- }
-}
-
/** Wake up all processes waiting for a Surf action to finish */
static void SIMIX_wake_processes()
{
double time = 0;
do {
- XBT_DEBUG("New Schedule Round; size(queue)=%lu", xbt_dynar_length(simix_global->process_to_run));
+ XBT_DEBUG("New Schedule Round; size(queue)=%zu", simix_global->process_to_run.size());
SIMIX_execute_tasks();
- while (not xbt_dynar_is_empty(simix_global->process_to_run)) {
- XBT_DEBUG("New Sub-Schedule Round; size(queue)=%lu", xbt_dynar_length(simix_global->process_to_run));
+ while (not simix_global->process_to_run.empty()) {
+ XBT_DEBUG("New Sub-Schedule Round; size(queue)=%zu", simix_global->process_to_run.size());
/* Run all processes that are ready to run, possibly in parallel */
SIMIX_process_runall();
- /* Move all killer processes to the end of the list, because killing a process that have an ongoing simcall is a bad idea */
- xbt_dynar_three_way_partition(simix_global->process_that_ran, process_syscall_color);
-
/* answer sequentially and in a fixed arbitrary order all the simcalls that were issued during that sub-round */
/* WARNING, the order *must* be fixed or you'll jeopardize the simulation reproducibility (see RR-7653) */
* That would thus be a pure waste of time.
*/
- unsigned int iter;
- smx_actor_t process;
- xbt_dynar_foreach(simix_global->process_that_ran, iter, process) {
+ for (smx_actor_t process : simix_global->process_that_ran) {
if (process->simcall.call != SIMCALL_NONE) {
SIMIX_simcall_handle(&process->simcall, 0);
}
/* Clean processes to destroy */
SIMIX_process_empty_trash();
- XBT_DEBUG("### time %f, #processes %zu, #to_run %lu", time, simix_global->process_list.size(),
- xbt_dynar_length(simix_global->process_to_run));
+ XBT_DEBUG("### time %f, #processes %zu, #to_run %zu", time, simix_global->process_list.size(),
+ simix_global->process_to_run.size());
- if (xbt_dynar_is_empty(simix_global->process_to_run) && not simix_global->process_list.empty())
+ if (simix_global->process_to_run.empty() && not simix_global->process_list.empty())
simgrid::simix::onDeadlock();
- } while (time > -1.0 || not xbt_dynar_is_empty(simix_global->process_to_run));
+ } while (time > -1.0 || not simix_global->process_to_run.empty());
if (simix_global->process_list.size() != 0) {
#include <signal.h>
#include <map>
+#include <vector>
/********************************** Simix Global ******************************/
public:
smx_context_factory_t context_factory = nullptr;
- xbt_dynar_t process_to_run = nullptr;
- xbt_dynar_t process_that_ran = nullptr;
+ std::vector<smx_actor_t> process_to_run;
+ std::vector<smx_actor_t> process_that_ran;
std::map<aid_t, smx_actor_t> process_list;
#if SIMGRID_HAVE_MC
/* MCer cannot read the std::map above in the remote process, so we copy the info it needs in a dynar.
/* 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 "private.h"
#include "simgrid/s4u/Engine.hpp"
#include "simgrid/s4u/Host.hpp"
-#include "private.h"
#include "smpi_comm.hpp"
#include "smpi_datatype_derived.hpp"
#include "smpi_process.hpp"
#include "smpi_status.hpp"
+#include "src/simix/ActorImpl.hpp"
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_pmpi, smpi, "Logging specific to SMPI (pmpi)");
{
smpi_bench_end();
// FIXME: should kill all processes in comm instead
- simcall_process_kill(SIMIX_process_self());
+ smx_actor_t process = SIMIX_process_self();
+ simgrid::simix::kernelImmediate([process] { SIMIX_process_kill(process, process); });
return MPI_SUCCESS;
}
smpi_bench_end();
if (request == nullptr) {
- retval = MPI_ERR_ARG;
+ retval = MPI_ERR_ARG;
} else if (comm == MPI_COMM_NULL) {
- retval = MPI_ERR_COMM;
+ retval = MPI_ERR_COMM;
} else if (not datatype->is_valid()) {
retval = MPI_ERR_TYPE;
} else if (dst == MPI_PROC_NULL) {
- retval = MPI_SUCCESS;
+ retval = MPI_SUCCESS;
} else {
- *request = simgrid::smpi::Request::send_init(buf, count, datatype, dst, tag, comm);
- retval = MPI_SUCCESS;
+ *request = simgrid::smpi::Request::send_init(buf, count, datatype, dst, tag, comm);
+ retval = MPI_SUCCESS;
}
smpi_bench_begin();
if (retval != MPI_SUCCESS && request != nullptr)
return retval;
}
-int PMPI_Sendrecv(void *sendbuf, int sendcount, MPI_Datatype sendtype, int dst, int sendtag, void *recvbuf,
- int recvcount, MPI_Datatype recvtype, int src, int recvtag, MPI_Comm comm, MPI_Status * status)
+int PMPI_Sendrecv(void* sendbuf, int sendcount, MPI_Datatype sendtype, int dst, int sendtag, void* recvbuf,
+ int recvcount, MPI_Datatype recvtype, int src, int recvtag, MPI_Comm comm, MPI_Status* status)
{
int retval = 0;
retval = MPI_ERR_TAG;
} else {
- int rank = comm != MPI_COMM_NULL ? smpi_process()->index() : -1;
- int dst_traced = comm->group()->index(dst);
- int src_traced = comm->group()->index(src);
- instr_extra_data extra = xbt_new0(s_instr_extra_data_t,1);
- extra->type = TRACING_SENDRECV;
- extra->src = src_traced;
- extra->dst = dst_traced;
- int known=0;
- extra->datatype1 = encode_datatype(sendtype, &known);
- int dt_size_send = 1;
- if(known==0)
- dt_size_send = sendtype->size();
- extra->send_size = sendcount*dt_size_send;
- extra->datatype2 = encode_datatype(recvtype, &known);
- int dt_size_recv = 1;
- if(known==0)
- dt_size_recv = recvtype->size();
- extra->recv_size = recvcount*dt_size_recv;
-
- TRACE_smpi_ptp_in(rank, __FUNCTION__, extra);
- TRACE_smpi_send(rank, rank, dst_traced, sendtag,sendcount*sendtype->size());
-
- simgrid::smpi::Request::sendrecv(sendbuf, sendcount, sendtype, dst, sendtag, recvbuf, recvcount, recvtype, src, recvtag, comm,
- status);
- retval = MPI_SUCCESS;
-
- TRACE_smpi_ptp_out(rank, dst_traced, __FUNCTION__);
- TRACE_smpi_recv(src_traced, rank, recvtag);
+ int rank = comm != MPI_COMM_NULL ? smpi_process()->index() : -1;
+ int dst_traced = comm->group()->index(dst);
+ int src_traced = comm->group()->index(src);
+ instr_extra_data extra = xbt_new0(s_instr_extra_data_t, 1);
+ extra->type = TRACING_SENDRECV;
+ extra->src = src_traced;
+ extra->dst = dst_traced;
+ int known = 0;
+ extra->datatype1 = encode_datatype(sendtype, &known);
+ int dt_size_send = 1;
+ if (known == 0)
+ dt_size_send = sendtype->size();
+ extra->send_size = sendcount * dt_size_send;
+ extra->datatype2 = encode_datatype(recvtype, &known);
+ int dt_size_recv = 1;
+ if (known == 0)
+ dt_size_recv = recvtype->size();
+ extra->recv_size = recvcount * dt_size_recv;
+
+ TRACE_smpi_ptp_in(rank, __FUNCTION__, extra);
+ TRACE_smpi_send(rank, rank, dst_traced, sendtag, sendcount * sendtype->size());
+
+ simgrid::smpi::Request::sendrecv(sendbuf, sendcount, sendtype, dst, sendtag, recvbuf, recvcount, recvtype, src,
+ recvtag, comm, status);
+ retval = MPI_SUCCESS;
+
+ TRACE_smpi_ptp_out(rank, dst_traced, __FUNCTION__);
+ TRACE_smpi_recv(src_traced, rank, recvtag);
}
smpi_bench_begin();
void* recvbuf = xbt_new0(char, size);
retval = MPI_Sendrecv(buf, count, datatype, dst, sendtag, recvbuf, count, datatype, src, recvtag, comm, status);
if(retval==MPI_SUCCESS){
- simgrid::smpi::Datatype::copy(recvbuf, count, datatype, buf, count, datatype);
+ simgrid::smpi::Datatype::copy(recvbuf, count, datatype, buf, count, datatype);
}
xbt_free(recvbuf);
TRACE_smpi_ptp_out(rank, dst_traced, __FUNCTION__);
if (is_wait_for_receive) {
if(src_traced==MPI_ANY_SOURCE)
- src_traced = (status!=MPI_STATUS_IGNORE) ?
- comm->group()->rank(status->MPI_SOURCE) :
- src_traced;
+ src_traced = (status != MPI_STATUS_IGNORE) ? comm->group()->rank(status->MPI_SOURCE) : src_traced;
TRACE_smpi_recv(src_traced, dst_traced, tag_traced);
}
}
int is_wait_for_receive = savedvals[*index].recv;
if (is_wait_for_receive) {
if(savedvals[*index].src==MPI_ANY_SOURCE)
- src_traced = (status != MPI_STATUSES_IGNORE)
- ? savedvals[*index].comm->group()->rank(status->MPI_SOURCE)
- : savedvals[*index].src;
+ src_traced = (status != MPI_STATUSES_IGNORE) ? savedvals[*index].comm->group()->rank(status->MPI_SOURCE)
+ : savedvals[*index].src;
TRACE_smpi_recv(src_traced, dst_traced, savedvals[*index].tag);
}
TRACE_smpi_ptp_out(rank_traced, dst_traced, __FUNCTION__);
for (int i = 0; i < count; i++) {
if(savedvals[i].valid){
- //the src may not have been known at the beginning of the recv (MPI_ANY_SOURCE)
+ // the src may not have been known at the beginning of the recv (MPI_ANY_SOURCE)
int src_traced = savedvals[i].src;
int dst_traced = savedvals[i].dst;
int is_wait_for_receive = savedvals[i].recv;
if (is_wait_for_receive) {
if(src_traced==MPI_ANY_SOURCE)
- src_traced = (status!=MPI_STATUSES_IGNORE) ?
- savedvals[i].comm->group()->rank(status[i].MPI_SOURCE) : savedvals[i].src;
+ src_traced = (status != MPI_STATUSES_IGNORE) ? savedvals[i].comm->group()->rank(status[i].MPI_SOURCE)
+ : savedvals[i].src;
TRACE_smpi_recv(src_traced, dst_traced,savedvals[i].tag);
}
}
*flag=0;
return MPI_SUCCESS;
}
- try {
- *static_cast<void**>(attr_value) = attributes()->at(keyval);
+ const auto& attribs = attributes();
+ auto attr = attribs->find(keyval);
+ if (attr != attribs->end()) {
+ *static_cast<void**>(attr_value) = attr->second;
*flag=1;
- }
- catch (const std::out_of_range& oor) {
+ } else {
*flag=0;
}
return MPI_SUCCESS;
if (not attributes()->empty()) {
int flag=0;
for(auto it : attributes_){
- try{
- smpi_key_elem elem = T::keyvals_.at(it.first);
+ auto elm = T::keyvals_.find(it.first);
+ if (elm != T::keyvals_.end()) {
+ smpi_key_elem elem = elm->second;
if(elem != nullptr){
call_deleter<T>((T*)this, elem, it.first,it.second,&flag);
}
- }catch(const std::out_of_range& oor) {
+ } else {
//already deleted, not a problem;
flag=0;
}
#include <cctype>
#include <cstdarg>
#include <cwchar>
+#include <deque>
#include <simgrid/sg_config.h>
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(instr_smpi, instr, "Tracing SMPI");
-static xbt_dict_t keys;
+static std::unordered_map<char*, std::deque<std::string>*> keys;
static const char *smpi_colors[] ={
"recv", "1 0 0",
//get the dynar for src#dst
char aux[INSTR_DEFAULT_STR_SIZE];
snprintf(aux, INSTR_DEFAULT_STR_SIZE, "%d#%d#%d#%d", src, dst, tag, send);
- xbt_dynar_t d = static_cast<xbt_dynar_t>(xbt_dict_get_or_null(keys, aux));
+ auto it = keys.find(aux);
+ std::deque<std::string>* d;
- if (d == nullptr) {
- d = xbt_dynar_new(sizeof(char *), &xbt_free_ref);
- xbt_dict_set(keys, aux, d, nullptr);
- }
+ if (it == keys.end()) {
+ d = new std::deque<std::string>;
+ keys[aux] = d;
+ } else
+ d = it->second;
//generate the key
static unsigned long long counter = 0;
snprintf(key, n, "%d_%d_%d_%llu", src, dst, tag, counter);
//push it
- char *a = static_cast<char*> (xbt_strdup(key));
- xbt_dynar_push_as(d, char *, a);
+ d->push_back(key);
return key;
}
{
char aux[INSTR_DEFAULT_STR_SIZE];
snprintf(aux, INSTR_DEFAULT_STR_SIZE, "%d#%d#%d#%d", src, dst, tag, send==1?0:1);
- xbt_dynar_t d = static_cast<xbt_dynar_t>(xbt_dict_get_or_null(keys, aux));
-
- // first posted
- if(xbt_dynar_is_empty(d)){
- TRACE_smpi_put_key(src, dst, tag, key, n, send);
- return key;
+ auto it = keys.find(aux);
+ if (it == keys.end()) {
+ // first posted
+ TRACE_smpi_put_key(src, dst, tag, key, n, send);
+ } else {
+ snprintf(key, n, "%s", it->second->front().c_str());
+ it->second->pop_front();
}
-
- char *s = xbt_dynar_get_as (d, 0, char *);
- snprintf (key, n, "%s", s);
- xbt_dynar_remove_at (d, 0, nullptr);
return key;
}
-static xbt_dict_t process_category;
+static std::unordered_map<smx_actor_t, std::string> process_category;
static void cleanup_extra_data (instr_extra_data extra){
if(extra!=nullptr){
//declare category
TRACE_category (category);
- char processid[INSTR_DEFAULT_STR_SIZE];
- snprintf (processid, INSTR_DEFAULT_STR_SIZE, "%p", SIMIX_process_self());
- if (xbt_dict_get_or_null (process_category, processid))
- xbt_dict_remove (process_category, processid);
if (category != nullptr)
- xbt_dict_set (process_category, processid, xbt_strdup(category), nullptr);
+ process_category[SIMIX_process_self()] = category;
}
const char *TRACE_internal_smpi_get_category ()
if (not TRACE_smpi_is_enabled())
return nullptr;
- char processid[INSTR_DEFAULT_STR_SIZE];
- snprintf (processid, INSTR_DEFAULT_STR_SIZE, "%p", SIMIX_process_self());
- return static_cast<char*>(xbt_dict_get_or_null (process_category, processid));
+ auto it = process_category.find(SIMIX_process_self());
+ return (it == process_category.end()) ? nullptr : it->second.c_str();
}
void TRACE_smpi_alloc()
{
- keys = xbt_dict_new_homogeneous(xbt_dynar_free_voidp);
- process_category = xbt_dict_new_homogeneous(xbt_free_f);
+ // for symmetry
}
void TRACE_smpi_release()
{
- xbt_dict_free(&keys);
- xbt_dict_free(&process_category);
+ for (auto elm : keys)
+ delete elm.second;
}
void TRACE_smpi_init(int rank)
/* 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 "src/internal_config.h"
#include "private.h"
#include "private.hpp"
#include "simgrid/modelchecker.h"
-#include "src/mc/mc_replay.h"
-#include "smpi_process.hpp"
#include "smpi_comm.hpp"
+#include "smpi_process.hpp"
+#include "src/internal_config.h"
+#include "src/mc/mc_replay.h"
+#include <unordered_map>
#ifndef WIN32
#include <sys/mman.h>
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(smpi_bench, smpi, "Logging specific to SMPI (benchmarking)");
-
-xbt_dict_t samples = nullptr; /* Allocated on first use */
-
double smpi_cpu_threshold = -1;
double smpi_host_speed;
double smpi_total_benched_time = 0;
smpi_privatization_region_t smpi_privatization_regions;
-void smpi_bench_destroy()
-{
- xbt_dict_free(&samples);
-}
-
extern "C" XBT_PUBLIC(void) smpi_execute_flops_(double *flops);
void smpi_execute_flops_(double *flops)
{
int benching; /* 1: we are benchmarking; 0: we have enough data, no bench anymore */
} local_data_t;
-static char *sample_location(int global, const char *file, int line) {
+std::unordered_map<std::string, local_data_t*> samples; /* Allocated on first use */
+
+static std::string sample_location(int global, const char* file, int line)
+{
if (global) {
- return bprintf("%s:%d", file, line);
+ return std::string(file) + ":" + std::to_string(line);
} else {
- return bprintf("%s:%d:%d", file, line, smpi_process()->index());
+ return std::string(file) + ":" + std::to_string(line) + ":" + std::to_string(smpi_process()->index());
}
}
void smpi_sample_1(int global, const char *file, int line, int iters, double threshold)
{
- char *loc = sample_location(global, file, line);
+ std::string loc = sample_location(global, file, line);
smpi_bench_end(); /* Take time from previous, unrelated computation into account */
smpi_process()->set_sampling(1);
- if (samples==nullptr)
- samples = xbt_dict_new_homogeneous(free);
-
- local_data_t *data = static_cast<local_data_t *>(xbt_dict_get_or_null(samples, loc));
- if (data==nullptr) {
+ auto ld = samples.find(loc);
+ local_data_t* data;
+ if (ld == samples.end()) {
xbt_assert(threshold>0 || iters>0,
"You should provide either a positive amount of iterations to bench, or a positive maximal stderr (or both)");
- data = static_cast<local_data_t *>( xbt_new(local_data_t, 1));
+ data = static_cast<local_data_t*>(xbt_new(local_data_t, 1));
data->count = 0;
data->sum = 0.0;
data->sum_pow2 = 0.0;
data->threshold = threshold;
data->benching = 1; // If we have no data, we need at least one
data->mean = 0;
- xbt_dict_set(samples, loc, data, nullptr);
- XBT_DEBUG("XXXXX First time ever on benched nest %s.",loc);
+ samples[loc] = data;
+ XBT_DEBUG("XXXXX First time ever on benched nest %s.", loc.c_str());
} else {
+ data = ld->second;
if (data->iters != iters || data->threshold != threshold) {
XBT_ERROR("Asked to bench block %s with different settings %d, %f is not %d, %f. "
"How did you manage to give two numbers at the same line??",
- loc, data->iters, data->threshold, iters, threshold);
+ loc.c_str(), data->iters, data->threshold, iters, threshold);
THROW_IMPOSSIBLE;
}
// if we already have some data, check whether sample_2 should get one more bench or whether it should emulate
// the computation instead
data->benching = (sample_enough_benchs(data) == 0);
- XBT_DEBUG("XXXX Re-entering the benched nest %s. %s", loc,
+ XBT_DEBUG("XXXX Re-entering the benched nest %s. %s", loc.c_str(),
(data->benching ? "more benching needed" : "we have enough data, skip computes"));
}
- xbt_free(loc);
}
int smpi_sample_2(int global, const char *file, int line)
{
- char *loc = sample_location(global, file, line);
+ std::string loc = sample_location(global, file, line);
int res;
- xbt_assert(samples, "Y U NO use SMPI_SAMPLE_* macros? Stop messing directly with smpi_sample_* functions!");
- local_data_t *data = static_cast<local_data_t *>(xbt_dict_get(samples, loc));
- XBT_DEBUG("sample2 %s",loc);
- xbt_free(loc);
+ xbt_assert(not samples.empty(),
+ "Y U NO use SMPI_SAMPLE_* macros? Stop messing directly with smpi_sample_* functions!");
+ local_data_t* data = samples.at(loc);
+ XBT_DEBUG("sample2 %s", loc.c_str());
if (data->benching==1) {
// we need to run a new bench
void smpi_sample_3(int global, const char *file, int line)
{
- char *loc = sample_location(global, file, line);
+ std::string loc = sample_location(global, file, line);
- xbt_assert(samples, "Y U NO use SMPI_SAMPLE_* macros? Stop messing directly with smpi_sample_* functions!");
- local_data_t *data = static_cast<local_data_t *>(xbt_dict_get(samples, loc));
- XBT_DEBUG("sample3 %s",loc);
- xbt_free(loc);
+ xbt_assert(not samples.empty(),
+ "Y U NO use SMPI_SAMPLE_* macros? Stop messing directly with smpi_sample_* functions!");
+ local_data_t* data = samples.at(loc);
+ XBT_DEBUG("sample3 %s", loc.c_str());
if (data->benching==0)
THROW_IMPOSSIBLE;
}
extern "C" { /** These functions will be called from the user code **/
- smpi_trace_call_location_t* smpi_trace_get_call_location() {
- return smpi_process()->call_location();
- }
+smpi_trace_call_location_t* smpi_trace_get_call_location()
+{
+ return smpi_process()->call_location();
+}
- void smpi_trace_set_call_location(const char* file, const int line) {
- smpi_trace_call_location_t* loc = smpi_process()->call_location();
+void smpi_trace_set_call_location(const char* file, const int line)
+{
+ smpi_trace_call_location_t* loc = smpi_process()->call_location();
- loc->previous_filename = loc->filename;
- loc->previous_linenumber = loc->linenumber;
- loc->filename = file;
- loc->linenumber = line;
- }
+ loc->previous_filename = loc->filename;
+ loc->previous_linenumber = loc->linenumber;
+ loc->filename = file;
+ loc->linenumber = line;
+}
- /**
- * Required for Fortran bindings
- */
- void smpi_trace_set_call_location_(const char* file, int* line) {
- smpi_trace_set_call_location(file, *line);
- }
+/** Required for Fortran bindings */
+void smpi_trace_set_call_location_(const char* file, int* line)
+{
+ smpi_trace_set_call_location(file, *line);
+}
- /**
- * Required for Fortran if -fsecond-underscore is activated
- */
- void smpi_trace_set_call_location__(const char* file, int* line) {
- smpi_trace_set_call_location(file, *line);
- }
+/** Required for Fortran if -fsecond-underscore is activated */
+void smpi_trace_set_call_location__(const char* file, int* line)
+{
+ smpi_trace_set_call_location(file, *line);
+}
+}
+
+void smpi_bench_destroy()
+{
+ for (auto elm : samples)
+ xbt_free(elm.second);
}
std::fprintf(stderr, "{");
for (auto elt : vec) {
std::fprintf(stderr, "(0x%zx, 0x%zx),", elt.first, elt.second);
- }
- std::fprintf(stderr, "}\n");
+ }
+ std::fprintf(stderr, "}\n");
}
static void memcpy_private(void* dest, const void* src, std::vector<std::pair<size_t, size_t>>& private_blocks)
{
- for(auto block : private_blocks) {
+ for (auto block : private_blocks)
memcpy((uint8_t*)dest+block.first, (uint8_t*)src+block.first, block.second-block.first);
- }
}
static void check_blocks(std::vector<std::pair<size_t, size_t>> &private_blocks, size_t buff_size) {
- for(auto block : private_blocks) {
+ for (auto block : private_blocks)
xbt_assert(block.first <= block.second && block.second <= buff_size, "Oops, bug in shared malloc.");
- }
}
void smpi_comm_copy_buffer_callback(smx_activity_t synchro, void *buff, size_t buff_size)
//xbt_free(comm->comm.src_data);// inside SMPI the request is kept inside the user data and should be free
comm->src_buff = nullptr;
}
- if(tmpbuff!=buff)xbt_free(tmpbuff);
-
+ if (tmpbuff != buff)
+ xbt_free(tmpbuff);
}
void smpi_comm_null_copy_buffer_callback(smx_activity_t comm, void *buff, size_t buff_size)
std::string str = std::string(xbt_cfg_get_string("smpi/papi-events"));
Tokenizer tokens(str, separator_units);
- // Iterate over all the computational units. This could be
- // processes, hosts, threads, ranks... You name it. I'm not exactly
- // sure what we will support eventually, so I'll leave it at the
- // general term "units".
+ // Iterate over all the computational units. This could be processes, hosts, threads, ranks... You name it.
+ // I'm not exactly sure what we will support eventually, so I'll leave it at the general term "units".
for (auto& unit_it : tokens) {
boost::char_separator<char> separator_events(":");
Tokenizer event_tokens(unit_it, separator_events);
// Note that we need to remove the name of the unit
// (that could also be the "default" value), which always comes first.
// Hence, we start at ++(events.begin())!
- for (Tokenizer::iterator events_it = ++(event_tokens.begin()); events_it != event_tokens.end(); events_it++) {
+ for (Tokenizer::iterator events_it = ++(event_tokens.begin()); events_it != event_tokens.end(); ++events_it) {
int event_code = PAPI_NULL;
char* event_name = const_cast<char*>((*events_it).c_str());
int smpi_is_privatization_file(char* file)
{
- return strncmp("/dev/shm/my-buffer-", file, std::strlen("/dev/shm/my-buffer-")) == 0;
+ const std::string buffer_path {"/dev/shm/my-buffer-"};
+ return buffer_path.compare(file) == 0;
}
void smpi_initialize_global_memory_segments()
* Associated data and metadata are used as follows:
*
* mmap #1
- * `allocs' dict ---- -.
+ * `allocs' map ---- -.
* ---------- shared_data_t shared_metadata_t / | | |
* .->| <name> | ---> -------------------- <--. ----------------- | | | |
* | ---------- | fd of <name> | | | size of mmap | --| | | |
* `----------------- | <name> | | ----------------- ---- |
* -------------------- | ^ |
* | | |
- * | | `allocs_metadata' dict |
+ * | | `allocs_metadata' map |
* | | ---------------------- |
* | `-- | <addr of mmap #1> |<-'
* | .-- | <addr of mmap #2> |<-.
#include "private.h"
#include "private.hpp"
-#include "xbt/dict.h"
-#include "xbt/ex.hpp"
#include <cerrno>
#include <sys/types.h>
} shared_metadata_t;
std::map<void*, shared_metadata_t> allocs_metadata;
-xbt_dict_t calls = nullptr; /* Allocated on first use */
+std::map<std::string, void*> calls;
+
#ifndef WIN32
static int smpi_shared_malloc_bogusfile = -1;
static int smpi_shared_malloc_bogusfile_huge_page = -1;
{
allocs.clear();
allocs_metadata.clear();
- xbt_dict_free(&calls);
+ calls.clear();
}
static size_t shm_size(int fd) {
int smpi_shared_known_call(const char* func, const char* input)
{
- char* loc = bprintf("%s:%s", func, input);
- int known = 0;
-
- if (calls==nullptr) {
- calls = xbt_dict_new_homogeneous(nullptr);
- }
- try {
- xbt_dict_get(calls, loc); /* Succeed or throw */
- known = 1;
- xbt_free(loc);
- }
- catch (xbt_ex& ex) {
- xbt_free(loc);
- if (ex.category != not_found_error)
- throw;
- }
- catch(...) {
- xbt_free(loc);
- throw;
- }
- return known;
+ std::string loc = std::string(func) + ":" + input;
+ return calls.find(loc) != calls.end();
}
void* smpi_shared_get_call(const char* func, const char* input) {
- char* loc = bprintf("%s:%s", func, input);
+ std::string loc = std::string(func) + ":" + input;
- if (calls == nullptr)
- calls = xbt_dict_new_homogeneous(nullptr);
- void* data = xbt_dict_get(calls, loc);
- xbt_free(loc);
- return data;
+ return calls.at(loc);
}
void* smpi_shared_set_call(const char* func, const char* input, void* data) {
- char* loc = bprintf("%s:%s", func, input);
-
- if (calls == nullptr)
- calls = xbt_dict_new_homogeneous(nullptr);
- xbt_dict_set(calls, loc, data, nullptr);
- xbt_free(loc);
+ std::string loc = std::string(func) + ":" + input;
+ calls[loc] = data;
return data;
}
-
* E --> F
* G --> H
*/
- for (Tokenizer::iterator token_iter = tokens.begin(); token_iter != tokens.end(); token_iter++) {
+ for (Tokenizer::iterator token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter) {
XBT_DEBUG("token : %s", token_iter->c_str());
Tokenizer factor_values(*token_iter, factor_separator);
s_smpi_factor_t fact;
xbt_die("Malformed radical for smpi factor: '%s'", smpi_coef_string);
}
unsigned int iteration = 0;
- for (Tokenizer::iterator factor_iter = factor_values.begin(); factor_iter != factor_values.end(); factor_iter++) {
+ for (Tokenizer::iterator factor_iter = factor_values.begin(); factor_iter != factor_values.end(); ++factor_iter) {
iteration++;
if (factor_iter == factor_values.begin()) { /* first element */
return MPI_COMM_WORLD;
} else if(F2C::f2c_lookup() != nullptr && id >= 0) {
char key[KEY_SIZE];
- try {
- return static_cast<MPI_Comm>(F2C::f2c_lookup()->at(get_key_id(key, id)));
- } catch (std::out_of_range& unfound) {
- return MPI_COMM_NULL;
- }
+ const auto& lookup = F2C::f2c_lookup();
+ auto comm = lookup->find(get_key_id(key, id));
+ return comm == lookup->end() ? MPI_COMM_NULL : static_cast<MPI_Comm>(comm->second);
} else {
return MPI_COMM_NULL;
}
if(id >= 0){
char key[KEY_SIZE];
- try {
- return f2c_lookup_->at(get_key(key, id));
- } catch (std::out_of_range& unfound) {
- return nullptr;
- }
+ auto comm = f2c_lookup_->find(get_key(key, id));
+ return comm == f2c_lookup_->end() ? nullptr : comm->second;
}else
return nullptr;
}
{
if (this == MPI_GROUP_EMPTY)
return MPI_UNDEFINED;
- try {
- return index_to_rank_map_.at(index);
- } catch (std::out_of_range& unfound) {
- return MPI_UNDEFINED;
- }
+ auto rank = index_to_rank_map_.find(index);
+ return rank == index_to_rank_map_.end() ? MPI_UNDEFINED : rank->second;
}
void Group::ref()
int Info::get(char *key, int valuelen, char *value, int *flag){
*flag=false;
- try {
- std::string tmpvalue = map_.at(key);
+ auto val = map_.find(key);
+ if (val != map_.end()) {
+ std::string tmpvalue = val->second;
memset(value, 0, valuelen);
memcpy(value, tmpvalue.c_str(),
(tmpvalue.length() + 1 < static_cast<size_t>(valuelen)) ? tmpvalue.length() + 1 : valuelen);
*flag=true;
return MPI_SUCCESS;
- } catch (std::out_of_range& unfound) {
+ } else {
return MPI_ERR_INFO_KEY;
}
}
int Info::get_valuelen(char *key, int *valuelen, int *flag){
*flag=false;
- try {
- *valuelen = map_.at(key).length();
+ auto val = map_.find(key);
+ if (val != map_.end()) {
+ *valuelen = val->second.length();
*flag=true;
return MPI_SUCCESS;
- } catch (std::out_of_range& unfound) {
+ } else {
return MPI_ERR_INFO_KEY;
}
}
{
MPI_Request request = nullptr; /* MC needs the comm to be set to nullptr during the call */
if(op==MPI_OP_NULL){
- request = new Request(buf==MPI_BOTTOM ? nullptr : buf, count, datatype, src, dst, tag,
- comm, RMA | NON_PERSISTENT | RECV | PREPARED);
+ request = new Request(buf == MPI_BOTTOM ? nullptr : buf, count, datatype, src, dst, tag, comm,
+ RMA | NON_PERSISTENT | RECV | PREPARED);
}else{
- request = new Request(buf==MPI_BOTTOM ? nullptr : buf, count, datatype, src, dst, tag,
- comm, RMA | NON_PERSISTENT | RECV | PREPARED | ACCUMULATE);
+ request = new Request(buf == MPI_BOTTOM ? nullptr : buf, count, datatype, src, dst, tag, comm,
+ RMA | NON_PERSISTENT | RECV | PREPARED | ACCUMULATE);
request->op_ = op;
}
return request;
MPI_Request Request::irecv_init(void *buf, int count, MPI_Datatype datatype, int src, int tag, MPI_Comm comm)
{
- return new Request(buf==MPI_BOTTOM ? nullptr : buf, count, datatype, src == MPI_ANY_SOURCE ? MPI_ANY_SOURCE :
- comm->group()->index(src), smpi_process()->index(), tag,
- comm, PERSISTENT | RECV | PREPARED);
+ return new Request(buf == MPI_BOTTOM ? nullptr : buf, count, datatype,
+ src == MPI_ANY_SOURCE ? MPI_ANY_SOURCE : comm->group()->index(src), smpi_process()->index(), tag,
+ comm, PERSISTENT | RECV | PREPARED);
}
MPI_Request Request::isend(void *buf, int count, MPI_Datatype datatype, int dst, int tag, MPI_Comm comm)
{
MPI_Request request = nullptr; /* MC needs the comm to be set to nullptr during the call */
- request = new Request(buf==MPI_BOTTOM ? nullptr : buf, count, datatype, smpi_process()->index(),
- comm->group()->index(dst), tag, comm, NON_PERSISTENT | ISEND | SEND);
+ request = new Request(buf == MPI_BOTTOM ? nullptr : buf, count, datatype, smpi_process()->index(),
+ comm->group()->index(dst), tag, comm, NON_PERSISTENT | ISEND | SEND);
request->start();
return request;
}
MPI_Request Request::issend(void *buf, int count, MPI_Datatype datatype, int dst, int tag, MPI_Comm comm)
{
MPI_Request request = nullptr; /* MC needs the comm to be set to nullptr during the call */
- request = new Request(buf==MPI_BOTTOM ? nullptr : buf, count, datatype, smpi_process()->index(),
- comm->group()->index(dst), tag,comm, NON_PERSISTENT | ISEND | SSEND | SEND);
+ request = new Request(buf == MPI_BOTTOM ? nullptr : buf, count, datatype, smpi_process()->index(),
+ comm->group()->index(dst), tag, comm, NON_PERSISTENT | ISEND | SSEND | SEND);
request->start();
return request;
}
MPI_Request Request::irecv(void *buf, int count, MPI_Datatype datatype, int src, int tag, MPI_Comm comm)
{
MPI_Request request = nullptr; /* MC needs the comm to be set to nullptr during the call */
- request = new Request(buf==MPI_BOTTOM ? nullptr : buf, count, datatype, src == MPI_ANY_SOURCE ? MPI_ANY_SOURCE :
- comm->group()->index(src), smpi_process()->index(), tag, comm,
- NON_PERSISTENT | RECV);
+ request = new Request(buf == MPI_BOTTOM ? nullptr : buf, count, datatype,
+ src == MPI_ANY_SOURCE ? MPI_ANY_SOURCE : comm->group()->index(src), smpi_process()->index(),
+ tag, comm, NON_PERSISTENT | RECV);
request->start();
return request;
}
void Request::send(void *buf, int count, MPI_Datatype datatype, int dst, int tag, MPI_Comm comm)
{
MPI_Request request = nullptr; /* MC needs the comm to be set to nullptr during the call */
- request = new Request(buf==MPI_BOTTOM ? nullptr : buf, count, datatype, smpi_process()->index(),
- comm->group()->index(dst), tag, comm, NON_PERSISTENT | SEND);
+ request = new Request(buf == MPI_BOTTOM ? nullptr : buf, count, datatype, smpi_process()->index(),
+ comm->group()->index(dst), tag, comm, NON_PERSISTENT | SEND);
request->start();
wait(&request, MPI_STATUS_IGNORE);
void Request::ssend(void *buf, int count, MPI_Datatype datatype, int dst, int tag, MPI_Comm comm)
{
MPI_Request request = nullptr; /* MC needs the comm to be set to nullptr during the call */
- request = new Request(buf==MPI_BOTTOM ? nullptr : buf, count, datatype, smpi_process()->index(),
- comm->group()->index(dst), tag, comm, NON_PERSISTENT | SSEND | SEND);
+ request = new Request(buf == MPI_BOTTOM ? nullptr : buf, count, datatype, smpi_process()->index(),
+ comm->group()->index(dst), tag, comm, NON_PERSISTENT | SSEND | SEND);
request->start();
wait(&request,MPI_STATUS_IGNORE);
location_ = st->getImpl();
std::map<std::string, sg_size_t>* content = location_->getContent();
// if file does not exist create an empty file
- try {
- size_ = content->at(path);
- } catch (std::out_of_range& unfound) {
+ auto sz = content->find(path);
+ if (sz != content->end()) {
+ size_ = sz->second;
+ } else {
size_ = 0;
content->insert({path, size_});
XBT_DEBUG("File '%s' was not found, file created.", path.c_str());
}
}
-void FileImpl::move(const char* fullpath)
+void FileImpl::move(std::string fullpath)
{
/* Check if the new full path is on the same mount point */
- if (not strncmp(mount_point_.c_str(), fullpath, mount_point_.size())) {
+ if (not strncmp(mount_point_.c_str(), fullpath.c_str(), mount_point_.size())) {
std::map<std::string, sg_size_t>* content = location_->getContent();
- try { // src file exists
- sg_size_t new_size = content->at(path_);
+ auto sz = content->find(path_);
+ if (sz != content->end()) { // src file exists
+ sg_size_t new_size = sz->second;
content->erase(path_);
- std::string path = std::string(fullpath).substr(mount_point_.size(), strlen(fullpath));
+ std::string path = fullpath.substr(mount_point_.length(), fullpath.length());
content->insert({path.c_str(), new_size});
- XBT_DEBUG("Move file from %s to %s, size '%llu'", path_.c_str(), fullpath, new_size);
- } catch (std::out_of_range& unfound) {
+ XBT_DEBUG("Move file from %s to %s, size '%llu'", path_.c_str(), fullpath.c_str(), new_size);
+ } else {
XBT_WARN("File %s doesn't exist", path_.c_str());
}
} else {
- XBT_WARN("New full path %s is not on the same mount point: %s.", fullpath, mount_point_.c_str());
+ XBT_WARN("New full path %s is not on the same mount point: %s.", fullpath.c_str(), mount_point_.c_str());
}
}
}
sg_size_t tell() { return current_position_; }
int seek(sg_offset_t offset, int origin);
int unlink();
- void move(const char* fullpath);
+ void move(std::string fullpath);
Action* read(sg_size_t size);
Action* write(sg_size_t size);
-/* Copyright (c) 2015. The SimGrid Team. All rights reserved. */
+/* Copyright (c) 2015-2017. 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. */
const char *PropertyHolder::getProperty(const char*key) {
if (properties_ == nullptr)
return nullptr;
- try {
- return properties_->at(key).c_str();
- } catch (std::out_of_range& unfound) {
- return nullptr;
- }
+ auto prop = properties_->find(key);
+ return prop == properties_->end() ? nullptr : prop->second.c_str();
}
/** @brief Change the value of a given key in the property set */
std::unordered_map<std::string, StorageImpl*>* StorageImpl::storages =
new std::unordered_map<std::string, StorageImpl*>();
-StorageImpl* StorageImpl::byName(const char* name)
+StorageImpl* StorageImpl::byName(std::string name)
{
if (storages->find(name) == storages->end())
return nullptr;
std::map<std::string, sg_size_t>* parse_content = new std::map<std::string, sg_size_t>();
- std::ifstream* fs = surf_ifsopen(filename.c_str());
+ std::ifstream* fs = surf_ifsopen(filename);
std::string line;
std::vector<std::string> tokens;
/** @brief Public interface */
s4u::Storage piface_;
- static StorageImpl* byName(const char* name);
+ static StorageImpl* byName(std::string name);
/** @brief Check if the Storage is used (if an action currently uses its resources) */
bool isUsed() override;
/**
* @brief Get the content of the current Storage
*
- * @return A xbt_dict_t with path as keys and size in bytes as values
+ * @return A map with path as keys and size in bytes as values
*/
virtual std::map<std::string, sg_size_t>* getContent();
simgrid::xbt::signal<void(simgrid::surf::CpuAction*, Action::State)> CpuAction::onStateChange;
+void CpuAction::suspend(){
+ Action::State previous = getState();
+ onStateChange(this, previous);
+ Action::suspend();
+}
+
+void CpuAction::resume(){
+ Action::State previous = getState();
+ onStateChange(this, previous);
+ Action::resume();
+}
+
void CpuAction::setState(Action::State state){
Action::State previous = getState();
Action::setState(state);
void updateRemainingLazy(double now) override;
std::list<Cpu*> cpus();
+
+ void suspend() override;
+ void resume() override;
};
}
}
//register EDGE types for triva configuration
- xbt_dict_set (trivaEdgeTypes, link_type->name, xbt_strdup("1"), nullptr);
+ trivaEdgeTypes.insert(link_type->name);
//create the link
static long long counter = 0;
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(instr_surf, instr, "Tracing Surf");
-void TRACE_surf_alloc()
-{
- TRACE_surf_resource_utilization_alloc();
-}
-
-void TRACE_surf_release()
-{
- TRACE_surf_resource_utilization_release();
-}
-
void TRACE_surf_host_set_speed(double date, const char *resource, double speed)
{
if (TRACE_categorized() || TRACE_uncategorized() || TRACE_platform()) {
XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(surf_network);
-double sg_sender_gap = 0.0;
double sg_latency_factor = 1.0; /* default value; can be set by model or from command line */
double sg_bandwidth_factor = 1.0; /* default value; can be set by model or from command line */
double sg_weight_S_parameter = 0.0; /* default value; can be set by model or from command line */
action->latCurrent_ = action->latency_;
action->latency_ *= latencyFactor(size);
action->rate_ = bandwidthConstraint(action->rate_, bandwidth_bound, size);
- if (haveGap_) {
- xbt_assert(not route->empty(),
- "Using a model with a gap (e.g., SMPI) with a platform without links (e.g. vivaldi)!!!");
-
- gapAppend(size, route->at(0), action);
- XBT_DEBUG("Comm %p: %s -> %s gap=%f (lat=%f)", action, src->getCname(), dst->getCname(), action->senderGap_,
- action->latency_);
- }
int constraints_per_variable = route->size();
if (back_route != nullptr)
return action;
}
-void NetworkCm02Model::gapAppend(double size, const LinkImpl* link, NetworkAction* action){
- // Nothing
-};
-
/************
* Resource *
************/
lastValue_ = lmm_variable_getvalue(getVariable());
}
-void NetworkCm02Link::gapAppend(double size, const LinkImpl* link, NetworkAction* action){
- // Nothing
-};
}
}
void updateActionsStateLazy(double now, double delta) override;
void updateActionsStateFull(double now, double delta) override;
Action* communicate(s4u::Host* src, s4u::Host* dst, double size, double rate) override;
- virtual void gapAppend(double size, const LinkImpl* link, NetworkAction* action);
-
-protected:
- bool haveGap_ = false;
};
/************
void apply_event(tmgr_trace_event_t event, double value) override;
void setBandwidth(double value) override;
void setLatency(double value) override;
- virtual void gapAppend(double size, const LinkImpl* link, NetworkAction* action);
};
/**********
NetworkCm02Action(Model* model, double cost, bool failed) : NetworkAction(model, cost, failed){};
virtual ~NetworkCm02Action() = default;
void updateRemainingLazy(double now) override;
-
-protected:
- double senderGap_;
};
}
}
-/* Copyright (c) 2014-2015. The SimGrid Team.
+/* Copyright (c) 2014-2017. The SimGrid Team.
*All rights reserved. */
/* This program is free software; you can redistribute it and/or modify it
simgrid::surf::IBNode* act_src;
simgrid::surf::IBNode* act_dst;
- try {
- act_src = ibModel->active_nodes.at(src->getName());
- } catch (std::out_of_range& unfound) {
+ auto asrc = ibModel->active_nodes.find(src->getName());
+ if (asrc != ibModel->active_nodes.end()) {
+ act_src = asrc->second;
+ } else {
throw std::out_of_range(std::string("Could not find '") + src->getCname() + "' active comms !");
}
- try {
- act_dst = ibModel->active_nodes.at(dst->getName());
- } catch (std::out_of_range& unfound) {
+ auto adst = ibModel->active_nodes.find(dst->getName());
+ if (adst != ibModel->active_nodes.end()) {
+ act_dst = adst->second;
+ } else {
throw std::out_of_range(std::string("Could not find '") + dst->getCname() + "' active comms !");
}
NetworkIBModel::NetworkIBModel() : NetworkSmpiModel()
{
- haveGap_ = false;
const char* IB_factors_string = xbt_cfg_get_string("smpi/IB-penalty-factors");
std::vector<std::string> radical_elements;
boost::split(radical_elements, IB_factors_string, boost::is_any_of(";"));
-/* Copyright (c) 2013-2015. The SimGrid Team.
+/* Copyright (c) 2013-2017. The SimGrid Team.
* All rights reserved. */
/* This program is free software; you can redistribute it and/or modify it
/* List of links */
std::unordered_map<std::string, LinkImpl*>* LinkImpl::links = new std::unordered_map<std::string, LinkImpl*>();
- LinkImpl* LinkImpl::byName(const char* name)
+ LinkImpl* LinkImpl::byName(std::string name)
{
- try {
- return links->at(name);
- } catch (std::out_of_range& unfound) {
- return nullptr;
- }
+ auto link = links->find(name);
+ return link == links->end() ? nullptr : link->second;
}
/** @brief Returns the amount of links in the platform */
int LinkImpl::linksCount()
static std::unordered_map<std::string, LinkImpl*>* links;
public:
- static LinkImpl* byName(const char* name);
+ static LinkImpl* byName(std::string name);
static int linksCount();
static LinkImpl** linksList();
static void linksExit();
* Callbacks *
*************/
-static void clusterCreation_cb(sg_platf_cluster_cbarg_t cluster)
+static void clusterCreation_cb(ClusterCreationArgs* cluster)
{
for (int i : *cluster->radicals) {
// Routers don't create a router on the other end of the private link by themselves.
NetPointNs3* host_dst = new NetPointNs3();
// Create private link
- char* host_id = bprintf("%s%d%s", cluster->prefix, i, cluster->suffix);
- NetPointNs3* host_src = sg_host_by_name(host_id)->pimpl_netpoint->extension<NetPointNs3>();
- xbt_assert(host_src, "Cannot find a NS3 host of name %s", host_id);
+ std::string host_id = cluster->prefix + std::to_string(i) + cluster->suffix;
+ NetPointNs3* host_src = sg_host_by_name(host_id.c_str())->pimpl_netpoint->extension<NetPointNs3>();
+ xbt_assert(host_src, "Cannot find a NS3 host of name %s", host_id.c_str());
// Any NS3 route is symmetrical
ns3_add_link(host_src, host_dst, cluster->bw, cluster->lat);
delete host_dst;
- free(host_id);
}
//Create link backbone
- ns3_add_cluster(cluster->id, cluster->bb_bw, cluster->bb_lat);
+ ns3_add_cluster(cluster->id.c_str(), cluster->bb_bw, cluster->bb_lat);
}
static void routeCreation_cb(bool symmetrical, simgrid::kernel::routing::NetPoint* src,
-/* Copyright (c) 2013-2015. The SimGrid Team.
+/* Copyright (c) 2013-2017. The SimGrid Team.
* All rights reserved. */
/* This program is free software; you can redistribute it and/or modify it
std::vector<s_smpi_factor_t> smpi_bw_factor;
std::vector<s_smpi_factor_t> smpi_lat_factor;
-xbt_dict_t gap_lookup = nullptr;
-
/*********
* Model *
*********/
surf_network_model = new simgrid::surf::NetworkSmpiModel();
all_existing_models->push_back(surf_network_model);
- xbt_cfg_setdefault_double("network/sender-gap", 10e-6);
xbt_cfg_setdefault_double("network/weight-S", 8775);
}
namespace simgrid {
- namespace surf {
-
- NetworkSmpiModel::NetworkSmpiModel() : NetworkCm02Model()
- {
- haveGap_ = true;
- }
-
- NetworkSmpiModel::~NetworkSmpiModel()
- {
- xbt_dict_free(&gap_lookup);
- }
-
- double NetworkSmpiModel::bandwidthFactor(double size)
- {
- if (smpi_bw_factor.empty())
- smpi_bw_factor = parse_factor(xbt_cfg_get_string("smpi/bw-factor"));
-
- double current = 1.0;
- for (const auto& fact : smpi_bw_factor) {
- if (size <= fact.factor) {
- XBT_DEBUG("%f <= %zu return %f", size, fact.factor, current);
- return current;
- } else
- current = fact.values.front();
- }
- XBT_DEBUG("%f > %zu return %f", size, smpi_bw_factor.back().factor, current);
+namespace surf {
- return current;
- }
-
- double NetworkSmpiModel::latencyFactor(double size)
- {
- if (smpi_lat_factor.empty())
- smpi_lat_factor = parse_factor(xbt_cfg_get_string("smpi/lat-factor"));
-
- double current=1.0;
- for (const auto& fact : smpi_lat_factor) {
- if (size <= fact.factor) {
- XBT_DEBUG("%f <= %zu return %f", size, fact.factor, current);
- return current;
- }else
- current=fact.values.front();
- }
- XBT_DEBUG("%f > %zu return %f", size, smpi_lat_factor.back().factor, current);
+NetworkSmpiModel::NetworkSmpiModel() : NetworkCm02Model()
+{
+}
+
+NetworkSmpiModel::~NetworkSmpiModel() = default;
+double NetworkSmpiModel::bandwidthFactor(double size)
+{
+ if (smpi_bw_factor.empty())
+ smpi_bw_factor = parse_factor(xbt_cfg_get_string("smpi/bw-factor"));
+
+ double current = 1.0;
+ for (const auto& fact : smpi_bw_factor) {
+ if (size <= fact.factor) {
+ XBT_DEBUG("%f <= %zu return %f", size, fact.factor, current);
return current;
- }
+ } else
+ current = fact.values.front();
+ }
+ XBT_DEBUG("%f > %zu return %f", size, smpi_bw_factor.back().factor, current);
+
+ return current;
+}
- double NetworkSmpiModel::bandwidthConstraint(double rate, double bound, double size)
- {
- return rate < 0 ? bound : std::min(bound, rate * bandwidthFactor(size));
- }
+double NetworkSmpiModel::latencyFactor(double size)
+{
+ if (smpi_lat_factor.empty())
+ smpi_lat_factor = parse_factor(xbt_cfg_get_string("smpi/lat-factor"));
- /************
- * Resource *
- ************/
+ double current = 1.0;
+ for (const auto& fact : smpi_lat_factor) {
+ if (size <= fact.factor) {
+ XBT_DEBUG("%f <= %zu return %f", size, fact.factor, current);
+ return current;
+ } else
+ current = fact.values.front();
+ }
+ XBT_DEBUG("%f > %zu return %f", size, smpi_lat_factor.back().factor, current);
+ return current;
+}
+double NetworkSmpiModel::bandwidthConstraint(double rate, double bound, double size)
+{
+ return rate < 0 ? bound : std::min(bound, rate * bandwidthFactor(size));
+}
- /**********
- * Action *
- **********/
+/************
+ * Resource *
+ ************/
- }
+/**********
+ * Action *
+ **********/
+}
}
-/* Copyright (c) 2013-2015. The SimGrid Team.
+/* Copyright (c) 2013-2017. The SimGrid Team.
* All rights reserved. */
/* This program is free software; you can redistribute it and/or modify it
NetworkSmpiModel();
~NetworkSmpiModel();
- using NetworkCm02Model::gapAppend; // Explicit about overloaded method (silence Woverloaded-virtual from clang)
double latencyFactor(double size);
double bandwidthFactor(double size);
double bandwidthConstraint(double rate, double bound, double size);
namespace simgrid {
namespace surf {
-simgrid::xbt::signal<void(sg_platf_cluster_cbarg_t)> on_cluster;
-
+simgrid::xbt::signal<void(ClusterCreationArgs*)> on_cluster;
}
}
}
/** @brief Add a "router" to the network element list */
-simgrid::kernel::routing::NetPoint* sg_platf_new_router(const char* name, const char* coords)
+simgrid::kernel::routing::NetPoint* sg_platf_new_router(std::string name, const char* coords)
{
simgrid::kernel::routing::NetZoneImpl* current_routing = routing_get_current();
if (current_routing->hierarchy_ == simgrid::kernel::routing::NetZoneImpl::RoutingMode::unset)
current_routing->hierarchy_ = simgrid::kernel::routing::NetZoneImpl::RoutingMode::base;
xbt_assert(nullptr == simgrid::s4u::Engine::getInstance()->getNetpointByNameOrNull(name),
- "Refusing to create a router named '%s': this name already describes a node.", name);
+ "Refusing to create a router named '%s': this name already describes a node.", name.c_str());
simgrid::kernel::routing::NetPoint* netpoint =
new simgrid::kernel::routing::NetPoint(name, simgrid::kernel::routing::NetPoint::Type::Router, current_routing);
- XBT_DEBUG("Router '%s' has the id %u", name, netpoint->id());
+ XBT_DEBUG("Router '%s' has the id %u", name.c_str(), netpoint->id());
if (coords && strcmp(coords, ""))
new simgrid::kernel::routing::vivaldi::Coords(netpoint, coords);
}
}
-void sg_platf_new_cluster(sg_platf_cluster_cbarg_t cluster)
+void sg_platf_new_cluster(ClusterCreationArgs* cluster)
{
using simgrid::kernel::routing::ClusterZone;
using simgrid::kernel::routing::DragonflyZone;
int rankId=0;
// What an inventive way of initializing the AS that I have as ancestor :-(
- s_sg_platf_AS_cbarg_t AS;
- AS.id = cluster->id;
+ ZoneCreationArgs zone;
+ zone.id = cluster->id;
switch (cluster->topology) {
case SURF_CLUSTER_TORUS:
- AS.routing = A_surfxml_AS_routing_ClusterTorus;
+ zone.routing = A_surfxml_AS_routing_ClusterTorus;
break;
case SURF_CLUSTER_DRAGONFLY:
- AS.routing = A_surfxml_AS_routing_ClusterDragonfly;
+ zone.routing = A_surfxml_AS_routing_ClusterDragonfly;
break;
case SURF_CLUSTER_FAT_TREE:
- AS.routing = A_surfxml_AS_routing_ClusterFatTree;
+ zone.routing = A_surfxml_AS_routing_ClusterFatTree;
break;
default:
- AS.routing = A_surfxml_AS_routing_Cluster;
+ zone.routing = A_surfxml_AS_routing_Cluster;
break;
}
- sg_platf_new_AS_begin(&AS);
+ sg_platf_new_Zone_begin(&zone);
simgrid::kernel::routing::ClusterZone* current_as = static_cast<ClusterZone*>(routing_get_current());
current_as->parse_specific_arguments(cluster);
}
for (int i : *cluster->radicals) {
- char * host_id = bprintf("%s%d%s", cluster->prefix, i, cluster->suffix);
- char * link_id = bprintf("%s_link_%d", cluster->id, i);
+ std::string host_id = std::string(cluster->prefix) + std::to_string(i) + cluster->suffix;
+ std::string link_id = std::string(cluster->id) + "_link_" + std::to_string(i);
- XBT_DEBUG("<host\tid=\"%s\"\tpower=\"%f\">", host_id, cluster->speeds.front());
+ XBT_DEBUG("<host\tid=\"%s\"\tpower=\"%f\">", host_id.c_str(), cluster->speeds.front());
s_sg_platf_host_cbarg_t host;
memset(&host, 0, sizeof(host));
- host.id = host_id;
+ host.id = host_id.c_str();
if ((cluster->properties != nullptr) && (not cluster->properties->empty())) {
host.properties = new std::map<std::string, std::string>;
sg_platf_new_host(&host);
XBT_DEBUG("</host>");
- XBT_DEBUG("<link\tid=\"%s\"\tbw=\"%f\"\tlat=\"%f\"/>", link_id, cluster->bw, cluster->lat);
+ XBT_DEBUG("<link\tid=\"%s\"\tbw=\"%f\"\tlat=\"%f\"/>", link_id.c_str(), cluster->bw, cluster->lat);
// All links are saved in a matrix;
// every row describes a single node; every node may have multiple links.
simgrid::surf::LinkImpl* linkUp = nullptr;
simgrid::surf::LinkImpl* linkDown = nullptr;
if(cluster->loopback_bw > 0 || cluster->loopback_lat > 0){
- std::string tmp_link = std::string(link_id) + "_loopback";
+ std::string tmp_link = link_id + "_loopback";
XBT_DEBUG("<loopback\tid=\"%s\"\tbw=\"%f\"/>", tmp_link.c_str(), cluster->loopback_bw);
LinkCreationArgs link;
- link.id = tmp_link.c_str();
+ link.id = tmp_link;
link.bandwidth = cluster->loopback_bw;
link.latency = cluster->loopback_lat;
link.policy = SURF_LINK_FATPIPE;
sg_platf_new_link(&link);
- linkUp = simgrid::surf::LinkImpl::byName(tmp_link.c_str());
- linkDown = simgrid::surf::LinkImpl::byName(tmp_link.c_str());
+ linkUp = simgrid::surf::LinkImpl::byName(tmp_link);
+ linkDown = simgrid::surf::LinkImpl::byName(tmp_link);
auto as_cluster = static_cast<ClusterZone*>(current_as);
as_cluster->privateLinks_.insert({rankId * as_cluster->linkCountPerNode_, {linkUp, linkDown}});
XBT_DEBUG("<limiter\tid=\"%s\"\tbw=\"%f\"/>", tmp_link.c_str(), cluster->limiter_link);
LinkCreationArgs link;
- link.id = tmp_link.c_str();
+ link.id = tmp_link;
link.bandwidth = cluster->limiter_link;
link.latency = 0;
link.policy = SURF_LINK_SHARED;
sg_platf_new_link(&link);
- linkDown = simgrid::surf::LinkImpl::byName(tmp_link.c_str());
+ linkDown = simgrid::surf::LinkImpl::byName(tmp_link);
linkUp = linkDown;
current_as->privateLinks_.insert(
{rankId * current_as->linkCountPerNode_ + current_as->hasLoopback_, {linkUp, linkDown}});
current_as->create_links_for_node(cluster, i, rankId,
rankId*current_as->linkCountPerNode_ + current_as->hasLoopback_ + current_as->hasLimiter_ );
}
- xbt_free(link_id);
- xbt_free(host_id);
rankId++;
}
delete cluster->properties;
// Add a router.
XBT_DEBUG(" ");
- XBT_DEBUG("<router id=\"%s\"/>", cluster->router_id);
- if (not cluster->router_id || not strcmp(cluster->router_id, "")) {
- char* newid = bprintf("%s%s_router%s", cluster->prefix, cluster->id, cluster->suffix);
- current_as->router_ = sg_platf_new_router(newid, NULL);
- free(newid);
+ XBT_DEBUG("<router id=\"%s\"/>", cluster->router_id.c_str());
+ if (cluster->router_id.empty()) {
+ std::string newid = std::string(cluster->prefix) + cluster->id + "_router" + cluster->suffix;
+ current_as->router_ = sg_platf_new_router(newid.c_str(), NULL);
} else {
current_as->router_ = sg_platf_new_router(cluster->router_id, NULL);
}
XBT_DEBUG("<link\tid=\"%s\" bw=\"%f\" lat=\"%f\"/>", link.id.c_str(), cluster->bb_bw, cluster->bb_lat);
sg_platf_new_link(&link);
- routing_cluster_add_backbone(simgrid::surf::LinkImpl::byName(link.id.c_str()));
+ routing_cluster_add_backbone(simgrid::surf::LinkImpl::byName(link.id));
}
XBT_DEBUG("</AS>");
- sg_platf_new_AS_seal();
+ sg_platf_new_Zone_seal();
simgrid::surf::on_cluster(cluster);
delete cluster->radicals;
XBT_DEBUG("Add a backbone to AS '%s'", current_routing->getCname());
}
-void sg_platf_new_cabinet(sg_platf_cabinet_cbarg_t cabinet)
+void sg_platf_new_cabinet(CabinetCreationArgs* cabinet)
{
for (int radical : *cabinet->radicals) {
- std::string hostname = std::string(cabinet->prefix) + std::to_string(radical) + std::string(cabinet->suffix);
+ std::string hostname = cabinet->prefix + std::to_string(radical) + cabinet->suffix;
s_sg_platf_host_cbarg_t host;
memset(&host, 0, sizeof(host));
host.pstate = 0;
link.id = "link_" + hostname;
sg_platf_new_link(&link);
- s_sg_platf_host_link_cbarg_t host_link;
- memset(&host_link, 0, sizeof(host_link));
- std::string tmp_link_up = std::string("link_") + hostname + "_UP";
- std::string tmp_link_down = std::string("link_") + hostname + "_DOWN";
- host_link.id = hostname.c_str();
- host_link.link_up = tmp_link_up.c_str();
- host_link.link_down = tmp_link_down.c_str();
+ HostLinkCreationArgs host_link;
+ host_link.id = hostname;
+ host_link.link_up = std::string("link_") + hostname + "_UP";
+ host_link.link_down = std::string("link_") + hostname + "_DOWN";
sg_platf_new_hostlink(&host_link);
}
delete cabinet->radicals;
"Refusing to add a second storage named \"%s\"", storage->id.c_str());
simgrid::surf::StorageType* stype;
- try {
- stype = storage_types.at(storage->type_id);
- } catch (std::out_of_range& unfound) {
+ auto st = storage_types.find(storage->type_id);
+ if (st != storage_types.end()) {
+ stype = st->second;
+ } else {
xbt_die("No storage type '%s'", storage->type_id.c_str());
}
arg->data = nullptr;
arg->host = host;
arg->kill_time = kill_time;
- arg->properties = current_property_set;
+ arg->properties = process->properties;
host->extension<simgrid::simix::Host>()->boot_processes.push_back(arg);
arg->data = nullptr;
arg->host = host;
arg->kill_time = kill_time;
- arg->properties = current_property_set;
+ arg->properties = process->properties;
XBT_DEBUG("Process %s@%s will be started at time %f", arg->name.c_str(), arg->host->getCname(), start_time);
SIMIX_timer_set(start_time, [arg, auto_restart]() {
XBT_DEBUG("Starting Process %s(%s) right now", arg->name.c_str(), host->getCname());
smx_actor_t actor = simix_global->create_process_function(arg->name.c_str(), std::move(code), nullptr, host,
- current_property_set, nullptr);
+ arg->properties, nullptr);
/* The actor creation will fail if the host is currently dead, but that's fine */
if (actor != nullptr) {
}
/**
- * \brief Add an AS to the platform
+ * \brief Add a Zone to the platform
*
- * Add a new autonomous system to the platform. Any elements (such as host,
- * router or sub-AS) added after this call and before the corresponding call
- * to sg_platf_new_AS_seal() will be added to this AS.
+ * Add a new autonomous system to the platform. Any elements (such as host, router or sub-Zone) added after this call
+ * and before the corresponding call to sg_platf_new_Zone_seal() will be added to this Zone.
*
- * Once this function was called, the configuration concerning the used
- * models cannot be changed anymore.
+ * Once this function was called, the configuration concerning the used models cannot be changed anymore.
*
- * @param AS the parameters defining the AS to build.
+ * @param zone the parameters defining the Zone to build.
*/
-simgrid::s4u::NetZone* sg_platf_new_AS_begin(sg_platf_AS_cbarg_t AS)
+simgrid::s4u::NetZone* sg_platf_new_Zone_begin(ZoneCreationArgs* zone)
{
if (not surf_parse_models_setup_already_called) {
/* Initialize the surf models. That must be done after we got all config, and before we need the models.
* any further config now that we created some real content */
/* search the routing model */
- simgrid::kernel::routing::NetZoneImpl* new_as = nullptr;
- switch(AS->routing){
+ simgrid::kernel::routing::NetZoneImpl* new_zone = nullptr;
+ switch (zone->routing) {
case A_surfxml_AS_routing_Cluster:
- new_as = new simgrid::kernel::routing::ClusterZone(current_routing, AS->id);
+ new_zone = new simgrid::kernel::routing::ClusterZone(current_routing, zone->id);
break;
case A_surfxml_AS_routing_ClusterDragonfly:
- new_as = new simgrid::kernel::routing::DragonflyZone(current_routing, AS->id);
+ new_zone = new simgrid::kernel::routing::DragonflyZone(current_routing, zone->id);
break;
case A_surfxml_AS_routing_ClusterTorus:
- new_as = new simgrid::kernel::routing::TorusZone(current_routing, AS->id);
+ new_zone = new simgrid::kernel::routing::TorusZone(current_routing, zone->id);
break;
case A_surfxml_AS_routing_ClusterFatTree:
- new_as = new simgrid::kernel::routing::FatTreeZone(current_routing, AS->id);
+ new_zone = new simgrid::kernel::routing::FatTreeZone(current_routing, zone->id);
break;
case A_surfxml_AS_routing_Dijkstra:
- new_as = new simgrid::kernel::routing::DijkstraZone(current_routing, AS->id, 0);
+ new_zone = new simgrid::kernel::routing::DijkstraZone(current_routing, zone->id, 0);
break;
case A_surfxml_AS_routing_DijkstraCache:
- new_as = new simgrid::kernel::routing::DijkstraZone(current_routing, AS->id, 1);
+ new_zone = new simgrid::kernel::routing::DijkstraZone(current_routing, zone->id, 1);
break;
case A_surfxml_AS_routing_Floyd:
- new_as = new simgrid::kernel::routing::FloydZone(current_routing, AS->id);
+ new_zone = new simgrid::kernel::routing::FloydZone(current_routing, zone->id);
break;
case A_surfxml_AS_routing_Full:
- new_as = new simgrid::kernel::routing::FullZone(current_routing, AS->id);
+ new_zone = new simgrid::kernel::routing::FullZone(current_routing, zone->id);
break;
case A_surfxml_AS_routing_None:
- new_as = new simgrid::kernel::routing::EmptyZone(current_routing, AS->id);
+ new_zone = new simgrid::kernel::routing::EmptyZone(current_routing, zone->id);
break;
case A_surfxml_AS_routing_Vivaldi:
- new_as = new simgrid::kernel::routing::VivaldiZone(current_routing, AS->id);
+ new_zone = new simgrid::kernel::routing::VivaldiZone(current_routing, zone->id);
break;
default:
xbt_die("Not a valid model!");
if (current_routing == nullptr) { /* it is the first one */
xbt_assert(simgrid::s4u::Engine::getInstance()->pimpl->netRoot_ == nullptr,
"All defined components must belong to a networking zone.");
- simgrid::s4u::Engine::getInstance()->pimpl->netRoot_ = new_as;
+ simgrid::s4u::Engine::getInstance()->pimpl->netRoot_ = new_zone;
} else {
/* set the father behavior */
if (current_routing->hierarchy_ == simgrid::kernel::routing::NetZoneImpl::RoutingMode::unset)
current_routing->hierarchy_ = simgrid::kernel::routing::NetZoneImpl::RoutingMode::recursive;
/* add to the sons dictionary */
- current_routing->getChildren()->push_back(static_cast<simgrid::s4u::NetZone*>(new_as));
+ current_routing->getChildren()->push_back(static_cast<simgrid::s4u::NetZone*>(new_zone));
}
/* set the new current component of the tree */
- current_routing = new_as;
+ current_routing = new_zone;
- simgrid::s4u::NetZone::onCreation(*new_as); // notify the signal
+ simgrid::s4u::NetZone::onCreation(*new_zone); // notify the signal
- return new_as;
+ return new_zone;
}
/**
* Once you've declared all the content of your AS, you have to seal
* it with this call. Your AS is not usable until you call this function.
*/
-void sg_platf_new_AS_seal()
+void sg_platf_new_Zone_seal()
{
xbt_assert(current_routing, "Cannot seal the current AS: none under construction");
current_routing->seal();
}
/** @brief Add a link connecting an host to the rest of its AS (which must be cluster or vivaldi) */
-void sg_platf_new_hostlink(sg_platf_host_link_cbarg_t hostlink)
+void sg_platf_new_hostlink(HostLinkCreationArgs* hostlink)
{
- simgrid::kernel::routing::NetPoint* netpoint = sg_host_by_name(hostlink->id)->pimpl_netpoint;
- xbt_assert(netpoint, "Host '%s' not found!", hostlink->id);
+ simgrid::kernel::routing::NetPoint* netpoint = sg_host_by_name(hostlink->id.c_str())->pimpl_netpoint;
+ xbt_assert(netpoint, "Host '%s' not found!", hostlink->id.c_str());
xbt_assert(dynamic_cast<simgrid::kernel::routing::ClusterZone*>(current_routing),
"Only hosts from Cluster and Vivaldi ASes can get an host_link.");
simgrid::surf::LinkImpl* linkUp = simgrid::surf::LinkImpl::byName(hostlink->link_up);
simgrid::surf::LinkImpl* linkDown = simgrid::surf::LinkImpl::byName(hostlink->link_down);
- xbt_assert(linkUp, "Link '%s' not found!", hostlink->link_up);
- xbt_assert(linkDown, "Link '%s' not found!", hostlink->link_down);
+ xbt_assert(linkUp, "Link '%s' not found!", hostlink->link_up.c_str());
+ xbt_assert(linkDown, "Link '%s' not found!", hostlink->link_down.c_str());
auto as_cluster = static_cast<simgrid::kernel::routing::ClusterZone*>(current_routing);
if (as_cluster->privateLinks_.find(netpoint->id()) != as_cluster->privateLinks_.end())
- surf_parse_error("Host_link for '%s' is already defined!",hostlink->id);
+ surf_parse_error(std::string("Host_link for '") + hostlink->id.c_str() + "' is already defined!");
XBT_DEBUG("Push Host_link for host '%s' to position %u", netpoint->cname(), netpoint->id());
as_cluster->privateLinks_.insert({netpoint->id(), {linkUp, linkDown}});
}
-void sg_platf_new_trace(sg_platf_trace_cbarg_t trace)
+void sg_platf_new_trace(TraceCreationArgs* trace)
{
tmgr_trace_t tmgr_trace;
- if (trace->file && strcmp(trace->file, "") != 0) {
+ if (not trace->file.empty()) {
tmgr_trace = tmgr_trace_new_from_file(trace->file);
} else {
- xbt_assert(strcmp(trace->pc_data, ""),
- "Trace '%s' must have either a content, or point to a file on disk.",trace->id);
+ xbt_assert(not trace->pc_data.empty(), "Trace '%s' must have either a content, or point to a file on disk.",
+ trace->id.c_str());
tmgr_trace = tmgr_trace_new_from_string(trace->id, trace->pc_data, trace->periodicity);
}
traces_set_list.insert({trace->id, tmgr_trace});
for (auto s : *simgrid::surf::StorageImpl::storagesMap()) {
simgrid::kernel::routing::NetPoint* host_elm = sg_netpoint_by_name_or_null(s.second->getHost().c_str());
if (not host_elm)
- surf_parse_error("Unable to attach storage %s: host %s does not exist.", s.second->cname(),
- s.second->getHost().c_str());
+ surf_parse_error(std::string("Unable to attach storage ") + s.second->cname() + ": host " + s.second->getHost() +
+ " does not exist.");
else
s.second->piface_.attached_to_ = sg_host_by_name(s.second->getHost().c_str());
}
}
}
-#include <simgrid/plugins/energy.h> // FIXME: this plugin should not be linked to the core
-#include <simgrid/plugins/load.h> // FIXME: this plugin should not be linked to the core
+#include <simgrid/plugins/energy.h> // FIXME: this plug-in should not be linked to the core
+#include <simgrid/plugins/load.h> // FIXME: this plug-in should not be linked to the core
s_surf_model_description_t surf_plugin_description[] = {
{"Energy", "Cpu energy consumption.", &sg_host_energy_plugin_init},
{nullptr, nullptr, nullptr} /* this array must be nullptr terminated */
};
-#if HAVE_THREAD_CONTEXTS
-static xbt_parmap_t surf_parmap = nullptr; /* parallel map on models */
-#endif
-
double NOW = 0;
double surf_get_clock()
# define FILE_DELIM "/" /* FIXME: move to better location */
#endif
-std::ifstream* surf_ifsopen(const char* name)
+std::ifstream* surf_ifsopen(std::string name)
{
std::ifstream* fs = new std::ifstream();
- xbt_assert(name);
- if (__surf_is_absolute_file_path(name)) { /* don't mess with absolute file names */
- fs->open(name, std::ifstream::in);
+ xbt_assert(not name.empty());
+ if (__surf_is_absolute_file_path(name.c_str())) { /* don't mess with absolute file names */
+ fs->open(name.c_str(), std::ifstream::in);
}
/* search relative files in the path */
return fs;
}
+
FILE *surf_fopen(const char *name, const char *mode)
{
FILE *file = nullptr;
if (not future_evt_set)
future_evt_set = new simgrid::trace_mgr::future_evt_set();
- TRACE_surf_alloc();
- simgrid::surf::surfExitCallbacks.connect(TRACE_surf_release);
-
sg_config_init(argc, argv);
if (MC_is_active())
future_evt_set = nullptr;
}
-#if HAVE_THREAD_CONTEXTS
- xbt_parmap_destroy(surf_parmap);
-#endif
-
tmgr_finalize();
sg_platf_exit();
simgrid::s4u::Engine::shutdown();
-/* Copyright (c) 2004-2016. The SimGrid Team. All rights reserved. */
+/* Copyright (c) 2004-2017. 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. */
/* user-visible parameters */
extern XBT_PRIVATE double sg_tcp_gamma;
-extern XBT_PRIVATE double sg_sender_gap;
extern XBT_PRIVATE double sg_latency_factor;
extern XBT_PRIVATE double sg_bandwidth_factor;
extern XBT_PRIVATE double sg_weight_S_parameter;
*/
XBT_PUBLIC_DATA(std::vector<sg_host_t>) host_that_restart;
-
-extern XBT_PRIVATE double sg_sender_gap;
-
namespace simgrid {
namespace surf {
/* Generic functions common to all models */
XBT_PRIVATE FILE *surf_fopen(const char *name, const char *mode);
-XBT_PRIVATE std::ifstream* surf_ifsopen(const char* name);
+XBT_PRIVATE std::ifstream* surf_ifsopen(std::string name);
/* The __surf_is_absolute_file_path() returns 1 if
* file_path is a absolute file path, in the other
namespace tmgr = simgrid::trace_mgr;
-static std::unordered_map<const char*, tmgr::trace*> trace_list;
+static std::unordered_map<std::string, tmgr::trace*> trace_list;
static inline bool doubleEq(double d1, double d2)
{
}
}
-tmgr_trace_t tmgr_trace_new_from_string(const char* name, std::string input, double periodicity)
+tmgr_trace_t tmgr_trace_new_from_string(std::string name, std::string input, double periodicity)
{
int linecount = 0;
tmgr_trace_t trace = new simgrid::trace_mgr::trace();
tmgr::DatedValue* last_event = &(trace->event_list.back());
- xbt_assert(trace_list.find(name) == trace_list.end(), "Refusing to define trace %s twice", name);
+ xbt_assert(trace_list.find(name) == trace_list.end(), "Refusing to define trace %s twice", name.c_str());
std::vector<std::string> list;
boost::split(list, input, boost::is_any_of("\n\r"));
continue;
xbt_assert(sscanf(val.c_str(), "%lg %lg\n", &event.date_, &event.value_) == 2, "%s:%d: Syntax error in trace\n%s",
- name, linecount, input.c_str());
+ name.c_str(), linecount, input.c_str());
xbt_assert(last_event->date_ <= event.date_,
- "%s:%d: Invalid trace: Events must be sorted, but time %g > time %g.\n%s", name, linecount,
+ "%s:%d: Invalid trace: Events must be sorted, but time %g > time %g.\n%s", name.c_str(), linecount,
last_event->date_, event.date_, input.c_str());
last_event->date_ = event.date_ - last_event->date_;
}
}
- trace_list.insert({xbt_strdup(name), trace});
+ trace_list.insert({name, trace});
return trace;
}
-tmgr_trace_t tmgr_trace_new_from_file(const char *filename)
+tmgr_trace_t tmgr_trace_new_from_file(std::string filename)
{
- xbt_assert(filename && filename[0], "Cannot parse a trace from the null or empty filename");
- xbt_assert(trace_list.find(filename) == trace_list.end(), "Refusing to define trace %s twice", filename);
+ xbt_assert(not filename.empty(), "Cannot parse a trace from an empty filename");
+ xbt_assert(trace_list.find(filename) == trace_list.end(), "Refusing to define trace %s twice", filename.c_str());
std::ifstream* f = surf_ifsopen(filename);
- xbt_assert(not f->fail(), "Cannot open file '%s' (path=%s)", filename, (boost::join(surf_path, ":")).c_str());
+ xbt_assert(not f->fail(), "Cannot open file '%s' (path=%s)", filename.c_str(), (boost::join(surf_path, ":")).c_str());
std::stringstream buffer;
buffer << f->rdbuf();
void tmgr_finalize()
{
- for (auto kv : trace_list) {
- xbt_free((char*)kv.first);
+ for (auto kv : trace_list)
delete kv.second;
- }
trace_list.clear();
}
XBT_PUBLIC(void) tmgr_finalize();
-XBT_PUBLIC(tmgr_trace_t) tmgr_trace_new_from_file(const char* filename);
-XBT_PUBLIC(tmgr_trace_t) tmgr_trace_new_from_string(const char* id, std::string input, double periodicity);
+XBT_PUBLIC(tmgr_trace_t) tmgr_trace_new_from_file(std::string filename);
+XBT_PUBLIC(tmgr_trace_t) tmgr_trace_new_from_string(std::string id, std::string input, double periodicity);
SG_END_DECL()
/* 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 SURF_SURFXML_PARSE_H
-#define SURF_SURFXML_PARSE_H
+#ifndef SURF_SURFXML_PARSE_HPP
+#define SURF_SURFXML_PARSE_HPP
-#include <xbt/dict.h>
-#include <xbt/function_types.h>
-#include <xbt/misc.h>
#include <xbt/signal.hpp>
SG_BEGIN_DECL()
XBT_PUBLIC(void) surf_parse_open(const char *file);
XBT_PUBLIC(void) surf_parse_close();
-XBT_PUBLIC(void) surf_parse_assert(bool cond, const char *fmt, ...) XBT_ATTRIB_PRINTF(2,3);
-XBT_PUBLIC(void) XBT_ATTRIB_NORETURN surf_parse_error(const char *msg,...) XBT_ATTRIB_PRINTF(1,2);
-XBT_PUBLIC(void) surf_parse_assert_netpoint(char* hostname, const char* pre, const char* post);
-XBT_PUBLIC(void) surf_parse_warn(const char *msg,...) XBT_ATTRIB_PRINTF(1,2);
-
-XBT_PUBLIC(double) surf_parse_get_double(const char *string);
-XBT_PUBLIC(int) surf_parse_get_int(const char *string);
-XBT_PUBLIC(double) surf_parse_get_time(const char *string, const char *entity_kind, const char *name);
-XBT_PUBLIC(double) surf_parse_get_size(const char *string, const char *entity_kind, const char *name);
-XBT_PUBLIC(double) surf_parse_get_bandwidth(const char *string, const char *entity_kind, const char *name);
-XBT_PUBLIC(double) surf_parse_get_speed(const char *string, const char *entity_kind, const char *name);
+XBT_PUBLIC(void) surf_parse_assert(bool cond, std::string msg);
+XBT_PUBLIC(void) XBT_ATTRIB_NORETURN surf_parse_error(std::string msg);
+XBT_PUBLIC(void) surf_parse_assert_netpoint(std::string hostname, std::string pre, std::string post);
+XBT_PUBLIC(void) surf_parse_warn(std::string msg);
+
+XBT_PUBLIC(double) surf_parse_get_double(std::string s);
+XBT_PUBLIC(int) surf_parse_get_int(std::string s);
+XBT_PUBLIC(double) surf_parse_get_time(const char* string, const char* entity_kind, std::string name);
+XBT_PUBLIC(double) surf_parse_get_size(const char* string, const char* entity_kind, std::string name);
+XBT_PUBLIC(double) surf_parse_get_bandwidth(const char* string, const char* entity_kind, std::string name);
+XBT_PUBLIC(double) surf_parse_get_speed(const char* string, const char* entity_kind, std::string name);
XBT_PUBLIC(int) surf_parse(); /* Entry-point to the parser */
} s_sg_platf_host_cbarg_t;
typedef s_sg_platf_host_cbarg_t* sg_platf_host_cbarg_t;
-typedef struct {
- const char* id;
- const char* link_up;
- const char* link_down;
-} s_sg_platf_host_link_cbarg_t;
-typedef s_sg_platf_host_link_cbarg_t* sg_platf_host_link_cbarg_t;
+class HostLinkCreationArgs {
+public:
+ std::string id;
+ std::string link_up;
+ std::string link_down;
+};
class LinkCreationArgs {
public:
std::vector<simgrid::surf::LinkImpl*>* link_list;
} s_sg_platf_route_cbarg_t;
-typedef struct s_sg_platf_cluster_cbarg *sg_platf_cluster_cbarg_t;
-typedef struct s_sg_platf_cluster_cbarg {
- const char* id;
- const char* prefix;
- const char* suffix;
- std::vector<int>* radicals;
+class ClusterCreationArgs {
+public:
+ std::string id;
+ std::string prefix;
+ std::string suffix;
+ std::vector<int>* radicals = nullptr;
std::vector<double> speeds;
- int core_amount;
- double bw;
- double lat;
- double bb_bw;
- double bb_lat;
- double loopback_bw;
- double loopback_lat;
- double limiter_link;
+ int core_amount = 0;
+ double bw = 0;
+ double lat = 0;
+ double bb_bw = 0;
+ double bb_lat = 0;
+ double loopback_bw = 0;
+ double loopback_lat = 0;
+ double limiter_link = 0;
e_surf_cluster_topology_t topology;
- const char* topo_parameters;
+ std::string topo_parameters;
std::map<std::string, std::string>* properties;
- const char* router_id;
+ std::string router_id;
e_surf_link_sharing_policy_t sharing_policy;
e_surf_link_sharing_policy_t bb_sharing_policy;
-} s_sg_platf_cluster_cbarg_t;
+};
-typedef struct s_sg_platf_cabinet_cbarg* sg_platf_cabinet_cbarg_t;
-typedef struct s_sg_platf_cabinet_cbarg {
- const char* id;
- const char* prefix;
- const char* suffix;
+class CabinetCreationArgs {
+public:
+ std::string id;
+ std::string prefix;
+ std::string suffix;
std::vector<int>* radicals;
double speed;
double bw;
double lat;
-} s_sg_platf_cabinet_cbarg_t;
+};
class StorageCreationArgs {
public:
const char *value;
} s_sg_platf_prop_cbarg_t;
-typedef struct s_sg_platf_trace_cbarg *sg_platf_trace_cbarg_t;
-typedef struct s_sg_platf_trace_cbarg {
- const char *id;
- const char *file;
+class TraceCreationArgs {
+public:
+ std::string id;
+ std::string file;
double periodicity;
- const char *pc_data;
-} s_sg_platf_trace_cbarg_t;
+ std::string pc_data;
+};
-typedef struct s_sg_platf_trace_connect_cbarg *sg_platf_trace_connect_cbarg_t;
-typedef struct s_sg_platf_trace_connect_cbarg {
+class TraceConnectCreationArgs {
+public:
e_surf_trace_connect_kind_t kind;
- const char *trace;
- const char *element;
-} s_sg_platf_trace_connect_cbarg_t;
+ std::string trace;
+ std::string element;
+};
typedef struct s_sg_platf_process_cbarg *sg_platf_process_cbarg_t;
typedef struct s_sg_platf_process_cbarg {
e_surf_process_on_failure_t on_failure;
} s_sg_platf_process_cbarg_t;
-typedef struct s_sg_platf_AS_cbarg *sg_platf_AS_cbarg_t;
-typedef struct s_sg_platf_AS_cbarg {
- const char *id;
+class ZoneCreationArgs {
+public:
+ std::string id;
int routing;
-} s_sg_platf_AS_cbarg_t;
+};
-#define SG_PLATF_AS_INITIALIZER {nullptr,0}
/* The default current property receiver. Setup in the corresponding opening callbacks. */
extern std::map<std::string, std::string>* current_property_set;
XBT_PUBLIC(void) sg_platf_begin(); // Start a new platform
XBT_PUBLIC(void) sg_platf_end(); // Finish the creation of the platform
-XBT_PUBLIC(simgrid::s4u::NetZone*) sg_platf_new_AS_begin(sg_platf_AS_cbarg_t AS); // Begin description of new AS
-XBT_PUBLIC(void) sg_platf_new_AS_seal(); // That AS is fully described
+XBT_PUBLIC(simgrid::s4u::NetZone*) sg_platf_new_Zone_begin(ZoneCreationArgs* zone); // Begin description of new Zone
+XBT_PUBLIC(void) sg_platf_new_Zone_seal(); // That Zone is fully described
-XBT_PUBLIC(void) sg_platf_new_host (sg_platf_host_cbarg_t host); // Add an host to the currently described AS
-XBT_PUBLIC(void) sg_platf_new_hostlink(sg_platf_host_link_cbarg_t h); // Add an host_link to the currently described AS
-XBT_PUBLIC(simgrid::kernel::routing::NetPoint*)
-sg_platf_new_router(const char* name, const char* coords); // Add a router to the currently described AS
-XBT_PUBLIC(void) sg_platf_new_link(LinkCreationArgs* link); // Add a link to the currently described AS
-XBT_PUBLIC(void) sg_platf_new_peer(PeerCreationArgs* peer); // Add a peer to the currently described AS
-XBT_PUBLIC(void) sg_platf_new_cluster(sg_platf_cluster_cbarg_t clust); // Add a cluster to the currently described AS
-XBT_PUBLIC(void) sg_platf_new_cabinet(sg_platf_cabinet_cbarg_t cabinet); // Add a cabinet to the currently described AS
+XBT_PUBLIC(void) sg_platf_new_host(sg_platf_host_cbarg_t host); // Add a host to the current Zone
+XBT_PUBLIC(void) sg_platf_new_hostlink(HostLinkCreationArgs* h); // Add a host_link to the current Zone
+XBT_PUBLIC(void) sg_platf_new_link(LinkCreationArgs* link); // Add a link to the current Zone
+XBT_PUBLIC(void) sg_platf_new_peer(PeerCreationArgs* peer); // Add a peer to the current Zone
+XBT_PUBLIC(void) sg_platf_new_cluster(ClusterCreationArgs* clust); // Add a cluster to the current Zone
+XBT_PUBLIC(void) sg_platf_new_cabinet(CabinetCreationArgs* cabinet); // Add a cabinet to the current Zone
+XBT_PUBLIC(simgrid::kernel::routing::NetPoint*) // Add a router to the current Zone
+sg_platf_new_router(std::string, const char* coords);
XBT_PUBLIC(void) sg_platf_new_route (sg_platf_route_cbarg_t route); // Add a route
XBT_PUBLIC(void) sg_platf_new_bypassRoute (sg_platf_route_cbarg_t bypassroute); // Add a bypassRoute
-XBT_PUBLIC(void) sg_platf_new_trace(sg_platf_trace_cbarg_t trace);
+XBT_PUBLIC(void) sg_platf_new_trace(TraceCreationArgs* trace);
-XBT_PUBLIC(void) sg_platf_new_storage(StorageCreationArgs* storage); // Add a storage to the currently described AS
+XBT_PUBLIC(void) sg_platf_new_storage(StorageCreationArgs* storage); // Add a storage to the current Zone
XBT_PUBLIC(void) sg_platf_new_storage_type(StorageTypeCreationArgs* storage_type);
XBT_PUBLIC(void) sg_platf_new_mount(MountCreationArgs* mount);
XBT_PUBLIC(void) sg_platf_new_process(sg_platf_process_cbarg_t process);
-XBT_PRIVATE void sg_platf_trace_connect(sg_platf_trace_connect_cbarg_t trace_connect);
+XBT_PRIVATE void sg_platf_trace_connect(TraceConnectCreationArgs* trace_connect);
/* Prototypes of the functions offered by flex */
XBT_PUBLIC(int) surf_parse_lex();
namespace simgrid {
namespace surf {
-extern XBT_PRIVATE simgrid::xbt::signal<void(sg_platf_cluster_cbarg_t)> on_cluster;
-
+extern XBT_PRIVATE simgrid::xbt::signal<void(ClusterCreationArgs*)> on_cluster;
}
}
#include "src/instr/instr_private.h" // TRACE_start(). FIXME: remove by subscribing tracing to the surf signals
#include "src/surf/cpu_interface.hpp"
#include "src/surf/network_interface.hpp"
-#include "xbt/dict.h"
#include "xbt/log.h"
#include "xbt/misc.h"
#include "xbt/str.h"
XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(surf_parse);
-
/* Trace related stuff */
XBT_PRIVATE std::unordered_map<std::string, tmgr_trace_t> traces_set_list;
XBT_PRIVATE std::unordered_map<std::string, std::string> trace_connect_list_host_avail;
XBT_PRIVATE std::unordered_map<std::string, std::string> trace_connect_list_link_lat;
SG_BEGIN_DECL()
-void sg_platf_trace_connect(sg_platf_trace_connect_cbarg_t trace_connect)
+void sg_platf_trace_connect(TraceConnectCreationArgs* trace_connect)
{
xbt_assert(traces_set_list.find(trace_connect->trace) != traces_set_list.end(),
- "Cannot connect trace %s to %s: trace unknown", trace_connect->trace, trace_connect->element);
+ "Cannot connect trace %s to %s: trace unknown", trace_connect->trace.c_str(),
+ trace_connect->element.c_str());
switch (trace_connect->kind) {
case SURF_TRACE_CONNECT_KIND_HOST_AVAIL:
trace_connect_list_link_lat.insert({trace_connect->trace, trace_connect->element});
break;
default:
- surf_parse_error("Cannot connect trace %s to %s: kind of trace unknown", trace_connect->trace,
- trace_connect->element);
+ surf_parse_error(std::string("Cannot connect trace ") + trace_connect->trace + " to " + trace_connect->element +
+ ": unknown kind of trace");
break;
}
}
surf_parse_close();
if (parse_status)
- surf_parse_error("Parse error in %s", file);
+ surf_parse_error(std::string("Parse error in ") + file);
}
}
/*
* Helping functions
*/
-void surf_parse_assert(bool cond, const char *fmt, ...) {
+void surf_parse_assert(bool cond, std::string msg)
+{
if (not cond) {
- va_list va;
- va_start(va,fmt);
int lineno = surf_parse_lineno;
- char *msg = bvprintf(fmt,va);
- va_end(va);
cleanup();
- XBT_ERROR("Parse error at %s:%d: %s", surf_parsed_filename, lineno, msg);
+ XBT_ERROR("Parse error at %s:%d: %s", surf_parsed_filename, lineno, msg.c_str());
surf_exit();
xbt_die("Exiting now");
}
}
-void surf_parse_error(const char *fmt, ...) {
- va_list va;
- va_start(va,fmt);
+
+void surf_parse_error(std::string msg)
+{
int lineno = surf_parse_lineno;
- char *msg = bvprintf(fmt,va);
- va_end(va);
cleanup();
- XBT_ERROR("Parse error at %s:%d: %s", surf_parsed_filename, lineno, msg);
+ XBT_ERROR("Parse error at %s:%d: %s", surf_parsed_filename, lineno, msg.c_str());
surf_exit();
xbt_die("Exiting now");
}
-void surf_parse_assert_netpoint(char* hostname, const char* pre, const char* post)
+
+void surf_parse_assert_netpoint(std::string hostname, std::string pre, std::string post)
{
- if (sg_netpoint_by_name_or_null(hostname) != nullptr) // found
+ if (sg_netpoint_by_name_or_null(hostname.c_str()) != nullptr) // found
return;
- std::string msg = std::string(pre);
- msg += hostname;
- msg += post;
- msg += " Existing netpoints: \n";
+ std::string msg = pre + hostname + post + " Existing netpoints: \n";
std::vector<simgrid::kernel::routing::NetPoint*> list;
simgrid::s4u::Engine::getInstance()->getNetpointList(&list);
break;
}
}
- surf_parse_error("%s", msg.c_str());
+ surf_parse_error(msg);
}
-void surf_parse_warn(const char *fmt, ...) {
- va_list va;
- va_start(va,fmt);
- char *msg = bvprintf(fmt,va);
- va_end(va);
- XBT_WARN("%s:%d: %s", surf_parsed_filename, surf_parse_lineno, msg);
- free(msg);
+void surf_parse_warn(std::string msg)
+{
+ XBT_WARN("%s:%d: %s", surf_parsed_filename, surf_parse_lineno, msg.c_str());
}
-double surf_parse_get_double(const char *string) {
- double res;
- int ret = sscanf(string, "%lg", &res);
- if (ret != 1)
- surf_parse_error("%s is not a double", string);
- return res;
+double surf_parse_get_double(std::string s)
+{
+ try {
+ return std::stod(s);
+ } catch (std::invalid_argument& ia) {
+ surf_parse_error(s + " is not a double");
+ return -1;
+ }
}
-int surf_parse_get_int(const char *string) {
- int res;
- int ret = sscanf(string, "%d", &res);
- if (ret != 1)
- surf_parse_error("%s is not an integer", string);
- return res;
+int surf_parse_get_int(std::string s)
+{
+ try {
+ return std::stoi(s);
+ } catch (std::invalid_argument& ia) {
+ surf_parse_error(s + " is not a double");
+ return -1;
+ }
}
/* Turn something like "1-4,6,9-11" into the vector {1,2,3,4,6,9,10,11} */
-static std::vector<int>* explodesRadical(const char* radicals)
+static std::vector<int>* explodesRadical(std::string radicals)
{
std::vector<int>* exploded = new std::vector<int>();
for (auto group : radical_elements) {
std::vector<std::string> radical_ends;
boost::split(radical_ends, group, boost::is_any_of("-"));
- int start = surf_parse_get_int((radical_ends.front()).c_str());
- int end = 0;
+ int start = surf_parse_get_int(radical_ends.front());
+ int end = 0;
switch (radical_ends.size()) {
case 1:
end = start;
break;
case 2:
- end = surf_parse_get_int((radical_ends.back()).c_str());
+ end = surf_parse_get_int(radical_ends.back());
break;
default:
- surf_parse_error("Malformed radical: %s", group.c_str());
+ surf_parse_error(std::string("Malformed radical: ") + group);
break;
}
for (int i = start; i <= end; i++)
};
/* Note: field `unit' for the last element of parameter `units' should be nullptr. */
-static double surf_parse_get_value_with_unit(const char *string, const struct unit_scale *units,
- const char *entity_kind, const char *name, const char *error_msg, const char *default_unit)
+static double surf_parse_get_value_with_unit(const char* string, const struct unit_scale* units,
+ const char* entity_kind, std::string name, const char* error_msg,
+ const char* default_unit)
{
char* ptr;
int i;
errno = 0;
double res = strtod(string, &ptr);
if (errno == ERANGE)
- surf_parse_error("value out of range: %s", string);
+ surf_parse_error(std::string("value out of range: ") + string);
if (ptr == string)
- surf_parse_error("cannot parse number: %s", string);
+ surf_parse_error(std::string("cannot parse number:") + string);
if (ptr[0] == '\0') {
if (res == 0)
return res; // Ok, 0 can be unit-less
- XBT_WARN("Deprecated unit-less value '%s' for %s %s. %s",string, entity_kind, name, error_msg);
+ XBT_WARN("Deprecated unit-less value '%s' for %s %s. %s", string, entity_kind, name.c_str(), error_msg);
ptr = (char*)default_unit;
}
for (i = 0; units[i].unit != nullptr && strcmp(ptr, units[i].unit) != 0; i++);
if (units[i].unit != nullptr)
res *= units[i].scale;
else
- surf_parse_error("unknown unit: %s", ptr);
+ surf_parse_error(std::string("unknown unit: ") + ptr);
return res;
}
-double surf_parse_get_time(const char *string, const char *entity_kind, const char *name)
+double surf_parse_get_time(const char* string, const char* entity_kind, std::string name)
{
const struct unit_scale units[] = {
{ "w", 7 * 24 * 60 * 60 },
"Append 's' to your time to get seconds", "s");
}
-double surf_parse_get_size(const char *string, const char *entity_kind, const char *name)
+double surf_parse_get_size(const char* string, const char* entity_kind, std::string name)
{
const struct unit_scale units[] = {
{ "EiB", pow(1024, 6) },
"Append 'B' to get bytes (or 'b' for bits but 1B = 8b).", "B");
}
-double surf_parse_get_bandwidth(const char *string, const char *entity_kind, const char *name)
+double surf_parse_get_bandwidth(const char* string, const char* entity_kind, std::string name)
{
const struct unit_scale units[] = {
{ "EiBps", pow(1024, 6) },
"Append 'Bps' to get bytes per second (or 'bps' for bits but 1Bps = 8bps)", "Bps");
}
-double surf_parse_get_speed(const char *string, const char *entity_kind, const char *name)
+double surf_parse_get_speed(const char* string, const char* entity_kind, std::string name)
{
const struct unit_scale units[] = {
{ "yottaflops", 1e24 },
"Append 'f' or 'flops' to your speed to get flop per second", "f");
}
-static std::vector<double> surf_parse_get_all_speeds(char* speeds, const char* entity_kind, const char* id){
+static std::vector<double> surf_parse_get_all_speeds(char* speeds, const char* entity_kind, std::string id)
+{
std::vector<double> speed_per_pstate;
std::map<std::string, std::string>* current_model_property_set = nullptr;
int ZONE_TAG = 0; // Whether we just opened a zone tag (to see what to do with the properties)
-/* dictionary of random generator data */
-xbt_dict_t random_data_list = nullptr;
-
YY_BUFFER_STATE surf_input_buffer;
FILE *surf_file_to_parse = nullptr;
void STag_surfxml_host___link(){
XBT_DEBUG("Create a Host_link for %s",A_surfxml_host___link_id);
- s_sg_platf_host_link_cbarg_t host_link;
- memset(&host_link,0,sizeof(host_link));
+ HostLinkCreationArgs host_link;
host_link.id = A_surfxml_host___link_id;
host_link.link_up = A_surfxml_host___link_up;
}
void ETag_surfxml_cluster(){
- s_sg_platf_cluster_cbarg_t cluster;
- memset(&cluster,0,sizeof(cluster));
- cluster.properties = current_property_set;
+ ClusterCreationArgs cluster;
+ cluster.properties = current_property_set;
current_property_set = nullptr;
cluster.id = A_surfxml_cluster_id;
cluster.topology= SURF_CLUSTER_DRAGONFLY ;
break;
default:
- surf_parse_error("Invalid cluster topology for cluster %s",
- cluster.id);
+ surf_parse_error(std::string("Invalid cluster topology for cluster ") + cluster.id);
break;
}
cluster.topo_parameters = A_surfxml_cluster_topo___parameters;
cluster.sharing_policy = SURF_LINK_FATPIPE;
break;
default:
- surf_parse_error("Invalid cluster sharing policy for cluster %s", cluster.id);
+ surf_parse_error(std::string("Invalid cluster sharing policy for cluster ") + cluster.id);
break;
}
switch (AX_surfxml_cluster_bb___sharing___policy) {
cluster.bb_sharing_policy = SURF_LINK_SHARED;
break;
default:
- surf_parse_error("Invalid bb sharing policy in cluster %s", cluster.id);
+ surf_parse_error(std::string("Invalid bb sharing policy in cluster ") + cluster.id);
break;
}
void STag_surfxml_cabinet(){
parse_after_config();
- s_sg_platf_cabinet_cbarg_t cabinet;
- memset(&cabinet,0,sizeof(cabinet));
+ CabinetCreationArgs cabinet;
cabinet.id = A_surfxml_cabinet_id;
cabinet.prefix = A_surfxml_cabinet_prefix;
cabinet.suffix = A_surfxml_cabinet_suffix;
- cabinet.speed = surf_parse_get_speed(A_surfxml_cabinet_speed, "speed of cabinet", cabinet.id);
- cabinet.bw = surf_parse_get_bandwidth(A_surfxml_cabinet_bw, "bw of cabinet", cabinet.id);
- cabinet.lat = surf_parse_get_time(A_surfxml_cabinet_lat, "lat of cabinet", cabinet.id);
+ cabinet.speed = surf_parse_get_speed(A_surfxml_cabinet_speed, "speed of cabinet", cabinet.id.c_str());
+ cabinet.bw = surf_parse_get_bandwidth(A_surfxml_cabinet_bw, "bw of cabinet", cabinet.id.c_str());
+ cabinet.lat = surf_parse_get_time(A_surfxml_cabinet_lat, "lat of cabinet", cabinet.id.c_str());
cabinet.radicals = explodesRadical(A_surfxml_cabinet_radical);
sg_platf_new_cabinet(&cabinet);
link.policy = SURF_LINK_FULLDUPLEX;
break;
default:
- surf_parse_error("Invalid sharing policy in link %s", link.id.c_str());
+ surf_parse_error(std::string("Invalid sharing policy in link ") + link.id);
break;
}
sg_platf_new_link(&link);
}
-void STag_surfxml_link___ctn(){
-
+void STag_surfxml_link___ctn()
+{
simgrid::surf::LinkImpl* link = nullptr;
- char *link_name=nullptr;
switch (A_surfxml_link___ctn_direction) {
case AU_surfxml_link___ctn_direction:
case A_surfxml_link___ctn_direction_NONE:
link = simgrid::surf::LinkImpl::byName(A_surfxml_link___ctn_id);
break;
case A_surfxml_link___ctn_direction_UP:
- link_name = bprintf("%s_UP", A_surfxml_link___ctn_id);
- link = simgrid::surf::LinkImpl::byName(link_name);
+ link = simgrid::surf::LinkImpl::byName(std::string(A_surfxml_link___ctn_id) + "_UP");
break;
case A_surfxml_link___ctn_direction_DOWN:
- link_name = bprintf("%s_DOWN", A_surfxml_link___ctn_id);
- link = simgrid::surf::LinkImpl::byName(link_name);
+ link = simgrid::surf::LinkImpl::byName(std::string(A_surfxml_link___ctn_id) + "_DOWN");
break;
default:
- surf_parse_error("Invalid direction for link %s", link_name);
+ surf_parse_error(std::string("Invalid direction for link ") + A_surfxml_link___ctn_id);
break;
}
- xbt_free(link_name); // no-op if it's already nullptr
const char* dirname = "";
switch (A_surfxml_link___ctn_direction) {
default:
dirname = "";
}
- surf_parse_assert(link != nullptr, "No such link: '%s'%s", A_surfxml_link___ctn_id, dirname);
+ surf_parse_assert(link != nullptr, std::string("No such link: '") + A_surfxml_link___ctn_id + "'" + dirname);
parsed_link_list.push_back(link);
}
}
void ETag_surfxml_trace(){
- s_sg_platf_trace_cbarg_t trace;
- memset(&trace,0,sizeof(trace));
+ TraceCreationArgs trace;
trace.id = A_surfxml_trace_id;
trace.file = A_surfxml_trace_file;
void STag_surfxml_trace___connect()
{
parse_after_config();
- s_sg_platf_trace_connect_cbarg_t trace_connect;
- memset(&trace_connect,0,sizeof(trace_connect));
+ TraceConnectCreationArgs trace_connect;
trace_connect.element = A_surfxml_trace___connect_element;
trace_connect.trace = A_surfxml_trace___connect_trace;
{
parse_after_config();
ZONE_TAG = 1;
- s_sg_platf_AS_cbarg_t AS = {A_surfxml_zone_id, (int)A_surfxml_zone_routing};
+ ZoneCreationArgs zone;
+ zone.id = A_surfxml_zone_id;
+ zone.routing = static_cast<int>(A_surfxml_zone_routing);
- sg_platf_new_AS_begin(&AS);
+ sg_platf_new_Zone_begin(&zone);
}
void ETag_surfxml_zone()
{
- sg_platf_new_AS_seal();
+ sg_platf_new_Zone_seal();
}
void STag_surfxml_config()
{
ZONE_TAG = 0;
- xbt_assert(current_property_set == nullptr, "Someone forgot to reset the property set to nullptr in its closing tag (or XML malformed)");
+ xbt_assert(current_property_set == nullptr,
+ "Someone forgot to reset the property set to nullptr in its closing tag (or XML malformed)");
XBT_DEBUG("START configuration name = %s",A_surfxml_config_id);
if (_sg_cfg_init_status == 2) {
surf_parse_error("All <config> tags must be given before any platform elements (such as <zone>, <host>, <cluster>, "
AX_surfxml_actor_function = AX_surfxml_process_function;
STag_surfxml_actor();
}
+
void STag_surfxml_actor()
{
ZONE_TAG = 0;
AX_surfxml_actor_on___failure = (AT_surfxml_actor_on___failure)AX_surfxml_process_on___failure;
ETag_surfxml_actor();
}
+
void ETag_surfxml_actor()
{
s_sg_platf_process_cbarg_t actor;
if (not current_model_property_set)
current_model_property_set = new std::map<std::string, std::string>();
- current_model_property_set->insert(
- {std::string(A_surfxml_model___prop_id), std::string(A_surfxml_model___prop_value)});
+ current_model_property_set->insert({A_surfxml_model___prop_id, A_surfxml_model___prop_value});
}
void ETag_surfxml_prop(){/* Nothing to do */}
inline ConfigurationElement* Config::getDictElement(const char* name)
{
- try {
- return options.at(name);
- } catch (std::out_of_range& unfound) {
- try {
- ConfigurationElement* res = aliases.at(name);
+ auto opt = options.find(name);
+ if (opt != options.end()) {
+ return opt->second;
+ } else {
+ auto als = aliases.find(name);
+ if (als != aliases.end()) {
+ ConfigurationElement* res = als->second;
if (warn_for_aliases)
XBT_INFO("Option %s has been renamed to %s. Consider switching.", name, res->getKey().c_str());
return res;
- } catch (std::out_of_range& missing_key) {
+ } else {
throw simgrid::config::missing_key_error(std::string("Bad config key: ") + name);
}
}
/* a generic DYNamic ARray implementation. */
-/* Copyright (c) 2004-2015. The SimGrid Team.
+/* Copyright (c) 2004-2017. The SimGrid Team.
* All rights reserved. */
/* This program is free software; you can redistribute it and/or modify it
return dynar; // to enable functional uses
}
-/** @brief Sorts a dynar according to their color assuming elements can have only three colors.
- * Since there are only three colors, it is linear and much faster than a classical sort.
- * See for example http://en.wikipedia.org/wiki/Dutch_national_flag_problem
- *
- * \param dynar the dynar to sort
- * \param color the color function of type (int (compar_fn*) (void*) (void*)). The return value of color is assumed to
- * be 0, 1, or 2.
- *
- * At the end of the call, elements with color 0 are at the beginning of the dynar, elements with color 2 are at the
- * end and elements with color 1 are in the middle.
- *
- * Remark: if the elements stored in the dynar are structures, the color function has to retrieve the field to sort
- * first.
- */
-extern "C" void xbt_dynar_three_way_partition(xbt_dynar_t const dynar, int_f_pvoid_t color)
-{
- unsigned long int i;
- unsigned long int p = -1;
- unsigned long int q = dynar->used;
- const unsigned long elmsize = dynar->elmsize;
- char* tmp[elmsize];
- void *elm;
-
- for (i = 0; i < q;) {
- void *elmi = _xbt_dynar_elm(dynar, i);
- int colori = color(elmi);
-
- if (colori == 1) {
- ++i;
- } else {
- if (colori == 0) {
- ++p;
- elm = _xbt_dynar_elm(dynar, p);
- ++i;
- } else { /* colori == 2 */
- --q;
- elm = _xbt_dynar_elm(dynar, q);
- }
- if (elm != elmi) {
- memcpy(tmp, elm, elmsize);
- memcpy(elm, elmi, elmsize);
- memcpy(elmi, tmp, elmsize);
- }
- }
- }
-}
-
/** @brief Transform a dynar into a nullptr terminated array.
*
* \param dynar the dynar to transform
/* 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 <atomic>
-#include <climits>
-
-#include "src/internal_config.h"
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifndef _WIN32
-#include <sys/syscall.h>
-#endif
-
-#if HAVE_FUTEX_H
-#include <climits>
-#include <linux/futex.h>
-#endif
-
-#include "xbt/parmap.h"
#include "xbt/log.h"
-#include "xbt/function_types.h"
-#include "xbt/dynar.h"
-#include "xbt/xbt_os_thread.h"
-#include "xbt/sysdep.h"
-#include "src/simix/smx_private.h"
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_parmap, xbt, "parmap: parallel map");
-
-typedef enum {
- XBT_PARMAP_WORK,
- XBT_PARMAP_DESTROY
-} e_xbt_parmap_flag_t;
-
-static void xbt_parmap_set_mode(xbt_parmap_t parmap, e_xbt_parmap_mode_t mode);
-static void *xbt_parmap_worker_main(void *parmap);
-static void xbt_parmap_work(xbt_parmap_t parmap);
-
-static void xbt_parmap_posix_master_wait(xbt_parmap_t parmap);
-static void xbt_parmap_posix_worker_signal(xbt_parmap_t parmap);
-static void xbt_parmap_posix_master_signal(xbt_parmap_t parmap);
-static void xbt_parmap_posix_worker_wait(xbt_parmap_t parmap, unsigned round);
-
-#if HAVE_FUTEX_H
-static void xbt_parmap_futex_master_wait(xbt_parmap_t parmap);
-static void xbt_parmap_futex_worker_signal(xbt_parmap_t parmap);
-static void xbt_parmap_futex_master_signal(xbt_parmap_t parmap);
-static void xbt_parmap_futex_worker_wait(xbt_parmap_t parmap, unsigned round);
-static void futex_wait(unsigned *uaddr, unsigned val);
-static void futex_wake(unsigned *uaddr, unsigned val);
-#endif
-
-static void xbt_parmap_busy_master_wait(xbt_parmap_t parmap);
-static void xbt_parmap_busy_worker_signal(xbt_parmap_t parmap);
-static void xbt_parmap_busy_master_signal(xbt_parmap_t parmap);
-static void xbt_parmap_busy_worker_wait(xbt_parmap_t parmap, unsigned round);
-
-/**
- * \brief Parallel map structure
- */
-typedef struct s_xbt_parmap {
- e_xbt_parmap_flag_t status; /**< is the parmap active or being destroyed? */
- unsigned work; /**< index of the current round */
- unsigned thread_counter; /**< number of workers that have done the work */
-
- unsigned int num_workers; /**< total number of worker threads including the controller */
- xbt_os_thread_t *workers; /**< worker thread handlers */
- void_f_pvoid_t fun; /**< function to run in parallel on each element of data */
- xbt_dynar_t data; /**< parameters to pass to fun in parallel */
- std::atomic<unsigned int> index; /**< index of the next element of data to pick */
-
- /* posix only */
- xbt_os_cond_t ready_cond;
- xbt_os_mutex_t ready_mutex;
- xbt_os_cond_t done_cond;
- xbt_os_mutex_t done_mutex;
-
- /* fields that depend on the synchronization mode */
- e_xbt_parmap_mode_t mode; /**< synchronization mode */
- void (*master_wait_f)(xbt_parmap_t); /**< wait for the workers to have done the work */
- void (*worker_signal_f)(xbt_parmap_t); /**< signal the master that a worker has done the work */
- void (*master_signal_f)(xbt_parmap_t); /**< wakes the workers threads to process tasks */
- void (*worker_wait_f)(xbt_parmap_t, unsigned); /**< waits for more work */
-} s_xbt_parmap_t;
-
-/**
- * \brief Thread data transmission structure
- */
-typedef struct s_xbt_parmap_thread_data{
- xbt_parmap_t parmap;
- int worker_id;
-} s_xbt_parmap_thread_data_t;
-
-typedef s_xbt_parmap_thread_data_t *xbt_parmap_thread_data_t;
-
-/**
- * \brief Creates a parallel map object
- * \param num_workers number of worker threads to create
- * \param mode how to synchronize the worker threads
- * \return the parmap created
- */
-xbt_parmap_t xbt_parmap_new(unsigned int num_workers, e_xbt_parmap_mode_t mode)
-{
- XBT_DEBUG("Create new parmap (%u workers)", num_workers);
-
- /* Initialize the thread pool data structure */
- xbt_parmap_t parmap = new s_xbt_parmap_t();
- parmap->workers = xbt_new(xbt_os_thread_t, num_workers);
-
- parmap->num_workers = num_workers;
- parmap->status = XBT_PARMAP_WORK;
- xbt_parmap_set_mode(parmap, mode);
-
- /* Create the pool of worker threads */
- parmap->workers[0] = nullptr;
-#if HAVE_PTHREAD_SETAFFINITY
- int core_bind = 0;
-#endif
- for (unsigned int i = 1; i < num_workers; i++) {
- xbt_parmap_thread_data_t data = xbt_new0(s_xbt_parmap_thread_data_t, 1);
- data->parmap = parmap;
- data->worker_id = i;
- parmap->workers[i] = xbt_os_thread_create(nullptr, xbt_parmap_worker_main, data, nullptr);
-#if HAVE_PTHREAD_SETAFFINITY
- xbt_os_thread_bind(parmap->workers[i], core_bind);
- if (core_bind != xbt_os_get_numcores() - 1)
- core_bind++;
- else
- core_bind = 0;
-#endif
- }
- return parmap;
-}
-
-/**
- * \brief Destroys a parmap
- * \param parmap the parmap to destroy
- */
-void xbt_parmap_destroy(xbt_parmap_t parmap)
-{
- if (not parmap) {
- return;
- }
-
- parmap->status = XBT_PARMAP_DESTROY;
- parmap->master_signal_f(parmap);
-
- unsigned int i;
- for (i = 1; i < parmap->num_workers; i++)
- xbt_os_thread_join(parmap->workers[i], nullptr);
-
- xbt_os_cond_destroy(parmap->ready_cond);
- xbt_os_mutex_destroy(parmap->ready_mutex);
- xbt_os_cond_destroy(parmap->done_cond);
- xbt_os_mutex_destroy(parmap->done_mutex);
-
- xbt_free(parmap->workers);
- delete parmap;
-}
-
-/**
- * \brief Sets the synchronization mode of a parmap.
- * \param parmap a parallel map object
- * \param mode the synchronization mode
- */
-static void xbt_parmap_set_mode(xbt_parmap_t parmap, e_xbt_parmap_mode_t mode)
-{
- if (mode == XBT_PARMAP_DEFAULT) {
-#if HAVE_FUTEX_H
- mode = XBT_PARMAP_FUTEX;
-#else
- mode = XBT_PARMAP_POSIX;
-#endif
- }
- parmap->mode = mode;
-
- switch (mode) {
- case XBT_PARMAP_POSIX:
- parmap->master_wait_f = &xbt_parmap_posix_master_wait;
- parmap->worker_signal_f = &xbt_parmap_posix_worker_signal;
- parmap->master_signal_f = &xbt_parmap_posix_master_signal;
- parmap->worker_wait_f = &xbt_parmap_posix_worker_wait;
-
- parmap->ready_cond = xbt_os_cond_init();
- parmap->ready_mutex = xbt_os_mutex_init();
- parmap->done_cond = xbt_os_cond_init();
- parmap->done_mutex = xbt_os_mutex_init();
- break;
- case XBT_PARMAP_FUTEX:
-#if HAVE_FUTEX_H
- parmap->master_wait_f = &xbt_parmap_futex_master_wait;
- parmap->worker_signal_f = &xbt_parmap_futex_worker_signal;
- parmap->master_signal_f = &xbt_parmap_futex_master_signal;
- parmap->worker_wait_f = &xbt_parmap_futex_worker_wait;
-
- xbt_os_cond_destroy(parmap->ready_cond);
- xbt_os_mutex_destroy(parmap->ready_mutex);
- xbt_os_cond_destroy(parmap->done_cond);
- xbt_os_mutex_destroy(parmap->done_mutex);
- break;
-#else
- xbt_die("Futex is not available on this OS.");
-#endif
- case XBT_PARMAP_BUSY_WAIT:
- parmap->master_wait_f = &xbt_parmap_busy_master_wait;
- parmap->worker_signal_f = &xbt_parmap_busy_worker_signal;
- parmap->master_signal_f = &xbt_parmap_busy_master_signal;
- parmap->worker_wait_f = &xbt_parmap_busy_worker_wait;
-
- xbt_os_cond_destroy(parmap->ready_cond);
- xbt_os_mutex_destroy(parmap->ready_mutex);
- xbt_os_cond_destroy(parmap->done_cond);
- xbt_os_mutex_destroy(parmap->done_mutex);
- break;
- case XBT_PARMAP_DEFAULT:
- THROW_IMPOSSIBLE;
- break;
- default:
- THROW_IMPOSSIBLE;
- }
-}
-
-/**
- * \brief Applies a list of tasks in parallel.
- * \param parmap a parallel map object
- * \param fun the function to call in parallel
- * \param data each element of this dynar will be passed as an argument to fun
- */
-void xbt_parmap_apply(xbt_parmap_t parmap, void_f_pvoid_t fun, xbt_dynar_t data)
-{
- /* Assign resources to worker threads (we are maestro here)*/
- parmap->fun = fun;
- parmap->data = data;
- parmap->index = 0;
- parmap->master_signal_f(parmap); // maestro runs futex_wait to wake all the minions (the working threads)
- xbt_parmap_work(parmap); // maestro works with its minions
- parmap->master_wait_f(parmap); // When there is no more work to do, then maestro waits for the last minion to stop
- XBT_DEBUG("Job done"); // ... and proceeds
-}
-
-/**
- * \brief Returns a next task to process.
- *
- * Worker threads call this function to get more work.
- *
- * \return the next task to process, or nullptr if there is no more work
- */
-void* xbt_parmap_next(xbt_parmap_t parmap)
-{
- unsigned int index = parmap->index++;
- if (index < xbt_dynar_length(parmap->data)) {
- return xbt_dynar_get_as(parmap->data, index, void*);
- }
- return nullptr;
-}
-
-static void xbt_parmap_work(xbt_parmap_t parmap)
-{
- unsigned int index = parmap->index++;
- while (index < xbt_dynar_length(parmap->data)){
- parmap->fun(xbt_dynar_get_as(parmap->data, index, void*));
- index = parmap->index++;
- }
-}
-
-/**
- * \brief Main function of a worker thread.
- * \param arg the parmap
- */
-static void *xbt_parmap_worker_main(void *arg)
-{
- xbt_parmap_thread_data_t data = static_cast<xbt_parmap_thread_data_t>(arg);
- xbt_parmap_t parmap = data->parmap;
- unsigned round = 0;
- smx_context_t context = SIMIX_context_new(std::function<void()>(), nullptr, nullptr);
- SIMIX_context_set_current(context);
-
- XBT_DEBUG("New worker thread created");
-
- /* Worker's main loop */
- while (1) {
- round++;
- parmap->worker_wait_f(parmap, round);
- if (parmap->status == XBT_PARMAP_WORK) {
- XBT_DEBUG("Worker %d got a job", data->worker_id);
-
- xbt_parmap_work(parmap);
- parmap->worker_signal_f(parmap);
-
- XBT_DEBUG("Worker %d has finished", data->worker_id);
- /* We are destroying the parmap */
- } else {
- delete context;
- xbt_free(data);
- return nullptr;
- }
- }
-}
-
-#if HAVE_FUTEX_H
-static void futex_wait(unsigned *uaddr, unsigned val)
-{
- XBT_VERB("Waiting on futex %p", uaddr);
- syscall(SYS_futex, uaddr, FUTEX_WAIT_PRIVATE, val, nullptr, nullptr, 0);
-}
-
-static void futex_wake(unsigned *uaddr, unsigned val)
-{
- XBT_VERB("Waking futex %p", uaddr);
- syscall(SYS_futex, uaddr, FUTEX_WAKE_PRIVATE, val, nullptr, nullptr, 0);
-}
-#endif
-
-/**
- * \brief Starts the parmap: waits for all workers to be ready and returns.
- *
- * This function is called by the controller thread.
- *
- * \param parmap a parmap
- */
-static void xbt_parmap_posix_master_wait(xbt_parmap_t parmap)
-{
- xbt_os_mutex_acquire(parmap->done_mutex);
- if (parmap->thread_counter < parmap->num_workers) {
- /* wait for all workers to be ready */
- xbt_os_cond_wait(parmap->done_cond, parmap->done_mutex);
- }
- xbt_os_mutex_release(parmap->done_mutex);
-}
-
-/**
- * \brief Ends the parmap: wakes the controller thread when all workers terminate.
- *
- * This function is called by all worker threads when they end (not including the controller).
- *
- * \param parmap a parmap
- */
-static void xbt_parmap_posix_worker_signal(xbt_parmap_t parmap)
-{
- xbt_os_mutex_acquire(parmap->done_mutex);
- parmap->thread_counter++;
- if (parmap->thread_counter == parmap->num_workers) {
- /* all workers have finished, wake the controller */
- xbt_os_cond_signal(parmap->done_cond);
- }
- xbt_os_mutex_release(parmap->done_mutex);
-}
-
-/**
- * \brief Wakes all workers and waits for them to finish the tasks.
- *
- * This function is called by the controller thread.
- *
- * \param parmap a parmap
- */
-static void xbt_parmap_posix_master_signal(xbt_parmap_t parmap)
-{
- xbt_os_mutex_acquire(parmap->ready_mutex);
- parmap->thread_counter = 1;
- parmap->work++;
- /* wake all workers */
- xbt_os_cond_broadcast(parmap->ready_cond);
- xbt_os_mutex_release(parmap->ready_mutex);
-}
-
-/**
- * \brief Waits for some work to process.
- *
- * This function is called by each worker thread (not including the controller) when it has no more work to do.
- *
- * \param parmap a parmap
- * \param round the expected round number
- */
-static void xbt_parmap_posix_worker_wait(xbt_parmap_t parmap, unsigned round)
-{
- xbt_os_mutex_acquire(parmap->ready_mutex);
- /* wait for more work */
- if (parmap->work != round) {
- xbt_os_cond_wait(parmap->ready_cond, parmap->ready_mutex);
- }
- xbt_os_mutex_release(parmap->ready_mutex);
-}
-
-#if HAVE_FUTEX_H
-/**
- * \brief Starts the parmap: waits for all workers to be ready and returns.
- *
- * This function is called by the controller thread.
- *
- * \param parmap a parmap
- */
-static void xbt_parmap_futex_master_wait(xbt_parmap_t parmap)
-{
- unsigned count = parmap->thread_counter;
- while (count < parmap->num_workers) {
- /* wait for all workers to be ready */
- futex_wait(&parmap->thread_counter, count);
- count = parmap->thread_counter;
- }
-}
-
-/**
- * \brief Ends the parmap: wakes the controller thread when all workers terminate.
- *
- * This function is called by all worker threads when they end (not including the controller).
- *
- * \param parmap a parmap
- */
-static void xbt_parmap_futex_worker_signal(xbt_parmap_t parmap)
-{
- unsigned count = __sync_add_and_fetch(&parmap->thread_counter, 1);
- if (count == parmap->num_workers) {
- /* all workers have finished, wake the controller */
- futex_wake(&parmap->thread_counter, INT_MAX);
- }
-}
-
-/**
- * \brief Wakes all workers and waits for them to finish the tasks.
- *
- * This function is called by the controller thread.
- *
- * \param parmap a parmap
- */
-static void xbt_parmap_futex_master_signal(xbt_parmap_t parmap)
-{
- parmap->thread_counter = 1;
- __sync_add_and_fetch(&parmap->work, 1);
- /* wake all workers */
- futex_wake(&parmap->work, INT_MAX);
-}
-
-/**
- * \brief Waits for some work to process.
- *
- * This function is called by each worker thread (not including the controller) when it has no more work to do.
- *
- * \param parmap a parmap
- * \param round the expected round number
- */
-static void xbt_parmap_futex_worker_wait(xbt_parmap_t parmap, unsigned round)
-{
- unsigned work = parmap->work;
- /* wait for more work */
- while (work != round) {
- futex_wait(&parmap->work, work);
- work = parmap->work;
- }
-}
-#endif
-
-/**
- * \brief Starts the parmap: waits for all workers to be ready and returns.
- *
- * This function is called by the controller thread.
- *
- * \param parmap a parmap
- */
-static void xbt_parmap_busy_master_wait(xbt_parmap_t parmap)
-{
- while (parmap->thread_counter < parmap->num_workers) {
- xbt_os_thread_yield();
- }
-}
-
-/**
- * \brief Ends the parmap: wakes the controller thread when all workers terminate.
- *
- * This function is called by all worker threads when they end.
- *
- * \param parmap a parmap
- */
-static void xbt_parmap_busy_worker_signal(xbt_parmap_t parmap)
-{
- __sync_add_and_fetch(&parmap->thread_counter, 1);
-}
-
-/**
- * \brief Wakes all workers and waits for them to finish the tasks.
- *
- * This function is called by the controller thread.
- *
- * \param parmap a parmap
- */
-static void xbt_parmap_busy_master_signal(xbt_parmap_t parmap)
-{
- parmap->thread_counter = 1;
- __sync_add_and_fetch(&parmap->work, 1);
-}
-
-/**
- * \brief Waits for some work to process.
- *
- * This function is called by each worker thread (not including the controller) when it has no more work to do.
- *
- * \param parmap a parmap
- * \param round the expected round number
- */
-static void xbt_parmap_busy_worker_wait(xbt_parmap_t parmap, unsigned round)
-{
- /* wait for more work */
- while (parmap->work != round) {
- xbt_os_thread_yield();
- }
-}
fs = new std::ifstream(filename, std::ifstream::in);
xbt_assert(fs->is_open(), "Cannot read replay file '%s'", filename);
}
+ ReplayReader(const ReplayReader&) = delete;
~ReplayReader()
{
delete fs;
} else {
// Else, I have to store it for the relevant colleague
std::queue<ReplayAction*>* otherqueue = nullptr;
- try {
- otherqueue = action_queues.at(evtname);
- } catch (std::out_of_range& unfound) { // Damn. Create the queue of that guy
+ auto act = action_queues.find(evtname);
+ if (act != action_queues.end()) {
+ otherqueue = act->second;
+ } else { // Damn. Create the queue of that guy
otherqueue = new std::queue<ReplayAction*>();
action_queues.insert({evtname, otherqueue});
}
/** @brief Strip whitespace (or other characters) from the beginning of a string.
*
- * Strips the whitespaces from the begining of s.
+ * Strips the whitespaces from the beginning of s.
* By default (when char_list=nullptr), these characters get stripped:
*
* - " " (ASCII 32 (0x20)) space.
memmove(s, cur, strlen(cur) + 1);
}
-/** @brief Strip whitespace (or other characters) from the end and the begining of a string.
+/** @brief Strip whitespace (or other characters) from the end and the beginning of a string.
*
* Strips the whitespaces from both the beginning and the end of s.
* By default (when char_list=nullptr), these characters get stripped:
* @param str the string to modify
* @param from char to search
* @param to char to put instead
- * @param occurence number of changes to do (=0 means all)
+ * @param occurrence number of changes to do (=0 means all)
*/
void xbt_str_subst(char *str, char from, char to, int occurence)
{
int lexical_block_variable = 50;
test_local_variable(process.binary_info.get(), "main", "lexical_block_variable", &lexical_block_variable, &cursor);
- s_foo my_foo;
+ s_foo my_foo = {0};
test_type_by_name(process, my_foo);
_exit(0);
set(teshsuite_src ${teshsuite_src} ${CMAKE_CURRENT_SOURCE_DIR}/${x}/${x}.cpp)
endforeach()
+add_executable (bittorrent app-bittorrent/bittorrent.c app-bittorrent/messages.c app-bittorrent/peer.c app-bittorrent/tracker.c app-bittorrent/connection.c)
+target_link_libraries(bittorrent simgrid)
+set_target_properties(bittorrent PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/app-bittorrent)
+foreach (file bittorrent connection messages peer tracker)
+ set(teshsuite_src ${teshsuite_src} ${CMAKE_CURRENT_SOURCE_DIR}/app-bittorrent/${file}.c ${CMAKE_CURRENT_SOURCE_DIR}/app-bittorrent/${file}.h)
+endforeach()
+
+
set(teshsuite_src ${teshsuite_src} PARENT_SCOPE)
-set(tesh_files ${tesh_files} PARENT_SCOPE)
+set(tesh_files ${tesh_files} ${CMAKE_CURRENT_SOURCE_DIR}/app-bittorrent/app-bittorrent.tesh PARENT_SCOPE)
+set(bin_files ${bin_files} ${CMAKE_CURRENT_SOURCE_DIR}/app-bittorrent/generate.py PARENT_SCOPE)
set(txt_files ${txt_files} ${CMAKE_CURRENT_SOURCE_DIR}/actions-comm/actions-comm.txt
${CMAKE_CURRENT_SOURCE_DIR}/actions-comm/actions-comm_split_p0.txt
${CMAKE_CURRENT_SOURCE_DIR}/actions-comm/actions-comm_split_p1.txt
set(xml_files ${xml_files} ${CMAKE_CURRENT_SOURCE_DIR}/actions-comm/actions-comm_d.xml
${CMAKE_CURRENT_SOURCE_DIR}/actions-comm/actions-comm_split_d.xml
${CMAKE_CURRENT_SOURCE_DIR}/actions-storage/actions-storage_d.xml
- ${CMAKE_CURRENT_SOURCE_DIR}/trace_integration/test-hbp1.0-hbp1.0-hbp1.0.xml
+ ${CMAKE_CURRENT_SOURCE_DIR}/app-bittorrent/app-bittorrent_d.xml
+ ${CMAKE_CURRENT_SOURCE_DIR}/trace_integration/test-hbp1.0-hbp1.0-hbp1.0.xml
${CMAKE_CURRENT_SOURCE_DIR}/trace_integration/test-hbp1.0-hbp3.0-hbp4.0.xml
${CMAKE_CURRENT_SOURCE_DIR}/trace_integration/test-hbp1.5-hbp1.5.xml
${CMAKE_CURRENT_SOURCE_DIR}/trace_integration/test-hbp1-c0s0-c0s1.xml
ADD_TESH_FACTORIES(tesh-msg-${x} "thread;boost;ucontext;raw" --setenv srcdir=${CMAKE_HOME_DIRECTORY}/teshsuite/msg/${x} --cd ${CMAKE_BINARY_DIR}/teshsuite/msg/${x} ${CMAKE_HOME_DIRECTORY}/teshsuite/msg/${x}/${x}.tesh)
endforeach()
-foreach(x actions-comm actions-storage)
+foreach(x actions-comm actions-storage app-bittorrent)
ADD_TESH_FACTORIES(tesh-msg-${x} "thread;ucontext;raw;boost" --setenv bindir=${CMAKE_BINARY_DIR}/teshsuite/msg/${x} --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/platforms --cd ${CMAKE_HOME_DIRECTORY}/teshsuite/msg/${x} ${x}.tesh)
endforeach()
# One context factory is enough for these ones
foreach(x cloud-sharing)
ADD_TESH(tesh-msg-${x} --setenv srcdir=${CMAKE_HOME_DIRECTORY}/teshsuite/msg/${x} --cd ${CMAKE_BINARY_DIR}/teshsuite/msg/${x} ${CMAKE_HOME_DIRECTORY}/teshsuite/msg/${x}/${x}.tesh)
endforeach()
+
+ADD_TESH_FACTORIES(tesh-app-bittorrent-parallel "thread;ucontext;raw" --cfg contexts/nthreads:4 ${CONTEXTS_SYNCHRO} --setenv bindir=${CMAKE_BINARY_DIR}/teshsuite/msg/app-bittorrent --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/platforms --cd ${CMAKE_HOME_DIRECTORY}/teshsuite/msg/app-bittorrent app-bittorrent.tesh)
! timeout 10
! output sort 19
-$ $SG_TEST_EXENV ${bindir:=.}/bittorrent ${srcdir:=.}/cluster.xml ${srcdir:=.}/../msg/app-bittorrent/app-bittorrent_d.xml "--log=root.fmt:[%12.6r]%e(%i:%P@%h)%e%m%n"
+$ ${bindir:=.}/bittorrent ${srcdir:=.}/cluster.xml app-bittorrent_d.xml "--log=root.fmt:[%12.6r]%e(%i:%P@%h)%e%m%n"
> [ 0.000000] (1:tracker@node-0.acme.org) Tracker launched.
> [ 0.000000] (2:peer@node-1.acme.org) Hi, I'm joining the network with id 2
> [ 0.000000] (3:peer@node-2.acme.org) Hi, I'm joining the network with id 3
--- /dev/null
+<?xml version='1.0'?>
+<!DOCTYPE platform SYSTEM "http://simgrid.gforge.inria.fr/simgrid/simgrid.dtd">
+<platform version="4.1">
+
+ <actor host="node-0.acme.org" function="tracker">
+ <argument value="3000" />
+ </actor>
+
+ <actor host="node-1.acme.org" function="peer">
+ <argument value="00000002"/> <!-- my id -->
+ <argument value="5000" /> <!-- end time -->
+ <argument value="1" /> <!-- indicates if the peer is a seed at the beginning of the simulation -->
+ </actor>
+ <actor host="node-2.acme.org" function="peer">
+ <argument value="00000003"/> <!-- my id -->
+ <argument value="5000" /> <!-- end time -->
+ </actor>
+ <actor host="node-3.acme.org" function="peer">
+ <argument value="00000004"/> <!-- my id -->
+ <argument value="5000" /> <!-- end time -->
+ </actor>
+ <actor host="node-4.acme.org" function="peer">
+ <argument value="00000005"/> <!-- my id -->
+ <argument value="5000" /> <!-- end time -->
+ <argument value="1" /> <!-- indicates if the peer is a seed at the beginning of the simulation -->
+ </actor>
+ <actor host="node-5.acme.org" function="peer">
+ <argument value="00000006"/> <!-- my id -->
+ <argument value="5000" /> <!-- end time -->
+ </actor>
+ <actor host="node-6.acme.org" function="peer">
+ <argument value="00000007"/> <!-- my id -->
+ <argument value="5000" /> <!-- end time -->
+ </actor>
+ <actor host="node-7.acme.org" function="peer">
+ <argument value="00000008"/> <!-- my id -->
+ <argument value="5000" /> <!-- end time -->
+ </actor>
+</platform>
#include <xbt/RngStream.h>
/** Bittorrent example launcher */
-int main(int argc, char *argv[])
+int main(int argc, char* argv[])
{
msg_host_t host;
unsigned i;
MSG_init(&argc, argv);
/* Check the arguments */
- xbt_assert (argc > 2, "Usage: %s platform_file deployment_file", argv[0]);
+ xbt_assert(argc > 2, "Usage: %s platform_file deployment_file", argv[0]);
MSG_create_environment(argv[1]);
xbt_dynar_t host_list = MSG_hosts_as_dynar();
- xbt_dynar_foreach(host_list, i, host) {
+ xbt_dynar_foreach (host_list, i, host) {
char descr[512];
snprintf(descr, sizeof descr, "RngSream<%s>", MSG_host_get_name(host));
RngStream stream = RngStream_CreateStream(descr);
MSG_main();
- xbt_dynar_foreach(host_list, i, host) {
+ xbt_dynar_foreach (host_list, i, host) {
RngStream stream = (RngStream)MSG_host_get_data(host);
RngStream_DeleteStream(&stream);
MSG_host_set_data(host, NULL);
-/* Copyright (c) 2012-2014, 2016. The SimGrid Team.
+/* Copyright (c) 2012-2014, 2016-2017. The SimGrid Team.
* All rights reserved. */
/* This program is free software; you can redistribute it and/or modify it
#define MAILBOX_SIZE 40
#define TRACKER_MAILBOX "tracker_mailbox"
/** Max number of pairs sent by the tracker to clients */
-#define MAXIMUM_PAIRS 50
+#define MAXIMUM_PEERS 50
/** Interval of time where the peer should send a request to the tracker */
#define TRACKER_QUERY_INTERVAL 1000
/** Communication size for a task to the tracker */
-#define TRACKER_COMM_SIZE 0.01
+#define TRACKER_COMM_SIZE 1
#define GET_PEERS_TIMEOUT 10000
#define TIMEOUT_MESSAGE 10
#define TRACKER_RECEIVE_TIMEOUT 10
/** Number of pieces the peer asks for simultaneously */
#define MAX_PIECES 1
-#endif /* BITTORRENT_BITTORRENT_H_ */
+#endif /* BITTORRENT_BITTORRENT_H_ */
{
connection_t connection = xbt_new(s_connection_t, 1);
- connection->id = id;
- connection->mailbox = bprintf("%d", id);
- connection->bitfield = 0;
- connection->current_piece = -1;
- connection->interested = 0;
- connection->am_interested = 0;
- connection->choked_upload = 1;
+ connection->id = id;
+ connection->mailbox = bprintf("%d", id);
+ connection->bitfield = 0;
+ connection->current_piece = -1;
+ connection->interested = 0;
+ connection->am_interested = 0;
+ connection->choked_upload = 1;
connection->choked_download = 1;
- connection->peer_speed = 0;
- connection->last_unchoke = 0;
+ connection->peer_speed = 0;
+ connection->last_unchoke = 0;
return connection;
}
connection->peer_speed = connection->peer_speed * 0.6 + speed * 0.4;
}
-void connection_free(void *data)
+void connection_free(void* data)
{
- connection_t co = (connection_t) data;
+ connection_t co = (connection_t)data;
xbt_free(co->mailbox);
xbt_free(co);
}
-int connection_has_piece(connection_t connection, unsigned int piece){
- return (connection->bitfield & 1U<<piece);
+int connection_has_piece(connection_t connection, unsigned int piece)
+{
+ return (connection->bitfield & 1U << piece);
}
/** Contains the connection data of a peer. */
typedef struct s_connection {
- int id; //Peer id
- unsigned int bitfield; //Fields
- char *mailbox;
+ int id; // Peer id
+ unsigned int bitfield; // Fields
+ char* mailbox;
int messages_count;
double peer_speed;
double last_unchoke;
int current_piece;
- unsigned int am_interested:1; //Indicates if we are interested in something the peer has
- unsigned int interested:1; //Indicates if the peer is interested in one of our pieces
- unsigned int choked_upload:1; //Indicates if the peer is choked for the current peer
- unsigned int choked_download:1; //Indicates if the peer has choked the current peer
+ unsigned int am_interested : 1; // Indicates if we are interested in something the peer has
+ unsigned int interested : 1; // Indicates if the peer is interested in one of our pieces
+ unsigned int choked_upload : 1; // Indicates if the peer is choked for the current peer
+ unsigned int choked_download : 1; // Indicates if the peer has choked the current peer
} s_connection_t;
-typedef s_connection_t *connection_t;
+typedef s_connection_t* connection_t;
/** @brief Build a new connection object from the peer id.
* @param id id of the peer
*/
void connection_add_speed_value(connection_t connection, double speed);
/** Frees a connection object */
-void connection_free(void *data);
+void connection_free(void* data);
int connection_has_piece(connection_t connection, unsigned int piece);
-#endif /* BITTORRENT_CONNECTION_H_ */
+#endif /* BITTORRENT_CONNECTION_H_ */
--- /dev/null
+/* Copyright (c) 2012-2014. 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 "messages.h"
+#include "bittorrent.h"
+
+XBT_LOG_NEW_DEFAULT_CATEGORY(msg_messages, "Messages specific for the message factory");
+
+#define BITS_TO_BYTES(x) (((x) / 8 + (x) % 8) ? 1 : 0)
+
+/** @brief Build a new empty message
+ * @param type type of the message
+ * @param issuer_host_name hostname of the issuer, for debugging purposes
+ * @param mailbox mailbox where the peer should answer
+ * @param peer_id id of the issuer
+ * @param size message size in bytes
+ */
+msg_task_t task_message_new(e_message_type type, const char* issuer_host_name, const char* mailbox, int peer_id,
+ int size)
+{
+ message_t message = xbt_new(s_message_t, 1);
+ message->issuer_host_name = issuer_host_name;
+ message->peer_id = peer_id;
+ message->mailbox = mailbox;
+ message->type = type;
+ msg_task_t task = MSG_task_create(NULL, 0, size, message);
+ XBT_DEBUG("type: %d size: %d", (int)type, size);
+ return task;
+}
+
+/** Builds a message containing an index. */
+msg_task_t task_message_index_new(e_message_type type, const char* issuer_host_name, const char* mailbox, int peer_id,
+ int index, int varsize)
+{
+ msg_task_t task = task_message_new(type, issuer_host_name, mailbox, peer_id, task_message_size(type) + varsize);
+ message_t message = MSG_task_get_data(task);
+ message->index = index;
+ return task;
+}
+
+msg_task_t task_message_bitfield_new(const char* issuer_host_name, const char* mailbox, int peer_id,
+ unsigned int bitfield, int bitfield_size)
+{
+ msg_task_t task = task_message_new(MESSAGE_BITFIELD, issuer_host_name, mailbox, peer_id,
+ task_message_size(MESSAGE_BITFIELD) + BITS_TO_BYTES(bitfield_size));
+ message_t message = MSG_task_get_data(task);
+ message->bitfield = bitfield;
+ return task;
+}
+
+msg_task_t task_message_request_new(const char* issuer_host_name, const char* mailbox, int peer_id, int index,
+ int block_index, int block_length)
+{
+ msg_task_t task = task_message_index_new(MESSAGE_REQUEST, issuer_host_name, mailbox, peer_id, index, 0);
+ message_t message = MSG_task_get_data(task);
+ message->block_index = block_index;
+ message->block_length = block_length;
+ return task;
+}
+
+msg_task_t task_message_piece_new(const char* issuer_host_name, const char* mailbox, int peer_id, int index,
+ int block_index, int block_length, int block_size)
+{
+ msg_task_t task =
+ task_message_index_new(MESSAGE_PIECE, issuer_host_name, mailbox, peer_id, index, block_length * block_size);
+ message_t message = MSG_task_get_data(task);
+ message->block_index = block_index;
+ message->block_length = block_length;
+ return task;
+}
+
+void task_message_free(void* task)
+{
+ message_t message = MSG_task_get_data(task);
+ xbt_free(message);
+ MSG_task_destroy(task);
+}
+
+int task_message_size(e_message_type type)
+{
+ int size = 0;
+ switch (type) {
+ case MESSAGE_HANDSHAKE:
+ size = MESSAGE_HANDSHAKE_SIZE;
+ break;
+ case MESSAGE_CHOKE:
+ size = MESSAGE_CHOKE_SIZE;
+ break;
+ case MESSAGE_UNCHOKE:
+ size = MESSAGE_UNCHOKE_SIZE;
+ break;
+ case MESSAGE_INTERESTED:
+ case MESSAGE_NOTINTERESTED:
+ size = MESSAGE_INTERESTED_SIZE;
+ break;
+ case MESSAGE_HAVE:
+ size = MESSAGE_HAVE_SIZE;
+ break;
+ case MESSAGE_BITFIELD:
+ size = MESSAGE_BITFIELD_SIZE;
+ break;
+ case MESSAGE_REQUEST:
+ size = MESSAGE_REQUEST_SIZE;
+ break;
+ case MESSAGE_PIECE:
+ size = MESSAGE_PIECE_SIZE;
+ break;
+ case MESSAGE_CANCEL:
+ size = MESSAGE_CANCEL_SIZE;
+ break;
+ default:
+ THROW_IMPOSSIBLE;
+ }
+ return size;
+}
/** Message data */
typedef struct s_message {
e_message_type type;
- const char *mailbox;
- const char *issuer_host_name;
+ const char* mailbox;
+ const char* issuer_host_name;
int peer_id;
unsigned int bitfield;
int index;
int block_index;
int block_length;
} s_message_t;
-typedef s_message_t *message_t;
+typedef s_message_t* message_t;
/** Builds a new value-less message */
-msg_task_t task_message_new(e_message_type type, const char *issuer_host_name, const char *mailbox, int peer_id,
+msg_task_t task_message_new(e_message_type type, const char* issuer_host_name, const char* mailbox, int peer_id,
int size);
/** Builds a new "have/piece" message */
-msg_task_t task_message_index_new(e_message_type type, const char *issuer_host_name, const char *mailbox, int peer_id,
+msg_task_t task_message_index_new(e_message_type type, const char* issuer_host_name, const char* mailbox, int peer_id,
int index, int varsize);
/** Builds a new bitfield message */
-msg_task_t task_message_bitfield_new(const char *issuer_host_name, const char *mailbox, int peer_id,
+msg_task_t task_message_bitfield_new(const char* issuer_host_name, const char* mailbox, int peer_id,
unsigned int bitfield, int bitfield_size);
/** Builds a new "request" message */
-msg_task_t task_message_request_new(const char *issuer_host_name, const char *mailbox, int peer_id, int index,
+msg_task_t task_message_request_new(const char* issuer_host_name, const char* mailbox, int peer_id, int index,
int block_index, int block_length);
/** Build a new "piece" message */
-msg_task_t task_message_piece_new(const char *issuer_host_name, const char *mailbox, int peer_id, int index,
+msg_task_t task_message_piece_new(const char* issuer_host_name, const char* mailbox, int peer_id, int index,
int block_index, int block_length, int block_size);
/** Free a message task */
-void task_message_free(void *);
+void task_message_free(void*);
int task_message_size(e_message_type type);
-#endif /* BITTORRENT_MESSAGES_H_ */
+#endif /* BITTORRENT_MESSAGES_H_ */
* under the terms of the license (GNU LGPL) which comes with this package. */
#include "peer.h"
-#include "tracker.h"
#include "connection.h"
#include "messages.h"
+#include "tracker.h"
+#include <limits.h>
#include <simgrid/msg.h>
#include <xbt/RngStream.h>
-#include <limits.h>
XBT_LOG_NEW_DEFAULT_CATEGORY(msg_peers, "Messages specific for the peers");
* User parameters for transferred file data. For the test, the default values are :
* File size: 10 pieces * 5 blocks/piece * 16384 bytes/block = 819200 bytes
*/
-#define FILE_PIECES 10U
-#define PIECES_BLOCKS 5U
-#define BLOCK_SIZE 16384
+#define FILE_PIECES 10UL
+#define PIECES_BLOCKS 5UL
+#define BLOCK_SIZE 16384
static const unsigned long int FILE_SIZE = FILE_PIECES * PIECES_BLOCKS * BLOCK_SIZE;
/** Number of blocks asked by each request */
#define ENABLE_END_GAME_MODE 1
#define SLEEP_DURATION 1
-int count_pieces(unsigned int bitfield){
- int count=0;
+int count_pieces(unsigned int bitfield)
+{
+ int count = 0;
unsigned int n = bitfield;
- while (n){
+ while (n) {
count += n & 1U;
- n >>= 1U ;
+ n >>= 1U;
}
return count;
}
-int peer_has_not_piece(peer_t peer, unsigned int piece){
- return !(peer->bitfield & 1U<<piece);
+int peer_has_not_piece(peer_t peer, unsigned int piece)
+{
+ return !(peer->bitfield & 1U << piece);
}
/** Check that a piece is not currently being download by the peer. */
-int peer_is_not_downloading_piece(peer_t peer, unsigned int piece){
- return !(peer->current_pieces & 1U<<piece);
+int peer_is_not_downloading_piece(peer_t peer, unsigned int piece)
+{
+ return !(peer->current_pieces & 1U << piece);
}
-void get_status(char **status, unsigned int bitfield){
- for(int i=FILE_PIECES-1; i>=0; i--)
+void get_status(char** status, unsigned int bitfield)
+{
+ for (int i = FILE_PIECES - 1; i >= 0; i--)
(*status)[i] = (bitfield & (1U << i)) ? '1' : '0';
(*status)[FILE_PIECES] = '\0';
}
/** Peer main function */
-int peer(int argc, char *argv[])
+int peer(int argc, char* argv[])
{
- //Check arguments
+ // Check arguments
xbt_assert(argc == 3 || argc == 4, "Wrong number of arguments");
- //Build peer object
- peer_t peer = peer_init(xbt_str_parse_int(argv[1],"Invalid ID: %s"), argc==4 ? 1:0);
+ // Build peer object
+ peer_t peer = peer_init(xbt_str_parse_int(argv[1], "Invalid ID: %s"), argc == 4 ? 1 : 0);
- //Retrieve deadline
- double deadline = xbt_str_parse_double(argv[2],"Invalid deadline: %s");
+ // Retrieve deadline
+ double deadline = xbt_str_parse_double(argv[2], "Invalid deadline: %s");
xbt_assert(deadline > 0, "Wrong deadline supplied");
- char *status = xbt_malloc0(FILE_PIECES+1);
+ char* status = xbt_malloc0(FILE_PIECES + 1);
get_status(&status, peer->bitfield);
XBT_INFO("Hi, I'm joining the network with id %d", peer->id);
- //Getting peer data from the tracker.
+ // Getting peer data from the tracker.
if (get_peers_data(peer)) {
XBT_DEBUG("Got %d peers from the tracker. Current status is: %s", xbt_dict_length(peer->peers), status);
peer->begin_receive_time = MSG_get_clock();
handle_message(peer, peer->task_received);
}
} else {
- //We don't execute the choke algorithm if we don't already have a piece
+ // We don't execute the choke algorithm if we don't already have a piece
if (MSG_get_clock() >= next_choked_update && count_pieces(peer->bitfield) > 0) {
update_choked_peers(peer);
next_choked_update += UPDATE_CHOKED_INTERVAL;
{
double next_choked_update = MSG_get_clock() + UPDATE_CHOKED_INTERVAL;
XBT_DEBUG("Start seeding.");
- //start the main seed loop
+ // start the main seed loop
while (MSG_get_clock() < deadline) {
if (peer->comm_received == NULL) {
peer->task_received = NULL;
} else {
if (MSG_get_clock() >= next_choked_update) {
update_choked_peers(peer);
- //TODO: Change the choked peer algorithm when seeding.
+ // TODO: Change the choked peer algorithm when seeding.
next_choked_update += UPDATE_CHOKED_INTERVAL;
} else {
MSG_process_sleep(SLEEP_DURATION);
*/
int get_peers_data(peer_t peer)
{
- int success = 0;
+ int success = 0;
double timeout = MSG_get_clock() + GET_PEERS_TIMEOUT;
- //Build the task to send to the tracker
- tracker_task_data_t data = tracker_task_data_new(MSG_host_get_name(MSG_host_self()), peer->mailbox_tracker,
- peer->id, 0, 0, FILE_SIZE);
+ // Build the task to send to the tracker
+ tracker_task_data_t data =
+ tracker_task_data_new(MSG_host_get_name(MSG_host_self()), peer->mailbox_tracker, peer->id, 0, 0, FILE_SIZE);
msg_task_t task_send = MSG_task_create(NULL, 0, TRACKER_COMM_SIZE, data);
while ((success == 0) && MSG_get_clock() < timeout) {
XBT_DEBUG("Sending a peer request to the tracker.");
}
}
- success = 0;
+ success = 0;
msg_task_t task_received = NULL;
while ((success == 0) && MSG_get_clock() < timeout) {
msg_comm_t comm_received = MSG_task_irecv(&task_received, peer->mailbox_tracker);
- msg_error_t status = MSG_comm_wait(comm_received, GET_PEERS_TIMEOUT);
+ msg_error_t status = MSG_comm_wait(comm_received, GET_PEERS_TIMEOUT);
if (status == MSG_OK) {
tracker_task_data_t data = MSG_task_get_data(task_received);
unsigned i;
int peer_id;
- //Add the peers the tracker gave us to our peer list.
- xbt_dynar_foreach(data->peers, i, peer_id) {
+ // Add the peers the tracker gave us to our peer list.
+ xbt_dynar_foreach (data->peers, i, peer_id) {
if (peer_id != peer->id)
- xbt_dict_set_ext(peer->peers, (char *) &peer_id, sizeof(int), connection_new(peer_id), NULL);
+ xbt_dict_set_ext(peer->peers, (char*)&peer_id, sizeof(int), connection_new(peer_id), NULL);
}
success = 1;
- //free the communication and the task
+ // free the communication and the task
MSG_comm_destroy(comm_received);
tracker_task_data_free(data);
MSG_task_destroy(task_received);
*/
peer_t peer_init(int id, int seed)
{
- peer_t peer = xbt_new(s_peer_t,1);
- peer->id = id;
+ peer_t peer = xbt_new(s_peer_t, 1);
+ peer->id = id;
peer->hostname = MSG_host_get_name(MSG_host_self());
- snprintf(peer->mailbox,MAILBOX_SIZE-1, "%d", id);
- snprintf(peer->mailbox_tracker,MAILBOX_SIZE-1, "tracker_%d", id);
+ snprintf(peer->mailbox, MAILBOX_SIZE - 1, "%d", id);
+ snprintf(peer->mailbox_tracker, MAILBOX_SIZE - 1, "tracker_%d", id);
peer->peers = xbt_dict_new_homogeneous(NULL);
peer->active_peers = xbt_dict_new_homogeneous(NULL);
if (seed) {
- peer->bitfield = (1U<<FILE_PIECES)-1U;
- peer->bitfield_blocks = (1ULL<<(FILE_PIECES * PIECES_BLOCKS))-1ULL ;
+ peer->bitfield = (1U << FILE_PIECES) - 1U;
+ peer->bitfield_blocks = (1ULL << (FILE_PIECES * PIECES_BLOCKS)) - 1ULL;
} else {
- peer->bitfield = 0;
+ peer->bitfield = 0;
peer->bitfield_blocks = 0;
}
/** Destroys a poor peer object. */
void peer_free(peer_t peer)
{
- char *key;
+ char* key;
connection_t connection;
xbt_dict_cursor_t cursor;
- xbt_dict_foreach(peer->peers, cursor, key, connection) {
+ xbt_dict_foreach (peer->peers, cursor, key, connection) {
connection_free(connection);
}
xbt_dict_free(&peer->peers);
*/
int has_finished(unsigned int bitfield)
{
- return bitfield == (1U<<FILE_PIECES)-1U;
+ return bitfield == (1U << FILE_PIECES) - 1U;
}
int nb_interested_peers(peer_t peer)
{
xbt_dict_cursor_t cursor = NULL;
- char *key;
+ char* key;
connection_t connection;
int nb = 0;
- xbt_dict_foreach(peer->peers, cursor, key, connection) {
+ xbt_dict_foreach (peer->peers, cursor, key, connection) {
if (connection->interested)
nb++;
}
void update_active_peers_set(peer_t peer, connection_t remote_peer)
{
if ((remote_peer->interested != 0) && (remote_peer->choked_upload == 0)) {
- //add in the active peers set
- xbt_dict_set_ext(peer->active_peers, (char *) &remote_peer->id, sizeof(int), remote_peer, NULL);
- } else if (xbt_dict_get_or_null_ext(peer->active_peers, (char *) &remote_peer->id, sizeof(int))) {
- xbt_dict_remove_ext(peer->active_peers, (char *) &remote_peer->id, sizeof(int));
+ // add in the active peers set
+ xbt_dict_set_ext(peer->active_peers, (char*)&remote_peer->id, sizeof(int), remote_peer, NULL);
+ } else if (xbt_dict_get_or_null_ext(peer->active_peers, (char*)&remote_peer->id, sizeof(int))) {
+ xbt_dict_remove_ext(peer->active_peers, (char*)&remote_peer->id, sizeof(int));
}
}
*/
void handle_message(peer_t peer, msg_task_t task)
{
- const char* type_names[10] =
- {"HANDSHAKE","CHOKE","UNCHOKE","INTERESTED","NOTINTERESTED","HAVE","BITFIELD","REQUEST", "PIECE", "CANCEL" };
+ const char* type_names[10] = {"HANDSHAKE", "CHOKE", "UNCHOKE", "INTERESTED", "NOTINTERESTED",
+ "HAVE", "BITFIELD", "REQUEST", "PIECE", "CANCEL"};
message_t message = MSG_task_get_data(task);
XBT_DEBUG("Received a %s message from %s (%s)", type_names[message->type], message->mailbox,
- message->issuer_host_name);
+ message->issuer_host_name);
connection_t remote_peer;
- remote_peer = xbt_dict_get_or_null_ext(peer->peers, (char *) &message->peer_id, sizeof(int));
+ remote_peer = xbt_dict_get_or_null_ext(peer->peers, (char*)&message->peer_id, sizeof(int));
switch (message->type) {
- case MESSAGE_HANDSHAKE:
- //Check if the peer is in our connection list.
- if (remote_peer == 0) {
- xbt_dict_set_ext(peer->peers, (char *) &message->peer_id, sizeof(int), connection_new(message->peer_id), NULL);
- send_handshake(peer, message->mailbox);
- }
- //Send our bitfield to the peer
- send_bitfield(peer, message->mailbox);
- break;
- case MESSAGE_BITFIELD:
- //Update the pieces list
- update_pieces_count_from_bitfield(peer, message->bitfield);
- //Store the bitfield
- remote_peer->bitfield = message->bitfield;
- xbt_assert(!remote_peer->am_interested, "Should not be interested at first");
- if (is_interested(peer, remote_peer)) {
- remote_peer->am_interested = 1;
- send_interested(peer, message->mailbox);
- }
- break;
- case MESSAGE_INTERESTED:
- xbt_assert((remote_peer != NULL), "A non-in-our-list peer has sent us a message. WTH ?");
- //Update the interested state of the peer.
- remote_peer->interested = 1;
- update_active_peers_set(peer, remote_peer);
- break;
- case MESSAGE_NOTINTERESTED:
- xbt_assert((remote_peer != NULL), "A non-in-our-list peer has sent us a message. WTH ?");
- remote_peer->interested = 0;
- update_active_peers_set(peer, remote_peer);
- break;
- case MESSAGE_UNCHOKE:
- xbt_assert((remote_peer != NULL), "A non-in-our-list peer has sent us a message. WTH ?");
- xbt_assert(remote_peer->choked_download);
- remote_peer->choked_download = 0;
- //Send requests to the peer, since it has unchoked us
- if (remote_peer->am_interested)
- request_new_piece_to_peer(peer, remote_peer);
- break;
- case MESSAGE_CHOKE:
- xbt_assert((remote_peer != NULL), "A non-in-our-list peer has sent us a message. WTH ?");
- xbt_assert(!remote_peer->choked_download);
- remote_peer->choked_download = 1;
- if (remote_peer->current_piece != -1)
- remove_current_piece(peer, remote_peer, remote_peer->current_piece);
- break;
- case MESSAGE_HAVE:
- XBT_DEBUG("\t for piece %d", message->index);
- xbt_assert((message->index >= 0 && message->index < FILE_PIECES), "Wrong HAVE message received");
- remote_peer->bitfield = remote_peer->bitfield | (1U<<message->index);
- peer->pieces_count[message->index]++;
- //If the piece is in our pieces, we tell the peer that we are interested.
- if ((remote_peer->am_interested == 0) && peer_has_not_piece(peer,message->index)) {
- remote_peer->am_interested = 1;
- send_interested(peer, message->mailbox);
- if (remote_peer->choked_download == 0)
+ case MESSAGE_HANDSHAKE:
+ // Check if the peer is in our connection list.
+ if (remote_peer == 0) {
+ xbt_dict_set_ext(peer->peers, (char*)&message->peer_id, sizeof(int), connection_new(message->peer_id), NULL);
+ send_handshake(peer, message->mailbox);
+ }
+ // Send our bitfield to the peer
+ send_bitfield(peer, message->mailbox);
+ break;
+ case MESSAGE_BITFIELD:
+ // Update the pieces list
+ update_pieces_count_from_bitfield(peer, message->bitfield);
+ // Store the bitfield
+ remote_peer->bitfield = message->bitfield;
+ xbt_assert(!remote_peer->am_interested, "Should not be interested at first");
+ if (is_interested(peer, remote_peer)) {
+ remote_peer->am_interested = 1;
+ send_interested(peer, message->mailbox);
+ }
+ break;
+ case MESSAGE_INTERESTED:
+ xbt_assert((remote_peer != NULL), "A non-in-our-list peer has sent us a message. WTH ?");
+ // Update the interested state of the peer.
+ remote_peer->interested = 1;
+ update_active_peers_set(peer, remote_peer);
+ break;
+ case MESSAGE_NOTINTERESTED:
+ xbt_assert((remote_peer != NULL), "A non-in-our-list peer has sent us a message. WTH ?");
+ remote_peer->interested = 0;
+ update_active_peers_set(peer, remote_peer);
+ break;
+ case MESSAGE_UNCHOKE:
+ xbt_assert((remote_peer != NULL), "A non-in-our-list peer has sent us a message. WTH ?");
+ xbt_assert(remote_peer->choked_download);
+ remote_peer->choked_download = 0;
+ // Send requests to the peer, since it has unchoked us
+ if (remote_peer->am_interested)
request_new_piece_to_peer(peer, remote_peer);
- }
- break;
- case MESSAGE_REQUEST:
- xbt_assert(remote_peer->interested);
- xbt_assert((message->index >= 0 && message->index < FILE_PIECES), "Wrong request received");
- if (remote_peer->choked_upload == 0) {
- XBT_DEBUG("\t for piece %d (%d,%d)", message->index, message->block_index,
- message->block_index + message->block_length);
- if (!peer_has_not_piece(peer, message->index)) {
- send_piece(peer, message->mailbox, message->index, message->block_index, message->block_length);
+ break;
+ case MESSAGE_CHOKE:
+ xbt_assert((remote_peer != NULL), "A non-in-our-list peer has sent us a message. WTH ?");
+ xbt_assert(!remote_peer->choked_download);
+ remote_peer->choked_download = 1;
+ if (remote_peer->current_piece != -1)
+ remove_current_piece(peer, remote_peer, remote_peer->current_piece);
+ break;
+ case MESSAGE_HAVE:
+ XBT_DEBUG("\t for piece %d", message->index);
+ xbt_assert((message->index >= 0 && message->index < FILE_PIECES), "Wrong HAVE message received");
+ remote_peer->bitfield = remote_peer->bitfield | (1U << message->index);
+ peer->pieces_count[message->index]++;
+ // If the piece is in our pieces, we tell the peer that we are interested.
+ if ((remote_peer->am_interested == 0) && peer_has_not_piece(peer, message->index)) {
+ remote_peer->am_interested = 1;
+ send_interested(peer, message->mailbox);
+ if (remote_peer->choked_download == 0)
+ request_new_piece_to_peer(peer, remote_peer);
}
- } else {
- XBT_DEBUG("\t for piece %d but he is choked.", message->peer_id);
- }
- break;
- case MESSAGE_PIECE:
- XBT_DEBUG(" \t for piece %d (%d,%d)", message->index, message->block_index,
- message->block_index + message->block_length);
- xbt_assert(!remote_peer->choked_download);
- xbt_assert(remote_peer->am_interested || ENABLE_END_GAME_MODE,
- "Can't received a piece if I'm not interested wihtout end-game mode!"
- "piece (%d) bitfield(%u) remote bitfield(%u)", message->index, peer->bitfield, remote_peer->bitfield);
- xbt_assert(remote_peer->choked_download != 1, "Can't received a piece if I'm choked !");
- xbt_assert((message->index >= 0 && message->index < FILE_PIECES), "Wrong piece received");
- //TODO: Execute à computation.
- if (peer_has_not_piece(peer,message->index)) {
- update_bitfield_blocks(peer, message->index, message->block_index, message->block_length);
- if (piece_complete(peer, message->index)) {
- //Removing the piece from our piece list
- remove_current_piece(peer, remote_peer, message->index);
- //Setting the fact that we have the piece
- peer->bitfield = peer->bitfield | (1U<<message->index);
- char* status = xbt_malloc0(FILE_PIECES+1);
- get_status(&status, peer->bitfield);
- XBT_DEBUG("My status is now %s", status);
- xbt_free(status);
- //Sending the information to all the peers we are connected to
- send_have(peer, message->index);
- //sending UNINTERESTED to peers that do not have what we want.
- update_interested_after_receive(peer);
- } else { // piece not completed
- send_request_to_peer(peer, remote_peer, message->index); // ask for the next block
+ break;
+ case MESSAGE_REQUEST:
+ xbt_assert(remote_peer->interested);
+ xbt_assert((message->index >= 0 && message->index < FILE_PIECES), "Wrong request received");
+ if (remote_peer->choked_upload == 0) {
+ XBT_DEBUG("\t for piece %d (%d,%d)", message->index, message->block_index,
+ message->block_index + message->block_length);
+ if (!peer_has_not_piece(peer, message->index)) {
+ send_piece(peer, message->mailbox, message->index, message->block_index, message->block_length);
+ }
+ } else {
+ XBT_DEBUG("\t for piece %d but he is choked.", message->peer_id);
}
- } else {
- XBT_DEBUG("However, we already have it");
- xbt_assert(ENABLE_END_GAME_MODE, "Should not happen because we don't use end game mode !");
- request_new_piece_to_peer(peer, remote_peer);
- }
- break;
- case MESSAGE_CANCEL:
- break;
- default:
- THROW_IMPOSSIBLE;
+ break;
+ case MESSAGE_PIECE:
+ XBT_DEBUG(" \t for piece %d (%d,%d)", message->index, message->block_index,
+ message->block_index + message->block_length);
+ xbt_assert(!remote_peer->choked_download);
+ xbt_assert(remote_peer->am_interested || ENABLE_END_GAME_MODE,
+ "Can't received a piece if I'm not interested wihtout end-game mode!"
+ "piece (%d) bitfield(%u) remote bitfield(%u)",
+ message->index, peer->bitfield, remote_peer->bitfield);
+ xbt_assert(remote_peer->choked_download != 1, "Can't received a piece if I'm choked !");
+ xbt_assert((message->index >= 0 && message->index < FILE_PIECES), "Wrong piece received");
+ // TODO: Execute à computation.
+ if (peer_has_not_piece(peer, message->index)) {
+ update_bitfield_blocks(peer, message->index, message->block_index, message->block_length);
+ if (piece_complete(peer, message->index)) {
+ // Removing the piece from our piece list
+ remove_current_piece(peer, remote_peer, message->index);
+ // Setting the fact that we have the piece
+ peer->bitfield = peer->bitfield | (1U << message->index);
+ char* status = xbt_malloc0(FILE_PIECES + 1);
+ get_status(&status, peer->bitfield);
+ XBT_DEBUG("My status is now %s", status);
+ xbt_free(status);
+ // Sending the information to all the peers we are connected to
+ send_have(peer, message->index);
+ // sending UNINTERESTED to peers that do not have what we want.
+ update_interested_after_receive(peer);
+ } else { // piece not completed
+ send_request_to_peer(peer, remote_peer, message->index); // ask for the next block
+ }
+ } else {
+ XBT_DEBUG("However, we already have it");
+ xbt_assert(ENABLE_END_GAME_MODE, "Should not happen because we don't use end game mode !");
+ request_new_piece_to_peer(peer, remote_peer);
+ }
+ break;
+ case MESSAGE_CANCEL:
+ break;
+ default:
+ THROW_IMPOSSIBLE;
}
- //Update the peer speed.
+ // Update the peer speed.
if (remote_peer) {
connection_add_speed_value(remote_peer, 1.0 / (MSG_get_clock() - peer->begin_receive_time));
}
{
int piece = select_piece_to_download(peer, remote_peer);
if (piece != -1) {
- peer->current_pieces|= (1U << (unsigned int) piece);
+ peer->current_pieces |= (1U << (unsigned int)piece);
send_request_to_peer(peer, remote_peer, piece);
}
}
if (count_pieces(peer->current_pieces) >= (FILE_PIECES - count_pieces(peer->bitfield)) &&
(is_interested(peer, remote_peer) != 0)) {
#if ENABLE_END_GAME_MODE == 0
- return -1;
+ return -1;
#endif
int nb_interesting_pieces = 0;
// compute the number of interesting pieces
for (int i = 0; i < FILE_PIECES; i++) {
- if (peer_has_not_piece(peer,i) && connection_has_piece(remote_peer,i)) {
+ if (peer_has_not_piece(peer, i) && connection_has_piece(remote_peer, i)) {
nb_interesting_pieces++;
}
}
xbt_assert(nb_interesting_pieces != 0);
// get a random interesting piece
int random_piece_index = RngStream_RandInt(peer->stream, 0, nb_interesting_pieces - 1);
- int current_index = 0;
+ int current_index = 0;
for (int i = 0; i < FILE_PIECES; i++) {
- if (peer_has_not_piece(peer,i) && connection_has_piece(remote_peer,i)) {
+ if (peer_has_not_piece(peer, i) && connection_has_piece(remote_peer, i)) {
if (random_piece_index == current_index) {
piece = i;
break;
int nb_interesting_pieces = 0;
// compute the number of interesting pieces
for (int i = 0; i < FILE_PIECES; i++) {
- if (peer_has_not_piece(peer, i) && connection_has_piece(remote_peer,i) && peer_is_not_downloading_piece(peer, i)) {
+ if (peer_has_not_piece(peer, i) && connection_has_piece(remote_peer, i) &&
+ peer_is_not_downloading_piece(peer, i)) {
nb_interesting_pieces++;
}
}
xbt_assert(nb_interesting_pieces != 0);
// get a random interesting piece
int random_piece_index = RngStream_RandInt(peer->stream, 0, nb_interesting_pieces - 1);
- int current_index = 0;
+ int current_index = 0;
for (int i = 0; i < FILE_PIECES; i++) {
- if (peer_has_not_piece(peer, i) && connection_has_piece(remote_peer,i) && peer_is_not_downloading_piece(peer, i)) {
+ if (peer_has_not_piece(peer, i) && connection_has_piece(remote_peer, i) &&
+ peer_is_not_downloading_piece(peer, i)) {
if (random_piece_index == current_index) {
piece = i;
break;
}
xbt_assert(piece != -1);
return piece;
- } else { // Rarest first policy
- short min = SHRT_MAX;
+ } else { // Rarest first policy
+ short min = SHRT_MAX;
int nb_min_pieces = 0;
int current_index = 0;
// compute the smallest number of copies of available pieces
for (int i = 0; i < FILE_PIECES; i++) {
- if (peer->pieces_count[i] < min && peer_has_not_piece(peer, i) && connection_has_piece(remote_peer,i) &&
+ if (peer->pieces_count[i] < min && peer_has_not_piece(peer, i) && connection_has_piece(remote_peer, i) &&
peer_is_not_downloading_piece(peer, i))
min = peer->pieces_count[i];
}
- xbt_assert(min != SHRT_MAX || (is_interested_and_free(peer, remote_peer) ==0));
+ xbt_assert(min != SHRT_MAX || (is_interested_and_free(peer, remote_peer) == 0));
// compute the number of rarest pieces
for (int i = 0; i < FILE_PIECES; i++) {
- if (peer->pieces_count[i] == min && peer_has_not_piece(peer, i) && connection_has_piece(remote_peer,i) &&
+ if (peer->pieces_count[i] == min && peer_has_not_piece(peer, i) && connection_has_piece(remote_peer, i) &&
peer_is_not_downloading_piece(peer, i))
nb_min_pieces++;
}
- xbt_assert(nb_min_pieces != 0 || (is_interested_and_free(peer, remote_peer)==0));
+ xbt_assert(nb_min_pieces != 0 || (is_interested_and_free(peer, remote_peer) == 0));
// get a random rarest piece
int random_rarest_index = RngStream_RandInt(peer->stream, 0, nb_min_pieces - 1);
for (int i = 0; i < FILE_PIECES; i++) {
- if (peer->pieces_count[i] == min && peer_has_not_piece(peer, i) && connection_has_piece(remote_peer,i) &&
+ if (peer->pieces_count[i] == min && peer_has_not_piece(peer, i) && connection_has_piece(remote_peer, i) &&
peer_is_not_downloading_piece(peer, i)) {
if (random_rarest_index == current_index) {
piece = i;
if (nb_interested_peers(peer) == 0)
return;
XBT_DEBUG("(%d) update_choked peers %u active peers", peer->id, xbt_dict_size(peer->active_peers));
- //update the current round
+ // update the current round
peer->round = (peer->round + 1) % 3;
- char *key;
- char *key_choked=NULL;
+ char* key;
+ char* key_choked = NULL;
connection_t peer_choosed = NULL;
- connection_t peer_choked = NULL;
- //remove a peer from the list
+ connection_t peer_choked = NULL;
+ // remove a peer from the list
xbt_dict_cursor_t cursor = NULL;
xbt_dict_cursor_first(peer->active_peers, &cursor);
if (xbt_dict_length(peer->active_peers) > 0) {
- key_choked = xbt_dict_cursor_get_key(cursor);
+ key_choked = xbt_dict_cursor_get_key(cursor);
peer_choked = xbt_dict_cursor_get_data(cursor);
}
xbt_dict_cursor_free(&cursor);
connection_t connection;
double unchoke_time = MSG_get_clock() + 1;
- xbt_dict_foreach(peer->peers, cursor, key, connection) {
- if (connection->last_unchoke < unchoke_time &&
- (connection->interested != 0) && (connection->choked_upload != 0)) {
+ xbt_dict_foreach (peer->peers, cursor, key, connection) {
+ if (connection->last_unchoke < unchoke_time && (connection->interested != 0) &&
+ (connection->choked_upload != 0)) {
unchoke_time = connection->last_unchoke;
peer_choosed = connection;
}
}
} else {
- //Random optimistic unchoking
+ // Random optimistic unchoking
if (peer->round == 0) {
int j = 0;
do {
- //We choose a random peer to unchoke.
+ // We choose a random peer to unchoke.
int id_chosen = RngStream_RandInt(peer->stream, 0, xbt_dict_length(peer->peers) - 1);
- int i = 0;
+ int i = 0;
connection_t connection;
- xbt_dict_foreach(peer->peers, cursor, key, connection) {
+ xbt_dict_foreach (peer->peers, cursor, key, connection) {
if (i == id_chosen) {
peer_choosed = connection;
break;
else
XBT_DEBUG("Nothing to do, keep going");
j++;
- } while (peer_choosed == NULL && j < MAXIMUM_PAIRS);
+ } while (peer_choosed == NULL && j < MAXIMUM_PEERS);
} else {
- //Use the "fastest download" policy.
+ // Use the "fastest download" policy.
connection_t connection;
double fastest_speed = 0.0;
- xbt_dict_foreach(peer->peers, cursor, key, connection) {
- if (connection->peer_speed > fastest_speed &&
- (connection->choked_upload != 0) && (connection->interested != 0)) {
- peer_choosed = connection;
+ xbt_dict_foreach (peer->peers, cursor, key, connection) {
+ if (connection->peer_speed > fastest_speed && (connection->choked_upload != 0) &&
+ (connection->interested != 0)) {
+ peer_choosed = connection;
fastest_speed = connection->peer_speed;
}
}
}
if (peer_choosed != NULL)
- XBT_DEBUG("(%d) update_choked peers unchoked (%d) ; int (%d) ; choked (%d) ",
- peer->id, peer_choosed->id, peer_choosed->interested, peer_choosed->choked_upload);
+ XBT_DEBUG("(%d) update_choked peers unchoked (%d) ; int (%d) ; choked (%d) ", peer->id, peer_choosed->id,
+ peer_choosed->interested, peer_choosed->choked_upload);
if (peer_choked != peer_choosed) {
if (peer_choked != NULL) {
xbt_assert((!peer_choked->choked_upload), "Tries to choked a choked peer");
peer_choked->choked_upload = 1;
- xbt_assert((*((int *) key_choked) == peer_choked->id));
+ xbt_assert((*((int*)key_choked) == peer_choked->id));
update_active_peers_set(peer, peer_choked);
XBT_DEBUG("(%d) Sending a CHOKE to %d", peer->id, peer_choked->id);
send_choked(peer, peer_choked->mailbox);
if (peer_choosed != NULL) {
xbt_assert((peer_choosed->choked_upload), "Tries to unchoked an unchoked peer");
peer_choosed->choked_upload = 0;
- xbt_dict_set_ext(peer->active_peers, (char *) &peer_choosed->id, sizeof(int), peer_choosed, NULL);
+ xbt_dict_set_ext(peer->active_peers, (char*)&peer_choosed->id, sizeof(int), peer_choosed, NULL);
peer_choosed->last_unchoke = MSG_get_clock();
XBT_DEBUG("(%d) Sending a UNCHOKE to %d", peer->id, peer_choosed->id);
update_active_peers_set(peer, peer_choosed);
*/
void update_interested_after_receive(peer_t peer)
{
- char *key;
+ char* key;
xbt_dict_cursor_t cursor;
connection_t connection;
- xbt_dict_foreach(peer->peers, cursor, key, connection) {
+ xbt_dict_foreach (peer->peers, cursor, key, connection) {
if (connection->am_interested != 0) {
int interested = 0;
- //Check if the peer still has a piece we want.
+ // Check if the peer still has a piece we want.
for (int i = 0; i < FILE_PIECES; i++) {
- if (peer_has_not_piece(peer, i) && connection_has_piece(connection,i)) {
+ if (peer_has_not_piece(peer, i) && connection_has_piece(connection, i)) {
interested = 1;
break;
}
}
- if (!interested) { //no more piece to download from connection
+ if (!interested) { // no more piece to download from connection
connection->am_interested = 0;
send_notinterested(peer, connection->mailbox);
}
xbt_assert((index >= 0 && index <= FILE_PIECES), "Wrong piece.");
xbt_assert((block_index >= 0 && block_index <= PIECES_BLOCKS), "Wrong block : %d.", block_index);
for (int i = block_index; i < (block_index + block_length); i++) {
- peer->bitfield_blocks |= (1ULL<<(unsigned int)(index * PIECES_BLOCKS + i));
+ peer->bitfield_blocks |= (1ULL << (unsigned int)(index * PIECES_BLOCKS + i));
}
}
int piece_complete(peer_t peer, int index)
{
for (int i = 0; i < PIECES_BLOCKS; i++) {
- if (!(peer->bitfield_blocks & 1ULL<<(index * PIECES_BLOCKS + i))) {
+ if (!(peer->bitfield_blocks & 1ULL << (index * PIECES_BLOCKS + i))) {
return 0;
}
}
int get_first_block(peer_t peer, int piece)
{
for (int i = 0; i < PIECES_BLOCKS; i++) {
- if (!(peer->bitfield_blocks & 1ULL<<(piece * PIECES_BLOCKS + i))) {
+ if (!(peer->bitfield_blocks & 1ULL << (piece * PIECES_BLOCKS + i))) {
return i;
}
}
/** Indicates if the remote peer has a piece not stored by the local peer */
int is_interested(peer_t peer, connection_t remote_peer)
{
- return remote_peer->bitfield & (peer->bitfield^((1<<FILE_PIECES)-1));
+ return remote_peer->bitfield & (peer->bitfield ^ ((1 << FILE_PIECES) - 1));
}
/** Indicates if the remote peer has a piece not stored by the local peer nor requested by the local peer */
int is_interested_and_free(peer_t peer, connection_t remote_peer)
{
for (int i = 0; i < FILE_PIECES; i++) {
- if (peer_has_not_piece(peer, i) && connection_has_piece(remote_peer,i) && peer_is_not_downloading_piece(peer, i)) {
+ if (peer_has_not_piece(peer, i) && connection_has_piece(remote_peer, i) && peer_is_not_downloading_piece(peer, i)) {
return 1;
}
}
void send_request_to_peer(peer_t peer, connection_t remote_peer, int piece)
{
remote_peer->current_piece = piece;
- xbt_assert(connection_has_piece(remote_peer,piece));
+ xbt_assert(connection_has_piece(remote_peer, piece));
int block_index = get_first_block(peer, piece);
if (block_index != -1) {
int block_length = MIN(BLOCKS_REQUESTED, PIECES_BLOCKS - block_index);
* @param peer peer data
* @param mailbox destination mailbox
*/
-void send_interested(peer_t peer, const char *mailbox)
+void send_interested(peer_t peer, const char* mailbox)
{
msg_task_t task = task_message_new(MESSAGE_INTERESTED, peer->hostname, peer->mailbox, peer->id,
task_message_size(MESSAGE_INTERESTED));
* @param peer peer data
* @param mailbox destination mailbox
*/
-void send_notinterested(peer_t peer, const char *mailbox)
+void send_notinterested(peer_t peer, const char* mailbox)
{
msg_task_t task = task_message_new(MESSAGE_NOTINTERESTED, peer->hostname, peer->mailbox, peer->id,
task_message_size(MESSAGE_NOTINTERESTED));
{
connection_t remote_peer;
xbt_dict_cursor_t cursor = NULL;
- char *key;
- xbt_dict_foreach(peer->peers, cursor, key, remote_peer) {
+ char* key;
+ xbt_dict_foreach (peer->peers, cursor, key, remote_peer) {
msg_task_t task = task_message_new(MESSAGE_HANDSHAKE, peer->hostname, peer->mailbox, peer->id,
task_message_size(MESSAGE_HANDSHAKE));
MSG_task_dsend(task, remote_peer->mailbox, task_message_free);
* @param peer peer data
* @param mailbox mailbox where to we send the message
*/
-void send_handshake(peer_t peer, const char *mailbox)
+void send_handshake(peer_t peer, const char* mailbox)
{
XBT_DEBUG("Sending a HANDSHAKE to %s", mailbox);
msg_task_t task = task_message_new(MESSAGE_HANDSHAKE, peer->hostname, peer->mailbox, peer->id,
}
/** Send a "choked" message to a peer. */
-void send_choked(peer_t peer, const char *mailbox)
+void send_choked(peer_t peer, const char* mailbox)
{
XBT_DEBUG("Sending a CHOKE to %s", mailbox);
- msg_task_t task = task_message_new(MESSAGE_CHOKE, peer->hostname, peer->mailbox, peer->id,
- task_message_size(MESSAGE_CHOKE));
+ msg_task_t task =
+ task_message_new(MESSAGE_CHOKE, peer->hostname, peer->mailbox, peer->id, task_message_size(MESSAGE_CHOKE));
MSG_task_dsend(task, mailbox, task_message_free);
}
/** Send a "unchoked" message to a peer */
-void send_unchoked(peer_t peer, const char *mailbox)
+void send_unchoked(peer_t peer, const char* mailbox)
{
XBT_DEBUG("Sending a UNCHOKE to %s", mailbox);
- msg_task_t task = task_message_new(MESSAGE_UNCHOKE, peer->hostname, peer->mailbox, peer->id,
- task_message_size(MESSAGE_UNCHOKE));
+ msg_task_t task =
+ task_message_new(MESSAGE_UNCHOKE, peer->hostname, peer->mailbox, peer->id, task_message_size(MESSAGE_UNCHOKE));
MSG_task_dsend(task, mailbox, task_message_free);
}
XBT_DEBUG("Sending HAVE message to all my peers");
connection_t remote_peer;
xbt_dict_cursor_t cursor = NULL;
- char *key;
- xbt_dict_foreach(peer->peers, cursor, key, remote_peer) {
+ char* key;
+ xbt_dict_foreach (peer->peers, cursor, key, remote_peer) {
msg_task_t task = task_message_index_new(MESSAGE_HAVE, peer->hostname, peer->mailbox, peer->id, piece,
task_message_size(MESSAGE_HAVE));
MSG_task_dsend(task, remote_peer->mailbox, task_message_free);
/** @brief Send a bitfield message to all the peers the peer has.
* @param peer peer data
*/
-void send_bitfield(peer_t peer, const char *mailbox)
+void send_bitfield(peer_t peer, const char* mailbox)
{
XBT_DEBUG("Sending a BITFIELD to %s", mailbox);
msg_task_t task = task_message_bitfield_new(peer->hostname, peer->mailbox, peer->id, peer->bitfield, FILE_PIECES);
}
/** Send a "request" message to a pair, containing a request for a piece */
-void send_request(peer_t peer, const char *mailbox, int piece, int block_index, int block_length)
+void send_request(peer_t peer, const char* mailbox, int piece, int block_index, int block_length)
{
XBT_DEBUG("Sending a REQUEST to %s for piece %d (%d,%d)", mailbox, piece, block_index, block_length);
msg_task_t task = task_message_request_new(peer->hostname, peer->mailbox, peer->id, piece, block_index, block_length);
}
/** Send a "piece" message to a pair, containing a piece of the file */
-void send_piece(peer_t peer, const char *mailbox, int piece, int block_index, int block_length)
+void send_piece(peer_t peer, const char* mailbox, int piece, int block_index, int block_length)
{
XBT_DEBUG("Sending the PIECE %d (%d,%d) to %s", piece, block_index, block_length, mailbox);
xbt_assert(piece >= 0, "Tried to send a piece that doesn't exist.");
- xbt_assert(!peer_has_not_piece(peer,piece), "Tried to send a piece that we doesn't have.");
- msg_task_t task = task_message_piece_new(peer->hostname, peer->mailbox, peer->id, piece, block_index, block_length,
- BLOCK_SIZE);
+ xbt_assert(!peer_has_not_piece(peer, piece), "Tried to send a piece that we doesn't have.");
+ msg_task_t task =
+ task_message_piece_new(peer->hostname, peer->mailbox, peer->id, piece, block_index, block_length, BLOCK_SIZE);
MSG_task_dsend(task, mailbox, task_message_free);
}
#ifndef BITTORRENT_PEER_H
#define BITTORRENT_PEER_H
+#include "bittorrent.h"
+#include "connection.h"
#include <simgrid/msg.h>
+#include <xbt/RngStream.h>
#include <xbt/dict.h>
#include <xbt/dynar.h>
-#include <xbt/RngStream.h>
-#include "connection.h"
-#include "bittorrent.h"
/** Peer data */
typedef struct s_peer {
- int id; //peer id
+ int id; // peer id
- unsigned int bitfield; //list of pieces the peer has.
- unsigned long long bitfield_blocks; //list of blocks the peer has.
- short *pieces_count; //number of peers that have each piece.
+ unsigned int bitfield; // list of pieces the peer has.
+ unsigned long long bitfield_blocks; // list of blocks the peer has.
+ short* pieces_count; // number of peers that have each piece.
- unsigned int current_pieces; //current pieces the peer is downloading
+ unsigned int current_pieces; // current pieces the peer is downloading
- xbt_dict_t peers; //peers list
- xbt_dict_t active_peers; //active peers list
- int round; //current round for the chocking algorithm.
+ xbt_dict_t peers; // peers list
+ xbt_dict_t active_peers; // active peers list
+ int round; // current round for the chocking algorithm.
- char mailbox[MAILBOX_SIZE]; //peer mailbox.
- char mailbox_tracker[MAILBOX_SIZE]; //pair mailbox while communicating with the tracker.
- const char *hostname; //peer hostname
+ char mailbox[MAILBOX_SIZE]; // peer mailbox.
+ char mailbox_tracker[MAILBOX_SIZE]; // pair mailbox while communicating with the tracker.
+ const char* hostname; // peer hostname
- msg_task_t task_received; //current task being received
- msg_comm_t comm_received; //current comm
+ msg_task_t task_received; // current task being received
+ msg_comm_t comm_received; // current comm
- RngStream stream; //RngStream for
+ RngStream stream; // RngStream for
- double begin_receive_time; //time when the receiving communication has begun, useful for calculating host speed.
+ double begin_receive_time; // time when the receiving communication has begun, useful for calculating host speed.
} s_peer_t;
-typedef s_peer_t *peer_t;
+typedef s_peer_t* peer_t;
/** Peer main function */
-int peer(int argc, char *argv[]);
-void get_status(char **status, unsigned int bitfield);
+int peer(int argc, char* argv[]);
+void get_status(char** status, unsigned int bitfield);
int get_peers_data(peer_t peer);
void leech_loop(peer_t peer, double deadline);
void send_handshake_all(peer_t peer);
-void send_interested(peer_t peer, const char *mailbox);
+void send_interested(peer_t peer, const char* mailbox);
-void send_notinterested(peer_t peer, const char *mailbox);
-void send_handshake(peer_t peer, const char *mailbox);
-void send_bitfield(peer_t peer, const char *mailbox);
-void send_choked(peer_t peer, const char *mailbox);
-void send_unchoked(peer_t peer, const char *mailbox);
+void send_notinterested(peer_t peer, const char* mailbox);
+void send_handshake(peer_t peer, const char* mailbox);
+void send_bitfield(peer_t peer, const char* mailbox);
+void send_choked(peer_t peer, const char* mailbox);
+void send_unchoked(peer_t peer, const char* mailbox);
void send_have(peer_t peer, int piece);
-void send_request(peer_t peer, const char *mailbox, int piece, int block_index, int block_length);
-void send_piece(peer_t peer, const char *mailbox, int piece, int block_index, int block_length);
+void send_request(peer_t peer, const char* mailbox, int piece, int block_index, int block_length);
+void send_piece(peer_t peer, const char* mailbox, int piece, int block_index, int block_length);
-#endif /* BITTORRENT_PEER_H */
+#endif /* BITTORRENT_PEER_H */
#include <simgrid/msg.h>
#include <xbt/RngStream.h>
-static void task_free(void *data);
+static void task_free(void* data);
XBT_LOG_NEW_DEFAULT_CATEGORY(msg_tracker, "Messages specific for the tracker");
/**
* @param argc number of arguments
* @param argv arguments
*/
-int tracker(int argc, char *argv[])
+int tracker(int argc, char* argv[])
{
- //Checking arguments
+ // Checking arguments
xbt_assert(argc == 2, "Wrong number of arguments for the tracker.");
- //Retrieving end time
- double deadline = xbt_str_parse_double(argv[1],"Invalid deadline: %s");
+ // Retrieving end time
+ double deadline = xbt_str_parse_double(argv[1], "Invalid deadline: %s");
xbt_assert(deadline > 0, "Wrong deadline supplied");
- RngStream stream = (RngStream) MSG_host_get_data(MSG_host_self());
- //Building peers array
+ RngStream stream = (RngStream)MSG_host_get_data(MSG_host_self());
+ // Building peers array
xbt_dynar_t peers_list = xbt_dynar_new(sizeof(int), NULL);
XBT_INFO("Tracker launched.");
comm_received = MSG_task_irecv(&task_received, TRACKER_MAILBOX);
}
if (MSG_comm_test(comm_received)) {
- //Check for correct status
+ // Check for correct status
if (MSG_comm_get_status(comm_received) == MSG_OK) {
- //Retrieve the data sent by the peer.
+ // Retrieve the data sent by the peer.
tracker_task_data_t data = MSG_task_get_data(task_received);
- //Add the peer to our peer list.
+ // Add the peer to our peer list.
if (is_in_list(peers_list, data->peer_id) == 0) {
xbt_dynar_push_as(peers_list, int, data->peer_id);
}
- //Sending peers to the peer
+ // Sending peers to the peer
int next_peer;
int peers_length = xbt_dynar_length(peers_list);
- for (int i = 0; i < MAXIMUM_PAIRS && i < peers_length; i++) {
+ for (int i = 0; i < MAXIMUM_PEERS && i < peers_length; i++) {
do {
next_peer = xbt_dynar_get_as(peers_list, RngStream_RandInt(stream, 0, peers_length - 1), int);
} while (is_in_list(data->peers, next_peer));
xbt_dynar_push_as(data->peers, int, next_peer);
}
- //setting the interval
+ // setting the interval
data->interval = TRACKER_QUERY_INTERVAL;
- //sending the task back to the peer.
+ // sending the task back to the peer.
MSG_task_dsend(task_received, data->mailbox, task_free);
- //destroy the communication.
+ // destroy the communication.
}
MSG_comm_destroy(comm_received);
comm_received = NULL;
MSG_process_sleep(1);
}
}
- //Free the remaining communication if any
+ // Free the remaining communication if any
if (comm_received) {
MSG_comm_destroy(comm_received);
}
- //Free the peers list
+ // Free the peers list
xbt_dynar_free(&peers_list);
XBT_INFO("Tracker is leaving");
* Build a new task for the tracker.
* @param issuer_host_name Hostname of the issuer. For debugging purposes
*/
-tracker_task_data_t tracker_task_data_new(const char *issuer_host_name, const char *mailbox, int peer_id,
- int uploaded, int downloaded, int left)
+tracker_task_data_t tracker_task_data_new(const char* issuer_host_name, const char* mailbox, int peer_id, int uploaded,
+ int downloaded, int left)
{
tracker_task_data_t task = xbt_new(s_tracker_task_data_t, 1);
- task->type = TRACKER_TASK_QUERY;
+ task->type = TRACKER_TASK_QUERY;
task->issuer_host_name = issuer_host_name;
- task->mailbox = mailbox;
- task->peer_id = peer_id;
- task->uploaded = uploaded;
- task->downloaded = downloaded;
- task->left = left;
+ task->mailbox = mailbox;
+ task->peer_id = peer_id;
+ task->uploaded = uploaded;
+ task->downloaded = downloaded;
+ task->left = left;
task->peers = xbt_dynar_new(sizeof(int), NULL);
* Free a tracker task that has not successfully been sent.
* @param data Task to free
*/
-static void task_free(void *data)
+static void task_free(void* data)
{
tracker_task_data_t task_data = MSG_task_get_data(data);
tracker_task_data_free(task_data);
--- /dev/null
+/* Copyright (c) 2012-2014. 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 BITTORRENT_TRACKER_H_
+#define BITTORRENT_TRACKER_H_
+#include "bittorrent.h"
+#include <xbt/dynar.h>
+/**
+ * Tracker main function
+ */
+int tracker(int argc, char* argv[]);
+/**
+ * Task types exchanged between a node and the tracker
+ */
+typedef enum { TRACKER_TASK_QUERY, TRACKER_TASK_ANSWER } e_tracker_task_type_t;
+/**
+ * Tasks exchanged between a tracker and peers.
+ */
+typedef struct s_tracker_task_data {
+ e_tracker_task_type_t type; // type of the task
+ const char* mailbox; // mailbox where the tracker should answer
+ const char* issuer_host_name; // hostname, for debug purposes
+ // Query data
+ int peer_id; // peer id
+ int uploaded; // how much the peer has already uploaded
+ int downloaded; // how much the peer has downloaded
+ int left; // how much the peer has left
+ // Answer data
+ int interval; // how often the peer should contact the tracker (unused for now)
+ xbt_dynar_t peers; // the peer list the peer has asked for.
+} s_tracker_task_data_t;
+typedef s_tracker_task_data_t* tracker_task_data_t;
+
+tracker_task_data_t tracker_task_data_new(const char* issuer_host_name, const char* mailbox, int peer_id, int uploaded,
+ int downloaded, int left);
+void tracker_task_data_free(tracker_task_data_t task);
+
+int is_in_list(xbt_dynar_t peers, int id);
+#endif /* BITTORRENT_TRACKER_H */
XBT_INFO("Sender spec: %s", args[0].c_str());
for (unsigned int test = 1; test <= args[0].size(); test++) {
this_actor::sleep_until(test * 5 - 5);
- char* mboxName = bprintf("Test #%u", test);
- simgrid::s4u::MailboxPtr mbox = simgrid::s4u::Mailbox::byName(mboxName);
+ std::string* mboxName = new std::string("Test #" + std::to_string(test));
+ simgrid::s4u::MailboxPtr mbox = simgrid::s4u::Mailbox::byName(mboxName->c_str());
switch (args[0][test - 1]) {
case 'r':
XBT_INFO("Receiver spec: %s", args[0].c_str());
for (unsigned int test = 1; test <= args[0].size(); test++) {
this_actor::sleep_until(test * 5 - 5);
- char* mboxName = bprintf("Test #%u", test);
- simgrid::s4u::MailboxPtr mbox = simgrid::s4u::Mailbox::byName(mboxName);
+ std::string mboxName = "Test #" + std::to_string(test);
+ simgrid::s4u::MailboxPtr mbox = simgrid::s4u::Mailbox::byName(mboxName.c_str());
void* received = nullptr;
switch (args[0][test - 1]) {
default:
xbt_die("Unknown receiver spec for test %u: '%c'", test, args[0][test - 1]);
}
-
- xbt_assert(strcmp(static_cast<char*>(received), mboxName) == 0);
- xbt_free(received);
- xbt_free(mboxName);
+ std::string* receivedStr = static_cast<std::string*>(received);
+ xbt_assert(*receivedStr == mboxName);
+ delete receivedStr;
XBT_INFO("Test %u OK", test);
}
simgrid::s4u::this_actor::sleep_for(0.5);
static void dump_platform()
{
int version = 4;
- xbt_dict_t props = nullptr;
- xbt_dict_cursor_t cursor = nullptr;
- char* key;
- char* data;
+ std::map<std::string, std::string>* props = nullptr;
std::printf("<?xml version='1.0'?>\n");
std::printf("<!DOCTYPE platform SYSTEM \"http://simgrid.gforge.inria.fr/simgrid/simgrid.dtd\">\n");
for (unsigned int i = 0; i < totalHosts; i++) {
std::printf(" <host id=\"%s\" speed=\"%.0f\"", hosts[i]->getCname(), sg_host_speed(hosts[i]));
- props = sg_host_get_properties(hosts[i]);
+ props = hosts[i]->getProperties();
if (hosts[i]->getCoreCount() > 1) {
std::printf(" core=\"%d\"", hosts[i]->getCoreCount());
}
- if (props && not xbt_dict_is_empty(props)) {
+ if (props && not props->empty()) {
std::printf(">\n");
- xbt_dict_foreach (props, cursor, key, data) {
- std::printf(" <prop id=\"%s\" value=\"%s\"/>\n", key, data);
+ for (auto kv : *props) {
+ std::printf(" <prop id=\"%s\" value=\"%s\"/>\n", kv.first.c_str(), kv.second.c_str());
}
std::printf(" </host>\n");
} else {
std::printf("/>\n");
}
- xbt_dict_free(&props);
}
// Routers
-foreach(x heap_bench log_large log_usage mallocator parallel_log_crashtest parmap_bench parmap_test)
+foreach(x heap_bench log_large log_usage mallocator parallel_log_crashtest)
add_executable (${x} ${x}/${x}.c)
target_link_libraries(${x} simgrid)
set_target_properties(${x} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${x})
set(teshsuite_src ${teshsuite_src} ${CMAKE_CURRENT_SOURCE_DIR}/${x}/${x}.c)
endforeach()
+foreach(x parmap_bench parmap_test)
+ add_executable (${x} ${x}/${x}.cpp)
+ target_link_libraries(${x} simgrid)
+ set_target_properties(${x} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${x})
+
+ set(tesh_files ${tesh_files} ${CMAKE_CURRENT_SOURCE_DIR}/${x}/${x}.tesh)
+ set(teshsuite_src ${teshsuite_src} ${CMAKE_CURRENT_SOURCE_DIR}/${x}/${x}.cpp)
+endforeach()
+
if(HAVE_MMALLOC)
add_executable (mmalloc_test ${CMAKE_CURRENT_SOURCE_DIR}/mmalloc/mmalloc_test.cpp)
target_link_libraries(mmalloc_test simgrid)
+++ /dev/null
-/* Copyright (c) 2012-2017. 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 "simgrid/msg.h"
-#include "src/internal_config.h" /* HAVE_FUTEX_H */
-#include "xbt/xbt_os_time.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <xbt/dynar.h>
-#include <xbt/parmap.h>
-#include <xbt/sysdep.h>
-
-#define MODES_DEFAULT 0x7
-#define TIMEOUT 10.0
-#define ARRAY_SIZE 10007
-#define FIBO_MAX 25
-
-void (*fun_to_apply)(void *);
-
-static const char *parmap_mode_name(e_xbt_parmap_mode_t mode)
-{
- static char name[80];
- switch (mode) {
- case XBT_PARMAP_POSIX:
- snprintf(name, sizeof name, "POSIX");
- break;
- case XBT_PARMAP_FUTEX:
- snprintf(name, sizeof name, "FUTEX");
- break;
- case XBT_PARMAP_BUSY_WAIT:
- snprintf(name, sizeof name, "BUSY_WAIT");
- break;
- case XBT_PARMAP_DEFAULT:
- snprintf(name, sizeof name, "DEFAULT");
- break;
- default:
- snprintf(name, sizeof name, "UNKNOWN(%d)", (int)mode);
- break;
- }
- return name;
-}
-
-static int parmap_skip_mode(e_xbt_parmap_mode_t mode)
-{
-#if !HAVE_FUTEX_H
- if (mode == XBT_PARMAP_FUTEX) {
- printf("not available\n");
- return 1;
- } else
-#endif
- return 0;
-}
-
-static unsigned fibonacci(unsigned n)
-{
- if (n < 2)
- return n;
- else
- return fibonacci(n - 1) + fibonacci(n - 2);
-}
-
-static void fun_small_comp(void *arg)
-{
- unsigned *u = arg;
- *u = 2 * *u + 1;
-}
-
-static void fun_big_comp(void *arg)
-{
- unsigned *u = arg;
- *u = fibonacci(*u % FIBO_MAX);
-}
-
-static void array_new(unsigned **a, xbt_dynar_t *data)
-{
- *a = xbt_malloc(ARRAY_SIZE * sizeof **a);
- *data = xbt_dynar_new(sizeof *a, NULL);
- xbt_dynar_shrink(*data, ARRAY_SIZE);
- for (int i = 0 ; i < ARRAY_SIZE ; i++) {
- (*a)[i] = i;
- xbt_dynar_push_as(*data, void*, &(*a)[i]);
- }
-}
-
-static void bench_parmap_full(int nthreads, e_xbt_parmap_mode_t mode)
-{
- unsigned *a;
- xbt_dynar_t data;
- xbt_parmap_t parmap;
- double elapsed_time;
-
- printf("** mode = %-15s ", parmap_mode_name(mode));
- fflush(stdout);
-
- if (parmap_skip_mode(mode))
- return;
-
- array_new(&a, &data);
-
- int i = 0;
- double start_time = xbt_os_time();
- do {
- parmap = xbt_parmap_new(nthreads, mode);
- xbt_parmap_apply(parmap, fun_to_apply, data);
- xbt_parmap_destroy(parmap);
- elapsed_time = xbt_os_time() - start_time;
- i++;
- } while (elapsed_time < TIMEOUT);
-
- printf("ran %d times in %g seconds (%g/s)\n", i, elapsed_time, i / elapsed_time);
-
- xbt_dynar_free(&data);
- xbt_free(a);
-}
-
-static void bench_parmap_apply(int nthreads, e_xbt_parmap_mode_t mode)
-{
- unsigned *a;
- xbt_dynar_t data;
- double elapsed_time;
-
- printf("** mode = %-15s ", parmap_mode_name(mode));
- fflush(stdout);
-
- if (parmap_skip_mode(mode))
- return;
-
- array_new(&a, &data);
-
- xbt_parmap_t parmap = xbt_parmap_new(nthreads, mode);
- int i = 0;
- double start_time = xbt_os_time();
- do {
- xbt_parmap_apply(parmap, fun_to_apply, data);
- elapsed_time = xbt_os_time() - start_time;
- i++;
- } while (elapsed_time < TIMEOUT);
- xbt_parmap_destroy(parmap);
-
- printf("ran %d times in %g seconds (%g/s)\n", i, elapsed_time, i / elapsed_time);
-
- xbt_dynar_free(&data);
- xbt_free(a);
-}
-
-static void bench_all_modes(void (*bench_fun)(int, e_xbt_parmap_mode_t),
- int nthreads, unsigned modes)
-{
- e_xbt_parmap_mode_t all_modes[] = {XBT_PARMAP_POSIX, XBT_PARMAP_FUTEX, XBT_PARMAP_BUSY_WAIT, XBT_PARMAP_DEFAULT};
-
- for (unsigned i = 0 ; i < sizeof all_modes / sizeof all_modes[0] ; i++) {
- if (1U << i & modes)
- bench_fun(nthreads, all_modes[i]);
- }
-}
-
-int main(int argc, char *argv[])
-{
- int nthreads;
- unsigned modes = MODES_DEFAULT;
-
- MSG_init(&argc, argv);
-
- if (argc != 2 && argc != 3) {
- fprintf(stderr, "Usage: %s nthreads [modes]\n"
- " nthreads - number of working threads\n"
- " modes - bitmask of modes to test\n",
- argv[0]);
- return EXIT_FAILURE;
- }
- nthreads = atoi(argv[1]);
- if (nthreads < 1) {
- fprintf(stderr, "ERROR: invalid thread count: %d\n", nthreads);
- return EXIT_FAILURE;
- }
- if (argc == 3)
- modes = strtol(argv[2], NULL, 0);
-
- printf("Parmap benchmark with %d workers (modes = %#x)...\n\n", nthreads, modes);
-
- fun_to_apply = &fun_small_comp;
-
- printf("Benchmark for parmap create+apply+destroy (small comp):\n");
- bench_all_modes(bench_parmap_full, nthreads, modes);
- printf("\n");
-
- printf("Benchmark for parmap apply only (small comp):\n");
- bench_all_modes(bench_parmap_apply, nthreads, modes);
- printf("\n");
-
- fun_to_apply = &fun_big_comp;
-
- printf("Benchmark for parmap create+apply+destroy (big comp):\n");
- bench_all_modes(bench_parmap_full, nthreads, modes);
- printf("\n");
-
- printf("Benchmark for parmap apply only (big comp):\n");
- bench_all_modes(bench_parmap_apply, nthreads, modes);
- printf("\n");
-
- return EXIT_SUCCESS;
-}
--- /dev/null
+/* Copyright (c) 2012-2017. 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 "src/internal_config.h" // HAVE_FUTEX_H
+#include <simgrid/msg.h>
+#include <xbt.h>
+#include <xbt/parmap.hpp>
+
+#include <cstdlib>
+#include <iomanip>
+#include <iostream>
+#include <numeric> // std::iota
+#include <string>
+#include <vector>
+
+#define MODES_DEFAULT 0x7
+#define TIMEOUT 10.0
+#define ARRAY_SIZE 10007
+#define FIBO_MAX 25
+
+void (*fun_to_apply)(unsigned*);
+
+static std::string parmap_mode_name(e_xbt_parmap_mode_t mode)
+{
+ std::string name;
+ switch (mode) {
+ case XBT_PARMAP_POSIX:
+ name = "POSIX";
+ break;
+ case XBT_PARMAP_FUTEX:
+ name = "FUTEX";
+ break;
+ case XBT_PARMAP_BUSY_WAIT:
+ name = "BUSY_WAIT";
+ break;
+ case XBT_PARMAP_DEFAULT:
+ name = "DEFAULT";
+ break;
+ default:
+ name = "UNKNOWN(" + std::to_string(mode) + ")";
+ break;
+ }
+ return name;
+}
+
+static bool parmap_skip_mode(e_xbt_parmap_mode_t mode)
+{
+ if (mode == XBT_PARMAP_FUTEX && not HAVE_FUTEX_H) {
+ std::cout << "not available\n";
+ return true;
+ } else {
+ return false;
+ }
+}
+
+static unsigned fibonacci(unsigned n)
+{
+ if (n < 2)
+ return n;
+ else
+ return fibonacci(n - 1) + fibonacci(n - 2);
+}
+
+static void fun_small_comp(unsigned* arg)
+{
+ *arg = 2 * *arg + 1;
+}
+
+static void fun_big_comp(unsigned* arg)
+{
+ *arg = fibonacci(*arg % FIBO_MAX);
+}
+
+static void bench_parmap_full(int nthreads, e_xbt_parmap_mode_t mode)
+{
+ std::cout << "** mode = " << std::left << std::setw(15) << parmap_mode_name(mode) << " ";
+ std::cout.flush();
+
+ if (parmap_skip_mode(mode))
+ return;
+
+ std::vector<unsigned> a(ARRAY_SIZE);
+ std::vector<unsigned*> data(ARRAY_SIZE);
+ std::iota(begin(a), end(a), 0);
+ std::iota(begin(data), end(data), &a[0]);
+
+ int i = 0;
+ double start_time = xbt_os_time();
+ double elapsed_time;
+ do {
+ {
+ simgrid::xbt::Parmap<unsigned*> parmap(nthreads, mode);
+ parmap.apply(fun_to_apply, data);
+ } // enclosing block to ensure that the parmap is destroyed here.
+ elapsed_time = xbt_os_time() - start_time;
+ i++;
+ } while (elapsed_time < TIMEOUT);
+
+ std::cout << "ran " << i << " times in " << elapsed_time << " seconds (" << (i / elapsed_time) << "/s)\n";
+}
+
+static void bench_parmap_apply(int nthreads, e_xbt_parmap_mode_t mode)
+{
+ std::cout << "** mode = " << std::left << std::setw(15) << parmap_mode_name(mode) << " ";
+ std::cout.flush();
+
+ if (parmap_skip_mode(mode))
+ return;
+
+ std::vector<unsigned> a(ARRAY_SIZE);
+ std::vector<unsigned*> data(ARRAY_SIZE);
+ std::iota(begin(a), end(a), 0);
+ std::iota(begin(data), end(data), &a[0]);
+
+ simgrid::xbt::Parmap<unsigned*> parmap(nthreads, mode);
+ int i = 0;
+ double start_time = xbt_os_time();
+ double elapsed_time;
+ do {
+ parmap.apply(fun_to_apply, data);
+ elapsed_time = xbt_os_time() - start_time;
+ i++;
+ } while (elapsed_time < TIMEOUT);
+
+ std::cout << "ran " << i << " times in " << elapsed_time << " seconds (" << (i / elapsed_time) << "/s)\n";
+}
+
+static void bench_all_modes(void (*bench_fun)(int, e_xbt_parmap_mode_t), int nthreads, unsigned modes)
+{
+ std::vector<e_xbt_parmap_mode_t> all_modes = {XBT_PARMAP_POSIX, XBT_PARMAP_FUTEX, XBT_PARMAP_BUSY_WAIT,
+ XBT_PARMAP_DEFAULT};
+
+ for (unsigned i = 0; i < all_modes.size(); i++) {
+ if (1U << i & modes)
+ bench_fun(nthreads, all_modes[i]);
+ }
+}
+
+int main(int argc, char* argv[])
+{
+ int nthreads;
+ unsigned modes = MODES_DEFAULT;
+
+ MSG_init(&argc, argv);
+
+ if (argc != 2 && argc != 3) {
+ std::cerr << "Usage: " << argv[0] << " nthreads [modes]\n"
+ << " nthreads - number of working threads\n"
+ << " modes - bitmask of modes to test\n";
+ return EXIT_FAILURE;
+ }
+ nthreads = atoi(argv[1]);
+ if (nthreads < 1) {
+ std::cerr << "ERROR: invalid thread count: " << nthreads << "\n";
+ return EXIT_FAILURE;
+ }
+ if (argc == 3)
+ modes = strtol(argv[2], NULL, 0);
+
+ std::cout << "Parmap benchmark with " << nthreads << " workers (modes = " << std::hex << modes << std::dec
+ << ")...\n\n";
+
+ fun_to_apply = &fun_small_comp;
+
+ std::cout << "Benchmark for parmap create+apply+destroy (small comp):\n";
+ bench_all_modes(bench_parmap_full, nthreads, modes);
+ std::cout << std::endl;
+
+ std::cout << "Benchmark for parmap apply only (small comp):\n";
+ bench_all_modes(bench_parmap_apply, nthreads, modes);
+ std::cout << std::endl;
+
+ fun_to_apply = &fun_big_comp;
+
+ std::cout << "Benchmark for parmap create+apply+destroy (big comp):\n";
+ bench_all_modes(bench_parmap_full, nthreads, modes);
+ std::cout << std::endl;
+
+ std::cout << "Benchmark for parmap apply only (big comp):\n";
+ bench_all_modes(bench_parmap_apply, nthreads, modes);
+ std::cout << std::endl;
+
+ return EXIT_SUCCESS;
+}
/* 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 "simgrid/msg.h"
-#include "src/internal_config.h"
-#include "xbt.h"
-#include "xbt/ex.h"
-#include "xbt/xbt_os_time.h"
+#include "src/internal_config.h" // HAVE_FUTEX_H
+#include <simgrid/msg.h>
+#include <xbt.h>
+#include <xbt/parmap.hpp>
+
+#include <algorithm>
+#include <cstdlib>
+#include <numeric> // std::iota
+#include <vector>
XBT_LOG_NEW_DEFAULT_CATEGORY(parmap_test, "Test for parmap");
-static void fun_double(void *arg)
+static void fun_double(unsigned* arg)
{
- unsigned *u = arg;
- *u = 2 * *u + 1;
+ *arg = 2 * *arg + 1;
}
static int test_parmap_basic(e_xbt_parmap_mode_t mode)
{
int ret = 0;
- unsigned num_workers;
- for (num_workers = 1 ; num_workers <= 16 ; num_workers *= 2) {
+ for (unsigned num_workers = 1; num_workers <= 16; num_workers *= 2) {
const unsigned len = 1033;
const unsigned num = 5;
- unsigned *a;
- xbt_dynar_t data;
- xbt_parmap_t parmap;
- unsigned i;
-
- parmap = xbt_parmap_new(num_workers, mode);
-
- a = xbt_malloc(len * sizeof *a);
- data = xbt_dynar_new(sizeof a, NULL);
- for (i = 0; i < len; i++) {
- a[i] = i;
- xbt_dynar_push_as(data, void *, &a[i]);
- }
- for (i = 0; i < num; i++)
- xbt_parmap_apply(parmap, fun_double, data);
+ simgrid::xbt::Parmap<unsigned*> parmap(num_workers, mode);
+ std::vector<unsigned> a(len);
+ std::vector<unsigned*> data(len);
+ std::iota(begin(a), end(a), 0);
+ std::iota(begin(data), end(data), &a[0]);
+
+ for (unsigned i = 0; i < num; i++)
+ parmap.apply(fun_double, data);
- for (i = 0; i < len; i++) {
+ for (unsigned i = 0; i < len; i++) {
unsigned expected = (1U << num) * (i + 1) - 1;
if (a[i] != expected) {
XBT_CRITICAL("with %u threads, a[%u]: expected %u, got %u", num_workers, i, expected, a[i]);
break;
}
}
-
- xbt_dynar_free(&data);
- xbt_free(a);
- xbt_parmap_destroy(parmap);
}
return ret;
}
-static void fun_get_id(void *arg)
+static void fun_get_id(uintptr_t* arg)
{
- *(uintptr_t *)arg = (uintptr_t)xbt_os_thread_self();
+ *arg = (uintptr_t)xbt_os_thread_self();
xbt_os_sleep(0.05);
}
-static int fun_compare(const void *pa, const void *pb)
-{
- uintptr_t a = *(uintptr_t *)pa;
- uintptr_t b = *(uintptr_t *)pb;
- return a < b ? -1 : a > b ? 1 : 0;
-}
-
static int test_parmap_extended(e_xbt_parmap_mode_t mode)
{
int ret = 0;
- unsigned num_workers;
- for (num_workers = 1 ; num_workers <= 16 ; num_workers *= 2) {
+ for (unsigned num_workers = 1; num_workers <= 16; num_workers *= 2) {
const unsigned len = 2 * num_workers;
- uintptr_t *a;
- xbt_parmap_t parmap;
- xbt_dynar_t data;
- unsigned i;
- unsigned count;
-
- parmap = xbt_parmap_new(num_workers, mode);
-
- a = xbt_malloc(len * sizeof *a);
- data = xbt_dynar_new(sizeof a, NULL);
- for (i = 0; i < len; i++)
- xbt_dynar_push_as(data, void *, &a[i]);
-
- xbt_parmap_apply(parmap, fun_get_id, data);
-
- qsort(a, len, sizeof a[0], fun_compare);
- count = 1;
- for (i = 1; i < len; i++)
- if (a[i] != a[i - 1])
- count++;
+
+ simgrid::xbt::Parmap<uintptr_t*> parmap(num_workers, mode);
+ std::vector<uintptr_t> a(len);
+ std::vector<uintptr_t*> data(len);
+ std::iota(begin(data), end(data), &a[0]);
+
+ parmap.apply(fun_get_id, data);
+
+ std::sort(begin(a), end(a));
+ unsigned count = std::distance(begin(a), std::unique(begin(a), end(a)));
if (count != num_workers) {
XBT_CRITICAL("only %u/%u threads did some work", count, num_workers);
ret = 1;
}
-
- xbt_dynar_free(&data);
- xbt_free(a);
- xbt_parmap_destroy(parmap);
}
return ret;
}
src/include/instr/instr_interface.h
src/include/mc/datatypes.h
src/include/mc/mc.h
- src/mc/mc_mmu.h
- src/mc/PageStore.hpp
- src/mc/mc_record.h
src/include/simgrid/sg_config.h
src/include/smpi/smpi_utils.hpp
src/include/surf/datatypes.h
src/include/surf/maxmin.h
src/include/surf/surf.h
+ src/include/xbt/parmap.hpp
+ src/mc/mc_mmu.h
+ src/mc/mc_record.h
+ src/mc/PageStore.hpp
src/msg/msg_private.h
src/simdag/dax.dtd
src/simdag/dax_dtd.c
include/smpi/smpi_extended_traces_fortran.h
include/smpi/forward.hpp
include/xbt.h
- include/xbt/RngStream.h
+ include/xbt/algorithm.hpp
include/xbt/asserts.h
include/xbt/automaton.h
include/xbt/automaton.hpp
+ include/xbt/backtrace.h
+ include/xbt/backtrace.hpp
include/xbt/base.h
include/xbt/config.h
include/xbt/config.hpp
include/xbt/cunit.h
include/xbt/dict.h
- include/xbt/string.hpp
- include/xbt/signal.hpp
include/xbt/dynar.h
include/xbt/dynar.hpp
include/xbt/ex.h
include/xbt/ex.hpp
include/xbt/exception.hpp
- include/xbt/backtrace.h
- include/xbt/backtrace.hpp
+ include/xbt/Extendable.hpp
include/xbt/file.h
- include/xbt/function_types.h
include/xbt/functional.hpp
+ include/xbt/function_types.h
include/xbt/future.hpp
include/xbt/graph.h
include/xbt/heap.h
- include/xbt/Extendable.hpp
include/xbt/log.h
include/xbt/log.hpp
include/xbt/mallocator.h
include/xbt/parmap.h
include/xbt/range.hpp
include/xbt/replay.hpp
+ include/xbt/RngStream.h
+ include/xbt/signal.hpp
include/xbt/str.h
+ include/xbt/string.hpp
include/xbt/swag.h
include/xbt/synchro.h
include/xbt/sysdep.h