diff options
| -rw-r--r-- | bitbake/lib/bb/runqueue.py | 60 | ||||
| -rw-r--r-- | bitbake/lib/bb/tests/runqueue-tests/classes/base.bbclass | 19 | ||||
| -rw-r--r-- | bitbake/lib/bb/tests/runqueue-tests/conf/bitbake.conf | 9 | ||||
| -rw-r--r-- | bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc1.conf | 1 | ||||
| -rw-r--r-- | bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc2.conf | 1 | ||||
| -rw-r--r-- | bitbake/lib/bb/tests/runqueue.py | 19 |
6 files changed, 98 insertions, 11 deletions
diff --git a/bitbake/lib/bb/runqueue.py b/bitbake/lib/bb/runqueue.py index 00c71070d2..fa848326d8 100644 --- a/bitbake/lib/bb/runqueue.py +++ b/bitbake/lib/bb/runqueue.py | |||
| @@ -68,6 +68,14 @@ def build_tid(mc, fn, taskname): | |||
| 68 | return "mc:" + mc + ":" + fn + ":" + taskname | 68 | return "mc:" + mc + ":" + fn + ":" + taskname |
| 69 | return fn + ":" + taskname | 69 | return fn + ":" + taskname |
| 70 | 70 | ||
| 71 | # Index used to pair up potentially matching multiconfig tasks | ||
| 72 | # We match on PN, taskname and hash being equal | ||
| 73 | def pending_hash_index(tid, rqdata): | ||
| 74 | (mc, fn, taskname, taskfn) = split_tid_mcfn(tid) | ||
| 75 | pn = rqdata.dataCaches[mc].pkg_fn[taskfn] | ||
| 76 | h = rqdata.runtaskentries[tid].hash | ||
| 77 | return pn + ":" + "taskname" + h | ||
| 78 | |||
| 71 | class RunQueueStats: | 79 | class RunQueueStats: |
| 72 | """ | 80 | """ |
| 73 | Holds statistics on the tasks handled by the associated runQueue | 81 | Holds statistics on the tasks handled by the associated runQueue |
| @@ -1717,6 +1725,7 @@ class RunQueueExecute: | |||
| 1717 | self.build_stamps = {} | 1725 | self.build_stamps = {} |
| 1718 | self.build_stamps2 = [] | 1726 | self.build_stamps2 = [] |
| 1719 | self.failed_tids = [] | 1727 | self.failed_tids = [] |
| 1728 | self.sq_deferred = {} | ||
| 1720 | 1729 | ||
| 1721 | self.stampcache = {} | 1730 | self.stampcache = {} |
| 1722 | 1731 | ||
| @@ -1921,17 +1930,32 @@ class RunQueueExecute: | |||
| 1921 | # Find the next setscene to run | 1930 | # Find the next setscene to run |
| 1922 | for nexttask in self.rqdata.runq_setscene_tids: | 1931 | for nexttask in self.rqdata.runq_setscene_tids: |
| 1923 | if nexttask in self.sq_buildable and nexttask not in self.sq_running and self.sqdata.stamps[nexttask] not in self.build_stamps.values(): | 1932 | if nexttask in self.sq_buildable and nexttask not in self.sq_running and self.sqdata.stamps[nexttask] not in self.build_stamps.values(): |
| 1924 | if nexttask in self.sqdata.unskippable: | ||
| 1925 | logger.debug(2, "Setscene task %s is unskippable" % nexttask) | ||
| 1926 | if nexttask not in self.sqdata.unskippable and len(self.sqdata.sq_revdeps[nexttask]) > 0 and self.sqdata.sq_revdeps[nexttask].issubset(self.scenequeue_covered) and self.check_dependencies(nexttask, self.sqdata.sq_revdeps[nexttask]): | 1933 | if nexttask not in self.sqdata.unskippable and len(self.sqdata.sq_revdeps[nexttask]) > 0 and self.sqdata.sq_revdeps[nexttask].issubset(self.scenequeue_covered) and self.check_dependencies(nexttask, self.sqdata.sq_revdeps[nexttask]): |
| 1927 | if nexttask not in self.rqdata.target_tids: | 1934 | if nexttask not in self.rqdata.target_tids: |
| 1928 | logger.debug(2, "Skipping setscene for task %s" % nexttask) | 1935 | logger.debug(2, "Skipping setscene for task %s" % nexttask) |
| 1929 | self.sq_task_skip(nexttask) | 1936 | self.sq_task_skip(nexttask) |
| 1930 | self.scenequeue_notneeded.add(nexttask) | 1937 | self.scenequeue_notneeded.add(nexttask) |
| 1938 | if nexttask in self.sq_deferred: | ||
| 1939 | del self.sq_deferred[nexttask] | ||
| 1940 | return True | ||
| 1941 | if nexttask in self.sq_deferred: | ||
| 1942 | if self.sq_deferred[nexttask] not in self.runq_complete: | ||
| 1943 | continue | ||
| 1944 | logger.debug(1, "Task %s no longer deferred" % nexttask) | ||
| 1945 | del self.sq_deferred[nexttask] | ||
| 1946 | valid = self.rq.validate_hashes(set([nexttask]), self.cooker.data, None, False) | ||
| 1947 | if not valid: | ||
| 1948 | logger.debug(1, "%s didn't become valid, skipping setscene" % nexttask) | ||
| 1949 | self.sq_task_failoutright(nexttask) | ||
| 1931 | return True | 1950 | return True |
| 1951 | else: | ||
| 1952 | self.sqdata.outrightfail.remove(nexttask) | ||
| 1932 | if nexttask in self.sqdata.outrightfail: | 1953 | if nexttask in self.sqdata.outrightfail: |
| 1954 | logger.debug(2, 'No package found, so skipping setscene task %s', nexttask) | ||
| 1933 | self.sq_task_failoutright(nexttask) | 1955 | self.sq_task_failoutright(nexttask) |
| 1934 | return True | 1956 | return True |
| 1957 | if nexttask in self.sqdata.unskippable: | ||
| 1958 | logger.debug(2, "Setscene task %s is unskippable" % nexttask) | ||
| 1935 | task = nexttask | 1959 | task = nexttask |
| 1936 | break | 1960 | break |
| 1937 | if task is not None: | 1961 | if task is not None: |
| @@ -1982,7 +2006,7 @@ class RunQueueExecute: | |||
| 1982 | if self.can_start_task(): | 2006 | if self.can_start_task(): |
| 1983 | return True | 2007 | return True |
| 1984 | 2008 | ||
| 1985 | if not self.sq_live and not self.sqdone: | 2009 | if not self.sq_live and not self.sqdone and not self.sq_deferred: |
| 1986 | logger.info("Setscene tasks completed") | 2010 | logger.info("Setscene tasks completed") |
| 1987 | logger.debug(1, 'We could skip tasks %s', "\n".join(sorted(self.scenequeue_covered))) | 2011 | logger.debug(1, 'We could skip tasks %s', "\n".join(sorted(self.scenequeue_covered))) |
| 1988 | 2012 | ||
| @@ -2083,6 +2107,13 @@ class RunQueueExecute: | |||
| 2083 | self.rq.read_workers() | 2107 | self.rq.read_workers() |
| 2084 | return self.rq.active_fds() | 2108 | return self.rq.active_fds() |
| 2085 | 2109 | ||
| 2110 | # No more tasks can be run. If we have deferred setscene tasks we should run them. | ||
| 2111 | if self.sq_deferred: | ||
| 2112 | tid = self.sq_deferred.pop(list(self.sq_deferred.keys())[0]) | ||
| 2113 | logger.warning("Runqeueue deadlocked on deferred tasks, forcing task %s" % tid) | ||
| 2114 | self.sq_task_failoutright(tid) | ||
| 2115 | return True | ||
| 2116 | |||
| 2086 | if len(self.failed_tids) != 0: | 2117 | if len(self.failed_tids) != 0: |
| 2087 | self.rq.state = runQueueFailed | 2118 | self.rq.state = runQueueFailed |
| 2088 | return True | 2119 | return True |
| @@ -2347,7 +2378,7 @@ class SQData(object): | |||
| 2347 | # Setscene tasks directly depended upon by the build | 2378 | # Setscene tasks directly depended upon by the build |
| 2348 | self.unskippable = set() | 2379 | self.unskippable = set() |
| 2349 | # List of setscene tasks which aren't present | 2380 | # List of setscene tasks which aren't present |
| 2350 | self.outrightfail = [] | 2381 | self.outrightfail = set() |
| 2351 | # A list of normal tasks a setscene task covers | 2382 | # A list of normal tasks a setscene task covers |
| 2352 | self.sq_covered_tasks = {} | 2383 | self.sq_covered_tasks = {} |
| 2353 | 2384 | ||
| @@ -2510,7 +2541,9 @@ def build_scenequeue_data(sqdata, rqdata, rq, cooker, stampcache, sqrq): | |||
| 2510 | 2541 | ||
| 2511 | rqdata.init_progress_reporter.next_stage() | 2542 | rqdata.init_progress_reporter.next_stage() |
| 2512 | 2543 | ||
| 2544 | multiconfigs = set() | ||
| 2513 | for tid in sqdata.sq_revdeps: | 2545 | for tid in sqdata.sq_revdeps: |
| 2546 | multiconfigs.add(mc_from_tid(tid)) | ||
| 2514 | if len(sqdata.sq_revdeps[tid]) == 0: | 2547 | if len(sqdata.sq_revdeps[tid]) == 0: |
| 2515 | sqrq.sq_buildable.add(tid) | 2548 | sqrq.sq_buildable.add(tid) |
| 2516 | 2549 | ||
| @@ -2552,10 +2585,21 @@ def build_scenequeue_data(sqdata, rqdata, rq, cooker, stampcache, sqrq): | |||
| 2552 | for v in valid: | 2585 | for v in valid: |
| 2553 | valid_new.append(v) | 2586 | valid_new.append(v) |
| 2554 | 2587 | ||
| 2555 | for tid in sqdata.sq_revdeps: | 2588 | hashes = {} |
| 2556 | if tid not in valid_new and tid not in noexec: | 2589 | for mc in sorted(multiconfigs): |
| 2557 | logger.debug(2, 'No package found, so skipping setscene task %s', tid) | 2590 | for tid in sqdata.sq_revdeps: |
| 2558 | sqdata.outrightfail.append(tid) | 2591 | if mc_from_tid(tid) != mc: |
| 2592 | continue | ||
| 2593 | if tid not in valid_new and tid not in noexec and tid not in sqrq.scenequeue_notcovered: | ||
| 2594 | sqdata.outrightfail.add(tid) | ||
| 2595 | |||
| 2596 | h = pending_hash_index(tid, rqdata) | ||
| 2597 | if h not in hashes: | ||
| 2598 | hashes[h] = tid | ||
| 2599 | else: | ||
| 2600 | sqrq.sq_deferred[tid] = hashes[h] | ||
| 2601 | bb.warn("Deferring %s after %s" % (tid, hashes[h])) | ||
| 2602 | |||
| 2559 | 2603 | ||
| 2560 | class TaskFailure(Exception): | 2604 | class TaskFailure(Exception): |
| 2561 | """ | 2605 | """ |
diff --git a/bitbake/lib/bb/tests/runqueue-tests/classes/base.bbclass b/bitbake/lib/bb/tests/runqueue-tests/classes/base.bbclass index e174c02dd6..cf38d09224 100644 --- a/bitbake/lib/bb/tests/runqueue-tests/classes/base.bbclass +++ b/bitbake/lib/bb/tests/runqueue-tests/classes/base.bbclass | |||
| @@ -4,7 +4,9 @@ SSTATEVALID ??= "" | |||
| 4 | def stamptask(d): | 4 | def stamptask(d): |
| 5 | import time | 5 | import time |
| 6 | 6 | ||
| 7 | thistask = d.expand("${PN}:${BB_CURRENTTASK}") | 7 | thistask = d.expand("${PN}:${BB_CURRENTTASK}") |
| 8 | if d.getVar("BB_CURRENT_MC") != "default": | ||
| 9 | thistask = d.expand("${BB_CURRENT_MC}:${PN}:${BB_CURRENTTASK}") | ||
| 8 | if thistask in d.getVar("SLOWTASKS").split(): | 10 | if thistask in d.getVar("SLOWTASKS").split(): |
| 9 | bb.note("Slowing task %s" % thistask) | 11 | bb.note("Slowing task %s" % thistask) |
| 10 | time.sleep(0.5) | 12 | time.sleep(0.5) |
| @@ -13,48 +15,63 @@ def stamptask(d): | |||
| 13 | f.write(thistask + "\n") | 15 | f.write(thistask + "\n") |
| 14 | 16 | ||
| 15 | python do_fetch() { | 17 | python do_fetch() { |
| 18 | # fetch | ||
| 16 | stamptask(d) | 19 | stamptask(d) |
| 17 | } | 20 | } |
| 18 | python do_unpack() { | 21 | python do_unpack() { |
| 22 | # unpack | ||
| 19 | stamptask(d) | 23 | stamptask(d) |
| 20 | } | 24 | } |
| 21 | python do_patch() { | 25 | python do_patch() { |
| 26 | # patch | ||
| 22 | stamptask(d) | 27 | stamptask(d) |
| 23 | } | 28 | } |
| 24 | python do_populate_lic() { | 29 | python do_populate_lic() { |
| 30 | # populate_lic | ||
| 25 | stamptask(d) | 31 | stamptask(d) |
| 26 | } | 32 | } |
| 27 | python do_prepare_recipe_sysroot() { | 33 | python do_prepare_recipe_sysroot() { |
| 34 | # prepare_recipe_sysroot | ||
| 28 | stamptask(d) | 35 | stamptask(d) |
| 29 | } | 36 | } |
| 30 | python do_configure() { | 37 | python do_configure() { |
| 38 | # configure | ||
| 31 | stamptask(d) | 39 | stamptask(d) |
| 32 | } | 40 | } |
| 33 | python do_compile() { | 41 | python do_compile() { |
| 42 | # compile | ||
| 34 | stamptask(d) | 43 | stamptask(d) |
| 35 | } | 44 | } |
| 36 | python do_install() { | 45 | python do_install() { |
| 46 | # install | ||
| 37 | stamptask(d) | 47 | stamptask(d) |
| 38 | } | 48 | } |
| 39 | python do_populate_sysroot() { | 49 | python do_populate_sysroot() { |
| 50 | # populate_sysroot | ||
| 40 | stamptask(d) | 51 | stamptask(d) |
| 41 | } | 52 | } |
| 42 | python do_package() { | 53 | python do_package() { |
| 54 | # package | ||
| 43 | stamptask(d) | 55 | stamptask(d) |
| 44 | } | 56 | } |
| 45 | python do_package_write_ipk() { | 57 | python do_package_write_ipk() { |
| 58 | # package_write_ipk | ||
| 46 | stamptask(d) | 59 | stamptask(d) |
| 47 | } | 60 | } |
| 48 | python do_package_write_rpm() { | 61 | python do_package_write_rpm() { |
| 62 | # package_write_rpm | ||
| 49 | stamptask(d) | 63 | stamptask(d) |
| 50 | } | 64 | } |
| 51 | python do_packagedata() { | 65 | python do_packagedata() { |
| 66 | # packagedata | ||
| 52 | stamptask(d) | 67 | stamptask(d) |
| 53 | } | 68 | } |
| 54 | python do_package_qa() { | 69 | python do_package_qa() { |
| 70 | # package_qa | ||
| 55 | stamptask(d) | 71 | stamptask(d) |
| 56 | } | 72 | } |
| 57 | python do_build() { | 73 | python do_build() { |
| 74 | # build | ||
| 58 | stamptask(d) | 75 | stamptask(d) |
| 59 | } | 76 | } |
| 60 | do_prepare_recipe_sysroot[deptask] = "do_populate_sysroot" | 77 | do_prepare_recipe_sysroot[deptask] = "do_populate_sysroot" |
diff --git a/bitbake/lib/bb/tests/runqueue-tests/conf/bitbake.conf b/bitbake/lib/bb/tests/runqueue-tests/conf/bitbake.conf index 8c7b754dab..96ee1cd5ec 100644 --- a/bitbake/lib/bb/tests/runqueue-tests/conf/bitbake.conf +++ b/bitbake/lib/bb/tests/runqueue-tests/conf/bitbake.conf | |||
| @@ -6,6 +6,11 @@ PROVIDES = "${PN}" | |||
| 6 | PN = "${@bb.parse.vars_from_file(d.getVar('FILE', False),d)[0]}" | 6 | PN = "${@bb.parse.vars_from_file(d.getVar('FILE', False),d)[0]}" |
| 7 | PF = "${BB_CURRENT_MC}:${PN}" | 7 | PF = "${BB_CURRENT_MC}:${PN}" |
| 8 | export PATH | 8 | export PATH |
| 9 | STAMP = "${TOPDIR}/stamps/${PN}" | 9 | TMPDIR ??= "${TOPDIR}" |
| 10 | T = "${TOPDIR}/workdir/${PN}/temp" | 10 | STAMP = "${TMPDIR}/stamps/${PN}" |
| 11 | T = "${TMPDIR}/workdir/${PN}/temp" | ||
| 11 | BB_NUMBER_THREADS = "4" | 12 | BB_NUMBER_THREADS = "4" |
| 13 | |||
| 14 | BB_HASHBASE_WHITELIST = "BB_CURRENT_MC" | ||
| 15 | |||
| 16 | include conf/multiconfig/${BB_CURRENT_MC}.conf | ||
diff --git a/bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc1.conf b/bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc1.conf new file mode 100644 index 0000000000..ecf23e1c73 --- /dev/null +++ b/bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc1.conf | |||
| @@ -0,0 +1 @@ | |||
| TMPDIR = "${TOPDIR}/mc1/" | |||
diff --git a/bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc2.conf b/bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc2.conf new file mode 100644 index 0000000000..eef338e4cc --- /dev/null +++ b/bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc2.conf | |||
| @@ -0,0 +1 @@ | |||
| TMPDIR = "${TOPDIR}/mc2/" | |||
diff --git a/bitbake/lib/bb/tests/runqueue.py b/bitbake/lib/bb/tests/runqueue.py index 4a65b5b6e7..f0cea6483f 100644 --- a/bitbake/lib/bb/tests/runqueue.py +++ b/bitbake/lib/bb/tests/runqueue.py | |||
| @@ -198,3 +198,22 @@ class RunQueueTests(unittest.TestCase): | |||
| 198 | 'b1:packagedata_setscene', 'b1:package_qa_setscene', 'b1:populate_sysroot_setscene'] | 198 | 'b1:packagedata_setscene', 'b1:package_qa_setscene', 'b1:populate_sysroot_setscene'] |
| 199 | self.assertEqual(set(tasks), set(expected)) | 199 | self.assertEqual(set(tasks), set(expected)) |
| 200 | 200 | ||
| 201 | def test_multiconfig_setscene_optimise(self): | ||
| 202 | with tempfile.TemporaryDirectory(prefix="runqueuetest") as tempdir: | ||
| 203 | extraenv = { | ||
| 204 | "BBMULTICONFIG" : "mc1 mc2", | ||
| 205 | "BB_SIGNATURE_HANDLER" : "basic" | ||
| 206 | } | ||
| 207 | cmd = ["bitbake", "b1", "mc:mc1:b1", "mc:mc2:b1"] | ||
| 208 | setscenetasks = ['package_write_ipk_setscene', 'package_write_rpm_setscene', 'packagedata_setscene', | ||
| 209 | 'populate_sysroot_setscene', 'package_qa_setscene'] | ||
| 210 | sstatevalid = "" | ||
| 211 | tasks = self.run_bitbakecmd(cmd, tempdir, sstatevalid, extraenv=extraenv) | ||
| 212 | expected = ['a1:' + x for x in self.alltasks] + ['b1:' + x for x in self.alltasks] + \ | ||
| 213 | ['mc1:b1:' + x for x in setscenetasks] + ['mc1:a1:' + x for x in setscenetasks] + \ | ||
| 214 | ['mc2:b1:' + x for x in setscenetasks] + ['mc2:a1:' + x for x in setscenetasks] + \ | ||
| 215 | ['mc1:b1:build', 'mc2:b1:build'] | ||
| 216 | for x in ['mc1:a1:package_qa_setscene', 'mc2:a1:package_qa_setscene', 'a1:build', 'a1:package_qa']: | ||
| 217 | expected.remove(x) | ||
| 218 | self.assertEqual(set(tasks), set(expected)) | ||
| 219 | |||
