[m-rev.] for review: stm runtime and library

Julien Fischer juliensf at csse.unimelb.edu.au
Wed Sep 26 18:46:24 AEST 2007


On Wed, 26 Sep 2007, Leon Ilario MIKA wrote:

> Estimated hours taken: 8
>
> Modifcation of Software Transactional Memory runtime and library to handle
> blocking and nested STM transactions.

I suggest:

 	Support blocking and nested transactions in the STM runtime.

> runtime/mercury_stm.c
> runtime/mercury_stm.h

Add a colon after each filename.

> 	Defined condition variables for the high-level C grade.  This

s/grade/grades/

> 	is used for the scheduling of threads with blocking transactions.
> 	Such grades used POSIX condition variables for this purpose.

s/POSIX/pthreads/

> 	Added wait queues to transaction variables.  These data structures
> 	maintain a list of all threads waiting for the value of the
> 	corresponding transaction variable to change.
>
> 	Added a function to block a transaction until the value of a
> 	transaction variable has changed.

> 	Added a function which permits the merging of a transaction log
> 	with it's parent.

I suggest:

 	Add a function that merges a transaction log with that of its
 	parent.

> runtime/stm_builtin.m

That should be, library/stm_builtin.m:

> 	Added utility predicates which will assist the checking of atomic
> 	goals durring the semantic analysis and error checking phase of the

s/durring/during/ (and below).

> 	compiler.  These are automatically inserted durring the construction
> 	of the hlds and automatically removed durring the expansion of
> 	stm_goals.
>
> 	Completed the implementation of the predicate "stm_block".

...

> Index: runtime/mercury_stm.c
> ===================================================================
> RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_stm.c,v
> retrieving revision 1.5
> diff -u -u -r1.5 mercury_stm.c
> --- runtime/mercury_stm.c	21 Sep 2007 06:13:12 -0000	1.5
> +++ runtime/mercury_stm.c	26 Sep 2007 05:22:51 -0000
>

...

> +void
> +MR_STM_merge_transactions(MR_STM_TransLog *tlog) {
> +
> +    MR_STM_TransLog     *parent_log;
> +    MR_STM_TransRecord  *parent_current;
> +    MR_STM_TransRecord  *current;
> +    MR_STM_TransRecord  *records_to_append_to_parent;
> +    MR_bool             found_tvar_in_parent;
> +
> +    MR_assert(tlog != NULL);
> +    MR_assert(tlog->MR_STM_tl_parent != NULL);
> +
> +    parent_log = tlog->MR_STM_tl_parent;
> +
> +    current = tlog->MR_STM_tl_records;
> +    while (current != NULL) {
> +
> +        found_tvar_in_parent = MR_NO;
> +        parent_current = parent_log->MR_STM_tl_records;
> +
> +        while (parent_current != NULL) {
> +            if (current->MR_STM_tr_var == parent_current->MR_STM_tr_var) {
> +                parent_current->MR_STM_tr_new_value =
> +                    current->MR_STM_tr_new_value;
> +                found_tvar_in_parent = MR_YES;
> +                break;
> +            }
> +
> +            parent_current = parent_current->MR_STM_tr_next;
> +        }
> +
> +        if (! found_tvar_in_parent) {
> +            MR_STM_record_transaction(parent_log,
> +                    current->MR_STM_tr_var, current->MR_STM_tr_old_value,
> +                    current->MR_STM_tr_new_value);
> +        }
> +
> +        current = current->MR_STM_tr_next;
> +    }
> +
> +    /* Deallocate child log */
> +#if !defined(MR_CONSERVATIVE_GC)
> +    /* XXX -- Free tlog and log entries */
> +#endif
> +}
> +
> +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);
> +
> +        MR_STM_condvar_wait(tlog, MR_STM_lock);
> +
> +        MR_STM_unwait(tlog, thread_condvar);
> +        MR_STM_condvar_destroy(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");

Mention STM in these assertion messages.

> +#endif


That's not quite right because (eventually) all low-level grades
will support STM, since they all support concurrency.
It should be something like:

#if defined(MR_THREAD_SAFE) || !defined(MR_HIGHLEVEL_CODE)

 	... as above ...

#else
 	MR_fatal_error("STM: blocking in non-parallel high-level C
 		grade.");
#endif

For the first case you will need to add a bit more code that causes
an abort in low-level grades (at least for now), e.g.

 	#if !defined(MR_HIGHLEVEL_CODE)
 		MR_fatal_error(...);
 	#endif

...

> Index: runtime/mercury_stm.h
> ===================================================================
> RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_stm.h,v
> retrieving revision 1.5
> diff -u -u -r1.5 mercury_stm.h
> --- runtime/mercury_stm.h	17 Sep 2007 13:28:56 -0000	1.5
> +++ runtime/mercury_stm.h	25 Sep 2007 05:35:24 -0000

...

> /*
> +** The type MR_STM_ConditionVar provides an abstract method of blocking and
> +** signalling threads based on conditions.
> +*/
> +#if defined(MR_HIGHLEVEL_CODE)
> +
> +    #if defined(MR_THREAD_SAFE)
> +        typedef pthread_cond_t  MR_STM_ConditionVar;
> +
> +        #define MR_STM_condvar_init(x)        pthread_cond_init(x, NULL)
> +        #define MR_STM_condvar_wait(x, y)     pthread_cond_wait(x, y)
> +        #define MR_STM_condvar_signal(x)      pthread_cond_signal(x)

Should that not be pthread_cond_broadcast()?

> +        #define MR_STM_condvar_destroy(x)     pthread_cond_destroy(x)
> +    #else
> +        typedef MR_Integer      MR_STM_ConditionVar;
> +        /*
> +        ** 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)
> +        #define MR_STM_condvar_destroy(x)
> +    #endif
> +



> /*
> +** Blocks a thread from execution.  This method is called by the thread
> +** which is to be blocked.  The STM lock MUST be aquired by the +** thread 
> before this method is called and acquires the lock when the thread
> +** is signalled.
> +*/
> +extern void
> +MR_STM_block_thread(MR_STM_TransLog *tlog);
> +
> +/*
> +** Merges a transaction with its parent.  Do not merge it with any
> +** other ancestors.  Aborts if the given transaction log does not have a
> +** parent.
> +*/
> +extern void
> +MR_STM_merge_transactions(MR_STM_TransLog *tlog);
> +
> +/*
> +** Reschedules all threads currently waiting on the given transaction
> +** variables.

s/variables/variable/

...


> Index: library/stm_builtin.m
> ===================================================================
> RCS file: /home/mercury/mercury1/repository/mercury/library/stm_builtin.m,v
> retrieving revision 1.12
> diff -u -u -r1.12 stm_builtin.m
> --- library/stm_builtin.m	17 Sep 2007 13:28:55 -0000	1.12
> +++ library/stm_builtin.m	26 Sep 2007 05:07:44 -0000
> @@ -171,6 +171,15 @@
> :- type stm_dummy_output
>     --->    stm_dummy_output.
>
> +    % Used to enforce the uniqueness of outer and inner variables.

 	... of out and inner variables in atomic scopes.

> +    % Will be removed before stm_expansion.
> +    %
> +:- pred stm_from_outer_to_inner_io(io::di, stm::uo) is det.
> +:- pred stm_from_outer_to_inner_stm(stm::di, stm::uo) is det.
> +
> +:- pred stm_from_inner_to_outer_io(stm::di, io::uo) is det.
> +:- pred stm_from_inner_to_outer_stm(stm::di, stm::uo) is det.
> +
> %-----------------------------------------------------------------------------%
> %-----------------------------------------------------------------------------%
>
> @@ -276,12 +285,43 @@
>     MR_STM_commit(STM);
> ").
>
> +:- pragma foreign_proc("C",
> +    stm_from_outer_to_inner_io(IO::di, STM::uo),
> +    [promise_pure, will_not_call_mercury, thread_safe],
> +"
> +    STM = NULL;
> +    MR_final_io_state(IO);
> +").
> +
> +:- pragma foreign_proc("C",
> +    stm_from_outer_to_inner_stm(STM0::di, STM::uo),
> +    [promise_pure, will_not_call_mercury, thread_safe],
> +"
> +    STM = STM0;
> +").
> +
> +:- pragma foreign_proc("C",
> +    stm_from_inner_to_outer_io(STM0::di, IO::uo),
> +    [promise_pure, will_not_call_mercury, thread_safe],
> +"
> +    STM0 = NULL;
> +    IO = MR_initial_io_state();
> +").
> +
> +:- pragma foreign_proc("C",
> +    stm_from_inner_to_outer_stm(STM0::di, STM::uo),
> +    [promise_pure, will_not_call_mercury, thread_safe],
> +"
> +    STM0 = NULL;
> +    STM = NULL;
> +").

These foreign procs should just call MR_fatal_error() since the bodies
here aren't ever supposed to be used.

The rest looks okay.

Julien.
--------------------------------------------------------------------------
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