Add thread control classes. (2)

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@1434 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
wuyizhong 2006-09-04 04:50:59 +00:00
parent 19bf6b15d0
commit abce9cbd99
2 changed files with 616 additions and 0 deletions

View File

@ -0,0 +1,217 @@
/** @file
This file is for single module thread definition.
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
package org.tianocore.build;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.Vector;
import org.apache.tools.ant.BuildListener;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Property;
import org.tianocore.build.GenBuildTask;
import org.tianocore.build.fpd.FpdParserForThread;
import org.tianocore.build.id.FpdModuleIdentification;
import org.tianocore.build.id.ModuleIdentification;
/**
Add more comment here.
@since GenBuild 1.0
**/
public class GenBuildThread implements Runnable {
private ModuleIdentification parentModuleId = null;
private ModuleIdentification moduleId = null;
private Set<FpdModuleIdentification> dependencies = new LinkedHashSet<FpdModuleIdentification>();
private int status = FpdParserForThread.STATUS_DEPENDENCY_NOT_READY;
private Project project = null;
public Object semaphore = new Object();
private String arch = null;
private boolean highPriority = false;
private Thread thread;
public GenBuildThread() {
thread = new Thread(this);
}
public boolean start() {
if (highPriority) {
thread.setPriority(Thread.MAX_PRIORITY);
}
status = FpdParserForThread.STATUS_START_RUN;
thread.start();
return true;
}
public void run() {
FpdModuleIdentification fpdModuleId = new FpdModuleIdentification(moduleId, arch);
//
// Prepare pass down properties
// ARCH, MODULE_GUID, MODULE_VERSION, PACKAGE_GUID, PACKAGE_VERSION, PLATFORM_FILE
//
Vector<Property> properties = new Vector<Property>();
Property property = new Property();
property.setName("ARCH");
property.setValue(arch);
properties.add(property);
property = new Property();
property.setName("MODULE_GUID");
property.setValue(moduleId.getGuid());
properties.add(property);
property = new Property();
property.setName("MODULE_VERSION");
if (moduleId.getVersion() == null) {
property.setValue("");
} else {
property.setValue(moduleId.getVersion());
}
properties.add(property);
property = new Property();
property.setName("PACKAGE_GUID");
property.setValue(moduleId.getPackage().getGuid());
properties.add(property);
property = new Property();
property.setName("PACKAGE_VERSION");
if (moduleId.getPackage().getVersion() == null) {
property.setValue("");
} else {
property.setValue(moduleId.getPackage().getVersion());
}
properties.add(property);
// property = new Property();
// property.setName("PLATFORM_FILE");
// property.setValue(arch);
// properties.add(property);
//
// Build the Module
//
GenBuildTask genBuildTask = new GenBuildTask();
Project newProject = new Project();
Hashtable passdownProperties = project.getProperties();
Iterator iter = passdownProperties.keySet().iterator();
while (iter.hasNext()) {
String item = (String) iter.next();
newProject.setProperty(item, (String) passdownProperties.get(item));
}
newProject.setInputHandler(project.getInputHandler());
Iterator listenerIter = project.getBuildListeners().iterator();
while (listenerIter.hasNext()) {
newProject.addBuildListener((BuildListener) listenerIter.next());
}
project.initSubProject(newProject);
genBuildTask.setProject(newProject);
genBuildTask.setExternalProperties(properties);
genBuildTask.parentId = parentModuleId;
genBuildTask.perform();
status = FpdParserForThread.STATUS_END_RUN;
System.out.println(fpdModuleId + " build finished. ");
//
//
//
synchronized (FpdParserForThread.deamonSemaphore) {
FpdParserForThread.subCount();
FpdParserForThread.deamonSemaphore.notifyAll();
}
}
public void setArch(String arch) {
this.arch = arch;
}
public void setDependencies(Set<FpdModuleIdentification> dependencies) {
this.dependencies = dependencies;
}
public void setModuleId(ModuleIdentification moduleId) {
this.moduleId = moduleId;
}
public void setParentModuleId(ModuleIdentification parentModuleId) {
this.parentModuleId = parentModuleId;
}
public void setProject(Project project) {
this.project = project;
}
public void setHighPriority(boolean highPriority) {
this.highPriority = highPriority;
}
public Set<FpdModuleIdentification> getDependencies() {
return dependencies;
}
public ModuleIdentification getModuleId() {
return moduleId;
}
public int getStatus() {
//
// Add code here to judge dependency
//
if (status == FpdParserForThread.STATUS_DEPENDENCY_NOT_READY) {
Iterator<FpdModuleIdentification> iter = dependencies.iterator();
boolean flag = true;
while (iter.hasNext()) {
FpdModuleIdentification item = iter.next();
if (FpdParserForThread.allThreads.get(item).getStatus() == 1) {
flag = false;
break ;
}
}
if (flag) {
status = FpdParserForThread.STATUS_DEPENDENCY_READY;
}
}
return status;
}
public void setStatus(int status) {
this.status = status;
}
}

View File

@ -0,0 +1,399 @@
/** @file
This file is ANT task FpdParserTask.
FpdParserTask is used to parse FPD (Framework Platform Description) and generate
build.out.xml. It is for Package or Platform build use.
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
package org.tianocore.build.fpd;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.taskdefs.Ant;
import org.apache.xmlbeans.XmlObject;
import org.tianocore.build.global.GlobalData;
import org.tianocore.build.global.OutputManager;
import org.tianocore.build.id.FpdModuleIdentification;
import org.tianocore.build.id.ModuleIdentification;
import org.tianocore.build.FrameworkBuildTask;
import org.tianocore.build.GenBuildThread;
import org.tianocore.common.exception.EdkException;
/**
<code>FpdParserTask</code> is an ANT task. The main function is parsing Framework
Platform Descritpion (FPD) XML file and generating its ANT build script for
corresponding platform.
<p>The task sets global properties PLATFORM, PLATFORM_DIR, PLATFORM_RELATIVE_DIR
and BUILD_DIR. </p>
<p>The task generates ${PLATFORM}_build.xml file which will be called by top level
build.xml. The task also generate Fv.inf files (File is for Tool GenFvImage)
and flash definition file (File is for Tool FlashMap) if necessary. </p>
<p>FpdParserTask task stores all FPD information to GlobalData. And parse
tools definition file to set up compiler options for different Target and
different ToolChainTag. </p>
<p>The method parseFpdFile is also prepared for single module build. </p>
<p>The usage is (take NT32 Platform for example):</p>
<pre>
&lt;FPDParser platformName="Nt32" /&gt;
</pre>
<p>The task will initialize all information through parsing Framework Database,
SPD, Tool chain configuration files. </p>
@since GenBuild 1.0
**/
public class FpdParserForThread extends FpdParserTask {
public static Map<FpdModuleIdentification, GenBuildThread> allThreads = new LinkedHashMap<FpdModuleIdentification, GenBuildThread>();
List<String> queueList = new ArrayList<String>();
public static Object deamonSemaphore = new Object();
static Object countSemaphore = new Object();
public static int STATUS_DEPENDENCY_NOT_READY = 1;
public static int STATUS_DEPENDENCY_READY = 2;
public static int STATUS_START_RUN = 3;
public static int STATUS_END_RUN = 4;
private int currentQueueCode = 0;
public static int currentRunNumber = 0;
/**
Public construct method. It is necessary for ANT task.
**/
public FpdParserForThread() {
}
/**
ANT task's entry method. The main steps is described as following:
<ul>
<li>Initialize global information (Framework DB, SPD files and all MSA files
listed in SPD). This step will execute only once in whole build process;</li>
<li>Parse specified FPD file; </li>
<li>Generate FV.inf files; </li>
<li>Generate PlatformName_build.xml file for Flatform build; </li>
<li>Collect PCD information. </li>
</ul>
@throws BuildException
Surface area is not valid.
**/
public void execute() throws BuildException {
//
// Parse FPD file
//
parseFpdFile();
//
// Prepare BUILD_DIR
//
isUnified = OutputManager.getInstance().prepareBuildDir(getProject());
//
// For every Target and ToolChain
//
String[] targetList = GlobalData.getToolChainInfo().getTargets();
for (int i = 0; i < targetList.length; i++) {
String[] toolchainList = GlobalData.getToolChainInfo().getTagnames();
for(int j = 0; j < toolchainList.length; j++) {
//
// Prepare FV_DIR
//
String ffsCommonDir = getProject().getProperty("BUILD_DIR") + File.separatorChar
+ targetList[i] + File.separatorChar
+ toolchainList[j];
File fvDir = new File(ffsCommonDir + File.separatorChar + "FV");
fvDir.mkdirs();
getProject().setProperty("FV_DIR", fvDir.getPath().replaceAll("(\\\\)", "/"));
//
// Gen Fv.inf files
//
genFvInfFiles(ffsCommonDir);
}
}
//
// Gen build.xml
//
PlatformBuildFileGenerator fileGenerator = new PlatformBuildFileGenerator(getProject(), outfiles, fvs, isUnified, saq);
fileGenerator.genBuildFile();
//
// Prepare Queue
//
queueList.add("libqueue");
String[] validFv = saq.getFpdValidImageNames();
for (int i = 0; i < validFv.length; i++) {
queueList.add(validFv[i]);
}
Iterator<String> fvsNameIter = fvs.keySet().iterator();
while (fvsNameIter.hasNext()) {
String fvName = fvsNameIter.next();
if (!isContain(validFv, fvName)) {
queueList.add(fvName);
}
}
//
// Ant call ${PLATFORM}_build.xml
//
Ant ant = new Ant();
ant.setProject(getProject());
ant.setAntfile(platformId.getFpdFile().getParent() + File.separatorChar + platformId.getName() + "_build.xml");
ant.setTarget("prebuild");
ant.setInheritAll(true);
ant.init();
ant.execute();
System.out.println("Task number is " + allThreads.size());
//
// Waiting for all thread over, or time out
//
synchronized (deamonSemaphore) {
//
// Initialize BUGBUG
//
while (true) {
//
// If all modules are already built
//
if (currentQueueCode >= queueList.size()) {
break ;
}
Set<FpdModuleIdentification> currentQueueModules = fvs.get(queueList.get(currentQueueCode));
if (currentQueueModules == null) {
++currentQueueCode;
continue ;
}
Iterator<FpdModuleIdentification> currentIter = currentQueueModules.iterator();
GenBuildThread a = null;
boolean existNoneReady = false;
while (currentIter.hasNext()) {
GenBuildThread item = allThreads.get(currentIter.next());
if (item.getStatus() == STATUS_DEPENDENCY_NOT_READY) {
existNoneReady = true;
} else if (item.getStatus() == STATUS_DEPENDENCY_READY) {
a = item;
addCount();
a.start();
if (currentRunNumber == FrameworkBuildTask.MAX_CONCURRENT_THREAD_NUMBER) {
break ;
}
}
}
if (a != null) {
//
// Exist ready thread
//
System.out.println("## Exist ready thread");
} else if (existNoneReady && currentRunNumber == 0) {
//
// No active thread, but still have dependency not read thread
//
throw new BuildException("Found can't resolve dependencies. ");
} else if (!existNoneReady && currentRunNumber == 0) {
//
// Current queue build finish, move to next
//
System.out.println("## Current queue build finish, move to next");
++currentQueueCode;
continue ;
} else {
//
// active thread exist, but no ready thread
//
System.out.println("## active thread exist, but no ready thread" + currentRunNumber);
}
try {
deamonSemaphore.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//
// call fvs, postbuild
//
ant = new Ant();
ant.setProject(getProject());
ant.setAntfile(platformId.getFpdFile().getParent() + File.separatorChar + platformId.getName() + "_build.xml");
ant.setTarget("fvs");
ant.setInheritAll(true);
ant.init();
ant.execute();
ant = new Ant();
ant.setProject(getProject());
ant.setAntfile(platformId.getFpdFile().getParent() + File.separatorChar + platformId.getName() + "_build.xml");
ant.setTarget("postbuild");
ant.setInheritAll(true);
ant.init();
ant.execute();
}
/**
Parse all modules listed in FPD file.
**/
void parseModuleSAFiles() throws EdkException{
Map<FpdModuleIdentification, Map<String, XmlObject>> moduleSAs = saq.getFpdModules();
//
// For every Module lists in FPD file.
//
Set<FpdModuleIdentification> keys = moduleSAs.keySet();
Iterator<FpdModuleIdentification> iter = keys.iterator();
while (iter.hasNext()) {
FpdModuleIdentification fpdModuleId = iter.next();
//
// Generate GenBuildThread
//
GenBuildThread genBuildThread = new GenBuildThread();
genBuildThread.setArch(fpdModuleId.getArch());
genBuildThread.setParentModuleId(null);
genBuildThread.setModuleId(fpdModuleId.getModule());
genBuildThread.setProject(getProject());
Set<FpdModuleIdentification> dependencies = new LinkedHashSet<FpdModuleIdentification>();
GlobalData.registerFpdModuleSA(fpdModuleId, moduleSAs.get(fpdModuleId));
//
// Add all dependent Library Instance
//
saq.push(GlobalData.getDoc(fpdModuleId));
ModuleIdentification[] libinstances = saq.getLibraryInstance(fpdModuleId.getArch());
saq.pop();
for (int i = 0; i < libinstances.length; i++) {
FpdModuleIdentification libFpdModuleId = new FpdModuleIdentification(libinstances[i], fpdModuleId.getArch());
//
// Add to dependencies
//
dependencies.add(libFpdModuleId);
//
// Create thread for library instances
//
GenBuildThread liBuildThread = new GenBuildThread();
liBuildThread.setArch(fpdModuleId.getArch());
liBuildThread.setParentModuleId(fpdModuleId.getModule());
liBuildThread.setModuleId(libinstances[i]);
liBuildThread.setProject(getProject());
liBuildThread.setStatus(STATUS_DEPENDENCY_READY);
liBuildThread.setHighPriority(true);
allThreads.put(libFpdModuleId, liBuildThread);
updateFvs("libqueue", libFpdModuleId);
}
genBuildThread.setDependencies(dependencies);
// if (dependencies.size() == 0) {
genBuildThread.setStatus(STATUS_DEPENDENCY_READY);
// }
allThreads.put(fpdModuleId, genBuildThread);
//
// Put fpdModuleId to the corresponding FV
//
saq.push(GlobalData.getDoc(fpdModuleId));
String fvBinding = saq.getModuleFvBindingKeyword();
fpdModuleId.setFvBinding(fvBinding);
updateFvs(fvBinding, fpdModuleId);
//
// Prepare for out put file name
//
ModuleIdentification moduleId = fpdModuleId.getModule();
String baseName = saq.getModuleOutputFileBasename();
if (baseName == null) {
baseName = moduleId.getName();
}
outfiles.put(fpdModuleId, fpdModuleId.getArch() + File.separatorChar
+ moduleId.getGuid() + "-" + baseName
+ getSuffix(moduleId.getModuleType()));
//
// parse module build options, if any
//
GlobalData.addModuleToolChainOption(fpdModuleId, parseModuleBuildOptions(false));
GlobalData.addModuleToolChainFamilyOption(fpdModuleId, parseModuleBuildOptions(true));
saq.pop();
}
}
private boolean isContain(String[] list, String item) {
for (int i = 0; i < list.length; i++) {
if (list[i].equalsIgnoreCase(item)) {
return true;
}
}
return false;
}
public synchronized static void addCount() {
synchronized (countSemaphore) {
++currentRunNumber;
}
}
public synchronized static void subCount() {
synchronized (countSemaphore) {
--currentRunNumber;
}
}
}