src/xbt/backtrace_windows.c
src/xbt/backtrace_dummy.c
src/xbt/setset_private.h
- src/xbt/parmap_private.h
src/xbt/automatonparse_promela.c
src/xbt/mmalloc/attach.c
src/xbt/mmalloc/detach.c
)
#### Generate the manpages
-if( NOT MANPAGE_DIR )
+if(NOT WIN32)
+if( NOT MANPAGE_DIR)
set( MANPAGE_DIR ${CMAKE_BINARY_DIR}/manpages )
endif( NOT MANPAGE_DIR)
install(FILES ${MANPAGE_DIR}/simgrid_update_xml.1
DESTINATION $ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/usr/share/man/man1)
+endif(NOT WIN32)
+
# binaries
install(PROGRAMS ${CMAKE_BINARY_DIR}/bin/smpicc
${CMAKE_BINARY_DIR}/bin/smpif2c
#include "msg/msg.h"
#include "surf/surf_private.h"
-extern routing_global_t global_routing;
-int totalHosts= 0;
-const m_host_t *hosts;
-
-int master(int argc, char *argv[]);
-int slave(int argc, char *argv[]);
+int host(int argc, char *argv[]);
+unsigned int task_comp_size = 50000000;
+unsigned int task_comm_size = 1000000;
+int number_of_hosts;
XBT_LOG_NEW_DEFAULT_CATEGORY(ring,
"Messages specific for this msg example");
-int master(int argc, char *argv[])
-{
- m_task_t task_s = NULL;
- m_task_t task_r = NULL;
- unsigned int task_comp_size = 50000000;
- unsigned int task_comm_size = 1000000;
- char mailbox[80];
- char buffer[20];
- int num = atoi(argv[1]);
-
- sprintf(mailbox, "host%d", num+1);
- if(num == totalHosts-1)
- sprintf(mailbox, "host%d", 0);
- sprintf(buffer, "Token");
-
- task_s = MSG_task_create(buffer,
- task_comp_size,
- task_comm_size,
- NULL);
- MSG_task_send(task_s,mailbox);
- XBT_INFO("Send Data to \"%s\"", mailbox);
-
- sprintf(mailbox, "host%d", num);
- MSG_task_receive(&(task_r), mailbox);
- XBT_INFO("Received \"%s\"", MSG_task_get_name(task_r));
- return 0;
-}
-
-int slave(int argc, char *argv[])
-{
- m_task_t task_s = NULL;
- m_task_t task_r = NULL;
- unsigned int task_comp_size = 50000000;
- unsigned int task_comm_size = 1000000;
- char mailbox[80];
- char buffer[20];
- int num = atoi(argv[1]);
-
- sprintf(mailbox, "host%d", num);
- MSG_task_receive(&(task_r), mailbox);
- XBT_INFO("Received \"%s\"", MSG_task_get_name(task_r));
- sprintf(mailbox, "host%d", num+1);
- if(num == totalHosts-1)
- sprintf(mailbox, "host%d", 0);
- sprintf(buffer, "Token");
- task_s = MSG_task_create(buffer,
- task_comp_size,
- task_comm_size,
- NULL);
- MSG_task_send(task_s, mailbox);
- XBT_INFO("Send Data to \"%s\"", mailbox);
-
- return 0;
-}
-
-static int surf_parse_bypass_application(void)
+int host(int argc, char *argv[])
{
- int i;
- static int AX_ptr;
- static int surfxml_bufferstack_size = 2048;
- static int surfxml_buffer_stack_stack_ptr = 0;
- static int surfxml_buffer_stack_stack[1024];
- /* allocating memory to the buffer, I think 2MB should be enough */
- surfxml_bufferstack = xbt_new0(char, surfxml_bufferstack_size);
-
- totalHosts = MSG_get_host_number();
- hosts = MSG_get_host_table();
-
- /* <platform> */
- SURFXML_BUFFER_SET(platform_version, "3");
-
- SURFXML_START_TAG(platform);
-
- XBT_DEBUG("process : %s en master",MSG_host_get_name(hosts[0]));
- /* <process host="host A" function="master"> */
- SURFXML_BUFFER_SET(process_host, MSG_host_get_name(hosts[0]));
- SURFXML_BUFFER_SET(process_function, "master");
- SURFXML_BUFFER_SET(process_start_time, "-1.0");
- SURFXML_BUFFER_SET(process_kill_time, "-1.0");
- SURFXML_START_TAG(process);
-
- /* <argument value="0"/> */
- SURFXML_BUFFER_SET(argument_value, "0");
- SURFXML_START_TAG(argument);
- SURFXML_END_TAG(argument);
- SURFXML_END_TAG(process);
-
- for(i=1;i<totalHosts;i++)
- {
- XBT_DEBUG("process : %s en slave",MSG_host_get_name(hosts[i]));
- /* <process host="host A" function="slave"> */
- SURFXML_BUFFER_SET(process_host,MSG_host_get_name(hosts[i]) );
- SURFXML_BUFFER_SET(process_function, "slave");
- SURFXML_BUFFER_SET(process_start_time, "-1.0");
- SURFXML_BUFFER_SET(process_kill_time, "-1.0");
- SURFXML_START_TAG(process);
-
- /* <argument value="num"/> */
- SURFXML_BUFFER_SET(argument_value, bprintf("%d",i));
- SURFXML_START_TAG(argument);
- SURFXML_END_TAG(argument);
- SURFXML_END_TAG(process);
- }
- /* </platform> */
- SURFXML_END_TAG(platform);
-
- free(surfxml_bufferstack);
- return 0;
+ int host_number = atoi(MSG_process_get_name(MSG_process_self()));
+ char mailbox[256];
+ m_task_t task = NULL;
+ _XBT_GNUC_UNUSED int res;
+
+ if (host_number == 0){ //master send then receive
+ sprintf(mailbox, "%d", host_number+1);
+ task = MSG_task_create("Token", task_comp_size, task_comm_size, NULL);
+ XBT_INFO("Host \"%d\" send '%s' to Host \"%s\"",host_number,task->name,mailbox);
+ MSG_task_send(task, mailbox);
+ task = NULL;
+ res = MSG_task_receive(&(task), MSG_process_get_name(MSG_process_self()));
+ xbt_assert(res == MSG_OK, "MSG_task_get failed");
+ XBT_INFO("Host \"%d\" received \"%s\"",host_number, MSG_task_get_name(task));
+ MSG_task_destroy(task);
+ }
+ else{ //slave receive then send
+ res = MSG_task_receive(&(task), MSG_process_get_name(MSG_process_self()));
+ xbt_assert(res == MSG_OK, "MSG_task_get failed");
+ XBT_INFO("Host \"%d\" received \"%s\"",host_number, MSG_task_get_name(task));
+
+ if(host_number+1 == number_of_hosts )
+ sprintf(mailbox, "0");
+ else
+ sprintf(mailbox, "%d", host_number+1);
+ XBT_INFO("Host \"%d\" send '%s' to Host \"%s\"",host_number,task->name,mailbox);
+ MSG_task_send(task, mailbox);
+ }
+ return 0;
}
typedef enum {
int main(int argc, char **argv)
{
- int res;
+ int i,res;
MSG_global_init(&argc, argv);
MSG_set_channel_number(MAX_CHANNEL);
MSG_create_environment(argv[1]);
-
- MSG_function_register("master", master);
- MSG_function_register("slave", slave);
- surf_parse = surf_parse_bypass_application;
- MSG_launch_application(NULL);
+ m_host_t *host_table = MSG_get_host_table();
+ number_of_hosts = MSG_get_host_number();
+ MSG_function_register("host", host);
+
+ XBT_INFO("Number of host '%d'",number_of_hosts);
+ for(i = 0 ; i<number_of_hosts; i++)
+ {
+ char* name_host = bprintf("%d",i);
+ MSG_process_create( name_host, host, NULL, host_table[i] );
+ free(name_host);
+ }
+ xbt_free(host_table);
res = MSG_main();
-
XBT_INFO("Simulation time %g", MSG_get_clock());
-
MSG_clean();
-
if (res == MSG_OK)
return 0;
else
#! ./tesh
-! output sort
$ $SG_TEST_EXENV ${bindir:=.}/token_ring ${srcdir:=.}/two_clusters.xml "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n"
-> [ 0.000000] (0:@) Bypassing the XML parser since surf_parse_open received a NULL pointer. If it is not what you want, go fix your code.
-> [ 0.066240] (1:master@bob1.hamburger.edu) Send Data to "host1"
-> [ 0.066240] (2:slave@bob3.hamburger.edu) Received "Token"
-> [ 0.242880] (2:slave@bob3.hamburger.edu) Send Data to "host2"
-> [ 0.242880] (3:slave@alice2.crepe.fr) Received "Token"
-> [ 0.309120] (3:slave@alice2.crepe.fr) Send Data to "host3"
-> [ 0.309120] (4:slave@alice3.crepe.fr) Received "Token"
-> [ 0.485760] (4:slave@alice3.crepe.fr) Send Data to "host4"
-> [ 0.485760] (5:slave@bob0.hamburger.edu) Received "Token"
-> [ 0.552000] (5:slave@bob0.hamburger.edu) Send Data to "host5"
-> [ 0.552000] (6:slave@bob2.hamburger.edu) Received "Token"
-> [ 0.618240] (6:slave@bob2.hamburger.edu) Send Data to "host6"
-> [ 0.618240] (7:slave@bob4.hamburger.edu) Received "Token"
-> [ 0.794880] (7:slave@bob4.hamburger.edu) Send Data to "host7"
-> [ 0.794880] (8:slave@alice0.crepe.fr) Received "Token"
-> [ 0.861120] (8:slave@alice0.crepe.fr) Send Data to "host8"
-> [ 0.861120] (9:slave@alice4.crepe.fr) Received "Token"
-> [ 0.927360] (10:slave@alice1.crepe.fr) Received "Token"
-> [ 0.927360] (9:slave@alice4.crepe.fr) Send Data to "host9"
+> [ 0.000000] (0:@) Number of host '10'
+> [ 0.000000] (1:0@bob1.hamburger.edu) Host "0" send 'Token' to Host "1"
+> [ 0.066240] (2:1@bob3.hamburger.edu) Host "1" received "Token"
+> [ 0.066240] (2:1@bob3.hamburger.edu) Host "1" send 'Token' to Host "2"
+> [ 0.242880] (3:2@alice2.crepe.fr) Host "2" received "Token"
+> [ 0.242880] (3:2@alice2.crepe.fr) Host "2" send 'Token' to Host "3"
+> [ 0.309120] (4:3@alice3.crepe.fr) Host "3" received "Token"
+> [ 0.309120] (4:3@alice3.crepe.fr) Host "3" send 'Token' to Host "4"
+> [ 0.485760] (5:4@bob0.hamburger.edu) Host "4" received "Token"
+> [ 0.485760] (5:4@bob0.hamburger.edu) Host "4" send 'Token' to Host "5"
+> [ 0.552000] (6:5@bob2.hamburger.edu) Host "5" received "Token"
+> [ 0.552000] (6:5@bob2.hamburger.edu) Host "5" send 'Token' to Host "6"
+> [ 0.618240] (7:6@bob4.hamburger.edu) Host "6" received "Token"
+> [ 0.618240] (7:6@bob4.hamburger.edu) Host "6" send 'Token' to Host "7"
+> [ 0.794880] (8:7@alice0.crepe.fr) Host "7" received "Token"
+> [ 0.794880] (8:7@alice0.crepe.fr) Host "7" send 'Token' to Host "8"
+> [ 0.861120] (9:8@alice4.crepe.fr) Host "8" received "Token"
+> [ 0.861120] (9:8@alice4.crepe.fr) Host "8" send 'Token' to Host "9"
+> [ 0.927360] (10:9@alice1.crepe.fr) Host "9" received "Token"
+> [ 0.927360] (10:9@alice1.crepe.fr) Host "9" send 'Token' to Host "0"
+> [ 1.104000] (1:0@bob1.hamburger.edu) Host "0" received "Token"
> [ 1.104000] (0:@) Simulation time 1.104
-> [ 1.104000] (10:slave@alice1.crepe.fr) Send Data to "host0"
-> [ 1.104000] (1:master@bob1.hamburger.edu) Received "Token"
-! output sort
$ $SG_TEST_EXENV ${bindir:=.}/token_ring ${srcdir:=.}/two_peers.xml --cfg=coordinates:yes "--log=root.fmt:[%12.6r]%e(%i:%P@%h)%e%m%n"
> [ 0.000000] (0:@) Configuration change: Set 'coordinates' to 'yes'
-> [ 0.000000] (0:@) Bypassing the XML parser since surf_parse_open received a NULL pointer. If it is not what you want, go fix your code.
-> [ 5.221778] (1:master@peer_100030591) Send Data to "host1"
-> [ 5.221778] (2:slave@peer_100036570) Received "Token"
-> [ 10.443556] (0:@) Simulation time 10.4436
-> [ 10.443556] (1:master@peer_100030591) Received "Token"
-> [ 10.443556] (2:slave@peer_100036570) Send Data to "host0"
\ No newline at end of file
+> [ 0.000000] (0:@) Number of host '2'
+> [ 0.000000] (1:0@peer_100030591) Host "0" send 'Token' to Host "1"
+> [ 0.110400] (2:1@peer_100036570) Host "1" received "Token"
+> [ 0.110400] (2:1@peer_100036570) Host "1" send 'Token' to Host "0"
+> [ 0.220800] (1:0@peer_100030591) Host "0" received "Token"
+> [ 0.220800] (0:@) Simulation time 0.2208
\ No newline at end of file
--- /dev/null
+#! /usr/bin/perl
+
+# L.Bobelin (Perl newbie) 25th of November
+# Quick script to generate hierarchical clusters. Usage : <the script> p s d where :
+# - p : 2^p gives the total number of hosts.
+# - s : cluster size
+# - d : degree of inner nodes.
+#
+# output is the standard one.
+#
+#
+#Each node is numbered by a DFS in the tree. Each cluster is numbered by the DFS number of the leaf it is attached to and the number of cluster for each leaf.
+# Other infos :
+# - Same bb_lat used for any routers inside (not that complicated to modify too).
+# - constants defined in the first part of the script corresponding to classic cluster parameters. links_bw and links_lat added for the inner tree links
+# - bb_lat and bb_bw used in any backbone of the tree.
+# - fails if you set an obviously too small total number of hosts compared to the cluster size (generates a lot of stuff for nothing actually).
+#
+
+use Math::BigInt;
+
+$prefix= "";
+$suffix= "";
+$bw= "125000000";
+$power= "1000000000";
+$lat= "5E-5";
+$bb_bw= "2250000000";
+$bb_lat= "5E-4";
+$links_bw= "2250000000";
+$links_lat= "5E-5";
+$id= "";
+
+$p = $ARGV[0];
+$s = $ARGV[1];
+$d = $ARGV[2];
+
+$p = Math::BigInt->new($p);
+$d = Math::BigInt->new($d);
+$s = Math::BigInt->new($s);
+
+$cabinetnodes= $d;
+$nbsons= $d;
+$radical= "1-" . $s;
+$last=$s;
+
+# Number of clusters to generate ? Update: I hate this bigInt package, the way it behaves is SO stupid
+$totalnumberofhosts = Math::BigInt->new("2");
+$totalnumberofhosts->bpow($p);
+
+$totalnumberofCluster= $totalnumberofhosts->copy();
+
+$totalnumberofCluster->bdiv($s);
+
+# checking if we have to have something non homogeneous
+if ($totalnumberofhosts->copy()->bmod($s) != 0 )
+ {
+ $totalnumberofCluster++;
+ $last= $totalnumberofhosts->copy()->bmod($s);
+ }
+
+# Calculating height
+
+$height= $totalnumberofCluster->copy();
+$height->broot($d);
+
+# Checking if an exact root exists
+if ( $height->bcmp(Math::BigInt->new("1")) != 0 && ($height->copy()->bpow($d))->bcmp($totalnumberofCluster)) {
+
+ $height++; #will have to deal with empty set of clusters.
+ }
+# debug stuff
+#print "Computed : \n";
+#print STDERR "height: " . $height . "\n";
+#print STDERR "totalnumberofhosts: " . $totalnumberofhosts . "\n";
+#print STDERR "totalnumberofcluster: " . $totalnumberofCluster . "\n";
+#print STDERR "last cluster size (if equals to cluster size, then all clusters will be homogeneous) : " . $last . "\n";
+
+# Counter for giving unique IDs to ASes.
+$ASnumber;
+$ASnumber = 0;
+
+# Printing preamble
+print "<?xml version='1.0'?>\n";
+print "<!DOCTYPE platform SYSTEM \"http://simgrid.gforge.inria.fr/simgrid.dtd\">\n";
+print "<platform version=\"3\">\n";
+
+
+# Initiate recursion ...
+&DF_creation(0);
+
+# Closing tag, and then back home
+print "</platform>\n";
+
+# Recursive stuff for depth first Se... Creation
+sub DF_creation {
+ my($currDepth) = @_;
+
+ # Curr AS creation
+ print "<AS id=\"". $prefix . "AS_" . $ASnumber . $suffix . "\" routing=\"Full\">\n";
+
+ # Curr router AS creation stuff
+ print "<AS id=\"". $prefix . "exitAS_" . $ASnumber . $suffix . "\" routing=\"Full\">\n";
+ print " <router id=\"" . $prefix . "router_" . $ASnumber . $suffix . "\"/>\n";
+ print "</AS>\n";
+ # Saving my current number to return it to my father
+ my $toReturn = $ASnumber;
+ $ASnumber++;
+ if ($currDepth<$height && $totalnumberofCluster > 0)
+ {
+ # Creating current AS inner stuff
+ # I should have a table of sons numbers.
+ my @tsons = ();
+ my $createdSons = 0;
+ for (my $i =1; $i<=$nbsons && $totalnumberofCluster > 0 ; $i++)
+ {
+ #saving this son in my tab ... recursive call to create ASes and cluster underneath
+ push(@tsons, &DF_creation($currDepth + 1));
+ $createdSons++;
+ #
+ # Creating link to this son
+ print "<link id=\"". $prefix . $tsons[$i-1] . $suffix . "\" bandwidth=\"" . $links_bw . "\" latency=\"" . $links_lat . "\"/>\n";
+ }
+ # curr backbone creation
+ print "<link id=\"". $prefix . "bb_" . $toReturn . $suffix . "\" bandwidth=\"" . $bb_bw . "\" latency=\"" . $bb_lat . "\"/>\n";
+ # Full routing AS to AS declaration
+ for (my $i =1; $i<=$createdSons ; $i++)
+ {
+ for (my $j =$i+1; $j<=$createdSons ; $j++)
+ {
+ print "<ASroute src=\"" . $prefix . "AS_" . $tsons[$i-1] . $suffix . "\"\n";
+ print " dst=\"" . $prefix . "AS_" . $tsons[$j-1] . $suffix . "\"\n";
+ print " gw_src=\"" . $prefix . "router_" . $tsons[$i-1] . $suffix . "\"\n";
+ print " gw_dst=\"" . $prefix . "router_" . $tsons[$j-1] . $suffix . "\"\n";
+ print " symmetrical=\"YES\">\n";
+
+ print " <link_ctn id=\"" . $prefix . $tsons[$i-1] . $suffix . "\"/>\n";
+ print " <link_ctn id=\"" . $prefix . "bb_" . $toReturn . $suffix . "\"/>\n";
+ print " <link_ctn id=\"" . $prefix . $tsons[$j-1] . $suffix . "\"/>\n";
+ print "</ASroute>\n";
+ }
+ }
+ # Now routes to the exit AS
+ for (my $i =1; $i<=$createdSons ; $i++)
+ {
+ print "<ASroute src=\"" . $prefix . "AS_" . $tsons[$i-1] . $suffix . "\"\n";
+ print " dst=\"" . $prefix . "exitAS_" . $toReturn . $suffix . "\"\n";
+ print " gw_src=\"" . $prefix . "router_" . $tsons[$i-1] . $suffix . "\"\n";
+ print " gw_dst=\"" . $prefix . "router_" . $toReturn . $suffix . "\"\n";
+ print " symmetrical=\"YES\">\n";
+ print " <link_ctn id=\"" . $prefix . $tsons[$i-1] . $suffix . "\"/>\n";
+ print " <link_ctn id=\"" . $prefix . "bb_" . $toReturn . $suffix . "\"/>\n";
+ print "</ASroute>\n";
+ }
+ print "</AS>\n";
+ # DO I have extra stuff to add ? I don't think so.
+ return $toReturn;
+ }
+ else { # On leaves,
+ my $lastNumberOfClusterCreated = 0;
+ #I must create clusters now
+ for(my $i = 1; $i <= $cabinetnodes && $totalnumberofCluster>0 ; $i++) {
+ $lastNumberOfClusterCreated++;
+ if ($totalnumberofCluster==1)
+ {
+ print "<cluster id=\"". $prefix . "cl_" . $toReturn . "_" . $i . $suffix . "\" prefix=\"" . $prefix . "c_" . $toReturn . "_" . $i . "-\" suffix=\"" . $suffix . "\" radical=\"1-"
+ . $last . "\" power=\"" . $power . "\" bw=\"" . $bw . "\" lat=\"" . $lat . "\" bb_bw=\"" . $bb_bw . "\" bb_lat=\"" . $bb_lat . "\"/>\n";
+ }
+ else
+ {
+ print "<cluster id=\"". $prefix . "cl_" . $toReturn . "_" . $i . $suffix . "\" prefix=\"" . $prefix . "c_" . $toReturn . "_" . $i . "-\" suffix=\"" . $suffix . "\" radical=\""
+ . $radical . "\" power=\"" . $power . "\" bw=\"" . $bw . "\" lat=\"" . $lat . "\" bb_bw=\"" . $bb_bw . "\" bb_lat=\"" . $bb_lat . "\"/>\n";
+ }
+ $totalnumberofCluster--;
+ }
+ # Creating links to clusters
+ for(my $i = 1; $i <= $lastNumberOfClusterCreated ; $i++) {
+ print "<link id=\"". $prefix . $toReturn . "_" . $i . $suffix . "\" bandwidth=\"" . $links_bw . "\" latency=\"" . $links_lat . "\"/>\n";
+ }
+
+ #
+ # curr backbone creation
+ print "<link id=\"". $prefix . "bb_" . $toReturn . $suffix . "\" bandwidth=\"" . $bb_bw . "\" latency=\"" . $bb_lat . "\"/>\n";
+
+ # I must create routes between clusters now
+ for (my $i =1; $i<=$lastNumberOfClusterCreated ; $i++)
+ {
+ for (my $j =$i+1; $j<=$lastNumberOfClusterCreated ; $j++)
+ {
+ print "<ASroute src=\"" . $prefix . "cl_" . $toReturn . "_" . $i . $suffix . "\"\n";
+ print " dst=\"" . $prefix . "cl_" . $toReturn . "_" . $j . $suffix . "\"\n";
+
+ print " gw_src=\"" . $prefix . "c_" . $toReturn . "_" . $i . "-" . $prefix . "cl_" . $toReturn . "_" . $i . $suffix . "_router" . $suffix ."\"\n";
+ print " gw_dst=\"" . $prefix . "c_" . $toReturn . "_" . $j . "-" . $prefix . "cl_" . $toReturn . "_" . $j . $suffix . "_router" . $suffix . "\"\n";
+ print " symmetrical=\"YES\">\n";
+
+ print " <link_ctn id=\"" . $prefix . $toReturn. "_" . $i . $suffix . "\"/>\n";
+ print " <link_ctn id=\"" . $prefix . "bb_" . $toReturn . $suffix . "\"/>\n";
+ print " <link_ctn id=\"" . $prefix . $toReturn . "_" . $j . $suffix . "\"/>\n";
+ print "</ASroute>\n";
+ }
+ }
+ # Now routes to the exit AS
+ for (my $i =1; $i<=$lastNumberOfClusterCreated ; $i++)
+ {
+ print "<ASroute src=\"" . $prefix . "cl_" . $toReturn . "_" . $i . $suffix . "\"\n";
+ print " dst=\"" . $prefix . "exitAS_" . $toReturn . $suffix . "\"\n";
+ # SAME HERE !!
+ print " gw_src=\"" . $prefix . "c_" . $toReturn . "_" . $i . "-" . $prefix . "cl_" . $toReturn . "_" . $i . $suffix . "_router" . $suffix ."\"\n";
+ print " gw_dst=\"" . $prefix . "router_" . $toReturn . $suffix . "\"\n";
+ print " symmetrical=\"YES\">\n";
+ print " <link_ctn id=\"" . $prefix . $toReturn . "_" . $i . $suffix . "\"/>\n";
+ print " <link_ctn id=\"" . $prefix . "bb_" . $toReturn . $suffix . "\"/>\n";
+ print "</ASroute>\n";
+ }
+ print "</AS>\n";
+ # Should be done with it...
+ return $toReturn;
+ }
+
+}
--- /dev/null
+#! /usr/bin/perl
+
+# L.Bobelin (Perl newbie) 24th of November
+# Quick script to generate hierarchical clusters. Usage : add the special cluster tag (description below) in your "normal" platform file. Then run the script :
+# - First arg : the input file where you midified your cluster tag
+# - Second one : the output file where all the stuff will be generated.
+# Builds a complete tree to access clusters ; each node of the tree is inclosed in an AS, where full routing applies.
+#
+# Number of cluster per leaf is given by cabinetnodes attr.
+#
+#
+# Choosed to modify a cluster tag to allow to give additional informations :
+# - nbsons : degree of inner
+# - height : tree heigth
+# - cabinetnodes : cluster per leaf
+#
+# Each node is numbered by a DFS in the tree. Each cluster is numbered by the DFS number of the leaf it is attached to and the number of cluster for each leaf.
+#
+#
+# Example syntax for hierarchical cluster creation :
+# <cluster id="AS_cb1" prefix="cb1-" suffix=".dc1.acloud.com" power="5.2297E9" bw="1.25E8" lat="1.0E-4 bb_bw="1.25E9" bb_lat="1.0E-4" radical="0-99" cabinetnodes="4" height="3" nbsons="2" links_lat="1.0E-4" links_bw="1.25E9"/>
+# Other infos :
+# - special tag has to be on one line because I don't want to bother with parsing issues
+# - Same bb_lat used for any routers inside (not that complicated to modify too)
+# - lame perl ? I'm a script kiddie in perl, it may well be my first perl stuff.
+# - Don't try to check or validate the modified file with the DTD, of course, as this is not a part of it.
+
+# Counter for giving unique IDs to ASes.
+$ASnumber;
+$ASnumber = 0;
+
+$infile;
+$outfile;
+
+$infile = $ARGV[0];
+$outfile = $ARGV[1];
+open IN, "$infile" || die "Cannot parse " . $infile . " ...\n";
+open OUT,">$outfile" || die "Cannot use the output file " . $outfile . " ...\n";
+my $line;
+while ($line = <IN>) {
+# looking for good lines.
+if ($line =~ / cabinetnodes=/)
+{ #Retrieving informations
+ ($line=~ /cabinetnodes=\"([^\"]*)/);
+ $cabinetnodes= $1;
+ ($line=~ /height=\"([^\"]*)/);
+ $height= $1;
+ ($line=~ /nbsons=\"([^\"]*)/);
+ $nbsons= $1;
+ ($line=~ /id=\"([^\"]*)/);
+ $id= $1;
+ ($line=~ /prefix=\"([^\"]*)/);
+ $prefix= $1;
+ ($line=~ /suffix=\"([^\"]*)/);
+ $suffix= $1;
+ ($line=~ /bw=\"([^\"]*)/);
+ $bw= $1;
+ ($line=~ /power=\"([^\"]*)/);
+ $power= $1;
+ ($line=~ /lat=\"([^\"]*)/);
+ $lat= $1;
+ ($line=~ /bb_bw=\"([^\"]*)/);
+ $bb_bw= $1;
+ ($line=~ /bb_lat=\"([^\"]*)/);
+ $bb_lat= $1;
+ ($line=~ /links_bw=\"([^\"]*)/);
+ $links_bw= $1;
+ ($line=~ /links_lat=\"([^\"]*)/);
+ $links_lat= $1;
+ ($line=~ /radical=\"([^\"]*)/);
+ $radical= $1;
+
+ print "Variables read : \n";
+ print "number of clusters in each cabinet: " . $cabinetnodes . "\n";
+ print "Tree heigth: " . $height . "\n";
+ print "Degree of each node: " . $nbsons . "\n";
+ print "General id: ". $id . "\n";
+ print "General prefix: " . $prefix . "\n";
+ print "General suffix: ". $suffix . "\n";
+ print "Bandwidth for cluster inner links: " . $bw . "\n";
+ print "Power for cluster nodes: " . $power . "\n";
+ print "Latency for clusters inner links :" . $lat . "\n";
+ print "Backbone bandwwidth (used in all backbones, including the tree ones):" . $bb_bw . "\n";
+ print "Backbone latency (used in all backbones, including the tree ones):" . $bb_lat . "\n";
+ print "Tree links bandwidth: " . $links_bw . "\n";
+ print "Tree links latency: " . $links_lat . "\n";
+ print "Radical: " . $radical . "\n";
+
+
+
+ &DF_creation(0);
+ }
+else {
+print OUT $line;
+}
+} #End while
+close IN;
+close OUT;
+print $infile . " -> " . $outfile . " ... Done.\n";
+
+# Recursive stuff for depth first Se... Creation
+sub DF_creation {
+ my($currDepth) = @_;
+
+ # Curr AS creation
+ print OUT "<AS id=\"". $prefix . "AS_" . $ASnumber . $suffix . "\" routing=\"Full\">\n";
+
+ # Curr router AS creation stuff
+ print OUT "<AS id=\"". $prefix . "exitAS_" . $ASnumber . $suffix . "\" routing=\"Full\">\n";
+ print OUT " <router id=\"" . $prefix . "router_" . $ASnumber . $suffix . "\"/>\n";
+ print OUT "</AS>\n";
+ # Saving my current number to return it to my father
+ my $toReturn = $ASnumber;
+ $ASnumber++;
+ if ($currDepth<$height)
+ {
+ # Creating current AS inner stuff
+ # I should have a table of sons numbers.
+ my @tsons = ();
+ for (my $i =1; $i<=$nbsons ; $i++)
+ {
+ #saving this son in my tab ... recursive call to create ASes and cluster underneath
+ push(@tsons, &DF_creation($currDepth + 1));
+ #
+ # Creating link to this son
+ print OUT "<link id=\"". $prefix . $tsons[$i-1] . $suffix . "\" bandwidth=\"" . $links_bw . "\" latency=\"" . $links_lat . "\"/>\n";
+ }
+ # curr backbone creation
+ print OUT "<link id=\"". $prefix . "bb_" . $toReturn . $suffix . "\" bandwidth=\"" . $bb_bw . "\" latency=\"" . $bb_lat . "\"/>\n";
+ # Full routing AS to AS declaration
+ for (my $i =1; $i<=$nbsons ; $i++)
+ {
+ for (my $j =$i+1; $j<=$nbsons ; $j++)
+ {
+ print OUT "<ASroute src=\"" . $prefix . "AS_" . $tsons[$i-1] . $suffix . "\"\n";
+ print OUT " dst=\"" . $prefix . "AS_" . $tsons[$j-1] . $suffix . "\"\n";
+ print OUT " gw_src=\"" . $prefix . "router_" . $tsons[$i-1] . $suffix . "\"\n";
+ print OUT " gw_dst=\"" . $prefix . "router_" . $tsons[$j-1] . $suffix . "\"\n";
+ print OUT " symmetrical=\"YES\">\n";
+
+ print OUT " <link_ctn id=\"" . $prefix . $tsons[$i-1] . $suffix . "\"/>\n";
+ print OUT " <link_ctn id=\"" . $prefix . "bb_" . $toReturn . $suffix . "\"/>\n";
+ print OUT " <link_ctn id=\"" . $prefix . $tsons[$j-1] . $suffix . "\"/>\n";
+ print OUT "</ASroute>\n";
+ }
+ }
+ # Now routes to the exit AS
+ for (my $i =1; $i<=$nbsons ; $i++)
+ {
+ print OUT "<ASroute src=\"" . $prefix . "AS_" . $tsons[$i-1] . $suffix . "\"\n";
+ print OUT " dst=\"" . $prefix . "exitAS_" . $toReturn . $suffix . "\"\n";
+ print OUT " gw_src=\"" . $prefix . "router_" . $tsons[$i-1] . $suffix . "\"\n";
+ print OUT " gw_dst=\"" . $prefix . "router_" . $toReturn . $suffix . "\"\n";
+ print OUT " symmetrical=\"YES\">\n";
+ print OUT " <link_ctn id=\"" . $prefix . $tsons[$i-1] . $suffix . "\"/>\n";
+ print OUT " <link_ctn id=\"" . $prefix . "bb_" . $toReturn . $suffix . "\"/>\n";
+ print OUT "</ASroute>\n";
+ }
+ print OUT "</AS>\n";
+ # DO I have extra stuff to add ? I don't think so.
+ return $toReturn;
+ }
+ else { # On leaves,
+
+ #I must create clusters now
+ for(my $i = 1; $i <= $cabinetnodes; $i++) {
+ print OUT "<cluster id=\"". $prefix . "cluster_" . $toReturn . $i . $suffix . "\" prefix=\"" . $prefix . "c_" . $toReturn. $i . "-\" suffix=\"" . $suffix . "\" radical=\""
+ . $radical . "\" power=\"" . $power . "\" bw=\"" . $bw . "\" lat=\"" . $lat . "\" bb_bw=\"" . $bb_bw . "\" bb_lat=\"" . $bb_lat . "\"/>\n";
+ }
+ # Creating links to clusters
+ for(my $i = 1; $i <= $cabinetnodes; $i++) {
+ print OUT "<link id=\"". $prefix . $toReturn . "_" . $i . $suffix . "\" bandwidth=\"" . $links_bw . "\" latency=\"" . $links_lat . "\"/>\n";
+ }
+
+ #
+ # curr backbone creation
+ print OUT "<link id=\"". $prefix . "bb_" . $toReturn . $suffix . "\" bandwidth=\"" . $bb_bw . "\" latency=\"" . $bb_lat . "\"/>\n";
+
+ # I must create routes between clusters now
+ for (my $i =1; $i<=$cabinetnodes ; $i++)
+ {
+ for (my $j =$i+1; $j<=$cabinetnodes ; $j++)
+ {
+ print OUT "<ASroute src=\"" . $prefix . "cluster_" . $toReturn . $i . $suffix . "\"\n";
+ print OUT " dst=\"" . $prefix . "cluster_" . $toReturn . $j . $suffix . "\"\n";
+
+ print OUT " gw_src=\"" . $prefix . "c_" . $toReturn. $i . "-" . $prefix . "cluster_" . $toReturn . $i . $suffix . "_router" . $suffix ."\"\n";
+ print OUT " gw_dst=\"" . $prefix . "c_" . $toReturn. $j . "-" . $prefix . "cluster_" . $toReturn . $j . $suffix . "_router" . $suffix . "\"\n";
+ print OUT " symmetrical=\"YES\">\n";
+
+ print OUT " <link_ctn id=\"" . $prefix . $toReturn. "_" . $i . $suffix . "\"/>\n";
+ print OUT " <link_ctn id=\"" . $prefix . "bb_" . $toReturn . $suffix . "\"/>\n";
+ print OUT " <link_ctn id=\"" . $prefix . $toReturn . "_" . $j . $suffix . "\"/>\n";
+ print OUT "</ASroute>\n";
+ }
+ }
+ # Now routes to the exit AS
+ for (my $i =1; $i<=$cabinetnodes ; $i++)
+ {
+ print OUT "<ASroute src=\"" . $prefix . "cluster_" . $toReturn . $i . $suffix . "\"\n";
+ print OUT " dst=\"" . $prefix . "exitAS_" . $toReturn . $suffix . "\"\n";
+ # SAME HERE !!
+ print OUT " gw_src=\"" . $prefix . "c_" . $toReturn. $i . "-" . $prefix . "cluster_" . $toReturn . $i . $suffix . "_router" . $suffix ."\"\n";
+ print OUT " gw_dst=\"" . $prefix . "router_" . $toReturn . $suffix . "\"\n";
+ print OUT " symmetrical=\"YES\">\n";
+ print OUT " <link_ctn id=\"" . $prefix . $toReturn . "_" . $i . $suffix . "\"/>\n";
+ print OUT " <link_ctn id=\"" . $prefix . "bb_" . $toReturn . $suffix . "\"/>\n";
+ print OUT "</ASroute>\n";
+ }
+ print OUT "</AS>\n";
+ # Should be done with it...
+ return $toReturn;
+ }
+
+}
int smx_context_stack_size = 128 * 1024;
#ifdef HAVE_THREAD_LOCAL_STORAGE
-__thread smx_context_t smx_current_context;
+static __thread smx_context_t smx_current_context_parallel;
#else
-smx_context_t smx_current_context; /* define it anyway, will be used in non-parallel mode */
static xbt_os_thread_key_t smx_current_context_key = 0;
#endif
-
+static smx_context_t smx_current_context_serial;
static int smx_parallel_contexts = 1;
static int smx_parallel_threshold = 2;
*/
XBT_INLINE smx_context_t SIMIX_context_get_current(void)
{
+ if (SIMIX_context_is_parallel()) {
#ifdef HAVE_THREAD_LOCAL_STORAGE
- return smx_current_context;
+ return smx_current_context_parallel;
#else
- return xbt_os_thread_get_specific(smx_current_context_key);
+ return xbt_os_thread_get_specific(smx_current_context_key);
#endif
+ }
+ else {
+ return smx_current_context_serial;
+ }
}
/**
*/
XBT_INLINE void SIMIX_context_set_current(smx_context_t context)
{
+ if (SIMIX_context_is_parallel()) {
#ifdef HAVE_THREAD_LOCAL_STORAGE
- smx_current_context = context;
+ smx_current_context_parallel = context;
#else
- xbt_os_thread_set_specific(smx_current_context_key, context);
+ xbt_os_thread_set_specific(smx_current_context_key, context);
#endif
+ }
+ else {
+ smx_current_context_serial = context;
+ }
}
void model_dijkstra_both_end(AS_t as)
{
- as_dijkstra_t THIS = (as_dijkstra_t) as;
+ as_dijkstra_t THIS_AS = (as_dijkstra_t) as;
xbt_node_t node = NULL;
unsigned int cursor2;
xbt_dynar_t nodes = NULL;
/* Create the topology graph */
- if(!THIS->route_graph)
- THIS->route_graph = xbt_graph_new_graph(1, NULL);
- if(!THIS->graph_node_map)
- THIS->graph_node_map = xbt_dict_new_homogeneous(&graph_node_map_elem_free);
+ if(!THIS_AS->route_graph)
+ THIS_AS->route_graph = xbt_graph_new_graph(1, NULL);
+ if(!THIS_AS->graph_node_map)
+ THIS_AS->graph_node_map = xbt_dict_new_homogeneous(&graph_node_map_elem_free);
- if (THIS->cached && !THIS->route_cache)
- THIS->route_cache = xbt_dict_new_homogeneous(&route_cache_elem_free);
+ if (THIS_AS->cached && !THIS_AS->route_cache)
+ THIS_AS->route_cache = xbt_dict_new_homogeneous(&route_cache_elem_free);
/* Add the loopback if needed */
if (as->hierarchy == SURF_ROUTING_BASE)
- add_loopback_dijkstra(THIS);
+ add_loopback_dijkstra(THIS_AS);
/* initialize graph indexes in nodes after graph has been built */
- nodes = xbt_graph_get_nodes(THIS->route_graph);
+ nodes = xbt_graph_get_nodes(THIS_AS->route_graph);
xbt_dynar_foreach(nodes, cursor2, node) {
graph_node_data_t data = xbt_graph_node_get_data(node);
} else if (!strcmp(src, dst) && are_processing_units) {
xbt_dynar_push(route->link_list, &(global_routing->loopback));
if (lat)
- *lat += surf_network_model->extension.network.get_link_latency(link);
+ *lat += surf_network_model->extension.network.get_link_latency(global_routing->loopback);
} else {
THROWF(arg_error,0,"No route from '%s' to '%s'??",src,dst);
//xbt_dynar_reset(route->link_list);
* under the terms of the license (GNU LGPL) which comes with this package. */
#include "gras_config.h"
#include <unistd.h>
+
#ifndef _XBT_WIN32
#include <sys/syscall.h>
#endif
#ifdef HAVE_FUTEX_H
- #include <linux/futex.h>
-#else
- #include "xbt/xbt_os_thread.h"
+#include <linux/futex.h>
#endif
-#include <errno.h>
-#include "parmap_private.h"
+
+#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"
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_parmap, xbt, "parmap: parallel map");
XBT_LOG_NEW_SUBCATEGORY(xbt_parmap_unit, xbt_parmap, "parmap unit testing");
-static void *_xbt_parmap_worker_main(void *parmap);
+typedef enum {
+ PARMAP_WORK = 0,
+ PARMAP_DESTROY
+} e_xbt_parmap_flag_t;
+
+static void xbt_parmap_start(xbt_parmap_t parmap);
+static void xbt_parmap_signal(xbt_parmap_t parmap);
+static void xbt_parmap_wait(xbt_parmap_t parmap);
+static void xbt_parmap_end(xbt_parmap_t parmap);
+static void *xbt_parmap_worker_main(void *parmap);
+
#ifdef HAVE_FUTEX_H
- static void futex_wait(int *uaddr, int val);
- static void futex_wake(int *uaddr, int val);
+static void futex_wait(int *uaddr, int val);
+static void futex_wake(int *uaddr, int val);
#endif
+
+/**
+ * \brief Parallel map structure
+ */
+typedef struct s_xbt_parmap {
+ e_xbt_parmap_flag_t status; /* is the parmap active or being destroyed? */
+
+ int work; /* index of the current round (1 is the first) */
+ int done; /* number of rounds already done */
+ unsigned int thread_counter; /* number of threads currently working */
+ unsigned int num_workers; /* total number of worker threads */
+ unsigned int workers_max_id; /* id of the next worker thread to create */
+ 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 */
+ unsigned int index; /* index of the next element of data to pick */
+} s_xbt_parmap_t;
+
+/**
+ * \brief Creates a parallel map object
+ * \param num_workers number of worker threads to create
+ * \return the parmap created
+ */
xbt_parmap_t xbt_parmap_new(unsigned int num_workers)
{
unsigned int i;
/* Initialize the thread pool data structure */
xbt_parmap_t parmap = xbt_new0(s_xbt_parmap_t, 1);
-#ifdef HAVE_FUTEX_H
- parmap->sync_event = xbt_new0(s_xbt_event_t, 1);
-#endif
+
parmap->num_workers = num_workers;
parmap->status = PARMAP_WORK;
-#ifdef HAVE_FUTEX_H
- parmap->sync_event->threads_to_wait = num_workers;
-#endif
+
/* Create the pool of worker threads */
- for(i=0; i < num_workers; i++){
- worker = xbt_os_thread_create(NULL, _xbt_parmap_worker_main, parmap, NULL);
+ for (i = 0; i < num_workers; i++) {
+ worker = xbt_os_thread_create(NULL, xbt_parmap_worker_main, parmap, NULL);
xbt_os_thread_detach(worker);
}
-#ifdef HAVE_FUTEX_H
- xbt_event_init(parmap->sync_event);
-#endif
+ xbt_parmap_start(parmap);
return parmap;
}
+/**
+ * \brief Destroys a parmap
+ * \param parmap the parmap to destroy
+ */
void xbt_parmap_destroy(xbt_parmap_t parmap)
-{
+{
parmap->status = PARMAP_DESTROY;
-#ifdef HAVE_FUTEX_H
- xbt_event_signal(parmap->sync_event);
- xbt_free(parmap->sync_event);
-#endif
+ xbt_parmap_signal(parmap);
xbt_free(parmap);
}
- void xbt_parmap_apply(xbt_parmap_t parmap, void_f_pvoid_t fun, xbt_dynar_t data)
+/**
+ * \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*/
parmap->fun = fun;
parmap->data = data;
parmap->index = 0;
-#ifdef HAVE_FUTEX_H
- xbt_event_signal(parmap->sync_event);
-#endif
+ xbt_parmap_signal(parmap);
XBT_DEBUG("Job done");
}
-void* xbt_parmap_next(xbt_parmap_t parmap) {
-
+/**
+ * \brief Returns a next task to process.
+ *
+ * Worker threads call this function to get more work.
+ *
+ * \return the next task to process, or NULL if there is no more work
+ */
+void* xbt_parmap_next(xbt_parmap_t parmap)
+{
unsigned int index = __sync_fetch_and_add(&parmap->index, 1);
if (index < xbt_dynar_length(parmap->data)) {
return xbt_dynar_get_as(parmap->data, index, void*);
return NULL;
}
-unsigned long xbt_parmap_get_worker_id(xbt_parmap_t parmap) {
+/**
+ * \brief Returns the worker id of the current thread.
+ * \param parmap a parmap
+ * \return the worker id
+ */
+unsigned long xbt_parmap_get_worker_id(xbt_parmap_t parmap)
+{
return (unsigned long) xbt_os_thread_get_extra_data();
}
-static void *_xbt_parmap_worker_main(void *arg)
+/**
+ * \brief Main function of a worker thread.
+ * \param arg the parmap
+ */
+static void *xbt_parmap_worker_main(void *arg)
{
unsigned int worker_id;
xbt_parmap_t parmap = (xbt_parmap_t) arg;
/* Worker's main loop */
while (1) {
-#ifdef HAVE_FUTEX_H
- xbt_event_wait(parmap->sync_event);
-#endif
+ xbt_parmap_wait(parmap);
if (parmap->status == PARMAP_WORK) {
XBT_DEBUG("Worker %u got a job", worker_id);
/* We are destroying the parmap */
} else {
-#ifdef HAVE_FUTEX_H
- xbt_event_end(parmap->sync_event);
-#endif
+ xbt_parmap_end(parmap);
XBT_DEBUG("Shutting down worker %u", worker_id);
return NULL;
}
XBT_VERB("Waking futex %p", uaddr);
syscall(SYS_futex, uaddr, FUTEX_WAKE_PRIVATE, val, NULL, NULL, 0);
}
+#endif
-void xbt_event_init(xbt_event_t event)
+/**
+ * \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_start(xbt_parmap_t parmap)
{
- int myflag = event->done;
- if(event->thread_counter < event->threads_to_wait)
- futex_wait(&event->done, myflag);
+#ifdef HAVE_FUTEX_H
+ int myflag = parmap->done;
+ if (parmap->thread_counter < parmap->num_workers) {
+ /* wait for all workers to be ready */
+ futex_wait(&parmap->done, myflag);
+ }
+#endif
}
-void xbt_event_signal(xbt_event_t event)
+/**
+ * \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_signal(xbt_parmap_t parmap)
{
- int myflag = event->done;
- event->thread_counter = 0;
- event->work++;
- futex_wake(&event->work, event->threads_to_wait);
- futex_wait(&event->done, myflag);
+#ifdef HAVE_FUTEX_H
+ int myflag = parmap->done;
+ parmap->thread_counter = 0;
+ parmap->work++;
+
+ /* wake all workers */
+ futex_wake(&parmap->work, parmap->num_workers);
+
+ /* wait for all of them to finish */
+ futex_wait(&parmap->done, myflag);
+#endif
}
-void xbt_event_wait(xbt_event_t event)
+/**
+ * \brief Waits for some work to process.
+ *
+ * This function is called by each worker when it has no more work to do.
+ *
+ * \param parmap a parmap
+ */
+static void xbt_parmap_wait(xbt_parmap_t parmap)
{
+#ifdef HAVE_FUTEX_H
int myflag;
unsigned int mycount;
- myflag = event->work;
- mycount = __sync_add_and_fetch(&event->thread_counter, 1);
- if(mycount == event->threads_to_wait){
- event->done++;
- futex_wake(&event->done, 1);
+ myflag = parmap->work;
+ mycount = __sync_add_and_fetch(&parmap->thread_counter, 1);
+ if (mycount == parmap->num_workers) {
+ /* all workers have finished, wake the controller */
+ parmap->done++;
+ futex_wake(&parmap->done, 1);
}
- futex_wait(&event->work, myflag);
+ /* wait for more work */
+ futex_wait(&parmap->work, myflag);
+#endif
}
-void xbt_event_end(xbt_event_t event)
+/**
+ * \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_end(xbt_parmap_t parmap)
{
+#ifdef HAVE_FUTEX_H
unsigned int mycount;
- mycount = __sync_add_and_fetch(&event->thread_counter, 1);
- if(mycount == event->threads_to_wait){
- event->done++;
- futex_wake(&event->done, 1);
+ mycount = __sync_add_and_fetch(&parmap->thread_counter, 1);
+ if (mycount == parmap->num_workers) {
+ /* all workers have finished, wake the controller */
+ parmap->done++;
+ futex_wake(&parmap->done, 1);
}
-}
#endif
+}
#ifdef SIMGRID_TEST
#include "xbt.h"
XBT_TEST_SUITE("parmap", "Parallel Map");
XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(xbt_parmap_unit);
-
-
xbt_parmap_t parmap;
void fun(void *arg);
{
xbt_test_add("Create the parmap");
- unsigned long i,j;
+ unsigned long i, j;
xbt_dynar_t data = xbt_dynar_new(sizeof(void *), NULL);
/* Create the parallel map */
parmap = xbt_parmap_new(10);
- for(j=0; j < 100; j++){
+ for(j = 0; j < 100; j++) {
xbt_dynar_push_as(data, void *, (void *)j);
}
- for(i=0; i < 5; i++)
+ for (i = 0; i < 5; i++) {
xbt_parmap_apply(parmap, fun, data);
+ }
/* Destroy the parmap */
xbt_parmap_destroy(parmap);
+++ /dev/null
-/* Copyright (c) 2004, 2005, 2007, 2009, 2010. 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_THREADPOOL_PRIVATE_H
-#define _XBT_THREADPOOL_PRIVATE_H
-
-#include "xbt/parmap.h"
-#include "xbt/xbt_os_thread.h"
-#include "xbt/sysdep.h"
-#include "xbt/dynar.h"
-#include "xbt/log.h"
-#include "xbt/xbt_os_time.h"
-
-typedef enum{
- PARMAP_WORK = 0,
- PARMAP_DESTROY
-} e_xbt_parmap_flag_t;
-
-#ifdef HAVE_FUTEX_H
-typedef struct s_xbt_event{
- int work;
- int done;
- unsigned int thread_counter;
- unsigned int threads_to_wait;
-}s_xbt_event_t, *xbt_event_t;
-
-void xbt_event_init(xbt_event_t event);
-void xbt_event_signal(xbt_event_t event);
-void xbt_event_wait(xbt_event_t event);
-void xbt_event_end(xbt_event_t event);
-#endif
-
-typedef struct s_xbt_parmap {
- e_xbt_parmap_flag_t status;
-#ifdef HAVE_FUTEX_H
- xbt_event_t sync_event;
-#endif
- unsigned int num_workers;
- unsigned int workers_max_id;
- void_f_pvoid_t fun;
- xbt_dynar_t data;
- unsigned int index;
-} s_xbt_parmap_t;
-
-#endif