Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of scm.gforge.inria.fr:/gitroot/simgrid/simgrid
authorMartin Quinson <martin.quinson@loria.fr>
Mon, 7 Dec 2015 16:27:27 +0000 (17:27 +0100)
committerMartin Quinson <martin.quinson@loria.fr>
Mon, 7 Dec 2015 16:27:27 +0000 (17:27 +0100)
65 files changed:
doc/doxygen/FAQ.doc
doc/manpage/smpirun.1
examples/java/async/async.tesh
examples/java/bittorrent/bittorrent.tesh
examples/java/chord/chord.tesh
examples/java/cloud/cloud.tesh
examples/java/cloud/migration/migration.tesh
examples/java/commTime/commtime.tesh
examples/java/kademlia/kademlia.tesh
examples/java/master_slave_bypass/bypass.tesh
examples/java/master_slave_kill/kill.tesh
examples/java/masterslave/masterslave.tesh
examples/java/migration/migration.tesh
examples/java/mutualExclusion/mutualexclusion.tesh
examples/java/pingPong/pingpong.tesh
examples/java/priority/priority.tesh
examples/java/reservationSurfPlugin/reservation_surf_plugin.tesh
examples/java/startKillTime/startKillTime.tesh
examples/java/surfCpuModel/surf_cpu_model.tesh
examples/java/surfPlugin/surf_plugin.tesh
examples/java/suspend/suspend.tesh
examples/java/tracing/tracingPingPong.tesh
examples/scala/master_slave_bypass/bypass.tesh
examples/scala/master_slave_kill/kill.tesh
examples/scala/masterslave/masterslave.tesh
include/simgrid/simix.h
include/simgrid/simix.hpp [new file with mode: 0644]
include/xbt/sysdep.h
src/bindings/java/JavaContext.cpp [new file with mode: 0644]
src/bindings/java/JavaContext.hpp [new file with mode: 0644]
src/bindings/java/jmsg.cpp [moved from src/bindings/java/jmsg.c with 71% similarity]
src/bindings/java/jmsg.h
src/bindings/java/jmsg_host.c
src/bindings/java/jmsg_host.h
src/bindings/java/jmsg_process.cpp [moved from src/bindings/java/jmsg_process.c with 84% similarity]
src/bindings/java/jmsg_process.h
src/bindings/java/jmsg_storage.c
src/bindings/java/jmsg_task.c
src/bindings/java/jmsg_vm.c
src/bindings/java/jxbt_utilities.h
src/bindings/java/smx_context_cojava.c [deleted file]
src/bindings/java/smx_context_cojava.h [deleted file]
src/bindings/java/smx_context_java.c [deleted file]
src/bindings/java/smx_context_java.h [deleted file]
src/simix/BoostContext.cpp [new file with mode: 0644]
src/simix/BoostContext.hpp [new file with mode: 0644]
src/simix/Context.cpp [new file with mode: 0644]
src/simix/RawContext.cpp [new file with mode: 0644]
src/simix/ThreadContext.cpp [new file with mode: 0644]
src/simix/ThreadContext.hpp [new file with mode: 0644]
src/simix/UContext.cpp [new file with mode: 0644]
src/simix/smx_context.cpp
src/simix/smx_context_base.cpp [deleted file]
src/simix/smx_context_boost.cpp [deleted file]
src/simix/smx_context_raw.cpp [deleted file]
src/simix/smx_context_sysv.cpp [deleted file]
src/simix/smx_context_thread.cpp [deleted file]
src/simix/smx_global.cpp
src/simix/smx_private.h
src/simix/smx_private.hpp [new file with mode: 0644]
src/simix/smx_process.cpp
src/smpi/smpi_global.c
src/xbt/parmap.cpp
teshsuite/java/sleep_host_off/sleep_host_off.tesh
tools/cmake/DefinePackages.cmake

index c5afe60..f70f833 100644 (file)
@@ -608,6 +608,19 @@ of the root tag. Currently, it should read:
 If your files are too old, you can use the simgrid_update_xml.pl
 script which can be found in the tools directory of the archive.
 
+\subsection faq_trouble_debug Debugging SMPI applications
+
+In order to debug SMPI programs, you can use the following options:
+
+- <b>-wrapper 'gdb --args'</b>: this option is used to use a wrapper
+  in order to call the SMPI process. Good candidates for this options
+  are "gdb --args", "valgrind", "rr record", "strace", etc;
+
+- <b>-foreground</b>: this options gives the debugger access to the terminal
+  which is needed in order to use an interactive debugger.
+
+Both options are needed in order to run the SMPI process under GDB.
+
 \subsection faq_trouble_valgrind Valgrind-related and other debugger issues
 
 If you don't, you really should use valgrind to debug your code, it's
index a9e3336..763664d 100644 (file)
@@ -23,7 +23,12 @@ Print the usage and a résumé of the available options
 Do not remove the generated files after execution.
 .TP
 \fB\-wrapper\fR <command>
-Use command to run the program (e.g. "valgrind").
+Use command to run the program (e.g. "valgrind", "gdb --args", "rr record").
+You usually want to use the "-foreground" option as well in order to have a TTY.
+.TP
+\fB\-foreground\fR
+Run the child process in the foreground.
+This gives the child process access to the TTY.
 .TP
 \fB\-map\fR
 Display the machine on which each process rank is mapped.
index 8a487e1..1b4b2a7 100644 (file)
@@ -3,7 +3,7 @@
 ! output sort 19
 ! timeout 30
 $ java -classpath ${classpath:=.} async/AsyncTest ${srcdir:=.}/../platforms/platform.xml ${srcdir:=.}/async/asyncDeployment.xml "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n"
-> [  0.000000] (0:@) Using regular java threads. Coroutines could speed your simulation up.
+> [  0.000000] (0:@) Using regular java threads.
 > [  0.000000] (10:async.Slave@Robert) Receiving on 'slave_8'
 > [  0.000000] (11:async.Slave@Sirois) Receiving on 'slave_9'
 > [  0.000000] (12:async.Slave@Monique) Receiving on 'slave_10'
index 89c28c2..2a27a0a 100644 (file)
@@ -4,7 +4,7 @@
 ! timeout 15
 
 $ java -classpath ${classpath:=.} bittorrent/Bittorrent ${srcdir:=.}/../platforms/platform.xml ${srcdir:=.}/bittorrent/bittorrent.xml
-> [0.000000] [jmsg/INFO] Using regular java threads. Coroutines could speed your simulation up.
+> [0.000000] [jmsg/INFO] Using regular java threads.
 > [5000.832370] [jmsg/INFO] MSG_main finished; Cleaning up the simulation...
 > [Boivin:bittorrent.Peer:(2) 0.000000] [jmsg/INFO] Hi, I'm joining the network with id 2
 > [Boivin:bittorrent.Peer:(2) 5000.048881] [jmsg/INFO] Here is my current status: 1111111111
index 4168a5c..01dc891 100644 (file)
@@ -3,7 +3,7 @@
 ! output sort 19
 
 $ java -classpath ${classpath:=.} chord/Chord ${srcdir:=.}/../platforms/platform.xml ${srcdir:=.}/chord/chord.xml
-> [0.000000] [jmsg/INFO] Using regular java threads. Coroutines could speed your simulation up.
+> [0.000000] [jmsg/INFO] Using regular java threads.
 > [652.540924] [jmsg/INFO] MSG_main finished; Cleaning up the simulation...
 > [Boivin:chord.Node:(7) 0.000000] [jmsg/INFO] Joining the ring with id 8 knowing node 1
 > [Gatien:chord.Node:(1) 0.000000] [jmsg/INFO] Joining the ring with id 48 knowing node 1
index 64a3c4b..d7386cf 100644 (file)
@@ -3,7 +3,7 @@
 ! output sort 19
 
 $ java -classpath ${classpath:=.} cloud/Cloud ${srcdir:=.}/../platforms/platform.xml "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n"
-> [  0.000000] (0:@) Using regular java threads. Coroutines could speed your simulation up.
+> [  0.000000] (0:@) Using regular java threads.
 > [  0.000000] (0:@) Start2  hosts
 > [  0.000000] (0:@) Create VM(VM00)@PM(Intel) with 0 mounted disks
 > [  0.000000] (0:@) Create VM(VM01)@PM(Provost) with 0 mounted disks
index 387a1ef..34b2b21 100644 (file)
@@ -1,7 +1,7 @@
 #! tesh
 
 $ java -classpath ${classpath:=.} cloud/migration/Main ${srcdir:=.}/../platforms/two_hosts_platform.xml ${srcdir:=.}/cloud/migration/deploy_simple.xml
-> [0.000000] [jmsg/INFO] Using regular java threads. Coroutines could speed your simulation up.
+> [0.000000] [jmsg/INFO] Using regular java threads.
 > [host0:cloud/migration/Test:(1) 0.000000] [jmsg/INFO] This example evaluates the migration time of a VM in presence of collocated VMs on the source and the dest nodes
 > [host0:cloud/migration/Test:(1) 0.000000] [jmsg/INFO] The migrated VM has a memory intensity rate of 70% of the network BW and a cpu load of 90% "(see cloudcom 2013 paper "Adding a Live Migration Model Into SimGrid" for further information) 
 > [host0:cloud/migration/Test:(1) 0.000000] [jmsg/INFO] Load of collocated VMs fluctuate between 0 and 90% in order to create a starvation issue and see whether it impacts or not the migration time
index cdd101c..d0f709c 100644 (file)
@@ -4,7 +4,7 @@
 ! timeout 15
 
 $ java -classpath ${classpath:=.} commTime/CommTimeTest ${srcdir:=.}/../platforms/platform.xml ${srcdir:=.}/commTime/commTimeDeployment.xml
-> [0.000000] [jmsg/INFO] Using regular java threads. Coroutines could speed your simulation up.
+> [0.000000] [jmsg/INFO] Using regular java threads.
 > [7016.452828] [jmsg/INFO] MSG_main finished; Cleaning up the simulation...
 > [Bellemarre:commTime.Slave:(15) 0.000000] [jmsg/INFO] Receiving on 'slave_13'
 > [Bellemarre:commTime.Slave:(15) 7006.341189] [jmsg/INFO] Received Finalize. I'm done. See you!
index d9a0acf..3adbb56 100644 (file)
@@ -3,7 +3,7 @@
 ! output sort 19
 
 $ java -classpath ${classpath:=.} kademlia/Kademlia ${srcdir:=.}/../platforms/platform.xml ${srcdir:=.}/kademlia/kademlia.xml
-> [0.000000] [jmsg/INFO] Using regular java threads. Coroutines could speed your simulation up.
+> [0.000000] [jmsg/INFO] Using regular java threads.
 > [900.000000] [jmsg/INFO] MSG_main finished; Cleaning up the simulation...
 > [Boivin:kademlia.Node:(2) 0.000000] [jmsg/INFO] Hi, I'm going to join the network with the id 1!
 > [Boivin:kademlia.Node:(2) 900.000000] [jmsg/INFO] 8/8 FIND_NODE have succedded.
index 01efba0..98a38b0 100644 (file)
@@ -3,7 +3,7 @@
 ! output sort 19
 
 $ java -classpath ${classpath:=.} master_slave_bypass/MsBypass ${srcdir:=.}/../platforms/platform.xml
-> [0.000000] [jmsg/INFO] Using regular java threads. Coroutines could speed your simulation up.
+> [0.000000] [jmsg/INFO] Using regular java threads.
 > [Boivin:process1:(1) 0.000000] [jmsg/INFO] Master Hello!
 > [Boivin:process1:(1) 0.000000] [jmsg/INFO] Create process on host 'Jacquelin'
 > [Jacquelin:process2:(2) 0.000000] [jmsg/INFO] Slave Hello!
index 022b338..9281484 100644 (file)
@@ -3,7 +3,7 @@
 ! output sort 19
 
 $ java -classpath ${classpath:=.} master_slave_kill/MsKill ${srcdir:=.}/../platforms/platform.xml
-> [0.000000] [jmsg/INFO] Using regular java threads. Coroutines could speed your simulation up.
+> [0.000000] [jmsg/INFO] Using regular java threads.
 > [Jacquelin:master:(1) 0.000000] [jmsg/INFO] Master Hello!
 > [Jacquelin:master:(1) 0.000000] [jmsg/INFO] Create process on host 'Boivin'
 > [Boivin:slave:(2) 0.000000] [jmsg/INFO] Slave Hello!
index 83b8fdb..2ff2848 100644 (file)
@@ -3,7 +3,7 @@
 ! output sort 19
 
 $ java -classpath ${classpath:=.} masterslave/Masterslave ${srcdir:=.}/../platforms/platform.xml ${srcdir:=.}/masterslave/masterslaveDeployment.xml "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n"
-> [  0.000000] (0:@) Using regular java threads. Coroutines could speed your simulation up.
+> [  0.000000] (0:@) Using regular java threads.
 > [  0.000000] (1:masterslave.Master@Jacquelin) Hello! Got 7 slaves and 5 tasks to process
 > [  0.000000] (2:masterslave.Forwarder@Jackson) Receiving on 'slave_0'
 > [  0.000000] (3:masterslave.Forwarder@Casavant) Receiving on 'slave_1'
index 9139002..3497f43 100644 (file)
@@ -3,7 +3,7 @@
 ! output sort 19
 
 $ java -classpath ${classpath:=.} migration/Migration ${srcdir:=.}/../platforms/platform.xml ${srcdir:=.}/migration/migrationDeployment.xml "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n"
-> [  0.000000] (0:@) Using regular java threads. Coroutines could speed your simulation up.
+> [  0.000000] (0:@) Using regular java threads.
 > [  0.000000] (1:migration.Emigrant@Jacquelin) I'll look for a new job on another machine where the grass is greener.
 > [  0.000000] (1:migration.Emigrant@Boivin) Yeah, found something to do
 > [  1.000000] (2:migration.Policeman@Boivin) Wait a bit before migrating the emigrant.
index c744230..1c03a20 100644 (file)
@@ -3,7 +3,7 @@
 ! output sort 19
 
 $ java -classpath ${classpath:=.} mutualExclusion/MutexCentral ${srcdir:=.}/../platforms/small_platform.xml ${srcdir:=.}/mutualExclusion/mutex_centralized_deployment.xml
-> [0.000000] [jmsg/INFO] Using regular java threads. Coroutines could speed your simulation up.
+> [0.000000] [jmsg/INFO] Using regular java threads.
 > [Jupiter:mutualExclusion.Node:(2) 0.000000] [jmsg/INFO] Send a request to the coordinator
 > [Fafard:mutualExclusion.Node:(3) 0.000000] [jmsg/INFO] Send a request to the coordinator
 > [Tremblay:mutualExclusion.Coordinator:(1) 0.019014] [jmsg/INFO] Got a request from mutualExclusion.Node. Queue empty: grant it
index 69c7dfe..93643a7 100644 (file)
@@ -3,7 +3,7 @@
 ! output sort 19
 
 $ java -classpath ${classpath:=.} pingPong/PingPongTest ${srcdir:=.}/../platforms/platform.xml ${srcdir:=.}/pingPong/pingPongDeployment.xml
-> [0.000000] [jmsg/INFO] Using regular java threads. Coroutines could speed your simulation up.
+> [0.000000] [jmsg/INFO] Using regular java threads.
 > [1.048882] [jmsg/INFO] MSG_main finished; Cleaning up the simulation...
 > [Boivin:pingPong.Receiver:(2) 0.000000] [jmsg/INFO] hello!
 > [Boivin:pingPong.Receiver:(2) 0.000000] [jmsg/INFO] try to get a task
index 32747db..19879a6 100644 (file)
@@ -3,7 +3,7 @@
 ! output sort 19
 
 $ java -classpath ${classpath:=.} priority/Priority ${srcdir:=.}/../platforms/platform.xml ${srcdir:=.}/priority/priorityDeployment.xml "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n"
-> [  0.000000] (0:@) Using regular java threads. Coroutines could speed your simulation up.
+> [  0.000000] (0:@) Using regular java threads.
 > [  0.000000] (1:priority.Test@Fafard) Hello! Running a task of size 7.6296E7 with priority 1.0
 > [  0.000000] (2:priority.Test@Fafard) Hello! Running a task of size 7.6296E7 with priority 2.0
 > [  0.833332] (2:priority.Test@Fafard) Goodbye now!
index 80f637f..d7d52c9 100644 (file)
@@ -1,7 +1,7 @@
 #! tesh
 
 $ java -classpath ${classpath:=.} reservationSurfPlugin/TestPlugin ${srcdir:=.}/../platforms/small_platform.xml ${srcdir:=.}/reservationSurfPlugin/reservationSurfPluginDeployment.xml
-> [0.000000] [jmsg/INFO] Using regular java threads. Coroutines could speed your simulation up.
+> [0.000000] [jmsg/INFO] Using regular java threads.
 > [Tremblay:reservationSurfPlugin.Sender:(1) 0.000000] [jmsg/INFO] helloo!
 > [Ginette:reservationSurfPlugin.Receiver:(2) 0.000000] [jmsg/INFO] helloo!
 > [0.000000] [jmsg/INFO] Trace: Communicate message of size 1.0 with rate -1.0 and bound 1.648342855615789E9 from Tremblay to Ginette
index dee888b..eadb5f6 100644 (file)
@@ -1,6 +1,6 @@
 #! tesh
 $ java -classpath ${classpath:=.} startKillTime/StartKillTime ${srcdir:=.}/../platforms/platform.xml ${srcdir:=.}/startKillTime/deployment_start_kill.xml
-> [0.000000] [jmsg/INFO] Using regular java threads. Coroutines could speed your simulation up.
+> [0.000000] [jmsg/INFO] Using regular java threads.
 > [Jacquelin:startKillTime.Master:(1) 0.000000] [jmsg/INFO] Hello!
 > [Boivin:startKillTime.Slave:(2) 1.000000] [jmsg/INFO] Hello!
 > [Jean_Yves:startKillTime.Slave:(3) 2.000000] [jmsg/INFO] Hello!
index a91d278..b855455 100644 (file)
@@ -2,7 +2,7 @@
 
 $ java -classpath ${classpath:=.} surfCpuModel/TestCpuModel ${srcdir:=.}/../platforms/small_platform.xml ${srcdir:=.}/surfCpuModel/surfCpuModelDeployment.xml --cfg=host/model:compound
 > [0.000000] [xbt_cfg/INFO] Configuration change: Set 'host/model' to 'compound'
-> [0.000000] [jmsg/INFO] Using regular java threads. Coroutines could speed your simulation up.
+> [0.000000] [jmsg/INFO] Using regular java threads.
 > [0.000000] [jmsg/INFO] Initialize Cpu Constant Model
 > [0.000000] [jmsg/INFO] New Cpu(Tremblay, 9.8095E7, 1.0)
 > [0.000000] [jmsg/INFO] New Cpu(Jupiter, 7.6296E7, 1.0)
index f0f720d..423cb4a 100644 (file)
@@ -9,7 +9,7 @@
 ! output sort
 #
 $ java -classpath ${classpath:=.} surfPlugin/TestPlugin ${srcdir:=.}/../platforms/small_platform.xml ${srcdir:=.}/surfPlugin/surfPluginDeployment.xml
-> [0.000000] [jmsg/INFO] Using regular java threads. Coroutines could speed your simulation up.
+> [0.000000] [jmsg/INFO] Using regular java threads.
 > [0.000000] [jmsg/INFO] Trace: Link created __loopback__
 > [0.000000] [jmsg/INFO] Trace: Link state changed __loopback__
 > [0.000000] [jmsg/INFO] Trace: Cpu created Tremblay
index ec22ec7..37b148b 100644 (file)
@@ -2,7 +2,7 @@
 
 ! output sort 19
 $ java -classpath ${classpath:=.} suspend/Suspend ${srcdir:=.}/../platforms/platform.xml ${srcdir:=.}/suspend/suspendDeployment.xml "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n"
-> [  0.000000] (0:@) Using regular java threads. Coroutines could speed your simulation up.
+> [  0.000000] (0:@) Using regular java threads.
 > [  0.000000] (1:suspend.DreamMaster@Jacquelin) Let's create a lazy guy.
 > [  0.000000] (1:suspend.DreamMaster@Jacquelin) Let's wait a little bit...
 > [  0.000000] (2:Lazy@Jacquelin) Nobody's watching me ? Let's go to sleep.
index f86e589..4b0937c 100644 (file)
@@ -3,7 +3,7 @@
 ! output sort 19
 
 $ java -classpath ${classpath:=.} tracing/TracingTest ${srcdir:=.}/../platforms/platform.xml ${srcdir:=.}/tracing/tracingPingPongDeployment.xml --cfg=tracing:yes  --cfg=tracing/filename:simulation.trace --cfg=tracing/platform:yes
-> [0.000000] [jmsg/INFO] Using regular java threads. Coroutines could speed your simulation up.
+> [0.000000] [jmsg/INFO] Using regular java threads.
 > [0.000000] [xbt_cfg/INFO] Configuration change: Set 'tracing' to 'yes'
 > [0.000000] [xbt_cfg/INFO] Configuration change: Set 'tracing/filename' to 'simulation.trace'
 > [0.000000] [xbt_cfg/INFO] Configuration change: Set 'tracing/platform' to 'yes'
index aa26972..a38a098 100644 (file)
@@ -2,7 +2,7 @@
 
 ! output sort 19
 $ java -classpath ${classpath:=.} master_slave_bypass/MsBypass ${srcdir:=.}/../platforms/small_platform.xml
-> [0.000000] [jmsg/INFO] Using regular java threads. Coroutines could speed your simulation up.
+> [0.000000] [jmsg/INFO] Using regular java threads.
 > [Jupiter:process1:(1) 0.000000] [jmsg/INFO] Master Hello!
 > [Jupiter:process1:(1) 0.000000] [jmsg/INFO] Create process on host 'Tremblay'
 > [Tremblay:process2:(2) 0.000000] [jmsg/INFO] Slave Hello!
index 12d0c9b..c06a0b8 100644 (file)
@@ -3,7 +3,7 @@
 ! output sort 19
 
 $ java -classpath ${classpath:=.} master_slave_kill/MsKill ${srcdir:=.}/../platforms/small_platform.xml
-> [0.000000] [jmsg/INFO] Using regular java threads. Coroutines could speed your simulation up.
+> [0.000000] [jmsg/INFO] Using regular java threads.
 > [Jupiter:master:(1) 0.000000] [jmsg/INFO] Master Hello!
 > [Jupiter:master:(1) 0.000000] [jmsg/INFO] Create process on host 'alice'
 > [Tremblay:slave:(2) 0.000000] [jmsg/INFO] Slave Hello!
index 83b8fdb..2ff2848 100644 (file)
@@ -3,7 +3,7 @@
 ! output sort 19
 
 $ java -classpath ${classpath:=.} masterslave/Masterslave ${srcdir:=.}/../platforms/platform.xml ${srcdir:=.}/masterslave/masterslaveDeployment.xml "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n"
-> [  0.000000] (0:@) Using regular java threads. Coroutines could speed your simulation up.
+> [  0.000000] (0:@) Using regular java threads.
 > [  0.000000] (1:masterslave.Master@Jacquelin) Hello! Got 7 slaves and 5 tasks to process
 > [  0.000000] (2:masterslave.Forwarder@Jackson) Receiving on 'slave_0'
 > [  0.000000] (3:masterslave.Forwarder@Casavant) Receiving on 'slave_1'
index 2d4da0f..9505538 100644 (file)
 #include "simgrid/datatypes.h"
 #include "simgrid/host.h"
 
+
+#ifdef __cplusplus
+
+namespace simgrid {
+namespace simix {
+  class Context;
+  class ContextFactory;
+}
+}
+
+typedef simgrid::simix::Context *smx_context_t;
+
+#else
+
+typedef struct s_smx_context *smx_context_t;
+
+#endif
+
+
+
 SG_BEGIN_DECL()
 
 /**************************** Scalar Values **********************************/
@@ -124,83 +144,17 @@ typedef struct s_smx_rvpoint *smx_rdv_t;
 XBT_PUBLIC(void*) SIMIX_comm_get_src_data(smx_synchro_t synchro);
 XBT_PUBLIC(void*) SIMIX_comm_get_dst_data(smx_synchro_t synchro);
 
-/******************************** Context *************************************/
-typedef struct s_smx_context *smx_context_t;
-typedef struct s_smx_context_factory *smx_context_factory_t;
-
 /* Process creation/destruction callbacks */
 typedef void (*void_pfn_smxprocess_t) (smx_process_t);
 /* for auto-restart function */
 typedef void (*void_pfn_sghost_t) (sg_host_t);
 
-/* The following function pointer types describe the interface that any context
-   factory should implement */
-
-
-typedef smx_context_t (*smx_pfn_context_factory_create_context_t)(
-  xbt_main_func_t, int, char **, void_pfn_smxprocess_t, smx_process_t process);
-typedef int (*smx_pfn_context_factory_finalize_t) (smx_context_factory_t*);
-typedef void (*smx_pfn_context_free_t) (smx_context_t);
-typedef void (*smx_pfn_context_start_t) (smx_context_t);
-typedef void (*smx_pfn_context_stop_t) (smx_context_t);
-typedef void (*smx_pfn_context_suspend_t) (smx_context_t context);
-typedef void (*smx_pfn_context_runall_t) (void);
-typedef smx_context_t (*smx_pfn_context_self_t) (void);
-typedef smx_process_t (*smx_pfn_context_get_process_t) (smx_context_t context);
-
-/* interface of the context factories */
-typedef struct s_smx_context_factory {
-  const char *name;
-  smx_pfn_context_factory_create_context_t create_context;
-  smx_pfn_context_factory_finalize_t finalize;
-  smx_pfn_context_free_t free;
-  smx_pfn_context_stop_t stop;
-  smx_pfn_context_suspend_t suspend;
-  smx_pfn_context_runall_t runall;
-  smx_pfn_context_self_t self;
-  smx_pfn_context_get_process_t get_process;
-} s_smx_context_factory_t;
-
-/* Hack: let msg load directly the right factory */
-typedef void (*smx_ctx_factory_initializer_t)(smx_context_factory_t*);
-XBT_PUBLIC_DATA(smx_ctx_factory_initializer_t) smx_factory_initializer_to_use;
 extern char* smx_context_factory_name;
 extern int smx_context_stack_size;
 extern int smx_context_stack_size_was_set;
 extern int smx_context_guard_size;
 extern int smx_context_guard_size_was_set;
 
-/* *********************** */
-/* Context type definition */
-/* *********************** */
-/* the following function pointers types describe the interface that all context
-   concepts must implement */
-/* each context type derive from this structure, so they must contain this structure
- * at their beginning -- OOP in C :/ */
-typedef struct s_smx_context {
-  s_xbt_swag_hookup_t hookup;
-  xbt_main_func_t code;
-  void_pfn_smxprocess_t cleanup_func;
-  smx_process_t process;
-  char **argv;
-  int argc;
-  unsigned iwannadie:1;
-} s_smx_ctx_base_t;
-
-/* methods of this class */
-XBT_PUBLIC(void) smx_ctx_base_factory_init(smx_context_factory_t *factory);
-XBT_PUBLIC(int) smx_ctx_base_factory_finalize(smx_context_factory_t *factory);
-
-XBT_PUBLIC(smx_context_t)
-smx_ctx_base_factory_create_context_sized(size_t size, xbt_main_func_t code,
-                                          int argc, char **argv,
-                                          void_pfn_smxprocess_t cleanup,
-                                          smx_process_t process);
-XBT_PUBLIC(void) smx_ctx_base_free(smx_context_t context);
-XBT_PUBLIC(void) smx_ctx_base_stop(smx_context_t context);
-XBT_PUBLIC(smx_context_t) smx_ctx_base_self(void);
-XBT_PUBLIC(smx_process_t) smx_ctx_base_get_process(smx_context_t context);
-
 XBT_PUBLIC(xbt_dynar_t) SIMIX_process_get_runnable(void);
 XBT_PUBLIC(smx_process_t) SIMIX_process_from_PID(int PID);
 XBT_PUBLIC(xbt_dynar_t) SIMIX_processes_as_dynar(void);
diff --git a/include/simgrid/simix.hpp b/include/simgrid/simix.hpp
new file mode 100644 (file)
index 0000000..99f476f
--- /dev/null
@@ -0,0 +1,88 @@
+/* Copyright (c) 2007-2010, 2012-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. */
+
+#ifndef SIMGRID_SIMIX_HPP
+#define SIMGRID_SIMIX_HPP
+
+#include <utility>
+#include <memory>
+
+#include <xbt/function_types.h>
+#include <simgrid/simix.h>
+
+namespace simgrid {
+namespace simix {
+
+class Context;
+class ContextFactory;
+
+class ContextFactory {
+private:
+  std::string name_;
+public:
+
+  ContextFactory(std::string name) : name_(std::move(name)) {}
+  virtual ~ContextFactory();
+  virtual Context* create_context(
+    xbt_main_func_t, int, char **, void_pfn_smxprocess_t,
+    smx_process_t process
+    ) = 0;
+  virtual void run_all() = 0;
+  virtual Context* self();
+  std::string const& name() const
+  {
+    return name_;
+  }
+private:
+  void declare_context(void* T, std::size_t size);
+protected:
+  template<class T, class... Args>
+  T* new_context(Args&&... args)
+  {
+    T* context = new T(std::forward<Args>(args)...);
+    this->declare_context(context, sizeof(T));
+    return context;
+  }
+};
+
+class Context {
+protected:
+  xbt_main_func_t code_ = nullptr;
+  int argc_ = 0;
+  char **argv_ = nullptr;
+private:
+  void_pfn_smxprocess_t cleanup_func_ = nullptr;
+  smx_process_t process_ = nullptr;
+public:
+  bool iwannadie;
+public:
+  Context(xbt_main_func_t code,
+          int argc, char **argv,
+          void_pfn_smxprocess_t cleanup_func,
+          smx_process_t process);
+  int operator()()
+  {
+    return code_(argc_, argv_);
+  }
+  smx_process_t process()
+  {
+    return this->process_;
+  }
+  void set_cleanup(void_pfn_smxprocess_t cleanup)
+  {
+    cleanup_func_ = cleanup;
+  }
+
+  // Virtual methods
+  virtual ~Context();
+  virtual void stop();
+  virtual void suspend() = 0;
+};
+
+}
+}
+
+#endif
\ No newline at end of file
index 4e407ab..0d09d8a 100644 (file)
 #ifndef _XBT_SYSDEP_H
 #define _XBT_SYSDEP_H
 
-#ifdef __cplusplus
-#include <type_traits>
-#endif
-
 #include "xbt/log.h"
 #include "xbt/misc.h"
 #include "xbt/asserts.h"
@@ -148,42 +144,11 @@ XBT_PUBLIC(void) xbt_free_ref(void *d);
 
 SG_END_DECL()
 
-/** @brief like calloc, but xbt_die() on error and don't memset to 0
-    @hideinitializer */
-#ifndef __cplusplus
-
 #define xbt_new(type, count)  ((type*)xbt_malloc (sizeof (type) * (count)))
 /** @brief like calloc, but xbt_die() on error
     @hideinitializer */
 #define xbt_new0(type, count) ((type*)xbt_malloc0 (sizeof (type) * (count)))
 
-#else
-
-/** C++ wrapper for xtb_new
- *
- *  This ensures that we do not xbt_new things that need a constructor.
- */
-template<typename T> inline
-T* xbt_new_(size_t count)
-{
-  static_assert(std::is_trivial<T>(),
-    "Cannot xbt_new this type");
-  return (T*) xbt_malloc(sizeof(T) * count);
-}
-
-template<typename T> inline
-T* xbt_new0_(size_t count)
-{
-  static_assert(std::is_trivial<T>(),
-    "Cannot xbt_new0 this type");
-  return (T*) xbt_malloc0(sizeof(T) * count);
-}
-
-#define xbt_new(type, count)  ::xbt_new_<type>(count)
-#define xbt_new0(type, count) ::xbt_new0_<type>(count)
-
-#endif
-
 /** @} */
 
 #endif                          /* _XBT_SYSDEP_H */
diff --git a/src/bindings/java/JavaContext.cpp b/src/bindings/java/JavaContext.cpp
new file mode 100644 (file)
index 0000000..f371d6f
--- /dev/null
@@ -0,0 +1,190 @@
+/* context_java - implementation of context switching for java threads */
+
+/* Copyright (c) 2009-2010, 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 <xbt/function_types.h>
+#include <simgrid/simix.h>
+#include <xbt/ex.h>
+#include "JavaContext.hpp"
+#include "jxbt_utilities.h"
+#include "xbt/dynar.h"
+#include "../../simix/smx_private.h"
+extern JavaVM *__java_vm;
+
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(jmsg, bindings, "MSG for Java(TM)");
+
+namespace simgrid {
+namespace java {
+
+simgrid::simix::ContextFactory* java_factory()
+{
+  XBT_INFO("Using regular java threads.");
+  return new JavaContextFactory();
+}
+
+JavaContextFactory::JavaContextFactory()
+  : ContextFactory("JavaContextFactory")
+{
+}
+
+JavaContextFactory::~JavaContextFactory()
+{
+}
+
+JavaContext* JavaContextFactory::self()
+{
+  return (JavaContext*) xbt_os_thread_get_extra_data();
+}
+
+JavaContext* JavaContextFactory::create_context(
+  xbt_main_func_t code, int argc, char ** argv,
+  void_pfn_smxprocess_t cleanup, smx_process_t process)
+{
+  return this->new_context<JavaContext>(code, argc, argv, cleanup, process);
+}
+
+void JavaContextFactory::run_all()
+{
+  xbt_dynar_t processes = SIMIX_process_get_runnable();
+  smx_process_t process;
+  unsigned int cursor;
+  xbt_dynar_foreach(processes, cursor, process) {
+    static_cast<JavaContext*>(SIMIX_process_get_context(process))->resume();
+  }
+}
+
+
+JavaContext::JavaContext(xbt_main_func_t code,
+        int argc, char **argv,
+        void_pfn_smxprocess_t cleanup_func,
+        smx_process_t process)
+  : Context(code, argc, argv, cleanup_func, process)
+{
+  static int thread_amount=0;
+  thread_amount++;
+
+  /* If the user provided a function for the process then use it
+     otherwise is the context for maestro */
+  if (code) {
+    if (argc == 0)
+      this->jprocess = (jobject) code;
+    else
+      this->jprocess = nullptr;
+    this->begin = xbt_os_sem_init(0);
+    this->end = xbt_os_sem_init(0);
+
+    TRY {
+       this->thread = xbt_os_thread_create(
+         nullptr, JavaContext::wrapper, this, nullptr);
+    }
+    CATCH_ANONYMOUS {
+      RETHROWF("Failed to create context #%d. You may want to switch to Java coroutines to increase your limits (error: %s)."
+               "See the Install section of simgrid-java documentation (in doc/install.html) for more on coroutines.",
+               thread_amount);
+    }
+  } else {
+    this->thread = nullptr;
+    xbt_os_thread_set_extra_data(this);
+  }
+}
+
+JavaContext::~JavaContext()
+{
+  if (this->thread) {
+    // We are not in maestro context
+    xbt_os_thread_join(this->thread, nullptr);
+    xbt_os_sem_destroy(this->begin);
+    xbt_os_sem_destroy(this->end);
+  }
+}
+
+void* JavaContext::wrapper(void *data)
+{
+  JavaContext* context = (JavaContext*)data;
+  xbt_os_thread_set_extra_data(context);
+  //Attach the thread to the JVM
+
+  JNIEnv *env;
+  XBT_ATTRIB_UNUSED jint error =
+    __java_vm->AttachCurrentThread((void **) &env, NULL);
+  xbt_assert((error == JNI_OK), "The thread could not be attached to the JVM");
+  context->jenv = get_current_thread_env();
+  //Wait for the first scheduling round to happen.
+  xbt_os_sem_acquire(context->begin);
+  //Create the "Process" object if needed.
+  if (context->argc_ > 0)
+    (*context)();
+  else {
+    smx_process_t process = SIMIX_process_self();
+    env->SetLongField(context->jprocess, jprocess_field_Process_bind,
+                         (intptr_t)process);
+  }
+
+  // Adrien, ugly path, just to bypass creation of context at low levels
+  // (i.e such as for the VM migration for instance)
+  if (context->jprocess != nullptr){
+    xbt_assert((context->jprocess != nullptr), "Process not created...");
+    //wait for the process to be able to begin
+    //TODO: Cache it
+    jfieldID jprocess_field_Process_startTime = jxbt_get_sfield(env, "org/simgrid/msg/Process", "startTime", "D");
+    jdouble startTime =  env->GetDoubleField(context->jprocess, jprocess_field_Process_startTime);
+    if (startTime > MSG_get_clock()) {
+      MSG_process_sleep(startTime - MSG_get_clock());
+    }
+    //Execution of the "run" method.
+    jmethodID id = jxbt_get_smethod(env, "org/simgrid/msg/Process", "run", "()V");
+    xbt_assert( (id != nullptr), "Method not found...");
+    env->CallVoidMethod(context->jprocess, id);
+  }
+  context->stop();
+  return nullptr;
+}
+
+void JavaContext::stop()
+{
+  /* I am the current process and I am dying */
+  if (this->iwannadie) {
+    this->iwannadie = 0;
+    JNIEnv *env = get_current_thread_env();
+    XBT_DEBUG("Gonna launch Killed Error");
+    // TODO Adrien, if the process has not been created at the java layer, why should we raise the exception/error at the java level (this happens
+    // for instance during the migration process that creates at the C level two processes: one on the SRC node and one on the DST node, if the DST process is killed.
+    // it is not required to raise an exception at the JAVA level, the low level should be able to manage such an issue correctly but this is not the case right now unfortunately ...
+    // TODO it will be nice to have the name of the process to help the end-user to know which Process has been killed
+   // jxbt_throw_by_name(env, "org/simgrid/msg/ProcessKilledError", bprintf("Process %s killed :) (file smx_context_java.c)", MSG_process_get_name( (msg_process_t)context) ));
+    jxbt_throw_by_name(env, "org/simgrid/msg/ProcessKilledError",
+      bprintf("Process %s killed :) (file JavaContext.cpp)",
+      simcall_process_get_name((smx_process_t) SIMIX_context_get_process(this))) );
+    XBT_DEBUG("Trigger a cancel error at the C level");
+    THROWF(cancel_error, 0, "process cancelled");
+  } else {
+    Context::stop();
+    /* detach the thread and kills it */
+    JNIEnv *env = this->jenv;
+    env->DeleteGlobalRef(this->jprocess);
+    XBT_ATTRIB_UNUSED jint error = __java_vm->DetachCurrentThread();
+    xbt_assert((error == JNI_OK), "The thread couldn't be detached.");
+    xbt_os_sem_release(this->end);
+    xbt_os_thread_exit(NULL);
+  }
+}
+
+void JavaContext::suspend()
+{
+  xbt_os_sem_release(this->end);
+  xbt_os_sem_acquire(this->begin);
+}
+
+// FIXME: inline those functions
+void JavaContext::resume()
+{
+  xbt_os_sem_release(this->begin);
+  xbt_os_sem_acquire(this->end);
+}
+
+}
+}
diff --git a/src/bindings/java/JavaContext.hpp b/src/bindings/java/JavaContext.hpp
new file mode 100644 (file)
index 0000000..fbad882
--- /dev/null
@@ -0,0 +1,69 @@
+/* Copyright (c) 2009-2010, 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 SIMGRID_JAVA_JAVA_CONTEXT_HPP
+#define SIMGRID_JAVA_JAVA_CONTEXT_HPP
+
+#include <jni.h>
+
+#include <xbt/misc.h>
+#include <simgrid/simix.h>
+#include <xbt/xbt_os_thread.h>
+
+#include "src/simix/smx_private.hpp"
+
+#include "jmsg.h"
+#include "jmsg_process.h"
+
+namespace simgrid {
+namespace java {
+
+class JavaContext;
+class JavacontextFactory;
+
+class JavaContext : public simgrid::simix::Context {
+public:
+  // The java process instance bound with the msg process structure:
+  jobject jprocess;
+  // JNI interface pointer associated to this thread:
+  JNIEnv *jenv;
+  xbt_os_thread_t thread;
+  // Sempahore used to schedule/yield the process:
+  xbt_os_sem_t begin;
+  // Semaphore used to schedule/unschedule the process:
+  xbt_os_sem_t end;
+public:
+  friend class JavaContextFactory;
+  JavaContext(xbt_main_func_t code,
+          int argc, char **argv,
+          void_pfn_smxprocess_t cleanup_func,
+          smx_process_t process);
+  ~JavaContext() override;
+  void stop() override;
+  void suspend() override;
+  void resume();
+private:
+  static void* wrapper(void *data);
+};
+
+class JavaContextFactory : public simgrid::simix::ContextFactory {
+public:
+  JavaContextFactory();
+  ~JavaContextFactory() override;
+  JavaContext* self() override;
+  JavaContext* create_context(
+    xbt_main_func_t, int, char **, void_pfn_smxprocess_t,
+    smx_process_t process
+    ) override;
+  void run_all() override;
+};
+
+XBT_PRIVATE simgrid::simix::ContextFactory* java_factory();
+
+}
+}
+
+#endif                          /* !_XBT_CONTEXT_JAVA_H */
similarity index 71%
rename from src/bindings/java/jmsg.c
rename to src/bindings/java/jmsg.cpp
index 979401a..ad979be 100644 (file)
@@ -10,9 +10,7 @@
 #include <simgrid/simix.h>
 #include <surf/surfxml_parse.h>
 #include <locale.h>
-
-#include "smx_context_java.h"
-#include "smx_context_cojava.h"
+#include <src/simix/smx_private.h>
 
 #include "jmsg_process.h"
 
@@ -25,6 +23,8 @@
 
 #include "jmsg.h"
 
+#include "JavaContext.hpp"
+
 /* Shut up some errors in eclipse online compiler. I wish such a pimple wouldn't be needed */
 #ifndef JNIEXPORT
 #define JNIEXPORT
@@ -34,6 +34,8 @@
 #endif
 /* end of eclipse-mandated pimple */
 
+SG_BEGIN_DECL()
+
 int JAVA_HOST_LEVEL;
 int JAVA_STORAGE_LEVEL;
 
@@ -52,7 +54,7 @@ JNIEnv *get_current_thread_env(void)
 {
   JNIEnv *env;
 
-  (*__java_vm)->AttachCurrentThread(__java_vm, (void **) &env, NULL);
+  __java_vm->AttachCurrentThread((void **) &env, NULL);
   return env;
 }
 
@@ -106,31 +108,28 @@ Java_org_simgrid_msg_Msg_init(JNIEnv * env, jclass cls, jobjectArray jargs)
   XBT_LOG_CONNECT(jmsg);
   XBT_LOG_CONNECT(jtrace);
 
-  (*env)->GetJavaVM(env, &__java_vm);
+  env->GetJavaVM(&__java_vm);
 
-  if ((*env)->FindClass(env, "java/dyn/Coroutine"))
-    smx_factory_initializer_to_use = SIMIX_ctx_cojava_factory_init;
-  else
-    smx_factory_initializer_to_use = SIMIX_ctx_java_factory_init;
-  jthrowable exc = (*env)->ExceptionOccurred(env);
+  simgrid::simix::factory_initializer = simgrid::java::java_factory;
+  jthrowable exc = env->ExceptionOccurred();
   if (exc) {
-    (*env)->ExceptionClear(env);
+    env->ExceptionClear();
   }
 
   setlocale(LC_NUMERIC,"C");
 
   if (jargs)
-    argc = (int) (*env)->GetArrayLength(env, jargs);
+    argc = (int) env->GetArrayLength(jargs);
 
   argc++;
   argv = xbt_new(char *, argc + 1);
   argv[0] = xbt_strdup("java");
 
   for (index = 0; index < argc - 1; index++) {
-    jval = (jstring) (*env)->GetObjectArrayElement(env, jargs, index);
-    tmp = (*env)->GetStringUTFChars(env, jval, 0);
+    jval = (jstring) env->GetObjectArrayElement(jargs, index);
+    tmp = env->GetStringUTFChars(jval, 0);
     argv[index + 1] = xbt_strdup(tmp);
-    (*env)->ReleaseStringUTFChars(env, jval, tmp);
+    env->ReleaseStringUTFChars(jval, tmp);
   }
   argv[argc] = NULL;
 
@@ -143,13 +142,6 @@ Java_org_simgrid_msg_Msg_init(JNIEnv * env, jclass cls, jobjectArray jargs)
     free(argv[index]);
 
   free(argv);
-
-  if (smx_factory_initializer_to_use == SIMIX_ctx_cojava_factory_init)
-    XBT_INFO("Using Coroutines. Your simulation is on steroid.");
-  else if (smx_factory_initializer_to_use == SIMIX_ctx_java_factory_init)
-    XBT_INFO("Using regular java threads. Coroutines could speed your simulation up.");
-  else
-    xbt_die("Unknown context factory. Please report bug.");
 }
 
 JNIEXPORT void JNICALL
@@ -198,11 +190,11 @@ Java_org_simgrid_msg_Msg_createEnvironment(JNIEnv * env, jclass cls,
 {
 
   const char *platformFile =
-      (*env)->GetStringUTFChars(env, jplatformFile, 0);
+      env->GetStringUTFChars(jplatformFile, 0);
 
   MSG_create_environment(platformFile);
 
-  (*env)->ReleaseStringUTFChars(env, jplatformFile, platformFile);
+  env->ReleaseStringUTFChars(jplatformFile, platformFile);
 }
 
 JNIEXPORT jobject JNICALL
@@ -227,44 +219,44 @@ Java_org_simgrid_msg_Msg_environmentGetRoutingRoot(JNIEnv * env, jclass cls)
 JNIEXPORT void JNICALL
 Java_org_simgrid_msg_Msg_debug(JNIEnv * env, jclass cls, jstring js)
 {
-  const char *s = (*env)->GetStringUTFChars(env, js, 0);
+  const char *s = env->GetStringUTFChars(js, 0);
   XBT_DEBUG("%s", s);
-  (*env)->ReleaseStringUTFChars(env, js, s);
+  env->ReleaseStringUTFChars(js, s);
 }
 JNIEXPORT void JNICALL
 Java_org_simgrid_msg_Msg_verb(JNIEnv * env, jclass cls, jstring js)
 {
-  const char *s = (*env)->GetStringUTFChars(env, js, 0);
+  const char *s = env->GetStringUTFChars(js, 0);
   XBT_VERB("%s", s);
-  (*env)->ReleaseStringUTFChars(env, js, s);
+  env->ReleaseStringUTFChars(js, s);
 }
 JNIEXPORT void JNICALL
 Java_org_simgrid_msg_Msg_info(JNIEnv * env, jclass cls, jstring js)
 {
-  const char *s = (*env)->GetStringUTFChars(env, js, 0);
+  const char *s = env->GetStringUTFChars(js, 0);
   XBT_INFO("%s", s);
-  (*env)->ReleaseStringUTFChars(env, js, s);
+  env->ReleaseStringUTFChars(js, s);
 }
 JNIEXPORT void JNICALL
 Java_org_simgrid_msg_Msg_warn(JNIEnv * env, jclass cls, jstring js)
 {
-  const char *s = (*env)->GetStringUTFChars(env, js, 0);
+  const char *s = env->GetStringUTFChars(js, 0);
   XBT_WARN("%s", s);
-  (*env)->ReleaseStringUTFChars(env, js, s);
+  env->ReleaseStringUTFChars(js, s);
 }
 JNIEXPORT void JNICALL
 Java_org_simgrid_msg_Msg_error(JNIEnv * env, jclass cls, jstring js)
 {
-  const char *s = (*env)->GetStringUTFChars(env, js, 0);
+  const char *s = env->GetStringUTFChars(js, 0);
   XBT_ERROR("%s", s);
-  (*env)->ReleaseStringUTFChars(env, js, s);
+  env->ReleaseStringUTFChars(js, s);
 }
 JNIEXPORT void JNICALL
 Java_org_simgrid_msg_Msg_critical(JNIEnv * env, jclass cls, jstring js)
 {
-  const char *s = (*env)->GetStringUTFChars(env, js, 0);
+  const char *s = env->GetStringUTFChars(js, 0);
   XBT_CRITICAL("%s", s);
-  (*env)->ReleaseStringUTFChars(env, js, s);
+  env->ReleaseStringUTFChars(js, s);
 }
 JNIEXPORT void JNICALL
 Java_org_simgrid_msg_Msg_deployApplication(JNIEnv * env, jclass cls,
@@ -272,7 +264,7 @@ Java_org_simgrid_msg_Msg_deployApplication(JNIEnv * env, jclass cls,
 {
 
   const char *deploymentFile =
-      (*env)->GetStringUTFChars(env, jdeploymentFile, 0);
+      env->GetStringUTFChars(jdeploymentFile, 0);
 
   SIMIX_function_register_default(create_jprocess);
   MSG_launch_application(deploymentFile);
@@ -286,37 +278,41 @@ static int create_jprocess(int argc, char *argv[]) {
   JNIEnv *env = get_current_thread_env();
   //Change the "." in class name for "/".
   xbt_str_subst(argv[0],'.','/',0);
-  jclass class_Process = (*env)->FindClass(env, argv[0]);
+  jclass class_Process = env->FindClass(argv[0]);
   xbt_str_subst(argv[0],'/','.',0);
   //Retrieve the methodID for the constructor
   xbt_assert((class_Process != NULL), "Class not found (%s). The deployment file must use the fully qualified class name, including the package. The case is important.", argv[0]);
-  jmethodID constructor_Process = (*env)->GetMethodID(env, class_Process, "<init>", "(Lorg/simgrid/msg/Host;Ljava/lang/String;[Ljava/lang/String;)V");
+  jmethodID constructor_Process = env->GetMethodID(class_Process, "<init>", "(Lorg/simgrid/msg/Host;Ljava/lang/String;[Ljava/lang/String;)V");
   xbt_assert((constructor_Process != NULL), "Constructor not found for class %s. Is there a (Host, String ,String[]) constructor in your class ?", argv[0]);
 
   //Retrieve the name of the process.
-  jstring jname = (*env)->NewStringUTF(env, argv[0]);
+  jstring jname = env->NewStringUTF(argv[0]);
   //Build the arguments
-  jobjectArray args = (jobjectArray)((*env)->NewObjectArray(env,argc - 1,
-  (*env)->FindClass(env,"java/lang/String"),
-  (*env)->NewStringUTF(env,"")));
+  jobjectArray args = (jobjectArray)env->NewObjectArray(argc - 1,
+    env->FindClass("java/lang/String"),
+    env->NewStringUTF(""));
   int i;
   for (i = 1; i < argc; i++)
-      (*env)->SetObjectArrayElement(env,args,i - 1,(*env)->NewStringUTF(env, argv[i]));
+      env->SetObjectArrayElement(args,i - 1,
+        env->NewStringUTF(argv[i]));
   //Retrieve the host for the process.
-  jstring jhostName = (*env)->NewStringUTF(env, MSG_host_get_name(MSG_host_self()));
+  jstring jhostName = env->NewStringUTF(MSG_host_get_name(MSG_host_self()));
   jobject jhost = Java_org_simgrid_msg_Host_getByName(env, NULL, jhostName);
   //creates the process
-  jobject jprocess = (*env)->NewObject(env, class_Process, constructor_Process, jhost, jname, args);
+  jobject jprocess = env->NewObject(class_Process, constructor_Process, jhost, jname, args);
   xbt_assert((jprocess != NULL), "Process allocation failed.");
-  jprocess = (*env)->NewGlobalRef(env, jprocess);
+  jprocess = env->NewGlobalRef(jprocess);
   //bind the process to the context
   msg_process_t process = MSG_process_self();
-  smx_ctx_java_t context = (smx_ctx_java_t)MSG_process_get_smx_ctx(process);
+  simgrid::java::JavaContext* context =
+    (simgrid::java::JavaContext*) MSG_process_get_smx_ctx(process);
   context->jprocess = jprocess;
-/* sets the PID and the PPID of the process */
-(*env)->SetIntField(env, jprocess, jprocess_field_Process_pid,(jint) MSG_process_get_PID(process));
-(*env)->SetIntField(env, jprocess, jprocess_field_Process_ppid, (jint) MSG_process_get_PPID(process));
+  /* sets the PID and the PPID of the process */
+  env->SetIntField(jprocess, jprocess_field_Process_pid,(jint) MSG_process_get_PID(process));
+  env->SetIntField(jprocess, jprocess_field_Process_ppid, (jint) MSG_process_get_PPID(process));
   jprocess_bind(jprocess, process, env);
 
   return 0;
 }
+
+SG_END_DECL()
index f101f73..bc8ad54 100644 (file)
 #include <simgrid/msg.h>
 #include <jni.h>
 
-extern int JAVA_HOST_LEVEL;
-extern xbt_lib_t host_lib;
+SG_BEGIN_DECL()
 
+extern int JAVA_HOST_LEVEL;
 extern int JAVA_STORAGE_LEVEL;
-extern xbt_lib_t storage_lib;
 
 JavaVM *get_java_VM(void);
 JNIEnv *get_current_thread_env(void);
@@ -68,4 +67,6 @@ JNIEXPORT void JNICALL
 Java_org_simgrid_msg_Msg_deployApplication(JNIEnv * env, jclass cls,
                                        jstring jdeploymentFile);
 
+SG_END_DECL()
+
 #endif                          /* !MSG4JAVA_H */
index 4b82931..c173e33 100644 (file)
@@ -12,7 +12,7 @@
 #include "jmsg_host.h"
 #include "jxbt_utilities.h"
 #include "jmsg_storage.h"
-
+#include <surf/surf_routing.h>
 
 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(jmsg);
 
index 0e03b94..4a82c34 100644 (file)
@@ -12,6 +12,8 @@
 #include <jni.h>
 #include "simgrid/msg.h"
 
+SG_BEGIN_DECL()
+
 /**
  * This function returns a new java host instance.
  *
@@ -224,3 +226,4 @@ Java_org_simgrid_msg_Host_setAsyncMailbox(JNIEnv * env, jclass cls_arg, jobject
 
 #endif                          /*!MSG_JHOST_H */
 
+SG_END_DECL()
similarity index 84%
rename from src/bindings/java/jmsg_process.c
rename to src/bindings/java/jmsg_process.cpp
index 7d83f3f..f8daf99 100644 (file)
 #include "jmsg.h"
 #include "jmsg_host.h"
 #include "jxbt_utilities.h"
-#include "smx_context_java.h"
-#include "smx_context_cojava.h"
+#include "JavaContext.hpp"
 
 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(jmsg);
 
+extern "C" {
+
 jfieldID jprocess_field_Process_bind;
 jfieldID jprocess_field_Process_host;
 jfieldID jprocess_field_Process_killTime;
@@ -26,59 +27,57 @@ jfieldID jprocess_field_Process_ppid;
 
 JNIEXPORT void JNICALL
 Java_org_simgrid_msg_Process_exit(JNIEnv *env, jobject jprocess) {
-  if (smx_factory_initializer_to_use == SIMIX_ctx_cojava_factory_init) {
-    msg_process_t process = jprocess_to_native_process(jprocess, env);
-    smx_context_t context = MSG_process_get_smx_ctx(process);
-    smx_ctx_cojava_stop(context);
-  }
+
 }
 
 jobject native_to_java_process(msg_process_t process)
 {
-  return ((smx_ctx_java_t)MSG_process_get_smx_ctx(process))->jprocess;
+  simgrid::java::JavaContext* context =
+    (simgrid::java::JavaContext*) MSG_process_get_smx_ctx(process);
+  return context->jprocess;
 }
 
 jobject jprocess_new_global_ref(jobject jprocess, JNIEnv * env)
 {
-  return (*env)->NewGlobalRef(env, jprocess);
+  return env->NewGlobalRef(jprocess);
 }
 
 void jprocess_delete_global_ref(jobject jprocess, JNIEnv * env)
 {
-  (*env)->DeleteGlobalRef(env, jprocess);
+  env->DeleteGlobalRef(jprocess);
 }
 
 void jprocess_join(jobject jprocess, JNIEnv * env)
 {
        msg_process_t process = jprocess_to_native_process(jprocess,env);
-       smx_ctx_java_t context = (smx_ctx_java_t)MSG_process_get_smx_ctx(process);
+       simgrid::java::JavaContext* context =
+    (simgrid::java::JavaContext*) MSG_process_get_smx_ctx(process);
        xbt_os_thread_join(context->thread,NULL);
 }
 
 msg_process_t jprocess_to_native_process(jobject jprocess, JNIEnv * env)
 {
   return
-    (msg_process_t)(intptr_t)(*env)->GetLongField(env, jprocess,
+    (msg_process_t)(intptr_t)env->GetLongField(jprocess,
                                                   jprocess_field_Process_bind);
 }
 
 void jprocess_bind(jobject jprocess, msg_process_t process, JNIEnv * env)
 {
-  (*env)->SetLongField(env, jprocess, jprocess_field_Process_bind,
+  env->SetLongField(jprocess, jprocess_field_Process_bind,
                        (intptr_t)process);
 }
 
 jlong jprocess_get_id(jobject jprocess, JNIEnv * env)
 {
   return
-    (intptr_t)(*env)->GetLongField(env, jprocess, jprocess_field_Process_id);
+    (intptr_t)env->GetLongField(jprocess, jprocess_field_Process_id);
 }
 
 jstring jprocess_get_name(jobject jprocess, JNIEnv * env)
 {
-  jstring jname = (jstring) (*env)->GetObjectField(env, jprocess, jprocess_field_Process_name);
-  return (*env)->NewGlobalRef(env, jname);
-
+  jstring jname = (jstring) env->GetObjectField(jprocess, jprocess_field_Process_name);
+  return (jstring) env->NewGlobalRef(jname);
 }
 
 jboolean jprocess_is_valid(jobject jprocess, JNIEnv * env)
@@ -88,11 +87,11 @@ jboolean jprocess_is_valid(jobject jprocess, JNIEnv * env)
   if (!id)
     return JNI_FALSE;
 
-  return (*env)->GetLongField(env, jprocess, id) ? JNI_TRUE : JNI_FALSE;
+  return env->GetLongField(jprocess, id) ? JNI_TRUE : JNI_FALSE;
 }
 JNIEXPORT void JNICALL
 Java_org_simgrid_msg_Process_nativeInit(JNIEnv *env, jclass cls) {
-  jclass jprocess_class_Process = (*env)->FindClass(env, "org/simgrid/msg/Process");
+  jclass jprocess_class_Process = env->FindClass("org/simgrid/msg/Process");
 
   jprocess_field_Process_name = jxbt_get_jfield(env, jprocess_class_Process, "name", "Ljava/lang/String;");
   jprocess_field_Process_bind = jxbt_get_jfield(env, jprocess_class_Process, "bind", "J");
@@ -120,7 +119,7 @@ Java_org_simgrid_msg_Process_create(JNIEnv * env,
   msg_process_t process;          /* the native process to create                         */
   msg_host_t host;                /* Where that process lives */
 
-  hostname = (*env)->GetStringUTFChars(env, jhostname, 0);
+  hostname = env->GetStringUTFChars((jstring) jhostname, 0);
 
   /* get the name of the java process */
   jname = jprocess_get_name(jprocess_arg, env);
@@ -146,11 +145,11 @@ Java_org_simgrid_msg_Process_create(JNIEnv * env,
   }
 
   /* build the C name of the process */
-  name = (*env)->GetStringUTFChars(env, jname, 0);
+  name = env->GetStringUTFChars(jname, 0);
   name = xbt_strdup(name);
 
   /* Retrieve the kill time from the process */
-  jdouble jkill = (*env)->GetDoubleField(env, jprocess, jprocess_field_Process_killTime);
+  jdouble jkill = env->GetDoubleField(jprocess, jprocess_field_Process_killTime);
   /* Actually build the MSG process */
   process = MSG_process_create_with_environment(name,
                                                (xbt_main_func_t) jprocess,
@@ -164,16 +163,16 @@ Java_org_simgrid_msg_Process_create(JNIEnv * env,
 
   /* release our reference to the process name (variable name becomes invalid) */
   //FIXME : This line should be uncommented but with mac it doesn't work. BIG WARNING
-  //(*env)->ReleaseStringUTFChars(env, jname, name);
-  (*env)->ReleaseStringUTFChars(env, jhostname, hostname);
+  //env->ReleaseStringUTFChars(jname, name);
+  env->ReleaseStringUTFChars((jstring) jhostname, hostname);
 
   /* sets the PID and the PPID of the process */
-  (*env)->SetIntField(env, jprocess, jprocess_field_Process_pid,(jint) MSG_process_get_PID(process));
-  (*env)->SetIntField(env, jprocess, jprocess_field_Process_ppid, (jint) MSG_process_get_PPID(process));
+  env->SetIntField(jprocess, jprocess_field_Process_pid,(jint) MSG_process_get_PID(process));
+  env->SetIntField(jprocess, jprocess_field_Process_ppid, (jint) MSG_process_get_PPID(process));
   /* sets the Host of the process */
-  jobject jhost = Java_org_simgrid_msg_Host_getByName(env,NULL,jhostname);
+  jobject jhost = Java_org_simgrid_msg_Host_getByName(env,NULL, (jstring)jhostname);
 
-  (*env)->SetObjectField(env, jprocess, jprocess_field_Process_host, jhost);
+  env->SetObjectField(jprocess, jprocess_field_Process_host, jhost);
 }
 
 JNIEXPORT jint JNICALL
@@ -211,16 +210,16 @@ Java_org_simgrid_msg_Process_getProperty(JNIEnv *env, jobject jprocess, jobject
     jxbt_throw_notbound(env, "process", jprocess);
     return NULL;
   }
-  const char *name = (*env)->GetStringUTFChars(env, jname, 0);
+  const char *name = env->GetStringUTFChars((jstring)jname, 0);
 
   const char *property = MSG_process_get_property_value(process, name);
   if (!property) {
     return NULL;
   }
 
-  jobject jproperty = (*env)->NewStringUTF(env, property);
+  jobject jproperty = env->NewStringUTF(property);
 
-  (*env)->ReleaseStringUTFChars(env, jname, name);
+  env->ReleaseStringUTFChars((jstring)jname, name);
 
   return jproperty;
 }
@@ -344,7 +343,7 @@ Java_org_simgrid_msg_Process_sleep(JNIEnv *env, jclass cls, jlong jmillis, jint
 
     //jmsg_throw_status(env,rv);
 
-    // adsein, the code above as been replaced by the code below. Indeed, according to the documentation, a sleep can only 
+    // adsein, the code above as been replaced by the code below. Indeed, according to the documentation, a sleep can only
     // trigger a host_failure exception. When the sleep crashes due to a host shutdown, the exception thrown by smx_context_java.c
     // is a cancelled_error, see bindings/java/smx_context_java.c, function void smx_ctx_java_stop(smx_context_t context) and src/msg/msg_gos.c
     // function  msg_error_t MSG_process_sleep(double nb_sec)
@@ -358,7 +357,7 @@ Java_org_simgrid_msg_Process_waitFor(JNIEnv * env, jobject jprocess,
 {
   msg_error_t rv;
   rv = MSG_process_sleep((double)jseconds);
-  if ((*env)->ExceptionOccurred(env))
+  if (env->ExceptionOccurred())
     return;
   if (rv != MSG_OK) {
     XBT_DEBUG("Status NOK");
@@ -404,7 +403,7 @@ Java_org_simgrid_msg_Process_migrate(JNIEnv * env,
     return;
   }
   /* change the host java side */
-  (*env)->SetObjectField(env, jprocess, jprocess_field_Process_host, jhost);
+  env->SetObjectField(jprocess, jprocess_field_Process_host, jhost);
 }
 JNIEXPORT void JNICALL
 Java_org_simgrid_msg_Process_setKillTime (JNIEnv *env , jobject jprocess, jdouble jkilltime) {
@@ -416,3 +415,5 @@ JNIEXPORT jint JNICALL
 Java_org_simgrid_msg_Process_getCount(JNIEnv * env, jclass cls) {
   return (jint) MSG_process_get_number();
 }
+
+}
index 974ff4a..7cd3c65 100644 (file)
@@ -13,6 +13,8 @@
 #include <simgrid/msg.h>
 #include <simgrid/simix.h>
 
+SG_BEGIN_DECL();
+
 //Cached java fields
 extern jfieldID jprocess_field_Process_bind;
 extern jfieldID jprocess_field_Process_host;
@@ -264,5 +266,6 @@ JNIEXPORT void JNICALL Java_org_simgrid_msg_Process_setKillTime
 JNIEXPORT jint JNICALL
 Java_org_simgrid_msg_Process_getCount(JNIEnv * env, jclass cls);
 
+SG_END_DECL();
 
 #endif                          /* !MSG_JPROCESS_H */
index d3fd8db..aadd0ab 100644 (file)
@@ -6,7 +6,9 @@
 /* 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 "xbt/str.h"
+#include <xbt/str.h>
+#include <surf/surf_routing.h>
+
 #include "simgrid/msg.h"
 #include "jmsg.h"
 #include "jmsg_storage.h"
index b8048f0..f9352b2 100644 (file)
@@ -8,8 +8,6 @@
 
 #include "jmsg.h"
 
-#include "smx_context_java.h"
-
 #include "jmsg_host.h"
 #include "jmsg_task.h"
 
@@ -19,6 +17,8 @@
 
 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(jmsg);
 
+jobject native_to_java_process(msg_process_t process);
+
 static jmethodID jtask_method_Comm_constructor;
 
 static jfieldID jtask_field_Task_bind;
index 54130c1..3dd3397 100644 (file)
@@ -12,6 +12,8 @@
 #include "jmsg_process.h"
 #include "jxbt_utilities.h"
 #include "simgrid/msg.h"
+#include <surf/surf_routing.h>
+
 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(jmsg);
 
 static jfieldID jvm_field_bind;
index 015a4f7..972c112 100644 (file)
 /* JNI GETTERS */
 /* *********** */
 
+SG_BEGIN_DECL()
+
 /* Search a class and throw an exception if not found */
 jclass jxbt_get_class(JNIEnv * env, const char *name);
 
 /* Search a method in a class and throw an exception if not found
    (it's ok to to pass a NULL class: it's a noop) */
-jmethodID jxbt_get_jmethod(JNIEnv * env, jclass class,
+jmethodID jxbt_get_jmethod(JNIEnv * env, jclass cls,
                            const char *name, const char *signature);
 
 /* Like the jxbt_get_class() but get a static method */
@@ -30,7 +32,7 @@ jmethodID jxbt_get_static_jmethod(JNIEnv * env, jclass cls,
 
 /* Search a field in a class and throw an exception if not found
    (it's ok to to pass a NULL class: it's a noop) */
-jfieldID jxbt_get_jfield(JNIEnv * env, jclass class,
+jfieldID jxbt_get_jfield(JNIEnv * env, jclass cls,
                          const char *name, const char *signature);
 
 
@@ -96,3 +98,5 @@ void jxbt_throw_task_cancelled(JNIEnv * env, char *details);
 /** Thrown when looking for a storage from name does not lead to anything */
 void jxbt_throw_storage_not_found(JNIEnv * env, const char *invalid_name);
 #endif                          /* ! JXBT_UTILITY_H */
+
+SG_END_DECL()
diff --git a/src/bindings/java/smx_context_cojava.c b/src/bindings/java/smx_context_cojava.c
deleted file mode 100644 (file)
index bfafcb4..0000000
+++ /dev/null
@@ -1,284 +0,0 @@
-/* context_cojava - implementation of context switching for java coroutines */
-
-/* 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 <xbt/function_types.h>
-#include <simgrid/simix.h>
-#include <xbt/ex.h>
-#include "smx_context_cojava.h"
-#include "jxbt_utilities.h"
-#include "xbt/dynar.h"
-
-
-//Coroutine methodID/class cache.
-jclass coclass;
-jmethodID coroutine_init;
-jmethodID coroutine_yield;
-jmethodID coroutine_yieldTo;
-jmethodID coroutine_stop;
-//Maestro java coroutine
-jobject cojava_maestro_coroutine;
-
-JNIEnv *global_env;
-
-static smx_context_t my_current_context = NULL;
-static smx_context_t maestro_context = NULL;
-
-
-xbt_dynar_t cojava_processes;
-static unsigned long int cojava_process_index = 0;
-
-extern JavaVM *__java_vm;
-
-XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(jmsg);
-
-
-static smx_context_t
-smx_ctx_cojava_factory_create_context(xbt_main_func_t code,
-                                      int argc, char **argv,
-                                      void_pfn_smxprocess_t cleanup_func,
-                                      smx_process_t process);
-
-static void smx_ctx_cojava_free(smx_context_t context);
-static void smx_ctx_cojava_suspend(smx_context_t context);
-static void smx_ctx_cojava_resume(smx_context_t new_context);
-static void smx_ctx_cojava_runall(void);
-static void* smx_ctx_cojava_run(void *data);
-static void smx_ctx_cojava_create_coroutine(smx_ctx_cojava_t context);
-void SIMIX_ctx_cojava_factory_init(smx_context_factory_t * factory)
-{
-  /* instantiate the context factory */
-  smx_ctx_base_factory_init(factory);
-
-  (*factory)->create_context = smx_ctx_cojava_factory_create_context;
-  /* Leave default behavior of (*factory)->finalize */
-  (*factory)->free = smx_ctx_cojava_free;
-  (*factory)->stop = smx_ctx_cojava_stop;
-  (*factory)->suspend = smx_ctx_cojava_suspend;
-  (*factory)->runall = smx_ctx_cojava_runall;
-  (*factory)->name = "ctx_cojava_factory";
-  //(*factory)->finalize = smx_ctx_base_factory_finalize;
-  (*factory)->self = smx_ctx_cojava_self;
-  (*factory)->get_process = smx_ctx_base_get_process;
-
-  global_env = get_current_thread_env();
-
-  coclass = (*global_env)->FindClass(global_env, "java/dyn/Coroutine");
-  xbt_assert((coclass != NULL), "Can't find java.dyn.Coroutine class.");
-  //Cache the method id we are going to use
-  coroutine_init = (*global_env)->GetMethodID(global_env, coclass, "<init>", "(Ljava/lang/Runnable;)V");
-  xbt_assert((coroutine_init != NULL), "Can't find <init>");
-  coroutine_stop = (*global_env)->GetMethodID(global_env, coclass, "stop", "()V");
-  xbt_assert((coroutine_stop != NULL), "Method not found...");
-  coroutine_yield = (*global_env)->GetStaticMethodID(global_env, coclass, "yield", "()V");
-  xbt_assert((coroutine_yield != NULL), "Method yield not found.");
-  coroutine_yieldTo = (*global_env)->GetStaticMethodID(global_env, coclass, "yieldTo", "(Ljava/dyn/Coroutine;)V");
-  xbt_assert((coroutine_yieldTo != NULL), "Method yieldTo not found.");
-
-  jclass class_thread = (*global_env)->FindClass(global_env, "java/lang/Thread");
-  xbt_assert((class_thread != NULL), "Can't find java.lang.Thread class");
-  
-  jclass class_coroutine_support = (*global_env)->FindClass(global_env, "java/dyn/CoroutineSupport");
-  xbt_assert((class_coroutine_support != NULL), "Can't find java.dyn.CoroutineSupport class");
-  jmethodID thread_get_current = (*global_env)->GetStaticMethodID(global_env, class_thread, "currentThread", "()Ljava/lang/Thread;");
-  xbt_assert((thread_get_current != NULL), "Can't find Thread.currentThread() method.");
-
-  /**
-   * Retrieve maetro coroutine object
-   */
-  jobject jthread;
-  jthread = (*global_env)->CallStaticObjectMethod(global_env, class_thread, thread_get_current);
-  xbt_assert((jthread != NULL), "Can't find current thread.");
-
-  jmethodID thread_get_coroutine_support = (*global_env)->GetMethodID(global_env, class_thread, "getCoroutineSupport", "()Ljava/dyn/CoroutineSupport;");
-  xbt_assert((thread_get_coroutine_support != NULL), "Can't find Thread.getCoroutineSupport method");
-
-  jobject jcoroutine_support;
-  jcoroutine_support = (*global_env)->CallObjectMethod(global_env, jthread, thread_get_coroutine_support);
-  xbt_assert((jcoroutine_support != NULL), "Can't find coroutine support object");
-  //FIXME ? Be careful, might change in the implementation (we are relying on private fields, so...).
-  jfieldID coroutine_support_thread_coroutine = (*global_env)->GetFieldID(global_env, class_coroutine_support, "threadCoroutine", "Ljava/dyn/Coroutine;");
-  xbt_assert((coroutine_support_thread_coroutine != NULL), "Can't find threadCoroutine field");
-  cojava_maestro_coroutine = (jobject)(*global_env)->GetObjectField(global_env, jcoroutine_support, coroutine_support_thread_coroutine);
-  xbt_assert((cojava_maestro_coroutine != NULL), "Can't find the thread coroutine.");
-  cojava_maestro_coroutine = (*global_env)->NewGlobalRef(global_env, cojava_maestro_coroutine);
-  xbt_assert((cojava_maestro_coroutine != NULL), "Can't get a global reference to the thread coroutine.");
-}
-smx_context_t smx_ctx_cojava_self(void)
-{
-       return my_current_context;
-}
-
-static smx_context_t
-smx_ctx_cojava_factory_create_context(xbt_main_func_t code,
-                                      int argc, char **argv,
-                                      void_pfn_smxprocess_t cleanup_func,
-                                      smx_process_t process)
-{
-       smx_ctx_cojava_t context = xbt_new0(s_smx_ctx_cojava_t, 1);
-  /* If the user provided a function for the process then use it
-     otherwise is the context for maestro */
-  if (code) {
-    if (argc == 0) {
-      context->jprocess = (jobject) code;
-    }
-    else {
-      context->jprocess = NULL;
-    }
-    context->super.cleanup_func = cleanup_func;
-
-    context->super.argc = argc;
-    context->super.argv = argv;
-    context->super.code = code;
-
-    smx_ctx_cojava_run(context);
-  }
-  else {
-       context->jcoroutine = NULL;
-       my_current_context = (smx_context_t)context;
-       maestro_context = (smx_context_t)context;
-  }
-  context->bound = 0;
-  context->super.process = process;
-  return (smx_context_t) context;
-}
-
-static void* smx_ctx_cojava_run(void *data) {
-  smx_ctx_cojava_t context = (smx_ctx_cojava_t)data;
-  my_current_context = (smx_context_t)context;
-  //Create the "Process" object if needed.
-  if (context->super.argc <= 0) {
-    smx_ctx_cojava_create_coroutine(context);
-  }
-  my_current_context = maestro_context;
-  return NULL;
-}
-static void smx_ctx_cojava_free(smx_context_t context)
-{
-  if (context) {
-    smx_ctx_cojava_t ctx_java = (smx_ctx_cojava_t) context;
-    if (ctx_java->jcoroutine) { /* We are not in maestro context */
-      JNIEnv *env = get_current_thread_env();
-      (*env)->DeleteGlobalRef(env, ctx_java->jcoroutine);
-      (*env)->DeleteGlobalRef(env, ctx_java->jprocess);
-    }
-  }
-  smx_ctx_base_free(context);
-}
-
-
-void smx_ctx_cojava_stop(smx_context_t context)
-{
-  /*
-   * The java stack needs to be empty, otherwise weird stuff
-   * will happen
-   */
-  if (context->iwannadie) {
-    context->iwannadie = 0;
-    JNIEnv *env = get_current_thread_env();
-    // TODO it will be nice to have the name of the process to help the end-user to know which Process has been killed
-    jxbt_throw_by_name(env, "org/simgrid/msg/ProcessKilledError", xbt_strdup("Process killed :) (file smx_context_cojava.c)"));
-    THROWF(cancel_error, 0, "process cancelled");
-  }
-  else {
-    smx_ctx_base_stop(context);
-    smx_ctx_cojava_suspend(context);
-  }
-}
-
-static void smx_ctx_cojava_suspend(smx_context_t context)
-{
-  smx_context_t previous_context = context;
-  unsigned long int i = cojava_process_index++;
-  jobject next_coroutine;
-
-  if (i < xbt_dynar_length(cojava_processes)) {
-    smx_context_t next_context = SIMIX_process_get_context(xbt_dynar_get_as(
-    cojava_processes,i, smx_process_t));
-    my_current_context = next_context;
-    XBT_DEBUG("Switching to %p",my_current_context);
-    smx_ctx_cojava_t java_context = (smx_ctx_cojava_t)(next_context);
-    if (!java_context->jprocess) {
-      java_context->super.code(java_context->super.argc, java_context->super.argv);
-      smx_ctx_cojava_create_coroutine(java_context);
-    }
-    else if (!java_context->bound) {
-      java_context->bound = 1;
-      smx_process_t process = SIMIX_process_self();
-      (*global_env)->SetLongField(global_env, java_context->jprocess,
-                                  jprocess_field_Process_bind,
-                                  (intptr_t)process);
-    }
-
-    next_coroutine = java_context->jcoroutine;
-  }
-  else {
-    //Give maestro the control back.
-    next_coroutine = cojava_maestro_coroutine;
-    my_current_context = maestro_context;
-  }
-  (*global_env)->CallStaticVoidMethod(global_env, coclass, coroutine_yieldTo, next_coroutine);
-  my_current_context = previous_context;
-}
-
-static void smx_ctx_cojava_resume(smx_context_t new_context) {
-  my_current_context = new_context;
-  smx_ctx_cojava_t java_context = (smx_ctx_cojava_t)(new_context);
-
-  if (!java_context->jprocess) {
-    java_context->super.code(java_context->super.argc, java_context->super.argv);
-    smx_ctx_cojava_create_coroutine(java_context);
-    java_context->bound = 1;
-  }
-  else if (!java_context->bound) {
-    java_context->bound = 1;
-    smx_process_t process = SIMIX_process_self();
-    (*global_env)->SetLongField(global_env, java_context->jprocess,
-                                jprocess_field_Process_bind, (intptr_t)process);
-  }
-  (*global_env)->CallStaticVoidMethod(global_env, coclass, coroutine_yieldTo, java_context->jcoroutine);
-}
-
-static void smx_ctx_cojava_runall(void)
-{
-  cojava_processes = SIMIX_process_get_runnable();
-  smx_process_t process;
-  if (!xbt_dynar_is_empty(cojava_processes)) {
-    process = xbt_dynar_get_as(cojava_processes, 0, smx_process_t);
-    cojava_process_index = 1;
-    /* Execute the first process */
-    smx_ctx_cojava_resume(SIMIX_process_get_context(process));
-  }
-}
-
-static void smx_ctx_cojava_create_coroutine(smx_ctx_cojava_t context) {
-  JNIEnv *env = get_current_thread_env();
-  jclass coclass = (*env)->FindClass(env, "java/dyn/Coroutine");
-  xbt_assert((coclass != NULL), "Can't find coroutine class ! :(");
-  jobject jcoroutine = (*env)->NewObject(env, coclass, coroutine_init, context->jprocess);
-  if (jcoroutine == NULL) {
-     FILE *conf= fopen("/proc/sys/vm/max_map_count","r");
-     if (conf) {
-       int limit=-1;
-        if(fscanf(conf,"%d",&limit) != 1)
-           xbt_die("Error while creating a new coroutine. Parse error.");
-       fclose(conf);
-       if (limit!=-1 && SIMIX_process_count() > (limit - 100) /2)
-          xbt_die("Error while creating a new coroutine. "
-                  "This seem due to the the vm.max_map_count system limit that is only equal to %d while we already have %d coroutines. "
-                  "Please check the install documentation to see how to increase this limit", limit, SIMIX_process_count());
-       if (limit == -1)
-         xbt_die("Error while creating a new coroutine. "
-                 "This seems to be a non-linux system, disabling the automatic verification that the system limit on the amount of memory maps is high enough.");
-       xbt_die("Error while creating a new coroutine. ");
-     }
-     
-  }
-   
-  jcoroutine = (*env)->NewGlobalRef(env, jcoroutine);
-  context->jcoroutine = jcoroutine;
-}
diff --git a/src/bindings/java/smx_context_cojava.h b/src/bindings/java/smx_context_cojava.h
deleted file mode 100644 (file)
index 85b8c03..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/* 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 _XBT_CONTEXT_COJAVA_H
-#define _XBT_CONTEXT_COJAVA_H
-
-#include <xbt/misc.h>
-#include <simgrid/simix.h>
-#include <xbt/xbt_os_thread.h>
-
-#include "jmsg.h"
-#include "jmsg_process.h"
-
-SG_BEGIN_DECL()
-
-typedef struct s_smx_ctx_cojava {
-  s_smx_ctx_base_t super;       /* Fields of super implementation */
-  jobject jprocess;             /* the java process instance bound with the msg process structure */
-  JNIEnv *jenv;                 /* jni interface pointer associated to this thread */
-  jobject jcoroutine;                                          /* java coroutine object */
-  int bound:1;
-} s_smx_ctx_cojava_t, *smx_ctx_cojava_t;
-
-void SIMIX_ctx_cojava_factory_init(smx_context_factory_t *factory);
-void smx_ctx_cojava_stop(smx_context_t context);
-smx_context_t smx_ctx_cojava_self(void);
-SG_END_DECL()
-
-#endif                          /* !_XBT_CONTEXT_JAVA_H */
diff --git a/src/bindings/java/smx_context_java.c b/src/bindings/java/smx_context_java.c
deleted file mode 100644 (file)
index 6d7206d..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-/* context_java - implementation of context switching for java threads */
-
-/* Copyright (c) 2009-2010, 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 <xbt/function_types.h>
-#include <simgrid/simix.h>
-#include <xbt/ex.h>
-#include "smx_context_java.h"
-#include "jxbt_utilities.h"
-#include "xbt/dynar.h"
-#include "../../simix/smx_private.h"
-extern JavaVM *__java_vm;
-
-XBT_LOG_NEW_DEFAULT_SUBCATEGORY(jmsg, bindings, "MSG for Java(TM)");
-
-static smx_context_t
-smx_ctx_java_factory_create_context(xbt_main_func_t code,
-                                    int argc, char **argv,
-                                    void_pfn_smxprocess_t cleanup_func,
-                                    smx_process_t process);
-
-static void smx_ctx_java_free(smx_context_t context);
-static void smx_ctx_java_suspend(smx_context_t context);
-static void smx_ctx_java_resume(smx_context_t new_context);
-static void smx_ctx_java_runall(void);
-static void* smx_ctx_java_thread_run(void *data);
-void SIMIX_ctx_java_factory_init(smx_context_factory_t * factory)
-{
-  /* instantiate the context factory */
-  smx_ctx_base_factory_init(factory);
-
-  (*factory)->create_context = smx_ctx_java_factory_create_context;
-  /* Leave default behavior of (*factory)->finalize */
-  (*factory)->free = smx_ctx_java_free;
-  (*factory)->stop = smx_ctx_java_stop;
-  (*factory)->suspend = smx_ctx_java_suspend;
-  (*factory)->runall = smx_ctx_java_runall;
-  (*factory)->name = "ctx_java_factory";
-  //(*factory)->finalize = smx_ctx_base_factory_finalize;
-  (*factory)->self = smx_ctx_java_self;
-  (*factory)->get_process = smx_ctx_base_get_process;
-}
-smx_context_t smx_ctx_java_self(void)
-{
-       return (smx_context_t)xbt_os_thread_get_extra_data();
-}
-
-static smx_context_t
-smx_ctx_java_factory_create_context(xbt_main_func_t code,
-                                    int argc, char **argv,
-                                    void_pfn_smxprocess_t cleanup_func,
-                                    smx_process_t process)
-{
-  static int thread_amount=0;
-  smx_ctx_java_t context = xbt_new0(s_smx_ctx_java_t, 1);
-  thread_amount++;
-  /* If the user provided a function for the process then use it
-     otherwise is the context for maestro */
-  if (code) {
-    if (argc == 0) {
-      context->jprocess = (jobject) code;
-    }
-    else {
-      context->jprocess = NULL;
-    }
-    context->super.cleanup_func = cleanup_func;
-    context->begin = xbt_os_sem_init(0);
-    context->end = xbt_os_sem_init(0);
-
-    context->super.argc = argc;
-    context->super.argv = argv;
-    context->super.code = code;
-
-    TRY {        
-       context->thread = xbt_os_thread_create(NULL,smx_ctx_java_thread_run,context,NULL);
-    }
-    CATCH_ANONYMOUS {
-      RETHROWF("Failed to create context #%d. You may want to switch to Java coroutines to increase your limits (error: %s)."
-               "See the Install section of simgrid-java documentation (in doc/install.html) for more on coroutines.",
-               thread_amount);
-    }
-  } else {
-       context->thread = NULL;
-    xbt_os_thread_set_extra_data(context);
-  }
-  context->super.process = process;
-  
-  return (smx_context_t) context;
-}
-
-static void* smx_ctx_java_thread_run(void *data) {
-  smx_ctx_java_t context = (smx_ctx_java_t)data;
-  xbt_os_thread_set_extra_data(context);
-  //Attach the thread to the JVM
-  JNIEnv *env;
-  XBT_ATTRIB_UNUSED jint error = (*__java_vm)->AttachCurrentThread(__java_vm, (void **) &env, NULL);
-  xbt_assert((error == JNI_OK), "The thread could not be attached to the JVM");
-  context->jenv = get_current_thread_env();
-  //Wait for the first scheduling round to happen.
-  xbt_os_sem_acquire(context->begin);
-  //Create the "Process" object if needed.
-  if (context->super.argc > 0) {
-    context->super.code(context->super.argc, context->super.argv);
-  }
-  else {
-    smx_process_t process = SIMIX_process_self();
-    (*env)->SetLongField(env, context->jprocess, jprocess_field_Process_bind,
-                         (intptr_t)process);
-  }
-
-  // Adrien, ugly path, just to bypass creation of context at low levels
-  // (i.e such as for the VM migration for instance)
-  if(context->jprocess != NULL){
-       xbt_assert((context->jprocess != NULL), "Process not created...");
-       //wait for the process to be able to begin
-       //TODO: Cache it
-       jfieldID jprocess_field_Process_startTime = jxbt_get_sfield(env, "org/simgrid/msg/Process", "startTime", "D");
-       jdouble startTime =  (*env)->GetDoubleField(env, context->jprocess, jprocess_field_Process_startTime);
-       if (startTime > MSG_get_clock()) {
-               MSG_process_sleep(startTime - MSG_get_clock());
-       }
-       //Execution of the "run" method.
-       jmethodID id = jxbt_get_smethod(env, "org/simgrid/msg/Process", "run", "()V");
-       xbt_assert( (id != NULL), "Method not found...");
-       (*env)->CallVoidMethod(env, context->jprocess, id);
-  }
-  smx_ctx_java_stop((smx_context_t)context);
-
-  return NULL;
-}
-
-static void smx_ctx_java_free(smx_context_t context)
-{
-  if (context) {
-    smx_ctx_java_t ctx_java = (smx_ctx_java_t) context;
-    if (ctx_java->thread) { /* We are not in maestro context */
-      xbt_os_thread_join(ctx_java->thread, NULL);
-      xbt_os_sem_destroy(ctx_java->begin);
-      xbt_os_sem_destroy(ctx_java->end);
-    }
-  }
-  smx_ctx_base_free(context);
-}
-
-
-void smx_ctx_java_stop(smx_context_t context)
-{
-  smx_ctx_java_t ctx_java = (smx_ctx_java_t)context;
-  /* I am the current process and I am dying */
-  if (context->iwannadie) {
-    context->iwannadie = 0;
-    JNIEnv *env = get_current_thread_env();
-    XBT_DEBUG("Gonna launch Killed Error");
-    // TODO Adrien, if the process has not been created at the java layer, why should we raise the exception/error at the java level (this happens
-    // for instance during the migration process that creates at the C level two processes: one on the SRC node and one on the DST node, if the DST process is killed. 
-    // it is not required to raise an exception at the JAVA level, the low level should be able to manage such an issue correctly but this is not the case right now unfortunately ...
-    // TODO it will be nice to have the name of the process to help the end-user to know which Process has been killed
-   // jxbt_throw_by_name(env, "org/simgrid/msg/ProcessKilledError", bprintf("Process %s killed :) (file smx_context_java.c)", MSG_process_get_name( (msg_process_t)context) ));
-    jxbt_throw_by_name(env, "org/simgrid/msg/ProcessKilledError", bprintf("Process %s killed :) (file smx_context_java.c)", simcall_process_get_name((smx_process_t) SIMIX_context_get_process(context))) );
-    XBT_DEBUG("Trigger a cancel error at the C level");
-    THROWF(cancel_error, 0, "process cancelled");
-  } else {
-    smx_ctx_base_stop(context);
-    /* detach the thread and kills it */
-    JNIEnv *env = ctx_java->jenv;
-    (*env)->DeleteGlobalRef(env,ctx_java->jprocess);
-    XBT_ATTRIB_UNUSED jint error = (*__java_vm)->DetachCurrentThread(__java_vm);
-    xbt_assert((error == JNI_OK), "The thread couldn't be detached.");
-    xbt_os_sem_release(((smx_ctx_java_t)context)->end);
-    xbt_os_thread_exit(NULL);
-  }
-}
-
-static void smx_ctx_java_suspend(smx_context_t context)
-{
-  smx_ctx_java_t ctx_java = (smx_ctx_java_t) context;
-  xbt_os_sem_release(ctx_java->end);
-  xbt_os_sem_acquire(ctx_java->begin);
-}
-
-// FIXME: inline those functions
-static void smx_ctx_java_resume(smx_context_t new_context)
-{
-  smx_ctx_java_t ctx_java = (smx_ctx_java_t) new_context;
-  xbt_os_sem_release(ctx_java->begin);
-  xbt_os_sem_acquire(ctx_java->end);
-}
-
-static void smx_ctx_java_runall(void)
-{
-  xbt_dynar_t processes = SIMIX_process_get_runnable();
-  smx_process_t process;
-  unsigned int cursor;
-  xbt_dynar_foreach(processes, cursor, process) {
-    smx_ctx_java_resume(SIMIX_process_get_context(process));
-  }
-}
diff --git a/src/bindings/java/smx_context_java.h b/src/bindings/java/smx_context_java.h
deleted file mode 100644 (file)
index fbeee13..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/* Copyright (c) 2009-2010, 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 _XBT_CONTEXT_JAVA_H
-#define _XBT_CONTEXT_JAVA_H
-
-#include <xbt/misc.h>
-#include <simgrid/simix.h>
-#include <xbt/xbt_os_thread.h>
-
-#include "jmsg.h"
-#include "jmsg_process.h"
-
-SG_BEGIN_DECL()
-
-typedef struct s_smx_ctx_java {
-  s_smx_ctx_base_t super;       /* Fields of super implementation */
-  jobject jprocess;             /* the java process instance bound with the msg process structure */
-  JNIEnv *jenv;                 /* jni interface pointer associated to this thread */
-  xbt_os_thread_t thread;
-  xbt_os_sem_t begin;           /* this semaphore is used to schedule/yield the process  */
-  xbt_os_sem_t end;             /* this semaphore is used to schedule/unschedule the process   */
-} s_smx_ctx_java_t, *smx_ctx_java_t;
-
-void SIMIX_ctx_java_factory_init(smx_context_factory_t *factory);
-void smx_ctx_java_stop(smx_context_t context);
-smx_context_t smx_ctx_java_self(void);
-SG_END_DECL()
-
-#endif                          /* !_XBT_CONTEXT_JAVA_H */
diff --git a/src/simix/BoostContext.cpp b/src/simix/BoostContext.cpp
new file mode 100644 (file)
index 0000000..f2e5cee
--- /dev/null
@@ -0,0 +1,298 @@
+/* Copyright (c) 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. */
+
+/** @file BoostContext.cpp Userspace context switching implementation based on Boost.Context */
+
+#include <cstdint>
+
+#include <boost/context/all.hpp>
+
+#include <xbt/log.h>
+#include <xbt/xbt_os_thread.h>
+
+#include "smx_private.h"
+#include "smx_private.hpp"
+#include "src/internal_config.h"
+#include "src/simix/BoostContext.hpp"
+
+XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_context);
+
+namespace simgrid {
+namespace simix {
+
+class BoostSerialContext : public BoostContext {
+public:
+  BoostSerialContext(xbt_main_func_t code,
+      int argc, char **argv,
+      void_pfn_smxprocess_t cleanup_func,
+      smx_process_t process)
+    : BoostContext(code, argc, argv, cleanup_func, process) {}
+  void stop() override;
+  void suspend() override;
+  void resume();
+};
+
+#ifdef CONTEXT_THREADS
+class BoostParallelContext : public BoostContext {
+public:
+  BoostParallelContext(xbt_main_func_t code,
+      int argc, char **argv,
+      void_pfn_smxprocess_t cleanup_func,
+      smx_process_t process)
+    : BoostContext(code, argc, argv, cleanup_func, process) {}
+  void stop() override;
+  void suspend() override;
+  void resume();
+};
+#endif
+
+// BoostContextFactory
+
+bool                BoostContext::parallel_        = false;
+xbt_parmap_t        BoostContext::parmap_          = nullptr;
+unsigned long       BoostContext::threads_working_ = 0;
+xbt_os_thread_key_t BoostContext::worker_id_key_;
+unsigned long       BoostContext::process_index_   = 0;
+BoostContext*       BoostContext::maestro_context_ = nullptr;
+std::vector<BoostContext*> BoostContext::workers_context_;
+
+BoostContextFactory::BoostContextFactory()
+  : ContextFactory("BoostContextFactory")
+{
+  BoostContext::parallel_ = SIMIX_context_is_parallel();
+  if (BoostContext::parallel_) {
+#ifndef CONTEXT_THREADS
+    xbt_die("No thread support for parallel context execution");
+#else
+    int nthreads = SIMIX_context_get_nthreads();
+    BoostContext::parmap_ = xbt_parmap_new(nthreads, SIMIX_context_get_parallel_mode());
+    BoostContext::workers_context_.clear();
+    BoostContext::workers_context_.resize(nthreads, nullptr);
+    BoostContext::maestro_context_ = nullptr;
+    xbt_os_thread_key_create(&BoostContext::worker_id_key_);
+#endif
+  }
+}
+
+BoostContextFactory::~BoostContextFactory()
+{
+#ifdef CONTEXT_THREADS
+  if (BoostContext::parmap_) {
+    xbt_parmap_destroy(BoostContext::parmap_);
+    BoostContext::parmap_ = nullptr;
+  }
+  BoostContext::workers_context_.clear();
+#endif
+}
+
+smx_context_t BoostContextFactory::create_context(
+  xbt_main_func_t code, int argc, char ** argv,
+  void_pfn_smxprocess_t cleanup_func, smx_process_t process)
+{
+  BoostContext* context = nullptr;
+  if (BoostContext::parallel_)
+#ifdef CONTEXT_THREADS
+    context = this->new_context<BoostParallelContext>(
+      code, argc, argv, cleanup_func, process);
+#else
+    xbt_die("No support for parallel execution");
+#endif
+  else
+    context = this->new_context<BoostSerialContext>(
+      code, argc, argv, cleanup_func, process);
+  return context;
+}
+
+void BoostContextFactory::run_all()
+{
+#ifdef CONTEXT_THREADS
+  if (BoostContext::parallel_) {
+    BoostContext::threads_working_ = 0;
+    xbt_parmap_apply(BoostContext::parmap_,
+      [](void* arg) {
+        smx_process_t process = static_cast<smx_process_t>(arg);
+        BoostContext* context  = static_cast<BoostContext*>(process->context);
+        return context->resume();
+      },
+      simix_global->process_to_run);
+  } else
+#endif
+  {
+    smx_process_t first_process =
+        xbt_dynar_get_as(simix_global->process_to_run, 0, smx_process_t);
+    BoostContext::process_index_ = 1;
+    /* execute the first process */
+    static_cast<BoostContext*>(first_process->context)->resume();
+  }
+}
+
+
+// BoostContext
+
+static void smx_ctx_boost_wrapper(std::intptr_t arg)
+{
+  BoostContext* context = (BoostContext*) arg;
+  (*context)();
+  context->stop();
+}
+
+BoostContext::BoostContext(xbt_main_func_t code,
+    int argc, char **argv,
+    void_pfn_smxprocess_t cleanup_func,
+    smx_process_t process)
+  : Context(code, argc, argv, cleanup_func, process)
+{
+
+  /* if the user provided a function for the process then use it,
+     otherwise it is the context for maestro */
+  if (code) {
+    this->stack_ = SIMIX_context_stack_new();
+    // We need to pass the bottom of the stack to make_fcontext,
+    // depending on the stack direction it may be the lower or higher address:
+  #if PTH_STACKGROWTH == -1
+    void* stack = (char*) this->stack_ + smx_context_usable_stack_size - 1;
+  #else
+    void* stack = this->stack_;
+  #endif
+    this->fc_ = boost::context::make_fcontext(
+                      stack,
+                      smx_context_usable_stack_size,
+                      smx_ctx_boost_wrapper);
+  } else {
+    #if HAVE_BOOST_CONTEXT == 1
+    this->fc_ = new boost::context::fcontext_t();
+    #endif
+    if (BoostContext::maestro_context_ == nullptr)
+      BoostContext::maestro_context_ = this;
+  }
+}
+
+BoostContext::~BoostContext()
+{
+#if HAVE_BOOST_CONTEXT == 1
+  if (!this->stack_)
+    delete this->fc_;
+#endif
+  if (this == maestro_context_)
+    maestro_context_ = nullptr;
+  SIMIX_context_stack_delete(this->stack_);
+}
+
+// BoostSerialContext
+
+void BoostContext::resume()
+{
+  SIMIX_context_set_current(this);
+#if HAVE_BOOST_CONTEXT == 1
+  boost::context::jump_fcontext(
+    maestro_context_->fc_, this->fc_,
+    (intptr_t) this);
+#else
+  boost::context::jump_fcontext(
+    &boost_maestro_context_->fc_, this->fc_,
+    (intptr_t) this);
+#endif
+}
+
+void BoostSerialContext::suspend()
+{
+  /* determine the next context */
+  BoostSerialContext* next_context = nullptr;
+  unsigned long int i = process_index_++;
+
+  if (i < xbt_dynar_length(simix_global->process_to_run)) {
+    /* 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_process_t)->context);
+  }
+  else {
+    /* all processes were run, return to maestro */
+    XBT_DEBUG("No more process to run");
+    next_context = static_cast<BoostSerialContext*>(
+      maestro_context_);
+  }
+  SIMIX_context_set_current((smx_context_t) next_context);
+  #if HAVE_BOOST_CONTEXT == 1
+  boost::context::jump_fcontext(
+    this->fc_, next_context->fc_, (intptr_t) next_context);
+  #else
+  boost::context::jump_fcontext(
+    &this->fc_, next_context->fc_, (intptr_t) next_context);
+  #endif
+}
+
+void BoostSerialContext::stop()
+{
+  BoostContext::stop();
+  this->suspend();
+}
+
+// BoostParallelContext
+
+#ifdef CONTEXT_THREADS
+
+void BoostParallelContext::suspend()
+{
+  smx_process_t next_work = (smx_process_t) xbt_parmap_next(parmap_);
+  BoostParallelContext* next_context = nullptr;
+
+  if (next_work != nullptr) {
+    XBT_DEBUG("Run next process");
+    next_context = static_cast<BoostParallelContext*>(next_work->context);
+  }
+  else {
+    XBT_DEBUG("No more processes to run");
+    unsigned long worker_id =
+      (unsigned long) xbt_os_thread_get_specific(worker_id_key_);
+    next_context = static_cast<BoostParallelContext*>(
+      workers_context_[worker_id]);
+  }
+
+  SIMIX_context_set_current((smx_context_t) next_context);
+#if HAVE_BOOST_CONTEXT == 1
+  boost::context::jump_fcontext(
+    this->fc_, next_context->fc_, (intptr_t)next_context);
+#else
+  boost::context::jump_fcontext(
+    &this->fc_, next_context->fc_, (intptr_t)next_context);
+#endif
+}
+
+void BoostParallelContext::stop()
+{
+  BoostContext::stop();
+  this->suspend();
+}
+
+void BoostParallelContext::resume()
+{
+  unsigned long worker_id = __sync_fetch_and_add(&threads_working_, 1);
+  xbt_os_thread_set_specific(worker_id_key_, (void*) worker_id);
+
+  BoostParallelContext* worker_context =
+    static_cast<BoostParallelContext*>(SIMIX_context_self());
+  workers_context_[worker_id] = worker_context;
+
+  SIMIX_context_set_current(this);
+#if HAVE_BOOST_CONTEXT == 1
+  boost::context::jump_fcontext(
+    worker_context->fc_, this->fc_, (intptr_t) this);
+#else
+  boost::context::jump_fcontext(
+    &worker_context->fc_, this->fc_, (intptr_t) this);
+#endif
+}
+
+#endif
+
+XBT_PRIVATE ContextFactory* boost_factory()
+{
+  return new BoostContextFactory();
+}
+
+}
+}
diff --git a/src/simix/BoostContext.hpp b/src/simix/BoostContext.hpp
new file mode 100644 (file)
index 0000000..4f64f41
--- /dev/null
@@ -0,0 +1,74 @@
+/* Copyright (c) 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. */
+
+/** @file BoostContext.hpp
+    Userspace context switching implementation based on Boost.Context */
+
+#ifndef SIMGRID_SIMIX_BOOST_CONTEXT_HPP
+#define SIMGRID_SIMIX_BOOST_CONTEXT_HPP
+
+#include <vector>
+
+#include <xbt/parmap.h>
+
+#include <simgrid/simix.hpp>
+
+
+namespace simgrid {
+namespace simix {
+
+class BoostContext;
+class BoostSerialContext;
+class BoostParallelContext;
+class BoostContextFactory;
+
+class BoostContext : public Context {
+protected: // static
+  static bool parallel_;
+  static xbt_parmap_t parmap_;
+  static std::vector<BoostContext*> workers_context_;
+  static unsigned long threads_working_;
+  static xbt_os_thread_key_t worker_id_key_;
+  static unsigned long process_index_;
+  static BoostContext* maestro_context_;
+protected:
+#if HAVE_BOOST_CONTEXT == 1
+  boost::context::fcontext_t* fc_ = nullptr;
+#else
+  boost::context::fcontext_t fc_;
+#endif
+  void* stack_ = nullptr;
+public:
+  friend BoostContextFactory;
+  BoostContext(xbt_main_func_t code,
+          int argc, char **argv,
+          void_pfn_smxprocess_t cleanup_func,
+          smx_process_t process);
+  ~BoostContext();
+  void resume();
+private:
+  static void wrapper(int first, ...);
+};
+
+class BoostContextFactory : public ContextFactory {
+public:
+  friend BoostContext;
+  friend BoostSerialContext;
+  friend BoostParallelContext;
+
+  BoostContextFactory();
+  virtual ~BoostContextFactory();
+  virtual Context* create_context(
+    xbt_main_func_t, int, char **, void_pfn_smxprocess_t,
+    smx_process_t process
+    ) override;
+  void run_all() override;
+};
+
+}
+}
+
+#endif
diff --git a/src/simix/Context.cpp b/src/simix/Context.cpp
new file mode 100644 (file)
index 0000000..fbfffc9
--- /dev/null
@@ -0,0 +1,80 @@
+/* Copyright (c) 2007-2010, 2012-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. */
+
+#include <simgrid/simix.hpp>
+
+#include "mc/mc.h"
+
+#include <src/simix/smx_private.h>
+
+void SIMIX_process_set_cleanup_function(
+  smx_process_t process, void_pfn_smxprocess_t cleanup)
+{
+  process->context->set_cleanup(cleanup);
+}
+
+namespace simgrid {
+namespace simix {
+
+ContextFactoryInitializer factory_initializer = nullptr;
+
+ContextFactory::~ContextFactory() {}
+
+Context* ContextFactory::self()
+{
+  return SIMIX_context_get_current();
+}
+
+void ContextFactory::declare_context(void* context, std::size_t size)
+{
+#ifdef HAVE_MC
+  /* Store the address of the stack in heap to compare it apart of heap comparison */
+  if(MC_is_active())
+    MC_ignore_heap(context, size);
+#endif
+}
+
+Context::Context(xbt_main_func_t code,
+        int argc, char **argv,
+        void_pfn_smxprocess_t cleanup_func,
+        smx_process_t process)
+  : process_(process), iwannadie(false)
+{
+  /* If the user provided a function for the process then use it.
+     Otherwise, it is the context for maestro and we should set it as the
+     current context */
+  if (code) {
+    this->cleanup_func_ = cleanup_func;
+    this->argc_ = argc;
+    this->argv_ = argv;
+    this->code_ = code;
+  } else {
+    SIMIX_context_set_current(this);
+  }
+}
+
+Context::~Context()
+{
+  if (this->argv_) {
+    for (int i = 0; i < this->argc_; i++)
+      free(this->argv_[i]);
+    free(this->argv_);
+  }
+}
+
+void Context::stop()
+{
+  if (this->cleanup_func_)
+    this->cleanup_func_(this->process_);
+  this->process_->suspended = 0;
+
+  this->iwannadie = false;
+  simcall_process_cleanup(this->process_);
+  this->iwannadie = true;
+}
+
+}
+}
\ No newline at end of file
diff --git a/src/simix/RawContext.cpp b/src/simix/RawContext.cpp
new file mode 100644 (file)
index 0000000..6247479
--- /dev/null
@@ -0,0 +1,587 @@
+/* Copyright (c) 2009-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. */
+
+/** \file Rawcontext.cpp 
+  * Fast context switching inspired from SystemV ucontexts.
+  *
+  * In contrast to System V context, it does not touch the signal mask
+  * which avoids making a system call (at least on Linux).
+  */
+
+#include <math.h>
+
+#include <xbt/log.h>
+#include <xbt/parmap.h>
+#include <xbt/dynar.h>
+
+#include "smx_private.h"
+#include "smx_private.hpp"
+#include "mc/mc.h"
+
+XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_context);
+
+// ***** Class definitions
+
+namespace simgrid {
+namespace simix {
+
+class RawContext;
+class RawContextFactory;
+
+class RawContext : public Context {
+protected:
+  void* stack_ = nullptr; 
+  /** pointer to top the stack stack */
+  void* stack_top_ = nullptr;
+public:
+  friend class RawContextFactory;
+  RawContext(xbt_main_func_t code,
+          int argc, char **argv,
+          void_pfn_smxprocess_t cleanup_func,
+          smx_process_t process);
+  ~RawContext();
+public:
+  static void wrapper(void* arg);
+  void stop() override;
+  void suspend() override;
+  void resume();
+private:
+  void suspend_serial();
+  void suspend_parallel();
+  void resume_serial();
+  void resume_parallel();
+};
+
+class RawContextFactory : public ContextFactory {
+public:
+  RawContextFactory();
+  ~RawContextFactory();
+  RawContext* create_context(
+    xbt_main_func_t, int, char **, void_pfn_smxprocess_t,
+    smx_process_t process
+    ) override;
+  void run_all() override;
+private:
+  void run_all_adaptative();
+  void run_all_serial();
+  void run_all_parallel();
+};
+
+ContextFactory* raw_factory()
+{
+  XBT_VERB("Using raw contexts. "
+    "Because the glibc is just not good enough for us.");
+  return new RawContextFactory();
+}
+
+}
+}
+
+// ***** Loads of static stuff
+
+#ifdef CONTEXT_THREADS
+static xbt_parmap_t raw_parmap;
+static simgrid::simix::RawContext** raw_workers_context;    /* space to save the worker context in each thread */
+static unsigned long 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 */
+#endif
+#ifdef ADAPTIVE_THRESHOLD
+#define SCHED_ROUND_LIMIT 5
+static xbt_os_timer_t round_time;
+static double par_time,seq_time;
+static double par_ratio,seq_ratio;
+static int reached_seq_limit, reached_par_limit;
+static unsigned int par_proc_that_ran = 0,seq_proc_that_ran = 0;  /* Counters of processes that have run in SCHED_ROUND_LIMIT scheduling rounds */
+static unsigned int seq_sched_round=0, par_sched_round=0; /* Amount of SR that ran serial/parallel*/
+/*Varables used to calculate running variance and mean*/
+static double prev_avg_par_proc=0,prev_avg_seq_proc=0;
+static double delta=0;
+static double s_par_proc=0,s_seq_proc=0; /*Standard deviation of number of processes computed in par/seq during the current simulation*/
+static double avg_par_proc=0,sd_par_proc=0;
+static double avg_seq_proc=0,sd_seq_proc=0;
+static long long par_window=(long long)HUGE_VAL,seq_window=0;
+#endif
+static unsigned long raw_process_index = 0;   /* index of the next process to run in the
+                                               * list of runnable processes */
+static simgrid::simix::RawContext* raw_maestro_context;
+
+static bool raw_context_parallel = false;
+#ifdef ADAPTIVE_THRESHOLD
+static bool raw_context_adaptative = false;
+#endif
+
+// ***** Raw context routines
+
+typedef void (*rawctx_entry_point_t)(void *);
+
+typedef void* raw_stack_t;
+extern "C" raw_stack_t raw_makecontext(void* malloced_stack, int stack_size,
+                                   rawctx_entry_point_t entry_point, void* arg);
+extern "C" void raw_swapcontext(raw_stack_t* old, raw_stack_t new_context);
+
+#if PROCESSOR_x86_64
+__asm__ (
+#if defined(APPLE)
+   ".text\n"
+   ".globl _raw_makecontext\n"
+   "_raw_makecontext:\n"
+#elif defined(_WIN32)
+   ".text\n"
+   ".globl raw_makecontext\n"
+   "raw_makecontext:\n"
+#else
+   ".text\n"
+   ".globl raw_makecontext\n"
+   ".type raw_makecontext,@function\n"
+   "raw_makecontext:\n"/* Calling convention sets the arguments in rdi, rsi, rdx and rcx, respectively */
+#endif
+   "   mov %rdi,%rax\n"      /* stack */
+   "   add %rsi,%rax\n"      /* size  */
+   "   andq $-16, %rax\n"    /* align stack */
+   "   movq $0,   -8(%rax)\n" /* @return for func */
+   "   mov %rdx,-16(%rax)\n" /* func */
+   "   mov %rcx,-24(%rax)\n" /* arg/rdi */
+   "   movq $0,  -32(%rax)\n" /* rsi */
+   "   movq $0,  -40(%rax)\n" /* rdx */
+   "   movq $0,  -48(%rax)\n" /* rcx */
+   "   movq $0,  -56(%rax)\n" /* r8  */
+   "   movq $0,  -64(%rax)\n" /* r9  */
+   "   movq $0,  -72(%rax)\n" /* rbp */
+   "   movq $0,  -80(%rax)\n" /* rbx */
+   "   movq $0,  -88(%rax)\n" /* r12 */
+   "   movq $0,  -96(%rax)\n" /* r13 */
+   "   movq $0, -104(%rax)\n" /* r14 */
+   "   movq $0, -112(%rax)\n" /* r15 */
+   "   sub $112,%rax\n"
+   "   ret\n"
+);
+
+__asm__ (
+#if defined(APPLE)
+   ".text\n"
+   ".globl _raw_swapcontext\n"
+   "_raw_swapcontext:\n"
+#elif defined(_WIN32)
+   ".text\n"
+   ".globl raw_swapcontext\n"
+   "raw_swapcontext:\n"
+#else
+   ".text\n"
+   ".globl raw_swapcontext\n"
+   ".type raw_swapcontext,@function\n"
+   "raw_swapcontext:\n" /* Calling convention sets the arguments in rdi and rsi, respectively */
+#endif
+   "   push %rdi\n"
+   "   push %rsi\n"
+   "   push %rdx\n"
+   "   push %rcx\n"
+   "   push %r8\n"
+   "   push %r9\n"
+   "   push %rbp\n"
+   "   push %rbx\n"
+   "   push %r12\n"
+   "   push %r13\n"
+   "   push %r14\n"
+   "   push %r15\n"
+   "   mov %rsp,(%rdi)\n" /* old */
+   "   mov %rsi,%rsp\n" /* new */
+   "   pop %r15\n"
+   "   pop %r14\n"
+   "   pop %r13\n"
+   "   pop %r12\n"
+   "   pop %rbx\n"
+   "   pop %rbp\n"
+   "   pop %r9\n"
+   "   pop %r8\n"
+   "   pop %rcx\n"
+   "   pop %rdx\n"
+   "   pop %rsi\n"
+   "   pop %rdi\n"
+   "   ret\n"
+);
+#elif PROCESSOR_i686
+__asm__ (
+#if defined(APPLE) || defined(_WIN32)
+   ".text\n"
+   ".globl _raw_makecontext\n"
+   "_raw_makecontext:\n"
+#else
+   ".text\n"
+   ".globl raw_makecontext\n"
+   ".type raw_makecontext,@function\n"
+   "raw_makecontext:\n"
+#endif
+   "   movl 4(%esp),%eax\n"   /* stack */
+   "   addl 8(%esp),%eax\n"   /* size  */
+   "   andl $-16, %eax\n"     /* align stack */
+   "   movl 12(%esp),%ecx\n"  /* func  */
+   "   movl 16(%esp),%edx\n"  /* arg   */
+   "   movl %edx, -4(%eax)\n"
+   "   movl $0,   -8(%eax)\n" /* @return for func */
+   "   movl %ecx,-12(%eax)\n"
+   "   movl $0,  -16(%eax)\n" /* ebp */
+   "   movl $0,  -20(%eax)\n" /* ebx */
+   "   movl $0,  -24(%eax)\n" /* esi */
+   "   movl $0,  -28(%eax)\n" /* edi */
+   "   subl $28,%eax\n"
+   "   retl\n"
+);
+
+__asm__ (
+#if defined(APPLE) || defined(_WIN32)
+   ".text\n"
+   ".globl _raw_swapcontext\n"
+   "_raw_swapcontext:\n"
+#else
+   ".text\n"
+   ".globl raw_swapcontext\n"
+   ".type raw_swapcontext,@function\n"
+   "raw_swapcontext:\n"
+#endif
+   "   movl 4(%esp),%eax\n" /* old */
+   "   movl 8(%esp),%edx\n" /* new */
+   "   pushl %ebp\n"
+   "   pushl %ebx\n"
+   "   pushl %esi\n"
+   "   pushl %edi\n"
+   "   movl %esp,(%eax)\n"
+   "   movl %edx,%esp\n"
+   "   popl %edi\n"
+   "   popl %esi\n"
+   "   popl %ebx\n"
+   "   popl %ebp\n"
+   "   retl\n"
+);
+#else
+
+
+/* If you implement raw contexts for other processors, don't forget to
+   update the definition of HAVE_RAWCTX in tools/cmake/CompleteInFiles.cmake */
+
+raw_stack_t raw_makecontext(void* malloced_stack, int stack_size,
+                            rawctx_entry_point_t entry_point, void* arg) {
+   THROW_UNIMPLEMENTED;
+}
+
+void raw_swapcontext(raw_stack_t* old, raw_stack_t new_context) {
+   THROW_UNIMPLEMENTED;
+}
+
+#endif
+
+// ***** Method definitions
+
+namespace simgrid {
+namespace simix {
+
+RawContextFactory::RawContextFactory()
+  : ContextFactory("RawContextFactory")
+{
+#ifdef ADAPTIVE_THRESHOLD
+  raw_context_adaptative = (SIMIX_context_get_parallel_threshold() > 1);
+#endif
+  raw_context_parallel = SIMIX_context_is_parallel();
+  if (raw_context_parallel) {
+#ifdef CONTEXT_THREADS
+    int nthreads = SIMIX_context_get_nthreads();
+    xbt_os_thread_key_create(&raw_worker_id_key);
+    // TODO, lazily init
+    raw_parmap = nullptr;
+    raw_workers_context = xbt_new(RawContext*, nthreads);
+    raw_maestro_context = nullptr;
+#endif
+    // TODO, if(SIMIX_context_get_parallel_threshold() > 1) => choose dynamically
+  }
+#ifdef ADAPTIVE_THRESHOLD
+  round_time = xbt_os_timer_new();
+  reached_seq_limit = 0;
+  reached_par_limit = 0;
+#endif
+}
+
+RawContextFactory::~RawContextFactory()
+{
+#ifdef CONTEXT_THREADS
+  if (raw_parmap)
+    xbt_parmap_destroy(raw_parmap);
+  xbt_free(raw_workers_context);
+#endif
+}
+
+RawContext* RawContextFactory::create_context(
+    xbt_main_func_t code, int argc, char ** argv,
+    void_pfn_smxprocess_t cleanup,
+    smx_process_t process)
+{
+  return this->new_context<RawContext>(code, argc, argv,
+    cleanup, process);
+}
+
+void RawContext::wrapper(void* arg)
+{
+  RawContext* context = (RawContext*) arg;
+  (*context)();
+  context->stop();
+}
+
+RawContext::RawContext(
+    xbt_main_func_t code, int argc, char ** argv,
+    void_pfn_smxprocess_t cleanup,
+    smx_process_t process)
+  : Context(code, argc, argv, cleanup, process)
+{
+   if (code) {
+     this->stack_ = SIMIX_context_stack_new();
+     this->stack_top_ = raw_makecontext(this->stack_,
+                         smx_context_usable_stack_size,
+                         RawContext::wrapper,
+                         this);
+   } else {
+     if(process != nullptr && raw_maestro_context == nullptr)
+       raw_maestro_context = this;
+     if (MC_is_active())
+       MC_ignore_heap(
+         &raw_maestro_context->stack_top_,
+         sizeof(raw_maestro_context->stack_top_));
+   }
+}
+
+RawContext::~RawContext()
+{
+  SIMIX_context_stack_delete(this->stack_);
+}
+
+void RawContext::stop()
+{
+  Context::stop();
+  this->suspend();
+}
+
+void RawContextFactory::run_all()
+{
+#ifdef ADAPTIVE_THRESHOLD
+  if (raw_context_adaptative)
+    run_all_adaptative();
+  else
+#endif
+  if (raw_context_parallel)
+    run_all_parallel();
+  else
+    run_all_serial();
+}
+
+void RawContextFactory::run_all_serial()
+{
+  smx_process_t first_process =
+      xbt_dynar_get_as(simix_global->process_to_run, 0, smx_process_t);
+  raw_process_index = 1;
+  static_cast<RawContext*>(first_process->context)->resume_serial();
+}
+
+void RawContextFactory::run_all_parallel()
+{
+#ifdef CONTEXT_THREADS
+  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_process_t process = static_cast<smx_process_t>(arg);
+        RawContext* context = static_cast<RawContext*>(process->context);
+        context->resume_parallel();
+      },
+      simix_global->process_to_run);
+#else
+  xbt_die("You asked for a parallel execution, but you don't have any threads.");
+#endif
+}
+
+void RawContext::suspend()
+{
+  if (raw_context_parallel)
+    RawContext::suspend_parallel();
+  else
+    RawContext::suspend_serial();
+}
+
+void RawContext::suspend_serial()
+{
+  /* determine the next context */
+  RawContext* next_context = nullptr;
+  unsigned long int i;
+  i = raw_process_index++;
+  if (i < xbt_dynar_length(simix_global->process_to_run)) {
+    /* execute the next process */
+    XBT_DEBUG("Run next process");
+    next_context = (RawContext*) xbt_dynar_get_as(
+        simix_global->process_to_run, i, smx_process_t)->context;
+  }
+  else {
+    /* all processes were run, return to maestro */
+    XBT_DEBUG("No more process to run");
+    next_context = (RawContext*) raw_maestro_context;
+  }
+  SIMIX_context_set_current(next_context);
+  raw_swapcontext(&this->stack_top_, next_context->stack_top_);
+}
+
+void RawContext::suspend_parallel()
+{
+#ifdef CONTEXT_THREADS
+  /* determine the next context */
+  smx_process_t next_work = (smx_process_t) xbt_parmap_next(raw_parmap);
+  RawContext* next_context = nullptr;
+
+  if (next_work != NULL) {
+    /* there is a next process to resume */
+    XBT_DEBUG("Run next process");
+    next_context = (RawContext*) next_work->context;
+  }
+  else {
+    /* all processes were run, go to the barrier */
+    XBT_DEBUG("No more processes to run");
+    unsigned long worker_id = (unsigned long)(uintptr_t)
+      xbt_os_thread_get_specific(raw_worker_id_key);
+    next_context = (RawContext*) raw_workers_context[worker_id];
+    XBT_DEBUG("Restoring worker stack %lu (working threads = %lu)",
+        worker_id, raw_threads_working);
+  }
+
+  SIMIX_context_set_current(next_context);
+  raw_swapcontext(&this->stack_top_, next_context->stack_top_);
+#endif
+}
+
+void RawContext::resume()
+{
+  if (raw_context_parallel)
+    resume_parallel();
+  else
+    resume_serial();
+}
+
+void RawContext::resume_serial()
+{
+  SIMIX_context_set_current(this);
+  raw_swapcontext(&raw_maestro_context->stack_top_, this->stack_top_);
+}
+
+void RawContext::resume_parallel()
+{
+#ifdef CONTEXT_THREADS
+  unsigned long worker_id = __sync_fetch_and_add(&raw_threads_working, 1);
+  xbt_os_thread_set_specific(raw_worker_id_key, (void*)(uintptr_t) worker_id);
+  RawContext* worker_context = (RawContext*) SIMIX_context_self();
+  raw_workers_context[worker_id] = worker_context;
+  XBT_DEBUG("Saving worker stack %lu", worker_id);
+  SIMIX_context_set_current(this);
+  raw_swapcontext(&worker_context->stack_top_, this->stack_top_);
+#else
+  xbt_die("Parallel execution disabled");
+#endif
+}
+
+/**
+ * \brief Resumes all processes ready to run.
+ */
+#ifdef ADAPTIVE_THRESHOLD
+void RawContectFactory::run_all_adaptative()
+{
+  unsigned long nb_processes = xbt_dynar_length(simix_global->process_to_run);
+  unsigned long threshold = SIMIX_context_get_parallel_threshold();
+  reached_seq_limit = (seq_sched_round % SCHED_ROUND_LIMIT == 0);
+  reached_par_limit = (par_sched_round % SCHED_ROUND_LIMIT == 0);
+
+  if(reached_seq_limit && reached_par_limit){
+    par_ratio = (par_proc_that_ran != 0) ? (par_time / (double)par_proc_that_ran) : 0;
+    seq_ratio = (seq_proc_that_ran != 0) ? (seq_time / (double)seq_proc_that_ran) : 0;
+    if(seq_ratio > par_ratio){
+       if(nb_processes < avg_par_proc) {
+          threshold = (threshold>2) ? threshold - 1 : threshold ;
+          SIMIX_context_set_parallel_threshold(threshold);
+        }
+    } else {
+        if(nb_processes > avg_seq_proc){
+          SIMIX_context_set_parallel_threshold(threshold+1);
+        }
+    }
+  }
+
+  if (nb_processes >= SIMIX_context_get_parallel_threshold()) {
+    simix_global->context_factory->suspend = smx_ctx_raw_suspend_parallel;
+    if (nb_processes < par_window){
+      par_sched_round++;
+      xbt_os_walltimer_start(round_time);
+      smx_ctx_raw_runall_parallel();
+      xbt_os_walltimer_stop(round_time);
+      par_time += xbt_os_timer_elapsed(round_time);
+
+      prev_avg_par_proc = avg_par_proc;
+      delta = nb_processes - avg_par_proc;
+      avg_par_proc = (par_sched_round==1) ? nb_processes : avg_par_proc + delta / (double) par_sched_round;
+
+      if(par_sched_round>=2){
+        s_par_proc = s_par_proc + (nb_processes - prev_avg_par_proc) * delta;
+        sd_par_proc = sqrt(s_par_proc / (par_sched_round-1));
+        par_window = (int) (avg_par_proc + sd_par_proc);
+      }else{
+        sd_par_proc = 0;
+      }
+
+      par_proc_that_ran += nb_processes;
+    } else{
+      smx_ctx_raw_runall_parallel();
+    }
+  } else {
+    simix_global->context_factory->suspend = smx_ctx_raw_suspend_serial;
+    if(nb_processes > seq_window){
+      seq_sched_round++;
+      xbt_os_walltimer_start(round_time);
+      smx_ctx_raw_runall_serial();
+      xbt_os_walltimer_stop(round_time);
+      seq_time += xbt_os_timer_elapsed(round_time);
+
+      prev_avg_seq_proc = avg_seq_proc;
+      delta = (nb_processes-avg_seq_proc);
+      avg_seq_proc = (seq_sched_round==1) ? nb_processes : avg_seq_proc + delta / (double) seq_sched_round;
+
+      if(seq_sched_round>=2){
+        s_seq_proc = s_seq_proc + (nb_processes - prev_avg_seq_proc)*delta;
+        sd_seq_proc = sqrt(s_seq_proc / (seq_sched_round-1));
+        seq_window = (int) (avg_seq_proc - sd_seq_proc);
+      } else {
+        sd_seq_proc = 0;
+      }
+
+      seq_proc_that_ran += nb_processes;
+    } else {
+      smx_ctx_raw_runall_serial();
+    }
+  }
+}
+
+#else
+
+// TODO
+void RawContextFactory::run_all_adaptative()
+{
+  unsigned long nb_processes = xbt_dynar_length(simix_global->process_to_run);
+  if (SIMIX_context_is_parallel()
+    && (unsigned long) SIMIX_context_get_parallel_threshold() < nb_processes) {
+        raw_context_parallel = true;
+        XBT_DEBUG("Runall // %lu", nb_processes);
+        this->run_all_parallel();
+    } else {
+        XBT_DEBUG("Runall serial %lu", nb_processes);
+        raw_context_parallel = false;
+        this->run_all_serial();
+    }
+}
+#endif
+
+}
+}
diff --git a/src/simix/ThreadContext.cpp b/src/simix/ThreadContext.cpp
new file mode 100644 (file)
index 0000000..19be3d4
--- /dev/null
@@ -0,0 +1,172 @@
+/* Copyright (c) 2009-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. */
+
+#include "xbt/function_types.h"
+#include "smx_private.h"
+#include "src/portable.h"           /* loads context system definitions */
+#include "xbt/swag.h"
+#include "xbt/xbt_os_thread.h"
+#include "src/xbt_modinter.h"       /* prototype of os thread module's init/exit in XBT */
+
+#include "src/simix/ThreadContext.hpp"
+
+XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_context);
+
+static xbt_os_sem_t smx_ctx_thread_sem = nullptr;
+
+namespace simgrid {
+namespace simix {
+
+XBT_PRIVATE ContextFactory* thread_factory()
+{
+  XBT_VERB("Activating thread context factory");
+  return new ThreadContextFactory();
+}
+
+ThreadContextFactory::ThreadContextFactory()
+  : ContextFactory("ThreadContextFactory")
+{
+  if (SIMIX_context_is_parallel()) {
+    smx_ctx_thread_sem = xbt_os_sem_init(SIMIX_context_get_nthreads());
+  } else {
+    smx_ctx_thread_sem = nullptr;
+  }
+}
+
+ThreadContextFactory::~ThreadContextFactory()
+{
+  if (smx_ctx_thread_sem) {
+    xbt_os_sem_destroy(smx_ctx_thread_sem);
+    smx_ctx_thread_sem = nullptr;
+  }
+}
+
+ThreadContext* ThreadContextFactory::create_context(
+    xbt_main_func_t code, int argc, char ** argv,
+    void_pfn_smxprocess_t cleanup,
+    smx_process_t process)
+{
+  return this->new_context<ThreadContext>(code, argc, argv, cleanup, process);
+}
+
+ThreadContext::ThreadContext(xbt_main_func_t code,
+    int argc, char **argv,
+    void_pfn_smxprocess_t cleanup,
+    smx_process_t process)
+  : Context(code, argc, argv, cleanup, process)
+{
+  /* If the user provided a function for the process then use it
+     otherwise is the context for maestro */
+  if (code) {
+    this->begin_ = xbt_os_sem_init(0);
+    this->end_ = xbt_os_sem_init(0);
+    if (smx_context_stack_size_was_set)
+      xbt_os_thread_setstacksize(smx_context_stack_size);
+    if (smx_context_guard_size_was_set)
+      xbt_os_thread_setguardsize(smx_context_guard_size);
+
+    /* create and start the process */
+    /* NOTE: The first argument to xbt_os_thread_create used to be the process *
+    * name, but now the name is stored at SIMIX level, so we pass a null  */
+    this->thread_ =
+      xbt_os_thread_create(NULL, ThreadContext::wrapper, this, this);
+
+    /* wait the starting of the newly created process */
+    xbt_os_sem_acquire(this->end_);
+
+  } else {
+    xbt_os_thread_set_extra_data(this);
+  }
+}
+
+void ThreadContextFactory::run_all()
+{
+  if (smx_ctx_thread_sem == nullptr) {
+    // Serial execution
+    smx_process_t process;
+    unsigned int cursor;
+    xbt_dynar_foreach(simix_global->process_to_run, cursor, process) {
+      XBT_DEBUG("Handling %p",process);
+      ThreadContext* context = static_cast<ThreadContext*>(process->context);
+      xbt_os_sem_release(context->begin_);
+      xbt_os_sem_acquire(context->end_);
+    }
+  } else {
+    // Parallel execution
+    unsigned int index;
+    smx_process_t process;
+    xbt_dynar_foreach(simix_global->process_to_run, index, process)
+      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_);
+  }
+}
+
+ThreadContext* ThreadContextFactory::self()
+{
+  return static_cast<ThreadContext*>(xbt_os_thread_get_extra_data());
+}
+
+ThreadContext::~ThreadContext()
+{
+  /* check if this is the context of maestro (it doesn't have a real thread) */
+  if (this->thread_) {
+    /* wait about the thread terminason */
+    xbt_os_thread_join(this->thread_, nullptr);
+
+    /* destroy the synchronisation objects */
+    xbt_os_sem_destroy(this->begin_);
+    xbt_os_sem_destroy(this->end_);
+  }
+}
+
+void *ThreadContext::wrapper(void *param)
+{
+  ThreadContext* context = static_cast<ThreadContext*>(param);
+
+#ifndef WIN32
+  /* Install alternate signal stack, for SIGSEGV handler. */
+  stack_t stack;
+  stack.ss_sp = sigsegv_stack;
+  stack.ss_size = sizeof sigsegv_stack;
+  stack.ss_flags = 0;
+  sigaltstack(&stack, nullptr);
+#endif
+  /* Tell the maestro we are starting, and wait for its green light */
+  xbt_os_sem_release(context->end_);
+  xbt_os_sem_acquire(context->begin_);
+  if (smx_ctx_thread_sem)       /* parallel run */
+    xbt_os_sem_acquire(smx_ctx_thread_sem);
+
+  (*context)();
+  context->stop();
+  return nullptr;
+}
+
+void ThreadContext::stop()
+{
+  Context::stop();
+  if (smx_ctx_thread_sem)
+    xbt_os_sem_release(smx_ctx_thread_sem);
+
+  // Signal to the maestro that it has finished:
+  xbt_os_sem_release(this->end_);
+
+  xbt_os_thread_exit(NULL);
+}
+
+void ThreadContext::suspend()
+{
+  if (smx_ctx_thread_sem)
+    xbt_os_sem_release(smx_ctx_thread_sem);
+  xbt_os_sem_release(this->end_);
+  xbt_os_sem_acquire(this->begin_);
+  if (smx_ctx_thread_sem)
+    xbt_os_sem_acquire(smx_ctx_thread_sem);
+}
+
+}
+}
diff --git a/src/simix/ThreadContext.hpp b/src/simix/ThreadContext.hpp
new file mode 100644 (file)
index 0000000..4ecd959
--- /dev/null
@@ -0,0 +1,57 @@
+/* Copyright (c) 2009-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. */
+
+/* \file ThreadContext.hpp Context switching with native threads */
+
+#ifndef SIMGRID_SIMIX_THREAD_CONTEXT_HPP
+#define SIMGRID_SIMIX_THREAD_CONTEXT_HPP
+
+#include <simgrid/simix.hpp>
+
+
+namespace simgrid {
+namespace simix {
+
+class ThreadContext;
+class ThreadContextFactory;
+
+class ThreadContext : public Context {
+public:
+  friend ThreadContextFactory;
+  ThreadContext(xbt_main_func_t code,
+          int argc, char **argv,
+          void_pfn_smxprocess_t cleanup_func,
+          smx_process_t process);
+  ~ThreadContext();
+  void stop() override;
+  void suspend() override;
+private:
+  /** A portable thread */
+  xbt_os_thread_t thread_;
+  /** Semaphore used to schedule/yield the process */
+  xbt_os_sem_t begin_;
+  /** Semaphore used to schedule/unschedule */
+  xbt_os_sem_t end_;
+private:
+  static void* wrapper(void *param);
+};
+
+class ThreadContextFactory : public ContextFactory {
+public:
+  ThreadContextFactory();
+  ~ThreadContextFactory();
+  virtual ThreadContext* create_context(
+    xbt_main_func_t, int, char **, void_pfn_smxprocess_t,
+    smx_process_t process
+    ) override;
+  void run_all() override;
+  ThreadContext* self() override;
+};
+
+}
+}
+
+#endif
\ No newline at end of file
diff --git a/src/simix/UContext.cpp b/src/simix/UContext.cpp
new file mode 100644 (file)
index 0000000..a5e8e8f
--- /dev/null
@@ -0,0 +1,396 @@
+/* Copyright (c) 2009-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. */
+
+/* \file UContext.cpp Context switching with ucontexts from System V         */
+
+#include <stdarg.h>
+
+#include "xbt/parmap.h"
+#include "smx_private.h"
+#include "smx_private.hpp"
+#include "src/internal_config.h"
+#include "src/context_sysv_config.h"        /* loads context system definitions */
+#include "mc/mc.h"
+
+#ifdef _XBT_WIN32
+#  include <xbt/win32_ucontext.h>     /* context relative declarations */
+#else
+#  include <ucontext.h>           /* context relative declarations */
+#endif
+
+/** Many integers are needed to store a pointer
+ *
+ * This is a bit paranoid about sizeof(smx_ctx_sysv_t) not being a multiple
+ * of sizeof(int), but it doesn't harm. */
+#define CTX_ADDR_LEN                            \
+  (sizeof(void*) / sizeof(int) +       \
+   !!(sizeof(void*) % sizeof(int)))
+
+/** A better makecontext
+ *
+ * Makecontext expects integer arguments, we the context
+ * variable is decomposed into a serie of integers and
+ * each integer is passed as argument to makecontext. */
+XBT_PRIVATE
+void simgrid_makecontext(ucontext* ucp, void (*func)(int first, ...), void* arg)
+{
+  int ctx_addr[CTX_ADDR_LEN];
+  memcpy(ctx_addr, &arg, sizeof(void*));
+  switch (CTX_ADDR_LEN) {
+  case 1:
+    makecontext(ucp, (void (*)())func, 1, ctx_addr[0]);
+    break;
+  case 2:
+    makecontext(ucp, (void (*)()) func, 2, ctx_addr[0], ctx_addr[1]);
+    break;
+  default:
+    xbt_die("Ucontexts are not supported on this arch yet (addr len = %zu/%zu = %zu)",
+            sizeof(void*), sizeof(int), CTX_ADDR_LEN);
+  }
+}
+
+XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_context);
+
+namespace simgrid {
+namespace simix {
+  class UContext;
+  class SerialUContext;
+  class ParallelUContext;
+  class UContextFactory;
+}
+}
+
+#ifdef CONTEXT_THREADS
+static xbt_parmap_t sysv_parmap;
+static simgrid::simix::ParallelUContext** sysv_workers_context;   /* space to save the worker's context in each thread */
+static unsigned long 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 */
+#endif
+static unsigned long sysv_process_index = 0;   /* index of the next process to run in the
+                                                * list of runnable processes */
+static simgrid::simix::UContext* sysv_maestro_context;
+static bool sysv_parallel;
+
+namespace simgrid {
+namespace simix {
+
+class UContext : public Context {
+protected:
+  ucontext_t uc_;         /* the ucontext that executes the code */
+  char *stack_ = nullptr; /* the thread stack */
+public:
+  friend UContextFactory;
+  UContext(xbt_main_func_t code,
+          int argc, char **argv,
+          void_pfn_smxprocess_t cleanup_func,
+          smx_process_t process);
+  ~UContext();
+protected:
+  static void wrapper(int first, ...);
+};
+
+class SerialUContext : public UContext {
+public:
+  SerialUContext(xbt_main_func_t code,
+          int argc, char **argv,
+          void_pfn_smxprocess_t cleanup_func,
+          smx_process_t process)
+    : UContext(code, argc, argv, cleanup_func, process)
+  {}
+  void stop() override;
+  void suspend() override;
+  void resume();
+};
+
+class ParallelUContext : public UContext {
+public:
+  ParallelUContext(xbt_main_func_t code,
+          int argc, char **argv,
+          void_pfn_smxprocess_t cleanup_func,
+          smx_process_t process)
+    : UContext(code, argc, argv, cleanup_func, process)
+  {}
+  void stop() override;
+  void suspend() override;
+  void resume();
+};
+
+class UContextFactory : public ContextFactory {
+public:
+  friend UContext;
+  friend SerialUContext;
+  friend ParallelUContext;
+
+  UContextFactory();
+  virtual ~UContextFactory();
+  virtual Context* create_context(
+    xbt_main_func_t, int, char **, void_pfn_smxprocess_t,
+    smx_process_t process
+    ) override;
+  void run_all() override;
+};
+
+XBT_PRIVATE ContextFactory* sysv_factory()
+{
+  XBT_VERB("Activating SYSV context factory");
+  return new UContextFactory();
+}
+
+UContextFactory::UContextFactory() : ContextFactory("UContextFactory")
+{
+  if (SIMIX_context_is_parallel()) {
+    sysv_parallel = true;
+#ifdef CONTEXT_THREADS  /* To use parallel ucontexts a thread pool is needed */
+    int nthreads = SIMIX_context_get_nthreads();
+    sysv_parmap = nullptr;
+    sysv_workers_context = xbt_new(ParallelUContext*, nthreads);
+    sysv_maestro_context = nullptr;
+    xbt_os_thread_key_create(&sysv_worker_id_key);
+#else
+    THROWF(arg_error, 0, "No thread support for parallel context execution");
+#endif
+  } else {
+    sysv_parallel = false;
+  }
+}
+
+UContextFactory::~UContextFactory()
+{
+#ifdef CONTEXT_THREADS
+  if (sysv_parmap)
+    xbt_parmap_destroy(sysv_parmap);
+  xbt_free(sysv_workers_context);
+#endif
+}
+
+/* This function is called by maestro at the beginning of a scheduling round to get all working threads executing some stuff
+ * It is much easier to understand what happens if you see the working threads as bodies that swap their soul for the
+ *    ones of the simulated processes that must run.
+ */
+void UContextFactory::run_all()
+{
+  if (sysv_parallel) {
+    #ifdef CONTEXT_THREADS
+      sysv_threads_working = 0;
+      // Parmap_apply ensures that every working thread get an index in the
+      // process_to_run array (through an atomic fetch_and_add),
+      //  and runs the smx_ctx_sysv_resume_parallel function on that index
+
+      // We lazily create the parmap because the parmap creates context
+      // 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_process_t process = (smx_process_t) arg;
+          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:
+      smx_process_t first_process =
+          xbt_dynar_get_as(simix_global->process_to_run, 0, smx_process_t);
+      sysv_process_index = 1;
+      SerialUContext* context =
+        static_cast<SerialUContext*>(first_process->context);
+      context->resume();
+  }
+}
+
+Context* UContextFactory::create_context(
+  xbt_main_func_t code, int argc, char ** argv,
+  void_pfn_smxprocess_t cleanup,
+  smx_process_t process
+  )
+{
+  if (sysv_parallel)
+    return new_context<ParallelUContext>(code, argc, argv, cleanup, process);
+  else
+    return new_context<SerialUContext>(code, argc, argv, cleanup, process);
+}
+
+UContext::UContext(xbt_main_func_t code,
+        int argc, char **argv,
+        void_pfn_smxprocess_t cleanup_func,
+        smx_process_t process)
+  : Context(code, argc, argv, cleanup_func, process)
+{
+  /* if the user provided a function for the process then use it,
+     otherwise it is the context for maestro */
+  if (code) {
+    this->stack_ = (char*) SIMIX_context_stack_new();
+    getcontext(&this->uc_);
+    this->uc_.uc_link = nullptr;
+    this->uc_.uc_stack.ss_sp = pth_skaddr_makecontext(
+          this->stack_, smx_context_usable_stack_size);
+    this->uc_.uc_stack.ss_size = pth_sksize_makecontext(
+          this->stack_, smx_context_usable_stack_size);
+    simgrid_makecontext(&this->uc_, UContext::wrapper, this);
+  } else {
+    if (process != NULL && sysv_maestro_context == NULL)
+      sysv_maestro_context = this;
+  }
+
+#ifdef HAVE_MC
+  if (MC_is_active() && code) {
+    MC_register_stack_area(this->stack_, context->process,
+                      &(this->uc_), smx_context_usable_stack_size);
+  }
+#endif
+}
+
+UContext::~UContext()
+{
+  SIMIX_context_stack_delete(this->stack_);
+}
+
+void UContext::wrapper(int first, ...)
+{
+  // Rebuild the Context* pointer from the integers:
+  int ctx_addr[CTX_ADDR_LEN];
+  UContext* context;
+  ctx_addr[0] = first;
+  if (CTX_ADDR_LEN > 1) {
+    va_list ap;
+    va_start(ap, first);
+    for (unsigned i = 1; i < CTX_ADDR_LEN; i++)
+      ctx_addr[i] = va_arg(ap, int);
+    va_end(ap);
+  }
+  memcpy(&context, ctx_addr, sizeof(UContext*));
+
+  (*context)();
+  context->stop();
+}
+
+void SerialUContext::stop()
+{
+  Context::stop();
+  this->suspend();
+}
+
+void SerialUContext::suspend()
+{
+  /* determine the next context */
+  SerialUContext* next_context = nullptr;
+  unsigned long int i = sysv_process_index++;
+
+  if (i < xbt_dynar_length(simix_global->process_to_run)) {
+    /* execute the next process */
+    XBT_DEBUG("Run next process");
+    next_context = (SerialUContext*) xbt_dynar_get_as(
+        simix_global->process_to_run,i, smx_process_t)->context;
+  }
+  else {
+    /* all processes were run, return to maestro */
+    XBT_DEBUG("No more process to run");
+    next_context = (SerialUContext*) sysv_maestro_context;
+  }
+  SIMIX_context_set_current(next_context);
+  swapcontext(&this->uc_, &next_context->uc_);
+}
+
+// UContextSerial
+
+void SerialUContext::resume()
+{
+  SIMIX_context_set_current(this);
+  swapcontext(&((SerialUContext*)sysv_maestro_context)->uc_, &this->uc_);
+}
+
+void ParallelUContext::stop()
+{
+  UContext::stop();
+  this->suspend();
+}
+
+/** Run one particular simulated process on the current thread. */
+void ParallelUContext::resume()
+{
+#ifdef CONTEXT_THREADS
+  // What is my containing body?
+  unsigned long worker_id = __sync_fetch_and_add(&sysv_threads_working, 1);
+  // 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();
+  // 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_;
+  // Write in simix that I switched my soul
+  SIMIX_context_set_current(this);
+   // Actually do that using the relevant library call:
+  swapcontext(worker_stack, &this->uc_);
+  // No body runs that soul anymore at this point.
+  // Instead the current body took the soul of simulated process
+  // The simulated process wakes back after the call to
+  // "SIMIX_context_suspend(self->context);" within
+  // smx_process.c::SIMIX_process_yield()
+
+  // From now on, the simulated processes will change their
+  // soul with the next soul to execute (in suspend_parallel, below).
+  // When nobody is to be executed in this scheduling round,
+  // the last simulated process will take back the initial
+  // soul of the current working thread
+#endif
+}
+
+/** Yield
+ *
+ * This function is called when a simulated process wants to yield back
+ * to the maestro in a blocking simcall. This naturally occurs within
+ * SIMIX_context_suspend(self->context), called from SIMIX_process_yield()
+ * Actually, it does not really yield back to maestro, but into the next
+ * process that must be executed. If no one is to be executed, then it
+ * yields to the initial soul that was in this working thread (that was
+ * saved in resume_parallel).
+ */
+void ParallelUContext::suspend()
+{
+#ifdef CONTEXT_THREADS
+  /* determine the next context */
+  // Get the next soul to embody now:
+  smx_process_t next_work = (smx_process_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 != NULL) {
+    // There is a next soul to embody (ie, a next process to resume)
+    XBT_DEBUG("Run next process");
+    next_context = (ParallelUContext*) next_work->context;
+  }
+  else {
+    // All processes were run, go to the barrier
+    XBT_DEBUG("No more processes to run");
+    // Get back the identity of my body that was stored when starting
+    // the scheduling round
+    unsigned long worker_id =
+        (unsigned long) xbt_os_thread_get_specific(sysv_worker_id_key);
+    // Deduce the initial soul of that body
+    next_context = (ParallelUContext*) sysv_workers_context[worker_id];
+    // When given that soul, the body will wait for the next scheduling round
+  }
+
+  next_stack = &next_context->uc_;
+
+  SIMIX_context_set_current(next_context);
+  // Get that next soul:
+  swapcontext(&this->uc_, next_stack);
+#endif
+}
+
+}
+}
+
index ace2095..bacb466 100644 (file)
@@ -11,6 +11,7 @@
 #include "xbt/swag.h"
 #include "xbt/xbt_os_thread.h"
 #include "smx_private.h"
+#include "smx_private.hpp"
 #include "simgrid/sg_config.h"
 #include "src/internal_config.h"
 #include "simgrid/modelchecker.h"
@@ -36,7 +37,6 @@ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_context, simix,
                                 "Context switching mechanism");
 
 char* smx_context_factory_name = NULL; /* factory name specified by --cfg=contexts/factory:value */
-smx_ctx_factory_initializer_t smx_factory_initializer_to_use = NULL;
 int smx_context_stack_size;
 int smx_context_stack_size_was_set = 0;
 int smx_context_guard_size;
@@ -63,33 +63,26 @@ void SIMIX_context_mod_init(void)
 #endif
   if (!simix_global->context_factory) {
     /* select the context factory to use to create the contexts */
-    if (smx_factory_initializer_to_use) {
-      smx_factory_initializer_to_use(&simix_global->context_factory);
-    }
+    if (simgrid::simix::factory_initializer)
+      simix_global->context_factory = simgrid::simix::factory_initializer();
     else { /* use the factory specified by --cfg=contexts/factory:value */
-
-
-      if (!strcmp(smx_context_factory_name, "thread")) {
-        /* use os threads (either pthreads or windows ones) */
-        SIMIX_ctx_thread_factory_init(&simix_global->context_factory);
-      }
+#if defined(CONTEXT_THREADS)
+      if (!strcmp(smx_context_factory_name, "thread"))
+        simix_global->context_factory = simgrid::simix::thread_factory();
+#else
+      if (0);
+#endif
 #ifdef CONTEXT_UCONTEXT
-      else if (!strcmp(smx_context_factory_name, "ucontext")) {
-        /* use ucontext */
-        SIMIX_ctx_sysv_factory_init(&simix_global->context_factory);
-      }
+      else if (!strcmp(smx_context_factory_name, "ucontext"))
+        simix_global->context_factory = simgrid::simix::sysv_factory();
 #endif
 #ifdef HAVE_RAWCTX
-      else if (!strcmp(smx_context_factory_name, "raw")) {
-        /* use raw contexts */
-        SIMIX_ctx_raw_factory_init(&simix_global->context_factory);
-      }
+      else if (!strcmp(smx_context_factory_name, "raw"))
+        simix_global->context_factory = simgrid::simix::raw_factory();
 #endif
 #ifdef HAVE_BOOST_CONTEXT
-      else if (!strcmp(smx_context_factory_name, "boost")) {
-        /* use Boost.Context */
-        SIMIX_ctx_boost_factory_init(&simix_global->context_factory);
-      }
+      else if (!strcmp(smx_context_factory_name, "boost"))
+        simix_global->context_factory = simgrid::simix::boost_factory();
 #endif
       else {
         XBT_ERROR("Invalid context factory specified. Valid factories on this machine:");
@@ -120,13 +113,8 @@ void SIMIX_context_mod_init(void)
  */
 void SIMIX_context_mod_exit(void)
 {
-  if (simix_global->context_factory) {
-    smx_pfn_context_factory_finalize_t finalize_factory;
-
-    /* finalize the context factory */
-    finalize_factory = simix_global->context_factory->finalize;
-    finalize_factory(&simix_global->context_factory);
-  }
+  delete simix_global->context_factory;
+  simix_global->context_factory = nullptr;
   xbt_dict_remove((xbt_dict_t) _sg_cfg_set,"contexts/factory");
 }
 
diff --git a/src/simix/smx_context_base.cpp b/src/simix/smx_context_base.cpp
deleted file mode 100644 (file)
index 8b8231a..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/* context_base - Code factorization across context switching implementations */
-
-/* Copyright (c) 2010-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. */
-
-#include "xbt/function_types.h"
-#include "simgrid/simix.h"
-#include "smx_private.h"
-#include "mc/mc.h"
-
-XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_context);
-
-void smx_ctx_base_factory_init(smx_context_factory_t *factory)
-{
-  /* instantiate the context factory */
-  *factory = xbt_new0(s_smx_context_factory_t, 1);
-
-  (*factory)->create_context = NULL;
-  (*factory)->finalize = smx_ctx_base_factory_finalize;
-  (*factory)->free = smx_ctx_base_free;
-  (*factory)->stop = smx_ctx_base_stop;
-  (*factory)->suspend = NULL;
-  (*factory)->runall = NULL;
-  (*factory)->self = smx_ctx_base_self;
-  (*factory)->get_process = smx_ctx_base_get_process;
-
-  (*factory)->name = "base context factory";
-}
-
-int smx_ctx_base_factory_finalize(smx_context_factory_t * factory)
-{
-  free(*factory);
-  *factory = NULL;
-  return 0;
-}
-
-smx_context_t
-smx_ctx_base_factory_create_context_sized(size_t size, xbt_main_func_t code,
-                                          int argc, char **argv,
-                                          void_pfn_smxprocess_t cleanup_func,
-                                          smx_process_t process)
-{
-  smx_context_t context = (smx_context_t) xbt_malloc0(size);
-
-  /* Store the address of the stack in heap to compare it apart of heap comparison */
-  if(MC_is_active())
-    MC_ignore_heap(context, size);
-
-  /* If the user provided a function for the process then use it.
-     Otherwise, it is the context for maestro and we should set it as the
-     current context */
-  if (code) {
-    context->cleanup_func = cleanup_func;
-    context->argc = argc;
-    context->argv = argv;
-    context->code = code;
-  } else {
-    SIMIX_context_set_current(context);
-  }
-  context->process = process;
-
-  return context;
-}
-
-void smx_ctx_base_free(smx_context_t context)
-{
-  int i;
-  if (context) {
-
-    /* free argv */
-    if (context->argv) {
-      for (i = 0; i < context->argc; i++)
-        free(context->argv[i]);
-
-      free(context->argv);
-    }
-
-    /* free structure */
-    free(context);
-  }
-}
-
-void smx_ctx_base_stop(smx_context_t context)
-{
-  if (context->cleanup_func)
-    context->cleanup_func(context->process);
-  context->process->suspended = 0;
-  context->iwannadie = 0;
-  simcall_process_cleanup(context->process);
-  context->iwannadie = 1;
-}
-
-smx_context_t smx_ctx_base_self(void)
-{
-  return SIMIX_context_get_current();
-}
-
-smx_process_t smx_ctx_base_get_process(smx_context_t context)
-{
-  return context->process;
-}
diff --git a/src/simix/smx_context_boost.cpp b/src/simix/smx_context_boost.cpp
deleted file mode 100644 (file)
index 70bae9b..0000000
+++ /dev/null
@@ -1,287 +0,0 @@
-/* Copyright (c) 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. */
-
-/** @file smx_context_boost.cpp Userspace context switching implementation based on Boost.Context */
-
-#include <cstdint>
-
-#include <boost/context/all.hpp>
-
-#include "xbt/log.h"
-#include "smx_private.h"
-#include "src/internal_config.h"
-
-XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_context);
-
-typedef struct s_smx_ctx_boost {
-  s_smx_ctx_base_t super;       /* Fields of super implementation */
-#if HAVE_BOOST_CONTEXT == 1
-  boost::context::fcontext_t* fc;
-#else
-  boost::context::fcontext_t fc;
-#endif
-  void* stack;
-} s_smx_ctx_boost_t, *smx_ctx_boost_t;
-
-static int smx_ctx_boost_factory_finalize(smx_context_factory_t *factory);
-static smx_context_t
-smx_ctx_boost_create_context(xbt_main_func_t code, int argc, char **argv,
-    void_pfn_smxprocess_t cleanup_func, smx_process_t process);
-static void smx_ctx_boost_free(smx_context_t context);
-
-static void smx_ctx_boost_wrapper(std::intptr_t arg);
-
-static void smx_ctx_boost_stop_serial(smx_context_t context);
-static void smx_ctx_boost_suspend_serial(smx_context_t context);
-static void smx_ctx_boost_resume_serial(smx_process_t first_process);
-static void smx_ctx_boost_runall_serial(void);
-
-#ifdef CONTEXT_THREADS
-static void smx_ctx_boost_stop_parallel(smx_context_t context);
-static void smx_ctx_boost_suspend_parallel(smx_context_t context);
-static void smx_ctx_boost_resume_parallel(smx_process_t first_process);
-static void smx_ctx_boost_runall_parallel(void);
-#endif
-
-#ifdef CONTEXT_THREADS
-static xbt_parmap_t boost_parmap;
-static smx_ctx_boost_t* boost_workers_context;
-static unsigned long boost_threads_working;
-static xbt_os_thread_key_t boost_worker_id_key;
-#endif
-
-static unsigned long boost_process_index = 0;
-static smx_ctx_boost_t boost_maestro_context;
-
-void SIMIX_ctx_boost_factory_init(smx_context_factory_t *factory)
-{
-  smx_ctx_base_factory_init(factory);
-  XBT_VERB("Activating boost context factory");
-
-  (*factory)->finalize = smx_ctx_boost_factory_finalize;
-  (*factory)->create_context = smx_ctx_boost_create_context;
-  /* Do not overload that method (*factory)->finalize */
-  (*factory)->free = smx_ctx_boost_free;
-  (*factory)->name = "smx_boost_context_factory";
-
-  if (SIMIX_context_is_parallel()) {
-#ifndef CONTEXT_THREADS
-    THROWF(arg_error, 0, "No thread support for parallel context execution");
-#else
-    int nthreads = SIMIX_context_get_nthreads();
-    boost_parmap = xbt_parmap_new(nthreads, SIMIX_context_get_parallel_mode());
-    boost_workers_context = xbt_new(smx_ctx_boost_t, nthreads);
-    boost_maestro_context = NULL;
-
-    xbt_os_thread_key_create(&boost_worker_id_key);
-
-    (*factory)->stop = smx_ctx_boost_stop_parallel;
-    (*factory)->suspend = smx_ctx_boost_suspend_parallel;
-    (*factory)->runall = smx_ctx_boost_runall_parallel;
-#endif
-  } else {
-    (*factory)->stop = smx_ctx_boost_stop_serial;
-    (*factory)->suspend = smx_ctx_boost_suspend_serial;
-    (*factory)->runall = smx_ctx_boost_runall_serial;
-  }
-}
-
-/* Initialization functions */
-
-static int smx_ctx_boost_factory_finalize(smx_context_factory_t *factory)
-{
-#ifdef CONTEXT_THREADS
-  if (boost_parmap) {
-    xbt_parmap_destroy(boost_parmap);
-    boost_parmap = nullptr;
-  }
-  xbt_free(boost_workers_context);
-  boost_workers_context = nullptr;
-#endif
-  return smx_ctx_base_factory_finalize(factory);
-}
-
-static smx_context_t
-smx_ctx_boost_create_context(xbt_main_func_t code, int argc, char **argv,
-    void_pfn_smxprocess_t cleanup_func, smx_process_t process)
-{
-  smx_ctx_boost_t context =
-      (smx_ctx_boost_t) smx_ctx_base_factory_create_context_sized(
-          sizeof(s_smx_ctx_boost_t),
-          code,
-          argc,
-          argv,
-          cleanup_func,
-          process);
-
-  /* if the user provided a function for the process then use it,
-     otherwise it is the context for maestro */
-  if (code) {
-    context->stack = SIMIX_context_stack_new();
-    // We need to pass the bottom of the stack to make_fcontext,
-    // depending on the stack direction it may be the lower or higher address:
-#if PTH_STACKGROWTH == -1
-    void* stack = (char*) context->stack + smx_context_usable_stack_size - 1;
-#else
-    void* stack = context->stack;
-#endif
-    context->fc = boost::context::make_fcontext(
-                      stack,
-                      smx_context_usable_stack_size,
-                      smx_ctx_boost_wrapper);
-  } else {
-    context->stack = nullptr;
-#if HAVE_BOOST_CONTEXT == 1
-    context->fc = new boost::context::fcontext_t();
-#endif
-    if (boost_maestro_context == nullptr)
-      boost_maestro_context = context;
-  }
-
-  return (smx_context_t) context;
-}
-
-static void smx_ctx_boost_free(smx_context_t c)
-{
-  smx_ctx_boost_t context = (smx_ctx_boost_t) c;
-  if (!context)
-    return;
-#if HAVE_BOOST_CONTEXT == 1
-  if (!context->stack)
-    delete context->fc;
-#endif
-  if ((smx_ctx_boost_t) c == boost_maestro_context)
-    boost_maestro_context = nullptr;
-  SIMIX_context_stack_delete(context->stack);
-  smx_ctx_base_free(c);
-}
-
-static void smx_ctx_boost_wrapper(std::intptr_t arg)
-{
-  smx_context_t context = (smx_context_t) arg;
-  context->code(context->argc, context->argv);
-  smx_ctx_boost_stop_serial(context);
-}
-
-static void smx_ctx_boost_stop_serial(smx_context_t context)
-{
-  smx_ctx_base_stop(context);
-  simix_global->context_factory->suspend(context);
-}
-
-static void smx_ctx_boost_suspend_serial(smx_context_t context)
-{
-  /* determine the next context */
-  smx_ctx_boost_t next_context;
-  unsigned long int i = boost_process_index++;
-
-  if (i < xbt_dynar_length(simix_global->process_to_run)) {
-    /* execute the next process */
-    XBT_DEBUG("Run next process");
-    next_context = (smx_ctx_boost_t) xbt_dynar_get_as(
-        simix_global->process_to_run, i, smx_process_t)->context;
-  }
-  else {
-    /* all processes were run, return to maestro */
-    XBT_DEBUG("No more process to run");
-    next_context = (smx_ctx_boost_t) boost_maestro_context;
-  }
-  SIMIX_context_set_current((smx_context_t) next_context);
-#if HAVE_BOOST_CONTEXT == 1
-  boost::context::jump_fcontext(
-    ((smx_ctx_boost_t)context)->fc, next_context->fc, (intptr_t)next_context);
-#else
-  boost::context::jump_fcontext(
-    &((smx_ctx_boost_t)context)->fc, next_context->fc, (intptr_t)next_context);
-#endif
-}
-
-static void smx_ctx_boost_resume_serial(smx_process_t first_process)
-{
-  smx_ctx_boost_t context = (smx_ctx_boost_t) first_process->context;
-  SIMIX_context_set_current((smx_context_t) context);
-#if HAVE_BOOST_CONTEXT == 1
-  boost::context::jump_fcontext(boost_maestro_context->fc, context->fc,
-    (intptr_t)context);
-#else
-  boost::context::jump_fcontext(&boost_maestro_context->fc, context->fc,
-    (intptr_t)context);
-#endif
-}
-
-static void smx_ctx_boost_runall_serial(void)
-{
-  smx_process_t first_process =
-      xbt_dynar_get_as(simix_global->process_to_run, 0, smx_process_t);
-  boost_process_index = 1;
-
-  /* execute the first process */
-  smx_ctx_boost_resume_serial(first_process);
-}
-
-// **** Parallel code
-
-#ifdef CONTEXT_THREADS
-
-static void smx_ctx_boost_stop_parallel(smx_context_t context)
-{
-  smx_ctx_base_stop(context);
-  smx_ctx_boost_suspend_parallel(context);
-}
-
-static void smx_ctx_boost_suspend_parallel(smx_context_t context)
-{
-  smx_process_t next_work = (smx_process_t) xbt_parmap_next(boost_parmap);
-  smx_ctx_boost_t next_context;
-
-  if (next_work != NULL) {
-    XBT_DEBUG("Run next process");
-    next_context = (smx_ctx_boost_t) next_work->context;
-  }
-  else {
-    XBT_DEBUG("No more processes to run");
-    unsigned long worker_id =
-        (unsigned long) xbt_os_thread_get_specific(boost_worker_id_key);
-    next_context = boost_workers_context[worker_id];
-  }
-
-  SIMIX_context_set_current((smx_context_t) next_context);
-#if HAVE_BOOST_CONTEXT == 1
-  boost::context::jump_fcontext(
-    ((smx_ctx_boost_t)context)->fc, next_context->fc, (intptr_t)next_context);
-#else
-  boost::context::jump_fcontext(
-    &((smx_ctx_boost_t)context)->fc, next_context->fc, (intptr_t)next_context);
-#endif
-}
-
-static void smx_ctx_boost_resume_parallel(smx_process_t process)
-{
-  unsigned long worker_id = __sync_fetch_and_add(&boost_threads_working, 1);
-  xbt_os_thread_set_specific(boost_worker_id_key, (void*) worker_id);
-
-  smx_ctx_boost_t worker_context = (smx_ctx_boost_t)SIMIX_context_self();
-  boost_workers_context[worker_id] = worker_context;
-  smx_ctx_boost_t context = (smx_ctx_boost_t) process->context;
-
-  SIMIX_context_set_current((smx_context_t) context);
-#if HAVE_BOOST_CONTEXT == 1
-  boost::context::jump_fcontext(worker_context->fc, context->fc,
-    (intptr_t)context);
-#else
-  boost::context::jump_fcontext(&worker_context->fc, context->fc,
-    (intptr_t)context);
-#endif
-}
-
-static void smx_ctx_boost_runall_parallel(void)
-{
-  boost_threads_working = 0;
-  xbt_parmap_apply(boost_parmap, (void_f_pvoid_t) smx_ctx_boost_resume_parallel,
-    simix_global->process_to_run);
-}
-
-#endif
diff --git a/src/simix/smx_context_raw.cpp b/src/simix/smx_context_raw.cpp
deleted file mode 100644 (file)
index 5ce86a9..0000000
+++ /dev/null
@@ -1,734 +0,0 @@
-/* context_raw - fast context switching inspired from System V ucontexts   */
-
-/* Copyright (c) 2009-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. */
-
-#include <math.h>
-#include "smx_private.h"
-#include "xbt/parmap.h"
-#include "xbt/dynar.h"
-#include "mc/mc.h"
-
-typedef char * raw_stack_t;
-typedef void (*rawctx_entry_point_t)(void *);
-
-typedef struct s_smx_ctx_raw {
-  s_smx_ctx_base_t super;         /* Fields of super implementation */
-  char *malloced_stack;           /* malloced area containing the stack */
-  raw_stack_t stack_top;          /* pointer to stack top (within previous area) */
-#ifdef TIME_BENCH_PER_SR
-  unsigned int thread;            /* Just for measuring purposes */
-#endif
-} s_smx_ctx_raw_t, *smx_ctx_raw_t;
-
-#ifdef CONTEXT_THREADS
-static xbt_parmap_t raw_parmap;
-static smx_ctx_raw_t* raw_workers_context;    /* space to save the worker context in each thread */
-static unsigned long 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 */
-#endif 
-#ifdef ADAPTIVE_THRESHOLD
-#define SCHED_ROUND_LIMIT 5
-xbt_os_timer_t round_time;
-double par_time,seq_time;
-double par_ratio,seq_ratio;
-int reached_seq_limit, reached_par_limit;
-static unsigned int par_proc_that_ran = 0,seq_proc_that_ran = 0;  /* Counters of processes that have run in SCHED_ROUND_LIMIT scheduling rounds */
-static unsigned int seq_sched_round=0, par_sched_round=0; /* Amount of SR that ran serial/parallel*/
-/*Varables used to calculate running variance and mean*/
-double prev_avg_par_proc=0,prev_avg_seq_proc=0;
-double delta=0;
-double s_par_proc=0,s_seq_proc=0; /*Standard deviation of number of processes computed in par/seq during the current simulation*/
-double avg_par_proc=0,sd_par_proc=0;
-double avg_seq_proc=0,sd_seq_proc=0;
-long long par_window=(long long)HUGE_VAL,seq_window=0;
-#endif
-
-static unsigned long raw_process_index = 0;   /* index of the next process to run in the
-                                               * list of runnable processes */
-static smx_ctx_raw_t raw_maestro_context;
-extern "C" raw_stack_t raw_makecontext(char* malloced_stack, int stack_size,
-                                   rawctx_entry_point_t entry_point, void* arg);
-extern "C" void raw_swapcontext(raw_stack_t* old, raw_stack_t new_context);
-
-#if PROCESSOR_x86_64
-__asm__ (
-#if defined(APPLE)
-   ".text\n"
-   ".globl _raw_makecontext\n"
-   "_raw_makecontext:\n"
-#elif defined(_WIN32)
-   ".text\n"
-   ".globl raw_makecontext\n"
-   "raw_makecontext:\n"
-#else
-   ".text\n"
-   ".globl raw_makecontext\n"
-   ".type raw_makecontext,@function\n"
-   "raw_makecontext:\n"/* Calling convention sets the arguments in rdi, rsi, rdx and rcx, respectively */
-#endif
-   "   mov %rdi,%rax\n"      /* stack */
-   "   add %rsi,%rax\n"      /* size  */
-   "   andq $-16, %rax\n"    /* align stack */
-   "   movq $0,   -8(%rax)\n" /* @return for func */
-   "   mov %rdx,-16(%rax)\n" /* func */
-   "   mov %rcx,-24(%rax)\n" /* arg/rdi */
-   "   movq $0,  -32(%rax)\n" /* rsi */
-   "   movq $0,  -40(%rax)\n" /* rdx */
-   "   movq $0,  -48(%rax)\n" /* rcx */
-   "   movq $0,  -56(%rax)\n" /* r8  */
-   "   movq $0,  -64(%rax)\n" /* r9  */
-   "   movq $0,  -72(%rax)\n" /* rbp */
-   "   movq $0,  -80(%rax)\n" /* rbx */
-   "   movq $0,  -88(%rax)\n" /* r12 */
-   "   movq $0,  -96(%rax)\n" /* r13 */
-   "   movq $0, -104(%rax)\n" /* r14 */
-   "   movq $0, -112(%rax)\n" /* r15 */
-   "   sub $112,%rax\n"
-   "   ret\n"
-);
-
-__asm__ (
-#if defined(APPLE)
-   ".text\n"
-   ".globl _raw_swapcontext\n"
-   "_raw_swapcontext:\n"
-#elif defined(_WIN32)
-   ".text\n"
-   ".globl raw_swapcontext\n"
-   "raw_swapcontext:\n"
-#else
-   ".text\n"
-   ".globl raw_swapcontext\n"
-   ".type raw_swapcontext,@function\n"
-   "raw_swapcontext:\n" /* Calling convention sets the arguments in rdi and rsi, respectively */
-#endif
-   "   push %rdi\n"
-   "   push %rsi\n"
-   "   push %rdx\n"
-   "   push %rcx\n"
-   "   push %r8\n"
-   "   push %r9\n"
-   "   push %rbp\n"
-   "   push %rbx\n"
-   "   push %r12\n"
-   "   push %r13\n"
-   "   push %r14\n"
-   "   push %r15\n"
-   "   mov %rsp,(%rdi)\n" /* old */
-   "   mov %rsi,%rsp\n" /* new */
-   "   pop %r15\n"
-   "   pop %r14\n"
-   "   pop %r13\n"
-   "   pop %r12\n"
-   "   pop %rbx\n"
-   "   pop %rbp\n"
-   "   pop %r9\n"
-   "   pop %r8\n"
-   "   pop %rcx\n"
-   "   pop %rdx\n"
-   "   pop %rsi\n"
-   "   pop %rdi\n"
-   "   ret\n"
-);
-#elif PROCESSOR_i686
-__asm__ (
-#if defined(APPLE) || defined(_WIN32)
-   ".text\n"
-   ".globl _raw_makecontext\n"
-   "_raw_makecontext:\n"
-#else
-   ".text\n"
-   ".globl raw_makecontext\n"
-   ".type raw_makecontext,@function\n"
-   "raw_makecontext:\n"
-#endif
-   "   movl 4(%esp),%eax\n"   /* stack */
-   "   addl 8(%esp),%eax\n"   /* size  */
-   "   andl $-16, %eax\n"     /* align stack */
-   "   movl 12(%esp),%ecx\n"  /* func  */
-   "   movl 16(%esp),%edx\n"  /* arg   */
-   "   movl %edx, -4(%eax)\n"
-   "   movl $0,   -8(%eax)\n" /* @return for func */
-   "   movl %ecx,-12(%eax)\n"
-   "   movl $0,  -16(%eax)\n" /* ebp */
-   "   movl $0,  -20(%eax)\n" /* ebx */
-   "   movl $0,  -24(%eax)\n" /* esi */
-   "   movl $0,  -28(%eax)\n" /* edi */
-   "   subl $28,%eax\n"
-   "   retl\n"
-);
-
-__asm__ (
-#if defined(APPLE) || defined(_WIN32)
-   ".text\n"
-   ".globl _raw_swapcontext\n"
-   "_raw_swapcontext:\n"
-#else
-   ".text\n"
-   ".globl raw_swapcontext\n"
-   ".type raw_swapcontext,@function\n"
-   "raw_swapcontext:\n"
-#endif
-   "   movl 4(%esp),%eax\n" /* old */
-   "   movl 8(%esp),%edx\n" /* new */
-   "   pushl %ebp\n"
-   "   pushl %ebx\n"
-   "   pushl %esi\n"
-   "   pushl %edi\n"
-   "   movl %esp,(%eax)\n"
-   "   movl %edx,%esp\n"
-   "   popl %edi\n"
-   "   popl %esi\n"
-   "   popl %ebx\n"
-   "   popl %ebp\n"
-   "   retl\n"
-);
-#else
-
-
-/* If you implement raw contexts for other processors, don't forget to
-   update the definition of HAVE_RAWCTX in tools/cmake/CompleteInFiles.cmake */
-
-raw_stack_t raw_makecontext(char* malloced_stack, int stack_size,
-                            rawctx_entry_point_t entry_point, void* arg) {
-   THROW_UNIMPLEMENTED;
-}
-
-void raw_swapcontext(raw_stack_t* old, raw_stack_t new_context) {
-   THROW_UNIMPLEMENTED;
-}
-
-#endif
-
-XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_context);
-
-#ifdef TIME_BENCH_PER_SR
-#include "xbt/xbt_os_time.h"
-#define NUM_THREADS 4
-static xbt_os_timer_t timer;
-static double time_thread_sr[NUM_THREADS];
-static double time_thread_ssr[NUM_THREADS];
-static double time_wasted_sr = 0;
-static double time_wasted_ssr = 0;
-static unsigned int sr_count = 0;
-static unsigned int ssr_count = 0;
-static char new_sr = 0;
-#endif
-
-#ifdef TIME_BENCH_ENTIRE_SRS
-static unsigned int sr_count = 0;
-static xbt_os_timer_t timer;
-#endif
-
-static void smx_ctx_raw_wrapper(smx_ctx_raw_t context);
-static int smx_ctx_raw_factory_finalize(smx_context_factory_t *factory);
-static smx_context_t smx_ctx_raw_create_context(xbt_main_func_t code, int argc,
-    char **argv, void_pfn_smxprocess_t cleanup_func, smx_process_t process);
-static void smx_ctx_raw_free(smx_context_t context);
-static void smx_ctx_raw_wrapper(smx_ctx_raw_t context);
-static void smx_ctx_raw_stop(smx_context_t context);
-static void smx_ctx_raw_suspend_serial(smx_context_t context);
-static void smx_ctx_raw_resume_serial(smx_process_t first_process);
-#ifdef TIME_BENCH_PER_SR
-static void smx_ctx_raw_runall_serial(xbt_dynar_t processes);
-void smx_ctx_raw_new_sr(void);
-#else
-static void smx_ctx_raw_runall_serial(void);
-#endif
-static void smx_ctx_raw_suspend_parallel(smx_context_t context);
-static void smx_ctx_raw_resume_parallel(smx_process_t first_process);
-static void smx_ctx_raw_runall_parallel(void);
-static void smx_ctx_raw_runall(void);
-
-/**
- * \brief Initializes the raw context factory.
- * \param factory where to initialize the factory
- */
-void SIMIX_ctx_raw_factory_init(smx_context_factory_t *factory)
-{
-
-  XBT_VERB("Using raw contexts. Because the glibc is just not good enough for us.");
-  smx_ctx_base_factory_init(factory);
-
-  (*factory)->finalize  = smx_ctx_raw_factory_finalize;
-  (*factory)->create_context = smx_ctx_raw_create_context;
-  /* Do not overload that method (*factory)->finalize */
-  (*factory)->free = smx_ctx_raw_free;
-  (*factory)->stop = smx_ctx_raw_stop;
-  (*factory)->name = "smx_raw_context_factory";
-
-  if (SIMIX_context_is_parallel()) {
-#ifdef CONTEXT_THREADS
-    int nthreads = SIMIX_context_get_nthreads();
-    xbt_os_thread_key_create(&raw_worker_id_key);
-    raw_parmap = xbt_parmap_new(nthreads, SIMIX_context_get_parallel_mode());
-    raw_workers_context = xbt_new(smx_ctx_raw_t, nthreads);
-    raw_maestro_context=NULL;
-
-#endif
-    if (SIMIX_context_get_parallel_threshold() > 1) {
-      /* choose dynamically */
-      (*factory)->runall = smx_ctx_raw_runall;
-      (*factory)->suspend = NULL;
-    }
-    else {
-      /* always parallel */
-      (*factory)->runall = smx_ctx_raw_runall_parallel;
-      (*factory)->suspend = smx_ctx_raw_suspend_parallel;
-    }
-  }
-  else {
-    /* always serial */
-    (*factory)->runall = smx_ctx_raw_runall_serial;
-    (*factory)->suspend = smx_ctx_raw_suspend_serial;
-  }
-#ifdef TIME_BENCH_ENTIRE_SRS
-  (*factory)->runall = smx_ctx_raw_runall;
-  (*factory)->suspend = NULL;
-  timer = xbt_os_timer_new();
-#endif  
-
-#ifdef ADAPTIVE_THRESHOLD
-  round_time = xbt_os_timer_new(); 
-  reached_seq_limit = 0;
-  reached_par_limit = 0;
-#endif
-
-#ifdef TIME_BENCH_PER_SR
-  timer = xbt_os_timer_new();
-#endif
-}
-
-/**
- * \brief Finalizes the raw context factory.
- * \param factory the raw context factory
- */
-static int smx_ctx_raw_factory_finalize(smx_context_factory_t *factory)
-{
-#ifdef TIME_BENCH_PER_SR
-  XBT_VERB("Total wasted time in %u SR: %f", sr_count, time_wasted_sr);
-  XBT_VERB("Total wasted time in %u SSR: %f", ssr_count, time_wasted_ssr);
-#endif
-
-#ifdef CONTEXT_THREADS
-  if (raw_parmap)
-    xbt_parmap_destroy(raw_parmap);
-  xbt_free(raw_workers_context);
-#endif
-  return smx_ctx_base_factory_finalize(factory);
-}
-
-/**
- * \brief Creates a new raw context.
- * \param code main function of this context or NULL to create the maestro
- * context
- * \param argc argument number
- * \param argv arguments to pass to the main function
- * \param cleanup_func a function to call to free the user data when the
- * context finished
- * \param process SIMIX process
- */
-static smx_context_t
-smx_ctx_raw_create_context(xbt_main_func_t code, int argc, char **argv,
-                           void_pfn_smxprocess_t cleanup_func,
-                           smx_process_t process)
-{
-
-  smx_ctx_raw_t context =
-      (smx_ctx_raw_t) smx_ctx_base_factory_create_context_sized(
-          sizeof(s_smx_ctx_raw_t),
-          code,
-          argc,
-          argv,
-          cleanup_func,
-          process);
-
-  /* if the user provided a function for the process then use it,
-     otherwise it is the context for maestro */
-     if (code) {
-       context->malloced_stack = (char*) SIMIX_context_stack_new();
-       context->stack_top =
-           raw_makecontext(context->malloced_stack,
-                           smx_context_usable_stack_size,
-                           (void_f_pvoid_t)smx_ctx_raw_wrapper, context);
-
-     } else {
-       if(process != NULL && raw_maestro_context==NULL)
-         raw_maestro_context = context;
-
-       if(MC_is_active())
-         MC_ignore_heap(&(raw_maestro_context->stack_top), sizeof(raw_maestro_context->stack_top));
-
-     }
-
-     return (smx_context_t) context;
-}
-
-/**
- * \brief Destroys a raw context.
- * \param context a raw context
- */
-static void smx_ctx_raw_free(smx_context_t context)
-{
-  if (context) {
-    SIMIX_context_stack_delete(((smx_ctx_raw_t) context)->malloced_stack);
-  }
-  smx_ctx_base_free(context);
-}
-
-/**
- * \brief Wrapper for the main function of a context.
- * \param context a raw context
- */
-static void smx_ctx_raw_wrapper(smx_ctx_raw_t context)
-{
-  (context->super.code) (context->super.argc, context->super.argv);
-
-  smx_ctx_raw_stop((smx_context_t) context);
-}
-
-/**
- * \brief Stops a raw context.
- *
- * This function is called when the main function of the context if finished.
- *
- * \param context the current context
- */
-static void smx_ctx_raw_stop(smx_context_t context)
-{
-  smx_ctx_base_stop(context);
-  simix_global->context_factory->suspend(context);
-}
-
-/**
- * \brief Suspends a running context and resumes another one or returns to
- * maestro.
- * \param context the current context
- */
-static void smx_ctx_raw_suspend_serial(smx_context_t context)
-{
-  /* determine the next context */
-  smx_context_t next_context;
-  unsigned long int i; 
-#ifdef TIME_BENCH_PER_SR
-  i = ++raw_process_index;
-#else
-  i = raw_process_index++;
-#endif
-  if (i < xbt_dynar_length(simix_global->process_to_run)) {
-    /* execute the next process */
-    XBT_DEBUG("Run next process");
-    next_context = xbt_dynar_get_as(
-        simix_global->process_to_run, i, smx_process_t)->context;
-  }
-  else {
-    /* all processes were run, return to maestro */
-    XBT_DEBUG("No more process to run");
-    next_context = (smx_context_t) raw_maestro_context;
-  }
-  SIMIX_context_set_current(next_context);
-  raw_swapcontext(&((smx_ctx_raw_t) context)->stack_top,
-      ((smx_ctx_raw_t) next_context)->stack_top);
-}
-
-/**
- * \brief Resumes sequentially all processes ready to run.
- * \param first_process the first process to resume
- */
-static void smx_ctx_raw_resume_serial(smx_process_t first_process)
-{
-  smx_ctx_raw_t context = (smx_ctx_raw_t) first_process->context;
-  SIMIX_context_set_current((smx_context_t) context);
-  raw_swapcontext(&raw_maestro_context->stack_top,
-      ((smx_ctx_raw_t) context)->stack_top);
-}
-
-#ifdef TIME_BENCH_PER_SR
-static void smx_ctx_raw_runall_serial(xbt_dynar_t processes)
-{
-  smx_process_t process;
-  unsigned int cursor;
-  double elapsed = 0;
-  double tmax = 0;
-  unsigned long num_proc = xbt_dynar_length(simix_global->process_to_run);
-  unsigned int t=0;
-  unsigned int data_size = (num_proc / NUM_THREADS) + ((num_proc % NUM_THREADS) ? 1 : 0);
-
-  ssr_count++;
-  time_thread_ssr[0] = 0;
-  xbt_dynar_foreach(processes, cursor, process){ 
-        XBT_VERB("Schedule item %u of %lu",cursor,num_proc);
-        if(cursor >= t * data_size + data_size){
-          if(time_thread_ssr[t] > tmax)
-            tmax = time_thread_ssr[t];
-          t++;
-          time_thread_ssr[t] = 0;
-        }
-
-        if(new_sr){
-          ((smx_ctx_raw_t)process->context)->thread = t;
-          time_thread_sr[t] = 0;
-        }
-
-        xbt_os_cputimer_start(timer);
-        smx_ctx_raw_resume_serial(process);
-        xbt_os_cputimer_stop(timer);
-        elapsed = xbt_os_timer_elapsed(timer);
-        time_thread_ssr[t] += elapsed;
-        time_thread_sr[((smx_ctx_raw_t)process->context)->thread] += elapsed;
-  }
-
-  if(new_sr)
-    new_sr = FALSE;
-
-  if(time_thread_ssr[t] > tmax)
-    tmax = time_thread_ssr[t];
-
-  for(cursor=0; cursor <= t; cursor++){
-    XBT_VERB("Time SSR thread %u = %f (max %f)", cursor, time_thread_ssr[cursor], tmax);
-    time_wasted_ssr += tmax - time_thread_ssr[cursor];
-  }
-}
-
-void smx_ctx_raw_new_sr(void)
-{
-  int i;
-  double tmax = 0;
-  new_sr = TRUE;
-  sr_count++;
-  for(i=0; i < NUM_THREADS; i++){
-    if(time_thread_sr[i] > tmax)
-      tmax = time_thread_sr[i];
-  }
-
-  for(i=0; i < NUM_THREADS; i++){
-    XBT_CRITICAL("Time SR thread %u = %f (max %f)", i, time_thread_sr[i], tmax);
-    time_wasted_sr += tmax - time_thread_sr[i];
-  }
-
-  XBT_CRITICAL("Total time SR %u = %f, %d", sr_count, tmax, xbt_dynar_length(simix_global->process_that_ran));
-  XBT_CRITICAL("New scheduling round");
-}
-#else
-/**
- * \brief Resumes sequentially all processes ready to run.
- */
-static void smx_ctx_raw_runall_serial(void)
-{
-  smx_process_t first_process =
-      xbt_dynar_get_as(simix_global->process_to_run, 0, smx_process_t);
-  raw_process_index = 1;
-
-  /* execute the first process */
-  smx_ctx_raw_resume_serial(first_process);
-}
-#endif
-
-/**
- * \brief Suspends a running context and resumes another one or returns to
- * the main function of the current worker thread.
- * \param context the context of the current worker thread
- */
-static void smx_ctx_raw_suspend_parallel(smx_context_t context)
-{
-#ifdef CONTEXT_THREADS
-  /* determine the next context */
-  smx_process_t next_work = (smx_process_t) xbt_parmap_next(raw_parmap);
-  smx_context_t next_context;
-  raw_stack_t next_stack;
-
-  if (next_work != NULL) {
-    /* there is a next process to resume */
-    XBT_DEBUG("Run next process");
-    next_context = next_work->context;
-    next_stack = ((smx_ctx_raw_t) next_context)->stack_top;
-  }
-  else {
-    /* all processes were run, go to the barrier */
-    XBT_DEBUG("No more processes to run");
-
-    unsigned long worker_id =
-        (unsigned long)(uintptr_t) xbt_os_thread_get_specific(raw_worker_id_key);
-
-    next_context = (smx_context_t)raw_workers_context[worker_id];
-    XBT_DEBUG("Restoring worker stack %lu (working threads = %lu)",
-        worker_id, raw_threads_working);
-    next_stack = ((smx_ctx_raw_t)next_context)->stack_top;
-  }
-
-  SIMIX_context_set_current(next_context);
-  raw_swapcontext(&((smx_ctx_raw_t) context)->stack_top, next_stack);
-#endif
-}
-
-/**
- * \brief Resumes sequentially in the current worker thread the processes ready
- * to run.
- * \param first_process the first process to resume
- */
-static void smx_ctx_raw_resume_parallel(smx_process_t first_process)
-{
-#ifdef CONTEXT_THREADS
-  unsigned long worker_id = __sync_fetch_and_add(&raw_threads_working, 1);
-  xbt_os_thread_set_specific(raw_worker_id_key, (void*)(uintptr_t) worker_id);
-  smx_ctx_raw_t worker_context = (smx_ctx_raw_t)SIMIX_context_self();
-  raw_workers_context[worker_id] = worker_context;
-  XBT_DEBUG("Saving worker stack %lu", worker_id);
-  raw_stack_t* worker_stack = &(worker_context)->stack_top;
-
-
-  smx_context_t context = first_process->context;
-  SIMIX_context_set_current(context);
-  raw_swapcontext(worker_stack, ((smx_ctx_raw_t) context)->stack_top);
-#endif
-}
-
-/**
- * \brief Resumes in parallel all processes ready to run.
- */
-static void smx_ctx_raw_runall_parallel(void)
-{
-#ifdef CONTEXT_THREADS
-  raw_threads_working = 0;
-  xbt_parmap_apply(raw_parmap, (void_f_pvoid_t) smx_ctx_raw_resume_parallel,
-      simix_global->process_to_run);
-#else
-  xbt_die("You asked for a parallel execution, but you don't have any threads.");
-#endif
-}
-
-/**
- * \brief Resumes all processes ready to run.
- */
-#ifdef ADAPTIVE_THRESHOLD
-static void smx_ctx_raw_runall(void)
-{
-  unsigned long nb_processes = xbt_dynar_length(simix_global->process_to_run);
-  unsigned long threshold = SIMIX_context_get_parallel_threshold();
-  reached_seq_limit = (seq_sched_round % SCHED_ROUND_LIMIT == 0); 
-  reached_par_limit = (par_sched_round % SCHED_ROUND_LIMIT == 0);
-
-  if(reached_seq_limit && reached_par_limit){
-    par_ratio = (par_proc_that_ran != 0) ? (par_time / (double)par_proc_that_ran) : 0;
-    seq_ratio = (seq_proc_that_ran != 0) ? (seq_time / (double)seq_proc_that_ran) : 0; 
-    if(seq_ratio > par_ratio){
-       if(nb_processes < avg_par_proc) {
-          threshold = (threshold>2) ? threshold - 1 : threshold ;
-          SIMIX_context_set_parallel_threshold(threshold);
-        }
-    } else {
-        if(nb_processes > avg_seq_proc){
-          SIMIX_context_set_parallel_threshold(threshold+1);
-        }
-    }
-  }
-
-  //XBT_CRITICAL("Thresh: %d", SIMIX_context_get_parallel_threshold());
-  if (nb_processes >= SIMIX_context_get_parallel_threshold()) {
-    simix_global->context_factory->suspend = smx_ctx_raw_suspend_parallel;
-    if(nb_processes < par_window){ 
-      par_sched_round++;
-      xbt_os_walltimer_start(round_time);
-      smx_ctx_raw_runall_parallel();
-      xbt_os_walltimer_stop(round_time);
-      par_time += xbt_os_timer_elapsed(round_time);
-
-      prev_avg_par_proc = avg_par_proc;
-      delta = nb_processes - avg_par_proc;
-      avg_par_proc = (par_sched_round==1) ? nb_processes : avg_par_proc + delta / (double) par_sched_round;
-
-      if(par_sched_round>=2){
-        s_par_proc = s_par_proc + (nb_processes - prev_avg_par_proc) * delta; 
-        sd_par_proc = sqrt(s_par_proc / (par_sched_round-1));
-        par_window = (int) (avg_par_proc + sd_par_proc);
-      }else{
-        sd_par_proc = 0;
-      }
-
-      par_proc_that_ran += nb_processes;
-    } else{
-      smx_ctx_raw_runall_parallel();
-    }
-  } else {
-    simix_global->context_factory->suspend = smx_ctx_raw_suspend_serial;
-    if(nb_processes > seq_window){ 
-      seq_sched_round++;
-      xbt_os_walltimer_start(round_time);
-      smx_ctx_raw_runall_serial();
-      xbt_os_walltimer_stop(round_time);
-      seq_time += xbt_os_timer_elapsed(round_time);
-
-      prev_avg_seq_proc = avg_seq_proc;
-      delta = (nb_processes-avg_seq_proc);
-      avg_seq_proc = (seq_sched_round==1) ? nb_processes : avg_seq_proc + delta / (double) seq_sched_round;
-
-      if(seq_sched_round>=2){
-        s_seq_proc = s_seq_proc + (nb_processes - prev_avg_seq_proc)*delta; 
-        sd_seq_proc = sqrt(s_seq_proc / (seq_sched_round-1));
-        seq_window = (int) (avg_seq_proc - sd_seq_proc);
-      } else {
-        sd_seq_proc = 0;
-      }
-
-      seq_proc_that_ran += nb_processes;
-    } else {
-      smx_ctx_raw_runall_serial();
-    }
-  }
-}
-
-#else
-
-static void smx_ctx_raw_runall(void)
-{
-#ifdef TIME_BENCH_ENTIRE_SRS
-  sr_count++;
-  timer = xbt_os_timer_new();
-  double elapsed = 0;
-#endif
-  unsigned long nb_processes = xbt_dynar_length(simix_global->process_to_run);
-  if (SIMIX_context_is_parallel()
-    && (unsigned long) SIMIX_context_get_parallel_threshold() < nb_processes) {
-        XBT_DEBUG("Runall // %lu", nb_processes);
-        simix_global->context_factory->suspend = smx_ctx_raw_suspend_parallel;
-
-     #ifdef TIME_BENCH_ENTIRE_SRS
-        xbt_os_walltimer_start(timer);
-     #endif
-
-        smx_ctx_raw_runall_parallel();
-
-     #ifdef TIME_BENCH_ENTIRE_SRS
-        xbt_os_walltimer_stop(timer);
-        elapsed = xbt_os_timer_elapsed(timer);
-     #endif
-    } else {
-        XBT_DEBUG("Runall serial %lu", nb_processes);
-        simix_global->context_factory->suspend = smx_ctx_raw_suspend_serial;
-
-      #ifdef TIME_BENCH_PER_SR
-        smx_ctx_raw_runall_serial(simix_global->process_to_run);
-      #else
-
-        #ifdef TIME_BENCH_ENTIRE_SRS
-          xbt_os_walltimer_start(timer);
-        #endif
-
-        smx_ctx_raw_runall_serial();
-
-        #ifdef TIME_BENCH_ENTIRE_SRS
-          xbt_os_walltimer_stop(timer);
-          elapsed = xbt_os_timer_elapsed(timer);
-        #endif
-      #endif
-    }
-
-#ifdef TIME_BENCH_ENTIRE_SRS
-  XBT_CRITICAL("Total time SR %u = %f, %d", sr_count, elapsed, nb_processes);
-#endif
-}
-#endif
diff --git a/src/simix/smx_context_sysv.cpp b/src/simix/smx_context_sysv.cpp
deleted file mode 100644 (file)
index e89857d..0000000
+++ /dev/null
@@ -1,311 +0,0 @@
-/* context_sysv - context switching with ucontexts from System V           */
-
-/* Copyright (c) 2009-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. */
-
-#include <stdarg.h>
-
-#include "xbt/parmap.h"
-#include "smx_private.h"
-#include "src/internal_config.h"
-#include "src/context_sysv_config.h"        /* loads context system definitions */
-#include "mc/mc.h"
-
-#ifdef _XBT_WIN32
-#  include <xbt/win32_ucontext.h>     /* context relative declarations */
-#else
-#  include <ucontext.h>           /* context relative declarations */
-#endif
-
-XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_context);
-
-typedef struct s_smx_ctx_sysv {
-  s_smx_ctx_base_t super;       /* Fields of super implementation */
-  ucontext_t uc;                /* the ucontext that executes the code */
-  char *stack;                  /* the thread stack */
-} s_smx_ctx_sysv_t, *smx_ctx_sysv_t;
-
-#ifdef CONTEXT_THREADS
-static xbt_parmap_t sysv_parmap;
-static smx_ctx_sysv_t* sysv_workers_context;   /* space to save the worker's context in each thread */
-static unsigned long 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 */
-#endif
-static unsigned long sysv_process_index = 0;   /* index of the next process to run in the
-                                                * list of runnable processes */
-static smx_ctx_sysv_t sysv_maestro_context;
-
-static int smx_ctx_sysv_factory_finalize(smx_context_factory_t *factory);
-static void smx_ctx_sysv_free(smx_context_t context);
-static smx_context_t
-smx_ctx_sysv_create_context(xbt_main_func_t code, int argc, char **argv,
-    void_pfn_smxprocess_t cleanup_func, smx_process_t process);
-
-static void smx_ctx_sysv_wrapper(int count, ...);
-
-static void smx_ctx_sysv_stop_serial(smx_context_t context);
-static void smx_ctx_sysv_suspend_serial(smx_context_t context);
-static void smx_ctx_sysv_resume_serial(smx_process_t first_process);
-static void smx_ctx_sysv_runall_serial(void);
-
-static void smx_ctx_sysv_stop_parallel(smx_context_t context);
-static void smx_ctx_sysv_suspend_parallel(smx_context_t context);
-static void smx_ctx_sysv_resume_parallel(smx_process_t first_process);
-static void smx_ctx_sysv_runall_parallel(void);
-
-/* This is a bit paranoid about sizeof(smx_ctx_sysv_t) not being a multiple of
- * sizeof(int), but it doesn't harm. */
-#define CTX_ADDR_LEN                            \
-  (sizeof(smx_ctx_sysv_t) / sizeof(int) +       \
-   !!(sizeof(smx_ctx_sysv_t) % sizeof(int)))
-
-void SIMIX_ctx_sysv_factory_init(smx_context_factory_t *factory)
-{
-  smx_ctx_base_factory_init(factory);
-  XBT_VERB("Activating SYSV context factory");
-
-  (*factory)->finalize = smx_ctx_sysv_factory_finalize;
-  (*factory)->create_context = smx_ctx_sysv_create_context;
-  /* Do not overload that method (*factory)->finalize */
-  (*factory)->free = smx_ctx_sysv_free;
-  (*factory)->name = "smx_sysv_context_factory";
-
-  if (SIMIX_context_is_parallel()) {
-#ifdef CONTEXT_THREADS  /* To use parallel ucontexts a thread pool is needed */
-    int nthreads = SIMIX_context_get_nthreads();
-    sysv_parmap = xbt_parmap_new(nthreads, SIMIX_context_get_parallel_mode());
-    sysv_workers_context = xbt_new(smx_ctx_sysv_t, nthreads);
-    sysv_maestro_context = NULL;
-    xbt_os_thread_key_create(&sysv_worker_id_key);
-    (*factory)->stop = smx_ctx_sysv_stop_parallel;
-    (*factory)->suspend = smx_ctx_sysv_suspend_parallel;
-    (*factory)->runall = smx_ctx_sysv_runall_parallel;
-#else
-    THROWF(arg_error, 0, "No thread support for parallel context execution");
-#endif
-  } else {
-    (*factory)->stop = smx_ctx_sysv_stop_serial;
-    (*factory)->suspend = smx_ctx_sysv_suspend_serial;
-    (*factory)->runall = smx_ctx_sysv_runall_serial;
-  }    
-}
-
-static int smx_ctx_sysv_factory_finalize(smx_context_factory_t *factory)
-{ 
-#ifdef CONTEXT_THREADS
-  if (sysv_parmap)
-    xbt_parmap_destroy(sysv_parmap);
-  xbt_free(sysv_workers_context);
-#endif
-  return smx_ctx_base_factory_finalize(factory);
-}
-
-static smx_context_t
-smx_ctx_sysv_create_context(xbt_main_func_t code, int argc, char **argv,
-                            void_pfn_smxprocess_t cleanup_func,
-                            smx_process_t process)
-{
-  int ctx_addr[CTX_ADDR_LEN];
-  smx_ctx_sysv_t context =
-    (smx_ctx_sysv_t) smx_ctx_base_factory_create_context_sized(
-      sizeof(s_smx_ctx_sysv_t),
-      code,
-      argc,
-      argv,
-      cleanup_func,
-      process);
-
-  /* if the user provided a function for the process then use it,
-     otherwise it is the context for maestro */
-  if (code) {
-
-    context->stack = (char*) SIMIX_context_stack_new();
-    getcontext(&(context->uc));
-
-    context->uc.uc_link = NULL;
-
-    context->uc.uc_stack.ss_sp =
-        pth_skaddr_makecontext(context->stack, smx_context_usable_stack_size);
-
-    context->uc.uc_stack.ss_size =
-        pth_sksize_makecontext(context->stack, smx_context_usable_stack_size);
-
-    memcpy(ctx_addr, &context, sizeof(smx_ctx_sysv_t));
-    switch (CTX_ADDR_LEN) {
-    case 1:
-      makecontext(&context->uc, (void (*)())smx_ctx_sysv_wrapper,
-                  1, ctx_addr[0]);
-      break;
-    case 2:
-      makecontext(&context->uc, (void (*)())smx_ctx_sysv_wrapper,
-                  2, ctx_addr[0], ctx_addr[1]);
-      break;
-    default:
-      xbt_die("Ucontexts are not supported on this arch yet (addr len = %zu/%zu = %zu)",
-              sizeof(smx_ctx_sysv_t), sizeof(int), CTX_ADDR_LEN);
-    }
-  } else {
-    if (process != NULL && sysv_maestro_context == NULL)
-      sysv_maestro_context = context;
-  }
-
-#ifdef HAVE_MC
-  if (MC_is_active() && code) {
-    MC_register_stack_area(context->stack, ((smx_context_t)context)->process,
-                      &(context->uc), smx_context_usable_stack_size);
-  }
-#endif
-
-  return (smx_context_t) context;
-}
-
-static void smx_ctx_sysv_free(smx_context_t context)
-{
-
-  if (context) {
-    SIMIX_context_stack_delete(((smx_ctx_sysv_t)context)->stack);
-  }
-  smx_ctx_base_free(context);
-}
-
-static void smx_ctx_sysv_wrapper(int first, ...)
-{ 
-  int ctx_addr[CTX_ADDR_LEN];
-  smx_ctx_sysv_t context;
-
-  ctx_addr[0] = first;
-  if (CTX_ADDR_LEN > 1) {
-    va_list ap;
-    va_start(ap, first);
-    for (unsigned i = 1; i < CTX_ADDR_LEN; i++)
-      ctx_addr[i] = va_arg(ap, int);
-    va_end(ap);
-  }
-  memcpy(&context, ctx_addr, sizeof(smx_ctx_sysv_t));
-  (context->super.code) (context->super.argc, context->super.argv);
-
-  simix_global->context_factory->stop((smx_context_t) context);
-}
-
-static void smx_ctx_sysv_stop_serial(smx_context_t context)
-{
-  smx_ctx_base_stop(context);
-  smx_ctx_sysv_suspend_serial(context);
-}
-
-static void smx_ctx_sysv_suspend_serial(smx_context_t context)
-{
-  /* determine the next context */
-  smx_context_t next_context;
-  unsigned long int i = sysv_process_index++;
-
-  if (i < xbt_dynar_length(simix_global->process_to_run)) {
-    /* execute the next process */
-    XBT_DEBUG("Run next process");
-    next_context = xbt_dynar_get_as(
-        simix_global->process_to_run,i, smx_process_t)->context;
-  }
-  else {
-    /* all processes were run, return to maestro */
-    XBT_DEBUG("No more process to run");
-    next_context = (smx_context_t) sysv_maestro_context;
-  }
-  SIMIX_context_set_current(next_context);
-  swapcontext(&((smx_ctx_sysv_t) context)->uc,
-      &((smx_ctx_sysv_t) next_context)->uc);
-}
-
-static void smx_ctx_sysv_resume_serial(smx_process_t first_process)
-{
-  smx_context_t context = first_process->context;
-  SIMIX_context_set_current(context);
-  swapcontext(&sysv_maestro_context->uc,
-      &((smx_ctx_sysv_t) context)->uc);
-}
-
-static void smx_ctx_sysv_runall_serial(void)
-{
-  smx_process_t first_process =
-      xbt_dynar_get_as(simix_global->process_to_run, 0, smx_process_t);
-  sysv_process_index = 1;
-
-  /* execute the first process */
-  smx_ctx_sysv_resume_serial(first_process);
-}
-
-static void smx_ctx_sysv_stop_parallel(smx_context_t context)
-{
-  smx_ctx_base_stop(context);
-  smx_ctx_sysv_suspend_parallel(context);
-}
-
-/* This function is called by maestro at the beginning of a scheduling round to get all working threads executing some stuff
- * It is much easier to understand what happens if you see the working threads as bodies that swap their soul for the
- *    ones of the simulated processes that must run.
- */
-static void smx_ctx_sysv_runall_parallel(void) {
-#ifdef CONTEXT_THREADS
-  sysv_threads_working = 0;
-  // parmap_apply ensures that every working thread get an index in the process_to_run array (through an atomic fetch_and_add),
-  //  and runs the smx_ctx_sysv_resume_parallel function on that index
-  xbt_parmap_apply(sysv_parmap, (void_f_pvoid_t) smx_ctx_sysv_resume_parallel,
-      simix_global->process_to_run);
-#else
-  xbt_die("You asked for a parallel execution, but you don't have any threads.");
-#endif
-}
-
-/* This function is in charge of running one particular simulated process on the current thread */
-static void smx_ctx_sysv_resume_parallel(smx_process_t simulated_process_to_run) {
-#ifdef CONTEXT_THREADS
-  unsigned long worker_id = __sync_fetch_and_add(&sysv_threads_working, 1); // what is my containing body?
-  xbt_os_thread_set_specific(sysv_worker_id_key, (void*) worker_id);        // Store the number of my containing body in os-thread-specific area
-  smx_ctx_sysv_t worker_context = (smx_ctx_sysv_t)SIMIX_context_self();     // get my current soul
-  sysv_workers_context[worker_id] = worker_context;                         // write down that this soul is hosted in that body (for now)
-  ucontext_t* worker_stack = &worker_context->uc;                           // retrieves the system-level info that fuels this soul
-
-  smx_context_t context = simulated_process_to_run->context;                // That's the first soul that I should become
-  SIMIX_context_set_current(context);                                       // write in simix that I switched my soul
-  swapcontext(worker_stack, &((smx_ctx_sysv_t) context)->uc);               // actually do that using the relevant syscall
-  // No body runs that soul anymore at this point. Instead the current body took the soul of simulated process
-  // The simulated process wakes back after the call to "SIMIX_context_suspend(self->context);" within smx_process.c::SIMIX_process_yield()
-
-  // From now on, the simulated processes will change their soul with the next soul to execute (in suspend_parallel, below).
-  // When nobody is to be executed in this scheduling round, the last simulated process will take back the initial soul of the current working thread
-#endif
-}
-
-/* This function is called when a simulated process wants to yield back to the maestro in a blocking simcall.
- *    This naturally occurs within SIMIX_context_suspend(self->context), called from SIMIX_process_yield()
- * Actually, it does not really yield back to maestro, but into the next process that must be executed.
- * If no one is to be executed, then it yields to the initial soul that was in this working thread (that was saved in resume_parallel).
- */
-static void smx_ctx_sysv_suspend_parallel(smx_context_t context) {
-#ifdef CONTEXT_THREADS
-  /* determine the next context */
-  smx_process_t next_work = (smx_process_t) xbt_parmap_next(sysv_parmap);  // get the next soul to embody now
-  smx_context_t next_context;
-  ucontext_t* next_stack;                                  // will contain the next soul to run, either simulated or initial minion's one
-
-  if (next_work != NULL) {                                 // there is a next soul to embody (ie, a next process to resume)
-    XBT_DEBUG("Run next process");
-    next_context = next_work->context;
-  }
-  else {
-    /* all processes were run, go to the barrier */
-    XBT_DEBUG("No more processes to run");
-    unsigned long worker_id =                             // Get back the identity of my body that was stored when starting the scheduling round
-        (unsigned long) xbt_os_thread_get_specific(sysv_worker_id_key);
-    next_context = (smx_context_t)sysv_workers_context[worker_id];  // deduce the initial soul of that body
-                                                                    // When given that soul, the body will wait for the next scheduling round
-  }
-
-  next_stack = &((smx_ctx_sysv_t)next_context)->uc;
-
-  SIMIX_context_set_current(next_context);
-  swapcontext(&((smx_ctx_sysv_t) context)->uc, next_stack);  // get that next soul
-#endif
-}
diff --git a/src/simix/smx_context_thread.cpp b/src/simix/smx_context_thread.cpp
deleted file mode 100644 (file)
index a151abf..0000000
+++ /dev/null
@@ -1,213 +0,0 @@
-/* context_thread - implementation of context switching with native threads */
-
-/* Copyright (c) 2009-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. */
-
-#include "xbt/function_types.h"
-#include "smx_private.h"
-#include "src/portable.h"           /* loads context system definitions */
-#include "xbt/swag.h"
-#include "xbt/xbt_os_thread.h"
-#include "src/xbt_modinter.h"       /* prototype of os thread module's init/exit in XBT */
-
-XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(simix_context);
-
-typedef struct s_smx_ctx_thread {
-  s_smx_ctx_base_t super;       /* Fields of super implementation */
-  xbt_os_thread_t thread;       /* a plain dumb thread (portable to posix or windows) */
-  xbt_os_sem_t begin;           /* this semaphore is used to schedule/yield the process  */
-  xbt_os_sem_t end;             /* this semaphore is used to schedule/unschedule the process   */
-} s_smx_ctx_thread_t, *smx_ctx_thread_t;
-
-static xbt_os_sem_t smx_ctx_thread_sem;
-
-static smx_context_t
-smx_ctx_thread_factory_create_context(xbt_main_func_t code,
-                                      int argc, char **argv,
-                                      void_pfn_smxprocess_t cleanup_func,
-                                      smx_process_t process);
-
-static void smx_ctx_thread_free(smx_context_t context);
-static void smx_ctx_thread_stop(smx_context_t context);
-static void smx_ctx_thread_suspend(smx_context_t context);
-static void smx_ctx_thread_runall_serial(void);
-static void smx_ctx_thread_runall_parallel(void);
-static smx_context_t smx_ctx_thread_self(void);
-
-static int smx_ctx_thread_factory_finalize(smx_context_factory_t *factory);
-static void *smx_ctx_thread_wrapper(void *param);
-
-void SIMIX_ctx_thread_factory_init(smx_context_factory_t * factory)
-{
-  smx_ctx_base_factory_init(factory);
-  XBT_VERB("Activating thread context factory");
-
-  (*factory)->finalize  = smx_ctx_thread_factory_finalize;
-  (*factory)->create_context = smx_ctx_thread_factory_create_context;
-  /* Do not overload that method (*factory)->finalize */
-  (*factory)->free = smx_ctx_thread_free;
-  (*factory)->stop = smx_ctx_thread_stop;
-  (*factory)->suspend = smx_ctx_thread_suspend;
-
-  if (SIMIX_context_is_parallel())
-    (*factory)->runall = smx_ctx_thread_runall_parallel;
-  else
-    (*factory)->runall = smx_ctx_thread_runall_serial;
-
-  (*factory)->self = smx_ctx_thread_self;
-  (*factory)->name = "ctx_thread_factory";
-
-  if (SIMIX_context_is_parallel()) {
-    smx_ctx_thread_sem = xbt_os_sem_init(SIMIX_context_get_nthreads());
-  } else {
-    smx_ctx_thread_sem = NULL;
-  }
-}
-
-static int smx_ctx_thread_factory_finalize(smx_context_factory_t *factory)
-{
-  if (smx_ctx_thread_sem) {
-    xbt_os_sem_destroy(smx_ctx_thread_sem);
-    smx_ctx_thread_sem = NULL;
-  }
-  return smx_ctx_base_factory_finalize(factory);
-}
-
-static smx_context_t
-smx_ctx_thread_factory_create_context(xbt_main_func_t code, int argc,
-                                      char **argv,
-                                      void_pfn_smxprocess_t cleanup_func,
-                                      smx_process_t process)
-{
-  smx_ctx_thread_t context = (smx_ctx_thread_t)
-      smx_ctx_base_factory_create_context_sized(sizeof(s_smx_ctx_thread_t),
-                                                code, argc, argv,
-                                                cleanup_func, process);
-
-  /* If the user provided a function for the process then use it
-     otherwise is the context for maestro */
-  if (code) {
-    context->begin = xbt_os_sem_init(0);
-    context->end = xbt_os_sem_init(0);
-    if (smx_context_stack_size_was_set)
-      xbt_os_thread_setstacksize(smx_context_stack_size);
-    if (smx_context_guard_size_was_set)
-      xbt_os_thread_setguardsize(smx_context_guard_size);
-
-    /* create and start the process */
-    /* NOTE: The first argument to xbt_os_thread_create used to be the process *
-    * name, but now the name is stored at SIMIX level, so we pass a null  */
-    context->thread =
-      xbt_os_thread_create(NULL, smx_ctx_thread_wrapper, context, context);
-
-
-    /* wait the starting of the newly created process */
-    xbt_os_sem_acquire(context->end);
-
-  } else {
-    xbt_os_thread_set_extra_data(context);
-  }
-
-  return (smx_context_t) context;
-}
-
-static void smx_ctx_thread_free(smx_context_t pcontext)
-{
-  smx_ctx_thread_t context = (smx_ctx_thread_t) pcontext;
-
-  /* check if this is the context of maestro (it doesn't have a real thread) */
-  if (context->thread) {
-    /* wait about the thread terminason */
-    xbt_os_thread_join(context->thread, NULL);
-
-    /* destroy the synchronisation objects */
-    xbt_os_sem_destroy(context->begin);
-    xbt_os_sem_destroy(context->end);
-  }
-
-  smx_ctx_base_free(pcontext);
-}
-
-static void smx_ctx_thread_stop(smx_context_t pcontext)
-{
-  smx_ctx_thread_t context = (smx_ctx_thread_t) pcontext;
-
-  /* please no debug here: our procdata was already free'd */
-  smx_ctx_base_stop(pcontext);
-
-  if (smx_ctx_thread_sem)       /* parallel run */
-    xbt_os_sem_release(smx_ctx_thread_sem);
-
-  /* signal to the maestro that it has finished */
-  xbt_os_sem_release(((smx_ctx_thread_t) context)->end);
-
-  /* exit */
-  /* We should provide return value in case other wants it */
-  xbt_os_thread_exit(NULL);
-}
-
-static void *smx_ctx_thread_wrapper(void *param)
-{
-  smx_ctx_thread_t context = (smx_ctx_thread_t) param;
-#ifndef WIN32
-  /* Install alternate signal stack, for SIGSEGV handler. */
-  stack_t stack;
-  stack.ss_sp = sigsegv_stack;
-  stack.ss_size = sizeof sigsegv_stack;
-  stack.ss_flags = 0;
-  sigaltstack(&stack, NULL);
-#endif
-  /* Tell the maestro we are starting, and wait for its green light */
-  xbt_os_sem_release(context->end);
-  xbt_os_sem_acquire(context->begin);
-  if (smx_ctx_thread_sem)       /* parallel run */
-    xbt_os_sem_acquire(smx_ctx_thread_sem);
-
-  (context->super.code) (context->super.argc, context->super.argv);
-
-  smx_ctx_thread_stop((smx_context_t) context);
-  return NULL;
-}
-
-static void smx_ctx_thread_suspend(smx_context_t context)
-{
-  if (smx_ctx_thread_sem)       /* parallel run */
-    xbt_os_sem_release(smx_ctx_thread_sem);
-  xbt_os_sem_release(((smx_ctx_thread_t) context)->end);
-  xbt_os_sem_acquire(((smx_ctx_thread_t) context)->begin);
-  if (smx_ctx_thread_sem)       /* parallel run */
-    xbt_os_sem_acquire(smx_ctx_thread_sem);
-}
-
-static void smx_ctx_thread_runall_serial(void)
-{
-  smx_process_t process;
-  unsigned int cursor;
-
-  xbt_dynar_foreach(simix_global->process_to_run, cursor, process) {
-    XBT_DEBUG("Handling %p",process);
-    xbt_os_sem_release(((smx_ctx_thread_t) process->context)->begin);
-    xbt_os_sem_acquire(((smx_ctx_thread_t) process->context)->end);
-  }
-}
-
-static void smx_ctx_thread_runall_parallel(void)
-{
-  unsigned int index;
-  smx_process_t process;
-
-  xbt_dynar_foreach(simix_global->process_to_run, index, process)
-    xbt_os_sem_release(((smx_ctx_thread_t) process->context)->begin);
-
-  xbt_dynar_foreach(simix_global->process_to_run, index, process) {
-     xbt_os_sem_acquire(((smx_ctx_thread_t) process->context)->end);
-  }
-}
-
-static smx_context_t smx_ctx_thread_self(void)
-{
-  return (smx_context_t) xbt_os_thread_get_extra_data();
-}
index 0f00476..ea20087 100644 (file)
@@ -12,6 +12,7 @@
 #endif
 
 #include "smx_private.h"
+#include "smx_private.hpp"
 #include "xbt/heap.h"
 #include "xbt/sysdep.h"
 #include "xbt/log.h"
index 6aa5775..f161b9a 100644 (file)
 #include "popping_private.h"
 #include "smx_synchro_private.h"
 
+#ifdef __cplusplus
+
+#include <simgrid/simix.hpp>
+
+namespace simgrid {
+namespace simix {
+
+/* Hack: let msg load directly the right factory
+ *
+ * This is a factory of factory! How nice is this?
+ */
+typedef ContextFactory* (*ContextFactoryInitializer)(void);
+XBT_PUBLIC_DATA(ContextFactoryInitializer) factory_initializer;
+
+}
+}
+
+typedef simgrid::simix::ContextFactory *smx_context_factory_t;
+
+#else
+
+typedef struct s_smx_context_factory *smx_context_factory_t;
+
+#endif
+
 SG_BEGIN_DECL()
 
 /* Define only for SimGrid benchmarking purposes */
@@ -37,6 +62,7 @@ SG_BEGIN_DECL()
 #ifdef TIME_BENCH_PER_SR
 XBT_PRIVATE void smx_ctx_raw_new_sr(void);
 #endif
+
 /********************************** Simix Global ******************************/
 typedef struct s_smx_global {
   smx_context_factory_t context_factory;
@@ -208,119 +234,18 @@ XBT_PRIVATE void SIMIX_context_stack_delete(void *stack);
 XBT_PRIVATE void SIMIX_context_set_current(smx_context_t context);
 XBT_PRIVATE smx_context_t SIMIX_context_get_current(void);
 
-/* All factories init */
-
-XBT_PRIVATE void SIMIX_ctx_thread_factory_init(smx_context_factory_t *factory);
-XBT_PRIVATE void SIMIX_ctx_sysv_factory_init(smx_context_factory_t *factory);
-XBT_PRIVATE void SIMIX_ctx_raw_factory_init(smx_context_factory_t *factory);
-XBT_PRIVATE void SIMIX_ctx_boost_factory_init(smx_context_factory_t *factory);
-
 /* ****************************** */
 /* context manipulation functions */
 /* ****************************** */
 
-/* Scenario for the end of a context:
- *
- * CASE 1: death after end of the main function
- *   the context_wrapper, called internally by the context module, calls
- *   SIMIX_context_stop after user code stops, smx_context_stop calls user
- *   cleanup_func if any (in context settings), add current process to trashbin
- *   and yields back to maestro.
- *   From time to time, maestro calls SIMIX_context_empty_trash, which destroy
- *   all the process and context data structures, and frees the memory
- *
- * CASE 2: brutal death
- *   SIMIX_process_kill (from any process) set process->iwannadie = 1 and then
- *   schedules the process. Then the process is awaken in the middle of the
- *   SIMIX_process_yield function, and at the end of it, it checks that
- *   iwannadie == 1, and call SIMIX_context_stop(same than first case afterward)
- */
-
-/**
- * \brief creates a new context for a user level process
- * \param code a main function
- * \param argc the number of arguments of the main function
- * \param argv the vector of arguments of the main function
- * \param cleanup_func the function to call when the context stops
- * \param cleanup_arg the argument of the cleanup_func function
- */
-static XBT_INLINE smx_context_t SIMIX_context_new(xbt_main_func_t code,
-                                                  int argc, char **argv,
-                                                  void_pfn_smxprocess_t cleanup_func,
-                                                  smx_process_t simix_process)
-{
-  if (!simix_global)
-    xbt_die("simix is not initialized, please call MSG_init first");
-  return simix_global->context_factory->create_context(code,
-                                                       argc, argv,
-                                                       cleanup_func,
-                                                       simix_process);
-}
-
-/**
- * \brief destroy a context
- * \param context the context to destroy
- * Argument must be stopped first -- runs in maestro context
- */
-static XBT_INLINE void SIMIX_context_free(smx_context_t context)
-{
-  simix_global->context_factory->free(context);
-}
-
-/**
- * \brief stops the execution of a context
- * \param context to stop
- */
-static XBT_INLINE void SIMIX_context_stop(smx_context_t context)
-{
-  simix_global->context_factory->stop(context);
-}
-
-/**
- \brief suspends a context and return the control back to the one which
-        scheduled it
- \param context the context to be suspended (it must be the running one)
- */
-static XBT_INLINE void SIMIX_context_suspend(smx_context_t context)
-{
-  simix_global->context_factory->suspend(context);
-}
-
-/**
- \brief Executes all the processes to run (in parallel if possible).
- */
-static XBT_INLINE void SIMIX_context_runall(void)
-{
-  if (!xbt_dynar_is_empty(simix_global->process_to_run)) {
-    simix_global->context_factory->runall();
-  }
-}
-
-/**
- \brief returns the current running context
- */
-static XBT_INLINE smx_context_t SIMIX_context_self(void)
-{
-  if (simix_global && simix_global->context_factory) {
-    return simix_global->context_factory->self();
-  }
-  return NULL;
-}
-
-/**
- \brief returns the SIMIX process associated to a context
- \param context The context
- \return The SIMIX process
- */
-static XBT_INLINE smx_process_t SIMIX_context_get_process(smx_context_t context)
-{
-  return simix_global->context_factory->get_process(context);
-}
-
 XBT_PUBLIC(int) SIMIX_process_get_maxpid(void);
 
 XBT_PRIVATE void SIMIX_post_create_environment(void);
 
+// FIXME, Dirty hack for SMPI+MSG
+XBT_PRIVATE void SIMIX_process_set_cleanup_function(
+  smx_process_t process, void_pfn_smxprocess_t cleanup);
+
 SG_END_DECL()
 
 #endif
diff --git a/src/simix/smx_private.hpp b/src/simix/smx_private.hpp
new file mode 100644 (file)
index 0000000..a0d704a
--- /dev/null
@@ -0,0 +1,102 @@
+/* Copyright (c) 2007-2010, 2012-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. */
+
+#ifndef SIMGRID_SIMIX_PRIVATE_HPP
+#define SIMGRID_SIMIX_PRIVATE_HPP
+
+#include <simgrid/simix.hpp>
+#include "smx_private.h"
+
+/**
+ * \brief creates a new context for a user level process
+ * \param code a main function
+ * \param argc the number of arguments of the main function
+ * \param argv the vector of arguments of the main function
+ * \param cleanup_func the function to call when the context stops
+ * \param cleanup_arg the argument of the cleanup_func function
+ */
+static inline smx_context_t SIMIX_context_new(xbt_main_func_t code,
+                                                  int argc, char **argv,
+                                                  void_pfn_smxprocess_t cleanup_func,
+                                                  smx_process_t simix_process)
+{
+  if (!simix_global)
+    xbt_die("simix is not initialized, please call MSG_init first");
+  return simix_global->context_factory->create_context(
+    code, argc, argv, cleanup_func, simix_process);
+}
+
+/**
+ * \brief destroy a context
+ * \param context the context to destroy
+ * Argument must be stopped first -- runs in maestro context
+ */
+static XBT_INLINE void SIMIX_context_free(smx_context_t context)
+{
+  delete context;
+}
+
+/**
+ * \brief stops the execution of a context
+ * \param context to stop
+ */
+static XBT_INLINE void SIMIX_context_stop(smx_context_t context)
+{
+  context->stop();
+}
+
+/**
+ \brief suspends a context and return the control back to the one which
+        scheduled it
+ \param context the context to be suspended (it must be the running one)
+ */
+static XBT_INLINE void SIMIX_context_suspend(smx_context_t context)
+{
+  context->suspend();
+}
+
+/**
+ \brief Executes all the processes to run (in parallel if possible).
+ */
+static XBT_INLINE void SIMIX_context_runall(void)
+{
+  if (!xbt_dynar_is_empty(simix_global->process_to_run))
+    simix_global->context_factory->run_all();
+}
+
+/**
+ \brief returns the current running context
+ */
+static XBT_INLINE smx_context_t SIMIX_context_self(void)
+{
+  if (simix_global && simix_global->context_factory)
+    return simix_global->context_factory->self();
+  else
+    return nullptr;
+}
+
+/**
+ \brief returns the SIMIX process associated to a context
+ \param context The context
+ \return The SIMIX process
+ */
+static XBT_INLINE smx_process_t SIMIX_context_get_process(smx_context_t context)
+{
+  return context->process();
+}
+
+namespace simgrid {
+namespace simix {
+
+XBT_PRIVATE ContextFactory* thread_factory();
+XBT_PRIVATE ContextFactory* sysv_factory();
+XBT_PRIVATE ContextFactory* raw_factory();
+XBT_PRIVATE ContextFactory* boost_factory();
+
+}
+}
+
+#endif
index 493977b..b56bae0 100644 (file)
@@ -11,6 +11,7 @@
 #include "mc/mc.h"
 #include "src/mc/mc_replay.h"
 #include "src/mc/mc_client.h"
+#include "src/simix/smx_private.hpp"
 
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_process, simix,
                                 "Logging specific to SIMIX (process)");
index 7047bcc..4001323 100644 (file)
@@ -79,7 +79,7 @@ void smpi_process_init(int *argc, char ***argv)
   if (argc && argv) {
     proc = SIMIX_process_self();
     //FIXME: dirty cleanup method to avoid using msg cleanup functions on these processes when using MSG+SMPI
-    proc->context->cleanup_func=SIMIX_process_cleanup;
+    SIMIX_process_set_cleanup_function(proc, SIMIX_process_cleanup);
     char* instance_id = (*argv)[1];
     int rank = atoi((*argv)[2]);
     index = smpi_process_index_of_smx_process(proc);
index 6c0e7e7..d3edb7b 100644 (file)
@@ -27,6 +27,7 @@
 #include "xbt/xbt_os_thread.h"
 #include "xbt/sysdep.h"
 #include "src/simix/smx_private.h"
+#include "src/simix/smx_private.hpp"
 
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_parmap, xbt, "parmap: parallel map");
 
index 949ad0a..fa4ff1c 100644 (file)
@@ -1,5 +1,5 @@
 $ java -classpath ${classpath:=.} sleep_host_off.Main ${srcdir:=.}/../../examples/platforms/small_platform.xml ${srcdir:=.}/sleep_host_off/sleep_host_off_d.xml "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n"
-> [  0.000000] (0:@) Using regular java threads. Coroutines could speed your simulation up.
+> [  0.000000] (0:@) Using regular java threads.
 > [  0.000000] (1:sleep_host_off.SleepHostOff@Tremblay) **** **** **** ***** ***** Test Sleep ***** ***** **** **** ****
 > [  0.000000] (1:sleep_host_off.SleepHostOff@Tremblay) Test sleep: Create a process on Jupiter, the process simply make periodic sleep, turn off Jupiter
 > [  0.000000] (2:sleep@Jupiter) I'm not dead
index f33ebcb..03adb42 100644 (file)
@@ -38,6 +38,7 @@ set(EXTRA_DIST
   src/simix/smx_io_private.h
   src/simix/smx_network_private.h
   src/simix/smx_private.h
+  src/simix/smx_private.hpp
   src/simix/smx_process_private.h
   src/simix/smx_synchro_private.h
   src/smpi/README
@@ -357,7 +358,7 @@ set(SIMIX_GENERATED_SRC
 set(SIMIX_SRC
   src/simix/libsmx.cpp
   src/simix/smx_context.cpp
-  src/simix/smx_context_base.cpp
+  src/simix/Context.cpp
   src/simix/smx_deployment.cpp
   src/simix/smx_environment.cpp
   src/simix/smx_global.cpp
@@ -376,22 +377,24 @@ set(SIMIX_SRC
 if (MSVC)
   set(EXTRA_DIST
       ${EXTRA_DIST}
-      src/simix/smx_context_raw.cpp)
+      src/simix/RawContext.cpp)
 else()
   set(SIMIX_SRC
       ${SIMIX_SRC}
-      src/simix/smx_context_raw.cpp)
+      src/simix/RawContext.cpp)
 endif()
 
 # Boost context may not be available
 if (HAVE_BOOST_CONTEXT)
   set(SIMIX_SRC
       ${SIMIX_SRC}
-      src/simix/smx_context_boost.cpp)
+      src/simix/BoostContext.hpp
+      src/simix/BoostContext.cpp)
 else()
   set(EXTRA_DIST
       ${EXTRA_DIST}
-      src/simix/smx_context_boost.cpp)
+      src/simix/BoostContext.hpp
+      src/simix/BoostContext.cpp)
 endif()
 
 set(S4U_SRC
@@ -492,7 +495,7 @@ set(JSURF_JAVA_GENERATED_SRC
 )
 
 set(JMSG_C_SRC
-  src/bindings/java/jmsg.c
+  src/bindings/java/jmsg.cpp
   src/bindings/java/jmsg.h
   src/bindings/java/jmsg_as.c
   src/bindings/java/jmsg_as.h
@@ -502,7 +505,7 @@ set(JMSG_C_SRC
   src/bindings/java/jmsg_file.h
   src/bindings/java/jmsg_host.c
   src/bindings/java/jmsg_host.h
-  src/bindings/java/jmsg_process.c
+  src/bindings/java/jmsg_process.cpp
   src/bindings/java/jmsg_process.h
   src/bindings/java/jmsg_rngstream.c
   src/bindings/java/jmsg_rngstream.h
@@ -514,10 +517,8 @@ set(JMSG_C_SRC
   src/bindings/java/jmsg_vm.h
   src/bindings/java/jxbt_utilities.c
   src/bindings/java/jxbt_utilities.h
-  src/bindings/java/smx_context_cojava.c
-  src/bindings/java/smx_context_cojava.h
-  src/bindings/java/smx_context_java.c
-  src/bindings/java/smx_context_java.h
+  src/bindings/java/JavaContext.cpp
+  src/bindings/java/JavaContext.hpp
   src/bindings/java/jmsg_storage.c
   src/bindings/java/jmsg_storage.h
 )
@@ -709,6 +710,7 @@ set(headers_to_install
   include/simgrid/platf_generator.h
   include/simgrid/plugins.h
   include/simgrid/simix.h
+  include/simgrid/simix.hpp
   include/simgrid/host.h
   include/simgrid/link.h
   include/simgrid/s4u/actor.hpp
@@ -777,13 +779,25 @@ set(source_of_generated_headers
 if(${CONTEXT_THREADS}) #pthread
   set(SURF_SRC
     ${SURF_SRC}
-    src/simix/smx_context_thread.cpp
+    src/simix/ThreadContext.cpp
+    src/simix/ThreadContext.hpp
+    )
+else() # NOT pthread
+  set(EXTRA_DIST
+    ${EXTRA_DIST}
+    src/simix/ThreadContext.cpp
+    src/simix/ThreadContext.hpp
+    )
+endif()
+
+if(${CONTEXT_THREADS}) #pthread
+  set(SURF_SRC
+    ${SURF_SRC}
     src/xbt/xbt_os_thread.c
     )
 else() # NOT pthread
   set(EXTRA_DIST
     ${EXTRA_DIST}
-    src/simix/smx_context_thread.cpp
     src/xbt/xbt_os_thread.c
     )
 endif()
@@ -791,12 +805,12 @@ endif()
 if(${CONTEXT_UCONTEXT}) #ucontext
   set(SURF_SRC
     ${SURF_SRC}
-    src/simix/smx_context_sysv.cpp
+    src/simix/UContext.cpp
     )
 else() # NOT ucontext
   set(EXTRA_DIST
     ${EXTRA_DIST}
-    src/simix/smx_context_sysv.cpp
+    src/simix/UContext.cpp
     )
 endif()
 
@@ -859,7 +873,8 @@ endif()
 if(WIN32)
   set(simgrid_sources
     ${simgrid_sources}
-    src/simix/smx_context_thread.cpp
+    src/simix/src/simix/ThreadContext.cpp
+    src/simix/src/simix/ThreadContext.hpp
     src/xbt/win32_ucontext.c
     src/xbt/xbt_os_thread.c
     )