From: "Bob Feng" <bob.c.feng@intel.com>
To: devel@edk2.groups.io
Cc: Liming Gao <liming.gao@intel.com>, Bob Feng <bob.c.feng@intel.com>
Subject: [Patch 11/11] BaseTools: Enhance Multiple-Process AutoGen
Date: Mon, 29 Jul 2019 16:44:56 +0800 [thread overview]
Message-ID: <20190729084456.18844-12-bob.c.feng@intel.com> (raw)
In-Reply-To: <20190729084456.18844-1-bob.c.feng@intel.com>
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1875
1. Set Log queue maxsize as thread number * 10
2. enhance ModuleUniqueBaseName function
3. fix bugs of build option pcd in sub Process
4. enhance error handling
5. fix bug in the function of duplicate modules handling.
Cc: Liming Gao <liming.gao@intel.com>
Signed-off-by: Bob Feng <bob.c.feng@intel.com>
---
.../Source/Python/AutoGen/AutoGenWorker.py | 55 +++++++++--
BaseTools/Source/Python/AutoGen/DataPipe.py | 11 ++-
.../Python/AutoGen/ModuleAutoGenHelper.py | 9 +-
.../Source/Python/AutoGen/PlatformAutoGen.py | 49 +++++++---
.../Source/Python/AutoGen/WorkspaceAutoGen.py | 2 +
BaseTools/Source/Python/build/build.py | 95 ++++++++++---------
6 files changed, 148 insertions(+), 73 deletions(-)
diff --git a/BaseTools/Source/Python/AutoGen/AutoGenWorker.py b/BaseTools/Source/Python/AutoGen/AutoGenWorker.py
index d1c55cffa8d0..de6a17396e12 100644
--- a/BaseTools/Source/Python/AutoGen/AutoGenWorker.py
+++ b/BaseTools/Source/Python/AutoGen/AutoGenWorker.py
@@ -14,20 +14,24 @@ import Common.GlobalData as GlobalData
import Common.EdkLogger as EdkLogger
import os
from Common.MultipleWorkspace import MultipleWorkspace as mws
from AutoGen.AutoGen import AutoGen
from Workspace.WorkspaceDatabase import BuildDB
-import time
+
try:
from queue import Empty
except:
from Queue import Empty
import traceback
import sys
from AutoGen.DataPipe import MemoryDataPipe
import logging
+def clearQ(q):
+ while not q.empty():
+ q.get_nowait()
+
class LogAgent(threading.Thread):
def __init__(self,log_q,log_level,log_file=None):
super(LogAgent,self).__init__()
self.log_q = log_q
self.log_level = log_level
@@ -88,45 +92,58 @@ class LogAgent(threading.Thread):
self._InfoLogger_agent.log(log_message.levelno,log_message.getMessage())
def kill(self):
self.log_q.put(None)
class AutoGenManager(threading.Thread):
- def __init__(self,autogen_workers, feedback_q):
+ def __init__(self,autogen_workers, feedback_q,error_event):
super(AutoGenManager,self).__init__()
self.autogen_workers = autogen_workers
self.feedback_q = feedback_q
self.Status = True
+ self.error_event = error_event
def run(self):
try:
+ fin_num = 0
while True:
badnews = self.feedback_q.get()
if badnews is None:
+ break
+ if badnews == "Done":
+ fin_num += 1
+ else:
self.Status = False
self.TerminateWorkers()
+ if fin_num == len(self.autogen_workers):
+ self.clearQueue()
+ for w in self.autogen_workers:
+ w.join()
break
except Exception:
return
- def kill(self):
- self.feedback_q.put(None)
-
+ def clearQueue(self):
+ taskq = self.autogen_workers[0].module_queue
+ logq = self.autogen_workers[0].log_q
+ clearQ(taskq)
+ clearQ(self.feedback_q)
+ clearQ(logq)
def TerminateWorkers(self):
- for w in self.autogen_workers:
- if w.is_alive():
- w.terminate()
-
+ self.error_event.set()
+ def kill(self):
+ self.feedback_q.put(None)
class AutoGenWorkerInProcess(mp.Process):
- def __init__(self,module_queue,data_pipe_file_path,feedback_q,file_lock, share_data,log_q):
+ def __init__(self,module_queue,data_pipe_file_path,feedback_q,file_lock, share_data,log_q,error_event):
mp.Process.__init__(self)
self.module_queue = module_queue
self.data_pipe_file_path =data_pipe_file_path
self.data_pipe = None
self.feedback_q = feedback_q
self.PlatformMetaFileSet = {}
self.file_lock = file_lock
self.share_data = share_data
self.log_q = log_q
+ self.error_event = error_event
def GetPlatformMetaFile(self,filepath,root):
try:
return self.PlatformMetaFileSet[(filepath,root)]
except:
self.PlatformMetaFileSet[(filepath,root)] = filepath
@@ -161,17 +178,28 @@ class AutoGenWorkerInProcess(mp.Process):
os.environ._data = self.data_pipe.Get("Env_Var")
GlobalData.gWorkspace = workspacedir
GlobalData.gDisableIncludePathCheck = False
GlobalData.gFdfParser = self.data_pipe.Get("FdfParser")
GlobalData.gDatabasePath = self.data_pipe.Get("DatabasePath")
+ pcd_from_build_option = []
+ for pcd_tuple in self.data_pipe.Get("BuildOptPcd"):
+ pcd_id = ".".join((pcd_tuple[0],pcd_tuple[1]))
+ if pcd_tuple[2].strip():
+ pcd_id = ".".join((pcd_id,pcd_tuple[2]))
+ pcd_from_build_option.append("=".join((pcd_id,pcd_tuple[3])))
+ GlobalData.BuildOptionPcd = pcd_from_build_option
module_count = 0
FfsCmd = self.data_pipe.Get("FfsCommand")
if FfsCmd is None:
FfsCmd = {}
PlatformMetaFile = self.GetPlatformMetaFile(self.data_pipe.Get("P_Info").get("ActivePlatform"),
self.data_pipe.Get("P_Info").get("WorkspaceDir"))
+ libConstPcd = self.data_pipe.Get("LibConstPcd")
+ Refes = self.data_pipe.Get("REFS")
while not self.module_queue.empty():
+ if self.error_event.is_set():
+ break
module_count += 1
module_file,module_root,module_path,module_basename,module_originalpath,module_arch,IsLib = self.module_queue.get()
modulefullpath = os.path.join(module_root,module_file)
taskname = " : ".join((modulefullpath,module_arch))
module_metafile = PathClass(module_file,module_root)
@@ -184,18 +212,25 @@ class AutoGenWorkerInProcess(mp.Process):
arch = module_arch
target = self.data_pipe.Get("P_Info").get("Target")
toolchain = self.data_pipe.Get("P_Info").get("ToolChain")
Ma = ModuleAutoGen(self.Wa,module_metafile,target,toolchain,arch,PlatformMetaFile,self.data_pipe)
Ma.IsLibrary = IsLib
+ if IsLib:
+ if (Ma.MetaFile.File,Ma.MetaFile.Root,Ma.Arch,Ma.MetaFile.Path) in libConstPcd:
+ Ma.ConstPcd = libConstPcd[(Ma.MetaFile.File,Ma.MetaFile.Root,Ma.Arch,Ma.MetaFile.Path)]
+ if (Ma.MetaFile.File,Ma.MetaFile.Root,Ma.Arch,Ma.MetaFile.Path) in Refes:
+ Ma.ReferenceModules = Refes[(Ma.MetaFile.File,Ma.MetaFile.Root,Ma.Arch,Ma.MetaFile.Path)]
Ma.CreateCodeFile()
Ma.CreateMakeFile(GenFfsList=FfsCmd.get((Ma.MetaFile.File, Ma.Arch),[]))
Ma.CreateAsBuiltInf()
except Empty:
pass
except:
traceback.print_exc(file=sys.stdout)
self.feedback_q.put(taskname)
+ finally:
+ self.feedback_q.put("Done")
def printStatus(self):
print("Processs ID: %d Run %d modules in AutoGen " % (os.getpid(),len(AutoGen.Cache())))
print("Processs ID: %d Run %d modules in AutoGenInfo " % (os.getpid(),len(AutoGenInfo.GetCache())))
groupobj = {}
diff --git a/BaseTools/Source/Python/AutoGen/DataPipe.py b/BaseTools/Source/Python/AutoGen/DataPipe.py
index 33d2b14c9add..2052084bdb4b 100644
--- a/BaseTools/Source/Python/AutoGen/DataPipe.py
+++ b/BaseTools/Source/Python/AutoGen/DataPipe.py
@@ -72,11 +72,11 @@ class MemoryDataPipe(DataPipe):
#Platform Module Pcds
ModulePcds = {}
for m in PlatformInfo.Platform.Modules:
m_pcds = PlatformInfo.Platform.Modules[m].Pcds
if m_pcds:
- ModulePcds[(m.File,m.Root)] = [PCD_DATA(
+ ModulePcds[(m.File,m.Root,m.Arch)] = [PCD_DATA(
pcd.TokenCName,pcd.TokenSpaceGuidCName,pcd.Type,
pcd.DatumType,pcd.SkuInfoList,pcd.DefaultValue,
pcd.MaxDatumSize,pcd.UserDefinedDefaultStoresFlag,pcd.validateranges,
pcd.validlists,pcd.expressions,pcd.CustomAttribute,pcd.TokenValue)
for pcd in PlatformInfo.Platform.Modules[m].Pcds.values()]
@@ -84,15 +84,22 @@ class MemoryDataPipe(DataPipe):
self.DataContainer = {"MOL_PCDS":ModulePcds}
#Module's Library Instance
ModuleLibs = {}
+ libModules = {}
for m in PlatformInfo.Platform.Modules:
module_obj = BuildDB.BuildObject[m,PlatformInfo.Arch,PlatformInfo.BuildTarget,PlatformInfo.ToolChain]
Libs = GetModuleLibInstances(module_obj, PlatformInfo.Platform, BuildDB.BuildObject, PlatformInfo.Arch,PlatformInfo.BuildTarget,PlatformInfo.ToolChain)
- ModuleLibs[(m.File,m.Root,module_obj.Arch)] = [(l.MetaFile.File,l.MetaFile.Root,l.Arch) for l in Libs]
+ for lib in Libs:
+ try:
+ libModules[(lib.MetaFile.File,lib.MetaFile.Root,lib.Arch,lib.MetaFile.Path)].append((m.File,m.Root,module_obj.Arch,m.Path))
+ except:
+ libModules[(lib.MetaFile.File,lib.MetaFile.Root,lib.Arch,lib.MetaFile.Path)] = [(m.File,m.Root,module_obj.Arch,m.Path)]
+ ModuleLibs[(m.File,m.Root,module_obj.Arch,m.Path)] = [(l.MetaFile.File,l.MetaFile.Root,l.Arch,l.MetaFile.Path) for l in Libs]
self.DataContainer = {"DEPS":ModuleLibs}
+ self.DataContainer = {"REFS":libModules}
#Platform BuildOptions
platform_build_opt = PlatformInfo.EdkIIBuildOption
diff --git a/BaseTools/Source/Python/AutoGen/ModuleAutoGenHelper.py b/BaseTools/Source/Python/AutoGen/ModuleAutoGenHelper.py
index 5186ca1da3e3..c7591253debd 100644
--- a/BaseTools/Source/Python/AutoGen/ModuleAutoGenHelper.py
+++ b/BaseTools/Source/Python/AutoGen/ModuleAutoGenHelper.py
@@ -595,14 +595,17 @@ class PlatformInfo(AutoGenInfo):
def ApplyLibraryInstance(self,module):
alldeps = self.DataPipe.Get("DEPS")
if alldeps is None:
alldeps = {}
- mod_libs = alldeps.get((module.MetaFile.File,module.MetaFile.Root,module.Arch),[])
+ mod_libs = alldeps.get((module.MetaFile.File,module.MetaFile.Root,module.Arch,module.MetaFile.Path),[])
retVal = []
- for (file_path,root,arch) in mod_libs:
- retVal.append(self.Wa.BuildDatabase[PathClass(file_path,root), arch, self.Target,self.ToolChain])
+ for (file_path,root,arch,abs_path) in mod_libs:
+ libMetaFile = PathClass(file_path,root)
+ libMetaFile.OriginalPath = PathClass(file_path,root)
+ libMetaFile.Path = abs_path
+ retVal.append(self.Wa.BuildDatabase[libMetaFile, arch, self.Target,self.ToolChain])
return retVal
## Parse build_rule.txt in Conf Directory.
#
# @retval BuildRule object
diff --git a/BaseTools/Source/Python/AutoGen/PlatformAutoGen.py b/BaseTools/Source/Python/AutoGen/PlatformAutoGen.py
index 9885c6a3a3bf..2a614e6a7134 100644
--- a/BaseTools/Source/Python/AutoGen/PlatformAutoGen.py
+++ b/BaseTools/Source/Python/AutoGen/PlatformAutoGen.py
@@ -131,10 +131,16 @@ class PlatformAutoGen(AutoGen):
self.DataPipe = MemoryDataPipe(self.BuildDir)
self.DataPipe.FillData(self)
return True
+ def FillData_LibConstPcd(self):
+ libConstPcd = {}
+ for LibAuto in self.LibraryAutoGenList:
+ if LibAuto.ConstPcd:
+ libConstPcd[(LibAuto.MetaFile.File,LibAuto.MetaFile.Root,LibAuto.Arch,LibAuto.MetaFile.Path)] = LibAuto.ConstPcd
+ self.DataPipe.DataContainer = {"LibConstPcd":libConstPcd}
## hash() operator of PlatformAutoGen
#
# The platform file path and arch string will be used to represent
# hash value of this object
#
@@ -1080,11 +1086,14 @@ class PlatformAutoGen(AutoGen):
@cached_property
def GetAllModuleInfo(self,WithoutPcd=True):
ModuleLibs = set()
for m in self.Platform.Modules:
module_obj = self.BuildDatabase[m,self.Arch,self.BuildTarget,self.ToolChain]
- Libs = GetModuleLibInstances(module_obj, self.Platform, self.BuildDatabase, self.Arch,self.BuildTarget,self.ToolChain)
+ if not bool(module_obj.LibraryClass):
+ Libs = GetModuleLibInstances(module_obj, self.Platform, self.BuildDatabase, self.Arch,self.BuildTarget,self.ToolChain)
+ else:
+ Libs = []
ModuleLibs.update( set([(l.MetaFile.File,l.MetaFile.Root,l.MetaFile.Path,l.MetaFile.BaseName,l.MetaFile.OriginalPath,l.Arch,True) for l in Libs]))
if WithoutPcd and module_obj.PcdIsDriver:
continue
ModuleLibs.add((m.File,m.Root,m.Path,m.BaseName,m.OriginalPath,module_obj.Arch,bool(module_obj.LibraryClass)))
@@ -1335,29 +1344,39 @@ class PlatformAutoGen(AutoGen):
else:
PlatformModuleOptions = {}
return ModuleTypeOptions,PlatformModuleOptions
+ def ModuleGuid(self,Module):
+ if os.path.basename(Module.MetaFile.File) != os.path.basename(Module.MetaFile.Path):
+ #
+ # Length of GUID is 36
+ #
+ return os.path.basename(Module.MetaFile.Path)[:36]
+ return Module.Guid
@cached_property
def UniqueBaseName(self):
retVal ={}
- name_path_map = {}
+ ModuleNameDict = {}
+ UniqueName = {}
for Module in self._MbList:
- name_path_map[Module.BaseName] = set()
- for Module in self._MbList:
- name_path_map[Module.BaseName].add(Module.MetaFile)
- for name in name_path_map:
- if len(name_path_map[name]) > 1:
- guidset = set()
- for metafile in name_path_map[name]:
- m = self.BuildDatabase[metafile, self.Arch, self.BuildTarget, self.ToolChain]
- retVal[name] = '%s_%s' % (name, m.Guid)
- guidset.add(m.Guid)
- samemodules = list(name_path_map[name])
- if len(guidset) > 1:
- EdkLogger.error("build", FILE_DUPLICATED, 'Modules have same BaseName and FILE_GUID:\n'
+ unique_base_name = '%s_%s' % (Module.BaseName,self.ModuleGuid(Module))
+ if unique_base_name not in ModuleNameDict:
+ ModuleNameDict[unique_base_name] = []
+ ModuleNameDict[unique_base_name].append(Module.MetaFile)
+ if Module.BaseName not in UniqueName:
+ UniqueName[Module.BaseName] = set()
+ UniqueName[Module.BaseName].add((self.ModuleGuid(Module),Module.MetaFile))
+ for module_paths in ModuleNameDict.values():
+ if len(module_paths) > 1 and len(set(module_paths))>1:
+ samemodules = list(set(module_paths))
+ EdkLogger.error("build", FILE_DUPLICATED, 'Modules have same BaseName and FILE_GUID:\n'
' %s\n %s' % (samemodules[0], samemodules[1]))
+ for name in UniqueName:
+ Guid_Path = UniqueName[name]
+ if len(Guid_Path) > 1:
+ retVal[name] = '%s_%s' % (name,Guid_Path.pop()[0])
return retVal
## Expand * in build option key
#
# @param Options Options to be expanded
# @param ToolDef Use specified ToolDef instead of full version.
diff --git a/BaseTools/Source/Python/AutoGen/WorkspaceAutoGen.py b/BaseTools/Source/Python/AutoGen/WorkspaceAutoGen.py
index ab58b21772c3..4ad92653a238 100644
--- a/BaseTools/Source/Python/AutoGen/WorkspaceAutoGen.py
+++ b/BaseTools/Source/Python/AutoGen/WorkspaceAutoGen.py
@@ -111,10 +111,12 @@ class WorkspaceAutoGen(AutoGen):
self.ProcessModuleFromPdf()
self.ProcessPcdType()
self.ProcessMixedPcd()
self.VerifyPcdsFromFDF()
self.CollectAllPcds()
+ for Pa in self.AutoGenObjectList:
+ Pa.FillData_LibConstPcd()
self.GeneratePkgLevelHash()
#
# Check PCDs token value conflict in each DEC file.
#
self._CheckAllPcdsTokenValueConflict()
diff --git a/BaseTools/Source/Python/build/build.py b/BaseTools/Source/Python/build/build.py
index 603d3aa6dad4..dc92495f3f08 100644
--- a/BaseTools/Source/Python/build/build.py
+++ b/BaseTools/Source/Python/build/build.py
@@ -707,11 +707,11 @@ class Build():
self.Fdf = BuildOptions.FdfFile
self.FdList = BuildOptions.RomImage
self.FvList = BuildOptions.FvImage
self.CapList = BuildOptions.CapName
self.SilentMode = BuildOptions.SilentMode
- self.ThreadNumber = BuildOptions.ThreadNumber
+ self.ThreadNumber = 1
self.SkipAutoGen = BuildOptions.SkipAutoGen
self.Reparse = BuildOptions.Reparse
self.SkuId = BuildOptions.SkuId
if self.SkuId:
GlobalData.gSKUID_CMD = self.SkuId
@@ -812,31 +812,32 @@ class Build():
EdkLogger.info("")
os.chdir(self.WorkspaceDir)
self.share_data = Manager().dict()
self.log_q = log_q
def StartAutoGen(self,mqueue, DataPipe,SkipAutoGen,PcdMaList,share_data):
- if SkipAutoGen:
- return
- feedback_q = mp.Queue()
- file_lock = mp.Lock()
- auto_workers = [AutoGenWorkerInProcess(mqueue,DataPipe.dump_file,feedback_q,file_lock,share_data,self.log_q) for _ in range(self.ThreadNumber)]
- self.AutoGenMgr = AutoGenManager(auto_workers,feedback_q)
- self.AutoGenMgr.start()
- for w in auto_workers:
- w.start()
- if PcdMaList is not None:
- for PcdMa in PcdMaList:
- PcdMa.CreateCodeFile(True)
- PcdMa.CreateMakeFile(GenFfsList = DataPipe.Get("FfsCommand").get((PcdMa.MetaFile.File, PcdMa.Arch),[]))
- PcdMa.CreateAsBuiltInf()
- for w in auto_workers:
- w.join()
- rt = self.AutoGenMgr.Status
- self.AutoGenMgr.kill()
- self.AutoGenMgr.join()
- self.AutoGenMgr = None
- return rt
+ try:
+ if SkipAutoGen:
+ return True,0
+ feedback_q = mp.Queue()
+ file_lock = mp.Lock()
+ error_event = mp.Event()
+ auto_workers = [AutoGenWorkerInProcess(mqueue,DataPipe.dump_file,feedback_q,file_lock,share_data,self.log_q,error_event) for _ in range(self.ThreadNumber)]
+ self.AutoGenMgr = AutoGenManager(auto_workers,feedback_q,error_event)
+ self.AutoGenMgr.start()
+ for w in auto_workers:
+ w.start()
+ if PcdMaList is not None:
+ for PcdMa in PcdMaList:
+ PcdMa.CreateCodeFile(True)
+ PcdMa.CreateMakeFile(GenFfsList = DataPipe.Get("FfsCommand").get((PcdMa.MetaFile.File, PcdMa.Arch),[]))
+ PcdMa.CreateAsBuiltInf()
+
+ self.AutoGenMgr.join()
+ rt = self.AutoGenMgr.Status
+ return rt, 0
+ except Exception as e:
+ return False,e.errcode
## Load configuration
#
# This method will parse target.txt and get the build configurations.
#
@@ -880,23 +881,10 @@ class Build():
ToolChainFamily.append(TAB_COMPILER_MSFT)
else:
ToolChainFamily.append(ToolDefinition[TAB_TOD_DEFINES_FAMILY][Tool])
self.ToolChainFamily = ToolChainFamily
- if self.ThreadNumber is None:
- self.ThreadNumber = self.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_MAX_CONCURRENT_THREAD_NUMBER]
- if self.ThreadNumber == '':
- self.ThreadNumber = 0
- else:
- self.ThreadNumber = int(self.ThreadNumber, 0)
-
- if self.ThreadNumber == 0:
- try:
- self.ThreadNumber = multiprocessing.cpu_count()
- except (ImportError, NotImplementedError):
- self.ThreadNumber = 1
-
if not self.PlatformFile:
PlatformFile = self.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_ACTIVE_PLATFORM]
if not PlatformFile:
# Try to find one in current directory
WorkingDirectory = os.getcwd()
@@ -911,10 +899,11 @@ class Build():
EdkLogger.error("build", RESOURCE_NOT_AVAILABLE,
ExtraData="No active platform specified in target.txt or command line! Nothing can be built.\n")
self.PlatformFile = PathClass(NormFile(PlatformFile, self.WorkspaceDir), self.WorkspaceDir)
+ self.ThreadNumber = ThreadNum()
## Initialize build configuration
#
# This method will parse DSC file and merge the configurations from
# command line and target.txt, then get the final build configurations.
#
@@ -1213,12 +1202,16 @@ class Build():
AutoGenObject.DataPipe.DataContainer = {"FfsCommand":FfsCommand}
self.Progress.Start("Generating makefile and code")
data_pipe_file = os.path.join(AutoGenObject.BuildDir, "GlobalVar_%s_%s.bin" % (str(AutoGenObject.Guid),AutoGenObject.Arch))
AutoGenObject.DataPipe.dump(data_pipe_file)
- autogen_rt = self.StartAutoGen(mqueue, AutoGenObject.DataPipe, self.SkipAutoGen, PcdMaList,self.share_data)
+ autogen_rt,errorcode = self.StartAutoGen(mqueue, AutoGenObject.DataPipe, self.SkipAutoGen, PcdMaList,self.share_data)
self.Progress.Stop("done!")
+ if not autogen_rt:
+ self.AutoGenMgr.TerminateWorkers()
+ self.AutoGenMgr.join(0.1)
+ raise FatalError(errorcode)
return autogen_rt
else:
# always recreate top/platform makefile when clean, just in case of inconsistency
AutoGenObject.CreateCodeFile(False)
AutoGenObject.CreateMakeFile(False)
@@ -1717,10 +1710,11 @@ class Build():
Ma = ModuleAutoGen(Wa, Module, BuildTarget, ToolChain, Arch, self.PlatformFile,Pa.DataPipe)
if Ma is None:
continue
if Ma.PcdIsDriver:
Ma.PlatformInfo = Pa
+ Ma.Workspace = Wa
PcdMaList.append(Ma)
self.BuildModules.append(Ma)
self._BuildPa(self.Target, Pa, FfsCommand=CmdListDict,PcdMaList=PcdMaList)
# Create MAP file when Load Fix Address is enabled.
@@ -2045,14 +2039,15 @@ class Build():
mqueue = mp.Queue()
for m in Pa.GetAllModuleInfo:
mqueue.put(m)
data_pipe_file = os.path.join(Pa.BuildDir, "GlobalVar_%s_%s.bin" % (str(Pa.Guid),Pa.Arch))
Pa.DataPipe.dump(data_pipe_file)
- autogen_rt = self.StartAutoGen(mqueue, Pa.DataPipe, self.SkipAutoGen, PcdMaList,self.share_data)
-
+ autogen_rt, errorcode = self.StartAutoGen(mqueue, Pa.DataPipe, self.SkipAutoGen, PcdMaList,self.share_data)
if not autogen_rt:
- return
+ self.AutoGenMgr.TerminateWorkers()
+ self.AutoGenMgr.join(0.1)
+ raise FatalError(errorcode)
self.AutoGenTime += int(round((time.time() - AutoGenStart)))
self.Progress.Stop("done!")
for Arch in Wa.ArchList:
MakeStart = time.time()
for Ma in BuildModules:
@@ -2286,20 +2281,35 @@ def LogBuildTime(Time):
TimeDurStr = time.strftime("%H:%M:%S", TimeDur)
return TimeDurStr
else:
return None
+def ThreadNum():
+ ThreadNumber = BuildOption.ThreadNumber
+ if ThreadNumber is None:
+ ThreadNumber = TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_MAX_CONCURRENT_THREAD_NUMBER]
+ if ThreadNumber == '':
+ ThreadNumber = 0
+ else:
+ ThreadNumber = int(ThreadNumber, 0)
+
+ if ThreadNumber == 0:
+ try:
+ ThreadNumber = multiprocessing.cpu_count()
+ except (ImportError, NotImplementedError):
+ ThreadNumber = 1
+ return ThreadNumber
## Tool entrance method
#
# This method mainly dispatch specific methods per the command line options.
# If no error found, return zero value so the caller of this tool can know
# if it's executed successfully or not.
#
# @retval 0 Tool was successful
# @retval 1 Tool failed
#
-LogQMaxSize = 60
+LogQMaxSize = ThreadNum() * 10
def Main():
StartTime = time.time()
#
# Create a log Queue
@@ -2432,13 +2442,11 @@ def Main():
else:
EdkLogger.error(X.ToolName, FORMAT_INVALID, File=X.FileName, Line=X.LineNumber, ExtraData=X.Message, RaiseError=False)
ReturnCode = FORMAT_INVALID
except KeyboardInterrupt:
if MyBuild is not None:
- if MyBuild.AutoGenMgr:
- MyBuild.AutoGenMgr.TerminateWorkers()
- MyBuild.AutoGenMgr.kill()
+
# for multi-thread build exits safely
MyBuild.Relinquish()
ReturnCode = ABORT_ERROR
if Option is not None and Option.debug is not None:
EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc())
@@ -2495,10 +2503,11 @@ def Main():
Log_Agent.kill()
Log_Agent.join()
return ReturnCode
if __name__ == '__main__':
+ mp.set_start_method('spawn')
r = Main()
## 0-127 is a safe return range, and 1 is a standard default error
if r < 0 or r > 127: r = 1
sys.exit(r)
--
2.20.1.windows.1
next prev parent reply other threads:[~2019-07-29 8:45 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-07-29 8:44 [Patch 00/11 V4] Enable multiple process AutoGen Bob Feng
2019-07-29 8:44 ` [Patch 01/11] BaseTools: Singleton the object to handle build conf file Bob Feng
2019-07-29 8:44 ` [Patch 02/11] BaseTools: Split WorkspaceAutoGen._InitWorker into multiple functions Bob Feng
2019-07-29 15:03 ` [edk2-devel] " Philippe Mathieu-Daudé
2019-07-30 2:10 ` Bob Feng
2019-07-30 12:38 ` Philippe Mathieu-Daudé
2019-07-29 8:44 ` [Patch 03/11] BaseTools: Add functions to get platform scope build options Bob Feng
2019-07-29 8:44 ` [Patch 04/11] BaseTools: Decouple AutoGen Objects Bob Feng
2019-07-29 8:44 ` [Patch 05/11] BaseTools: Enable Multiple Process AutoGen Bob Feng
2019-07-29 8:44 ` [Patch 06/11] BaseTools: Add shared data for processes Bob Feng
2019-07-29 8:44 ` [Patch 07/11] BaseTools: Add LogAgent to support multiple process Autogen Bob Feng
2019-07-29 8:44 ` [Patch 08/11] BaseTools: Move BuildOption parser out of build.py Bob Feng
2019-07-29 8:44 ` [Patch 09/11] BaseTools: Add the support for python 2 Bob Feng
2019-07-29 8:44 ` [Patch 10/11] BaseTools: Enable block queue log agent Bob Feng
2019-07-29 8:44 ` Bob Feng [this message]
2019-07-29 10:10 ` [edk2-devel] [Patch 00/11 V4] Enable multiple process AutoGen Laszlo Ersek
2019-07-30 7:31 ` Bob Feng
2019-07-30 14:02 ` Laszlo Ersek
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190729084456.18844-12-bob.c.feng@intel.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox