summaryrefslogtreecommitdiff
path: root/tools/binman/etype
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2021-07-06 19:36:37 +0300
committerSimon Glass <sjg@chromium.org>2021-07-21 19:27:35 +0300
commitc69d19c8f829d3320db5224f9f28d13cfb16049e (patch)
treec13527b8a6aecf176f48ee6c0f8f657bb4dd303a /tools/binman/etype
parent650ead1a4aac3010a029526d639682096c1d0469 (diff)
downloadu-boot-c69d19c8f829d3320db5224f9f28d13cfb16049e.tar.xz
binman: Support multithreading for building images
Some images may take a while to build, e.g. if they are large and use slow compression. Support compiling sections in parallel to speed things up. Signed-off-by: Simon Glass <sjg@chromium.org> (fixed to use a separate test file to fix flakiness)
Diffstat (limited to 'tools/binman/etype')
-rw-r--r--tools/binman/etype/section.py36
1 files changed, 33 insertions, 3 deletions
diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py
index c3bac026c1..92d3f3add4 100644
--- a/tools/binman/etype/section.py
+++ b/tools/binman/etype/section.py
@@ -9,10 +9,12 @@ images to be created.
"""
from collections import OrderedDict
+import concurrent.futures
import re
import sys
from binman.entry import Entry
+from binman import state
from dtoc import fdt_util
from patman import tools
from patman import tout
@@ -525,15 +527,43 @@ class Entry_section(Entry):
def GetEntryContents(self):
"""Call ObtainContents() for each entry in the section
"""
+ def _CheckDone(entry):
+ if not entry.ObtainContents():
+ next_todo.append(entry)
+ return entry
+
todo = self._entries.values()
for passnum in range(3):
+ threads = state.GetThreads()
next_todo = []
- for entry in todo:
- if not entry.ObtainContents():
- next_todo.append(entry)
+
+ if threads == 0:
+ for entry in todo:
+ _CheckDone(entry)
+ else:
+ with concurrent.futures.ThreadPoolExecutor(
+ max_workers=threads) as executor:
+ future_to_data = {
+ entry: executor.submit(_CheckDone, entry)
+ for entry in todo}
+ timeout = 60
+ if self.GetImage().test_section_timeout:
+ timeout = 0
+ done, not_done = concurrent.futures.wait(
+ future_to_data.values(), timeout=timeout)
+ # Make sure we check the result, so any exceptions are
+ # generated. Check the results in entry order, since tests
+ # may expect earlier entries to fail first.
+ for entry in todo:
+ job = future_to_data[entry]
+ job.result()
+ if not_done:
+ self.Raise('Timed out obtaining contents')
+
todo = next_todo
if not todo:
break
+
if todo:
self.Raise('Internal error: Could not complete processing of contents: remaining %s' %
todo)