Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Function call implicitly serializes build #116

Open
cspiel opened this issue Feb 11, 2019 · 0 comments
Open

Function call implicitly serializes build #116

cspiel opened this issue Feb 11, 2019 · 0 comments

Comments

@cspiel
Copy link
Collaborator

cspiel commented Feb 11, 2019

On my 4-way Linux box calling an OMake function in a rule body
serializes an otherwise parallel build. The following OMakefile
reproduces the behavior.

.LANGUAGE: program


iota(n) =
        iter(a, x) =
                if ge(x, n)
                        return a
                else
                        return iter(array(a, x), add(x, 1))
        init[] =
        return iter(init, int(0))


write_script_file(a_filename) =
        fprint(a_filename, $'''#! /bin/sh

sleep 1
cp $1 $2
''')


filenames = addprefix($'a', iota(8))

source_ext = $'.s'
direct_target_ext = $'.d'
procedure_target_ext = $'.p'
function_target_ext = $'.f'

sources = addsuffix(source_ext, filenames)
direct_targets = addsuffix(direct_target_ext, filenames)
procedure_targets = addsuffix(procedure_target_ext, filenames)
function_targets = addsuffix(function_target_ext, filenames)


.LANGUAGE: make


lock_file = lock
script_file = sleep-and-copy.sh
command = flock --no-fork --timeout=0.25 --verbose $(lock_file) /bin/sh $(script_file)


.PHONY: gen
.DEFAULT: gen
gen:
        touch $(sources)
        write_script_file($(script_file))


.PHONY: clean
clean:
        rm -f *$(direct_target_ext)
        rm -f *$(function_target_ext)
        rm -f *$(procedure_target_ext)
        rm -f $(lock_file)


.PHONY: distclean
distclean: clean
        rm -f *$(source_ext)
        rm -f $(script_file)


.PHONY: direct
direct: $(direct_targets)


.PHONY: proc
proc: $(procedure_targets)


.PHONY: func
func: $(function_targets)


##  omake -j1 direct           # Always works ok because of serial execution.
##  omake -j9 direct           # Intentionally fails, which proves the base
                               # case, i.e. the mutex correctly catches for the
                               # tests proper.

%$(direct_target_ext): %$(source_ext)
        $(command) $< $@


f(a_source, a_target) =
        $(command) $(a_source) $(a_target)
        return                 # This `return' statement is necessary to expose
                               # the quirk.  Without it, omake(1) complains
                               # `command not found in PATH: ' when using
                               # function-call syntax (but not procedure-call
                               # syntax).

##  Using procedure-call syntax `function(arg...)' makes the function
##  call *not* interfere with parallelization is expected; it mimics
##  direct execution.
##
##  omake -j1 proc             # Again, always works ok because of serial
##                             # execution.
##  omake -j9 proc             # Fails as expected.

%$(procedure_target_ext): %$(source_ext)
        f($<, $@)              # Respects parallel execution.


##  Using function-call syntax `$(function arg ...)' blocks
##  parallelization.
##
##  omake -j1 func             # Serially builds the targets as its `direct'
##                             # equivalent.
##  omake -j9 func             # Implicitly serializes the build, thus the
                               # build succeeds, where it should fail instead.

%$(function_target_ext): %$(source_ext)
        $(f $<, $@)            # Ignore any returned value from `f'?

To verify a truly parallel command execution at shell level, we call
flock with a command that certainly takes longer than the
timeout of flock. Use omake gen to create a starting
configuration.

Phony target direct evaluates command without any function call
interposed, so if everything is set up correctly

omake -j1 direct

builds all .d files and

omake -j9 direct

fails because the mutex ("lock") cannot be acquired.

Target func does not call command, but function f, which in turn
calls command. Here, both

omake -j1 func

and

omake -j9 func

succeed and build all .f files.

Curiously, in our example, phony target proc, which calls function
f with "procedure call" syntax

f(arg...)

in contrary to "function call" syntax of func

$(f arg...)

duplicates the findings of direct, this is, does not interfere with
parallel execution, as expected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant