[m-rev.] for review: extend parallel mmc make support

Peter Wang wangp at students.csse.unimelb.edu.au
Mon Apr 2 16:52:40 AEST 2007


Branches: main

Extend parallel mmc --make support.

compiler/make.program_target.m:
	Allow the target code and object code steps to be done in parallel.
	Force all interface files to be made before the Mercury -> target code
	step.  This prevents a problem when two parallel branches try to
	generate the same missing interface file later.

	Allow intermodule analysis to proceed in parallel, i.e. building
	`.analysis' files.  Ensure that all interface files are made before the
	analysis step also.


On my machine this can randomly trigger an assertion in glibc.

    mercury_compile: dl-open.c:438: dl_open_worker: Assertion `imap->l_type == lt_loaded' failed.

I think it's a race condition in glibc 2.3.6.  Running mmc make again
allows the build to progress (unless it trips up again later).
Non-parallel mmc make is not affected.


Index: compiler/make.program_target.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/make.program_target.m,v
retrieving revision 1.66
diff -u -r1.66 make.program_target.m
--- compiler/make.program_target.m	13 Feb 2007 00:16:55 -0000	1.66
+++ compiler/make.program_target.m	2 Apr 2007 06:34:28 -0000
@@ -146,8 +146,9 @@
             sorry(this_file, "mmc --make and target x86_64")
         ),
 
+        AllModulesList = set.to_sorted_list(AllModules),
         get_target_modules(IntermediateTargetType,
-            set.to_sorted_list(AllModules), ObjModules, !Info, !IO),
+            AllModulesList, ObjModules, !Info, !IO),
         IntermediateTargets = make_dependency_list(ObjModules,
             IntermediateTargetType),
         ObjTargets = make_dependency_list(ObjModules, ObjectTargetType),
@@ -156,25 +157,35 @@
             ObjModules, ForeignObjTargetsList, !Info, !IO),
         ForeignObjTargets = list.condense(ForeignObjTargetsList),
 
-        foldl2_maybe_stop_at_error(KeepGoing, make_module_target,
-            IntermediateTargets, BuildDepsSucceeded0, !Info, !IO),
-        (
-            BuildDepsSucceeded0 = yes,
-            foldl2_maybe_stop_at_error_maybe_parallel(KeepGoing,
-                make_module_target, ObjTargets,
-                BuildDepsSucceeded1, !Info, !IO)
-        ;
-            BuildDepsSucceeded0 = no,
-            BuildDepsSucceeded1 = no
-        ),
-        (
-            BuildDepsSucceeded1 = yes,
-            foldl2_maybe_stop_at_error(KeepGoing, make_module_target,
-                ForeignObjTargets,
-                BuildDepsSucceeded, !Info, !IO)
-        ;
-            BuildDepsSucceeded1 = no,
+        % Ensure all interface files are present before continuing.  This
+        % prevents a problem when two parallel branches try to generate the
+        % same missing interface file later.
+        %
+        make_all_interface_files(AllModulesList, IntsSucceeded, !Info, !IO),
+        ( IntsSucceeded = no, KeepGoing = no ->
             BuildDepsSucceeded = no
+        ;
+            foldl2_maybe_stop_at_error_maybe_parallel(KeepGoing,
+                make_module_target, IntermediateTargets,
+                BuildDepsSucceeded0, !Info, !IO),
+            (
+                BuildDepsSucceeded0 = yes,
+                foldl2_maybe_stop_at_error_maybe_parallel(KeepGoing,
+                    make_module_target, ObjTargets,
+                    BuildDepsSucceeded1, !Info, !IO)
+            ;
+                BuildDepsSucceeded0 = no,
+                BuildDepsSucceeded1 = no
+            ),
+            (
+                BuildDepsSucceeded1 = yes,
+                foldl2_maybe_stop_at_error(KeepGoing, make_module_target,
+                    ForeignObjTargets,
+                    BuildDepsSucceeded, !Info, !IO)
+            ;
+                BuildDepsSucceeded1 = no,
+                BuildDepsSucceeded = no
+            )
         ),
 
         linked_target_file_name(MainModuleName, FileType, OutputFileName, !IO),
@@ -580,25 +591,7 @@
             !Info, !IO)
     ;
         TargetType = misc_target_build_library,
-        ShortInts = make_dependency_list(AllModules,
-            module_target_unqualified_short_interface),
-        LongInts = make_dependency_list(AllModules,
-            module_target_long_interface),
-        globals.io_lookup_bool_option(intermodule_optimization,
-            Intermod, !IO),
-        (
-            Intermod = yes,
-            OptFiles = make_dependency_list(AllModules,
-                module_target_intermodule_interface)
-        ;
-            Intermod = no,
-            OptFiles = []
-        ),
-        globals.io_lookup_bool_option(keep_going, KeepGoing, !IO),
-        foldl2_maybe_stop_at_error(KeepGoing,
-            foldl2_maybe_stop_at_error(KeepGoing, make_module_target),
-            [ShortInts, LongInts, OptFiles],
-            IntSucceeded, !Info, !IO),
+        make_all_interface_files(AllModules, IntSucceeded, !Info, !IO),
         (
             IntSucceeded = yes,
             make_linked_target(
@@ -663,35 +656,78 @@
         )
     ).
 
+%-----------------------------------------------------------------------------%
+
+:- pred make_all_interface_files(list(module_name)::in, bool::out,
+    make_info::in, make_info::out, io::di, io::uo) is det.
+
+make_all_interface_files(AllModules, Succeeded, !Info, !IO) :-
+    ShortInts = make_dependency_list(AllModules,
+        module_target_unqualified_short_interface),
+    LongInts = make_dependency_list(AllModules,
+        module_target_long_interface),
+    globals.io_lookup_bool_option(intermodule_optimization, Intermod, !IO),
+    (
+        Intermod = yes,
+        OptFiles = make_dependency_list(AllModules,
+            module_target_intermodule_interface)
+    ;
+        Intermod = no,
+        OptFiles = []
+    ),
+    globals.io_lookup_bool_option(keep_going, KeepGoing, !IO),
+    foldl2_maybe_stop_at_error(KeepGoing,
+        foldl2_maybe_stop_at_error(KeepGoing, make_module_target),
+        [ShortInts, LongInts, OptFiles],
+        Succeeded, !Info, !IO).
+
+%-----------------------------------------------------------------------------%
+
 :- pred build_analysis_files(module_name::in, list(module_name)::in,
     bool::in, bool::out, make_info::in, make_info::out, io::di, io::uo)
     is det.
 
 build_analysis_files(MainModuleName, AllModules, Succeeded0, Succeeded,
         !Info, !IO) :-
-    get_target_modules(module_target_analysis_registry, AllModules,
-        TargetModules0, !Info, !IO),
     globals.io_lookup_bool_option(keep_going, KeepGoing, !IO),
     ( Succeeded0 = no, KeepGoing = no ->
         Succeeded = no
     ;
-        reverse_ordered_modules(!.Info ^ module_dependencies,
-            TargetModules0, TargetModules1),
-        % Filter out the non-local modules so we don't try to reanalyse them.
-        list.filter((pred(Mod::in) is semidet :- list.member(Mod, AllModules)),
-            TargetModules1, TargetModules),
-        make_local_module_id_options(MainModuleName, Succeeded1,
-            LocalModulesOpts, !Info, !IO),
-        (
-            Succeeded1 = yes,
-            build_analysis_files_2(MainModuleName, TargetModules, 
-                LocalModulesOpts, Succeeded0, Succeeded, !Info, !IO)
-        ;
-            Succeeded1 = no,
+        % Ensure all interface files are present before continuing.  This
+        % prevents a problem when two parallel branches try to generate the
+        % same missing interface file later.
+        %
+        make_all_interface_files(AllModules, Succeeded1, !Info, !IO),
+        ( Succeeded1 = no, KeepGoing = no ->
             Succeeded = no
+        ;
+            build_analysis_files_1(MainModuleName, AllModules,
+                Succeeded, !Info, !IO)
         )
     ).
 
+:- pred build_analysis_files_1(module_name::in, list(module_name)::in,
+    bool::out, make_info::in, make_info::out, io::di, io::uo) is det.
+
+build_analysis_files_1(MainModuleName, AllModules, Succeeded, !Info, !IO) :-
+    get_target_modules(module_target_analysis_registry, AllModules,
+        TargetModules0, !Info, !IO),
+    reverse_ordered_modules(!.Info ^ module_dependencies,
+        TargetModules0, TargetModules1),
+    % Filter out the non-local modules so we don't try to reanalyse them.
+    list.filter((pred(Mod::in) is semidet :- list.member(Mod, AllModules)),
+        TargetModules1, TargetModules),
+    make_local_module_id_options(MainModuleName, Succeeded0,
+        LocalModulesOpts, !Info, !IO),
+    (
+        Succeeded0 = yes,
+        build_analysis_files_2(MainModuleName, TargetModules, 
+            LocalModulesOpts, Succeeded0, Succeeded, !Info, !IO)
+    ;
+        Succeeded0 = no,
+        Succeeded = no
+    ).
+
 :- pred build_analysis_files_2(module_name::in, list(module_name)::in,
     list(string)::in, bool::in, bool::out, make_info::in, make_info::out,
     io::di, io::uo) is det.
@@ -699,7 +735,7 @@
 build_analysis_files_2(MainModuleName, TargetModules, LocalModulesOpts,
         Succeeded0, Succeeded, !Info, !IO) :-
     globals.io_lookup_bool_option(keep_going, KeepGoing, !IO),
-    foldl2_maybe_stop_at_error(KeepGoing,
+    foldl2_maybe_stop_at_error_maybe_parallel(KeepGoing,
         make_module_target_extra_options(LocalModulesOpts),
         make_dependency_list(TargetModules, module_target_analysis_registry),
         Succeeded1, !Info, !IO),
--------------------------------------------------------------------------
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