[m-rev.] for review: support STM in low level grades

Ben Mellor bmellor at csse.unimelb.edu.au
Sun May 3 22:26:53 AEST 2009


Allow the Software Transactional Memory (STM) system to work in low level C
grades.

runtime/mercury_stm.h
	In low level grades, define the type MR_STM_ConditionVar as an alias
	for MR_STM_TransLog*, and prototype the MR_STM_condvar_signal procedure.

runtime/mercury_stm.c
	MR_stm_block_thread is now conditional on MR_HIGHLEVEL_CODE.

	In low level grades, MR_STM_condvar_signal is defined to allow the
	transaction logs saved as "condition variables" to be "signalled".

library/stm_builtin.m
	In low level grades, stm_block saves the current context in the waiter
	queues of the STM variables mentioned in the context's transaction log,
	then calls MR_runnext to look for more work.



Index: runtime/mercury_stm.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_stm.c,v
retrieving revision 1.6
diff -u -r1.6 mercury_stm.c
--- runtime/mercury_stm.c	27 Feb 2008 07:23:57 -0000	1.6
+++ runtime/mercury_stm.c	3 May 2009 12:23:54 -0000
@@ -347,14 +347,22 @@
 #endif
 }
 
+
+#if defined(MR_HIGHLEVEL_CODE)
+/*
+** MR_STM_block_thread is called to block the thread in high level C grades,
+** using POSIX thread facilities, as there is a POSIX thread for every engine
+** in these grades. The low level C grade equivalent of this code is defined
+** in the stm_builtin library module.
+*/
 void
 MR_STM_block_thread(MR_STM_TransLog *tlog)
 {
 #if defined(MR_THREAD_SAFE)
-  #if defined(MR_HIGHLEVEL_CODE)
         MR_STM_ConditionVar     *thread_condvar;
 
         thread_condvar = MR_GC_NEW(MR_STM_ConditionVar);
+        MR_STM_condvar_init(thread_condvar);
 
         MR_STM_wait(tlog, thread_condvar);
 
@@ -370,11 +378,37 @@
         MR_STM_unwait(tlog, thread_condvar);
 
         MR_GC_free(thread_condvar);
-  #else
-        MR_fatal_error("Low-Level backend: Not implemented");
-  #endif
 #else
     MR_fatal_error("Blocking thread in non-parallel grade");
 #endif
+}
+#endif
+
+
+#if !defined(MR_HIGHLEVEL_CODE)
+/*
+** In the low level C grades, the "condition variable" created when an STM
+** transaction blocks is actually a pointer to the transaction log.
"Signalling" +** it consists of going through the STM variables listed in the
log and removing +** the waiters attached to them for the context listed in the
log. After this, +** the context can be safely rescheduled.
+*/
+void
+MR_STM_condvar_signal(MR_STM_ConditionVar *cvar)
+{
+    /*
+    ** Calling MR_STM_unwait here should be safe, as this signalling is called
+    ** in response to a commit, while the committing thread holds the global
+    ** STM lock. Note that a MR_STM_ConditionVar IS a MR_STM_TransLog if
+    ** MR_HIGHLEVEL_CODE is not defined, which is why cvar is passed twice.
+    */
+    MR_STM_unwait(cvar, cvar);
+
+#if defined(MR_STM_DEBUG)
+        fprintf(stderr, "STM RESCHEDULING: log <0x%.8lx>\n", (MR_Word)cvar);
+#endif
 
+    MR_schedule_context(MR_STM_context_from_condvar(cvar));
 }
+
+#endif
Index: runtime/mercury_stm.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_stm.h,v
retrieving revision 1.6
diff -u -r1.6 mercury_stm.h
--- runtime/mercury_stm.h	27 Feb 2008 07:23:57 -0000	1.6
+++ runtime/mercury_stm.h	3 May 2009 12:23:54 -0000
@@ -78,6 +78,7 @@
     #if defined(MR_THREAD_SAFE)
         typedef MercuryCond  MR_STM_ConditionVar;
 
+        #define MR_STM_condvar_init(x)        pthread_cond_init(x,
MR_COND_ATTR) #define MR_STM_condvar_wait(x, y)     MR_cond_wait(x, y)
         #define MR_STM_condvar_signal(x)      MR_cond_signal(x)
     #else
@@ -86,20 +87,18 @@
         ** Since these grades don't support concurrency, there is no
         ** need to block the thread.
         */
+        #define MR_STM_condvar_init(x)
         #define MR_STM_condvar_wait(x, y)
         #define MR_STM_condvar_signal(x)
     #endif
 
 #else /* !MR_HIGHLEVEL_CODE */
 
-    typedef MR_Context  *MR_STM_ConditionVar;
+    typedef MR_STM_TransLog  MR_STM_ConditionVar;
 
-    /*
-    ** These are dummy definitions; STM is not yet implemented for low level C
-    ** grades.
-    */
-    #define MR_STM_condvar_wait(x, y)
-    #define MR_STM_condvar_signal(x)
+    extern void MR_STM_condvar_signal(MR_STM_ConditionVar *cvar);
+
+    #define MR_STM_context_from_condvar(x)      (x->MR_STM_tl_thread)
 
 #endif /* !MR_HIGHLEVEL_CODE */
 
Index: library/stm_builtin.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/library/stm_builtin.m,v
retrieving revision 1.14
diff -u -r1.14 stm_builtin.m
--- library/stm_builtin.m	26 Feb 2009 23:43:08 -0000	1.14
+++ library/stm_builtin.m	3 May 2009 12:23:54 -0000
@@ -368,13 +368,100 @@
 
 %-----------------------------------------------------------------------------%
 
+
+% In high level C grades, stm_block calls a C procedure in the runtime that
+% blocks the POSIX thread until signalled, as there is one POSIX thread for
+% every Mercury thread.
+% In the low level C grades, this approach cannot be taken, as when the context
+% blocks the engine running in the POSIX thread needs to be able to look for
+% other work (there might only be a single engine/POSIX thread).
+
 :- pragma foreign_proc("C",
     stm_block(STM::ui),
     [will_not_call_mercury, thread_safe],
 "
+#if defined(MR_HIGHLEVEL_CODE)
     MR_STM_block_thread(STM);
+#else
+
+    MR_STM_wait(STM, STM);
+
+#if defined(MR_STM_DEBUG)
+        fprintf(stderr, ""STM BLOCKING: log <0x%.8lx>\n"", STM);
+#endif
+
+    MR_save_context(MR_ENGINE(MR_eng_this_context));
+
+    MR_ENGINE(MR_eng_this_context)->MR_ctxt_resume =
+        MR_ENTRY(mercury__stm_builtin__block_thread_resume);
+
+    MR_ENGINE(MR_eng_this_context) = NULL;
+    MR_UNLOCK(&MR_STM_lock, ""MR_STM_block_thread"");
+    MR_runnext();
+
+#endif
 ").
 
+
+% block_thread_resume is the piece of code we jump to when a thread suspended
+% after a failed STM transaction resumes
+:- pragma foreign_decl("C",
+"
+/*
+INIT mercury_sys_init_stm_builtin_modules
+*/
+
+#if (!defined MR_HIGHLEVEL_CODE)
+    MR_define_extern_entry(mercury__stm_builtin__block_thread_resume);
+#endif
+").
+
+:- pragma foreign_code("C",
+"
+#if (!defined MR_HIGHLEVEL_CODE)
+
+    MR_BEGIN_MODULE(hand_written_stm_builtin_module)
+        MR_init_entry_ai(mercury__stm_builtin__block_thread_resume);
+    MR_BEGIN_CODE
+
+    MR_define_entry(mercury__stm_builtin__block_thread_resume);
+    {
+        MR_proceed();
+    }
+    MR_END_MODULE
+
+#endif
+
+    /* forward decls to suppress gcc warnings */
+    void mercury_sys_init_stm_builtin_modules_init(void);
+    void mercury_sys_init_stm_builtin_modules_init_type_tables(void);
+    #ifdef  MR_DEEP_PROFILING
+    void mercury_sys_init_stm_builtin_modules_write_out_proc_statics(
+        FILE *deep_fp, FILE *procrep_fp);
+    #endif
+
+    void mercury_sys_init_stm_builtin_modules_init(void)
+    {
+    #if (!defined MR_HIGHLEVEL_CODE)
+        hand_written_stm_builtin_module();
+    #endif
+    }
+
+    void mercury_sys_init_stm_builtin_modules_init_type_tables(void)
+    {
+        /* no types to register */
+    }
+
+    #ifdef  MR_DEEP_PROFILING
+    void mercury_sys_init_stm_builtin_modules_write_out_proc_statics(
+        FILE *deep_fp, FILE *procrep_fp)
+    {
+        /* no proc_statics to write out */
+    }
+    #endif
+").
+
+
 %-----------------------------------------------------------------------------%
 %
 % Retry
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list