imported Iakin's public domain jcpuid library allowing the detection of CPU types from java

imported Iakin's modifications to jbigi to use the jcpuid library in detecting what jbigi implementation to load
imported and slightly updated Iakin's scripts to build jbigi for lots of architectures
(yay iakin!)
This commit is contained in:
jrandom
2004-08-21 07:56:53 +00:00
committed by zzz
parent f4754d7481
commit f7f05cfc8b
20 changed files with 1362 additions and 35 deletions

View File

@ -0,0 +1,39 @@
/*
* Created on Jul 17, 2004
*
*/
package freenet.support.CPUInformation;
/**
* @author Iakin
* An interface for classes that provide lowlevel information about AMD CPU's
*
* free (adj.): unencumbered; not under the control of others
* Written by Iakin in 2004 and released into the public domain
* with no warranty of any kind, either expressed or implied.
* It probably won't make your computer catch on fire, or eat
* your children, but it might. Use at your own risk.
*/
public interface AMDCPUInfo extends CPUInfo {
/**
* @return true iff the CPU present in the machine is at least an 'k6' CPU
*/
public boolean IsK6Compatible();
/**
* @return true iff the CPU present in the machine is at least an 'k6-2' CPU
*/
public boolean IsK6_2_Compatible();
/**
* @return true iff the CPU present in the machine is at least an 'k6-3' CPU
*/
public boolean IsK6_3_Compatible();
/**
* @return true iff the CPU present in the machine is at least an 'k7' CPU (Atlhon, Duron etc. and better)
*/
public boolean IsAthlonCompatible();
/**
* @return true iff the CPU present in the machine is at least an 'k8' CPU (Atlhon 64, Opteron etc. and better)
*/
public boolean IsAthlon64Compatible();
}

View File

@ -0,0 +1,553 @@
/*
* Created on Jul 14, 2004
*/
package freenet.support.CPUInformation;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
/**
* @author Iakin
* A class for retrieveing details about the CPU using the CPUID assembly instruction.
* A good resource for information about the CPUID instruction can be found here:
* http://www.paradicesoftware.com/specs/cpuid/index.htm
*
* free (adj.): unencumbered; not under the control of others
* Written by Iakin in 2004 and released into the public domain
* with no warranty of any kind, either expressed or implied.
* It probably won't make your computer catch on fire, or eat
* your children, but it might. Use at your own risk.
*/
public class CPUID {
/** did we load the native lib correctly? */
private static boolean _nativeOk = false;
/**
* do we want to dump some basic success/failure info to stderr during
* initialization? this would otherwise use the Log component, but this makes
* it easier for other systems to reuse this class
*/
private static final boolean _doLog = true;
//.matches() is a java 1.4+ addition, using a simplified version for 1.3+
//private static final boolean isX86 = System.getProperty("os.arch").toLowerCase().matches("i?[x0-9]86(_64)?");
private static final boolean isX86 = (-1 != System.getProperty("os.arch").indexOf("86"));
static
{
loadNative();
}
//A class that can (amongst other things I assume) represent the state of the
//different CPU registers after a call to the CPUID assembly method
protected static class CPUIDResult {
final int EAX;
final int EBX;
final int ECX;
final int EDX;
CPUIDResult(int EAX,int EBX,int ECX, int EDX)
{
this.EAX = EAX;
this.EBX = EBX;
this.ECX = ECX;
this.EDX = EDX;
}
}
/**Calls the indicated CPUID function and returns the result of the execution
*
* @param iFunction The CPUID function to call, should be 0 or larger
* @return The contents of the CPU registers after the call to the CPUID function
*/
private static native CPUIDResult doCPUID(int iFunction);
private static String getCPUVendorID()
{
CPUIDResult c = doCPUID(0);
StringBuffer sb= new StringBuffer(13);
sb.append((char)( c.EBX & 0xFF));
sb.append((char)((c.EBX >> 8) & 0xFF));
sb.append((char)((c.EBX >> 16) & 0xFF));
sb.append((char)((c.EBX >> 24) & 0xFF));
sb.append((char)( c.EDX & 0xFF));
sb.append((char)((c.EDX >> 8) & 0xFF));
sb.append((char)((c.EDX >> 16) & 0xFF));
sb.append((char)((c.EDX >> 24) & 0xFF));
sb.append((char)( c.ECX & 0xFF));
sb.append((char)((c.ECX >> 8) & 0xFF));
sb.append((char)((c.ECX >> 16) & 0xFF));
sb.append((char)((c.ECX >> 24) & 0xFF));
return sb.toString();
}
private static int getCPUFamily()
{
CPUIDResult c = doCPUID(1);
return (c.EAX >> 8) & 0xf;
}
private static int getCPUModel()
{
CPUIDResult c = doCPUID(1);
return (c.EAX >> 4) & 0xf;
}
private static int getCPUExtendedModel()
{
CPUIDResult c = doCPUID(1);
return (c.EAX >> 16) & 0xf;
}
private static int getCPUType()
{
CPUIDResult c = doCPUID(1);
return (c.EAX >> 12) & 0xf;
}
private static int getCPUExtendedFamily()
{
CPUIDResult c = doCPUID(1);
return (c.EAX >> 20) & 0xff;
}
private static int getCPUStepping()
{
CPUIDResult c = doCPUID(1);
return c.EAX & 0xf;
}
private static int getCPUFlags()
{
CPUIDResult c = doCPUID(1);
return c.EDX;
}
//Returns a CPUInfo item for the current type of CPU
//If I could I would declare this method in a interface named
//CPUInfoProvider and implement that interface in this class.
//This would make it easier for other people to understand that there
//is nothing preventing them from coding up new providers, probably using
//other detection methods than the x86-only CPUID instruction
public static CPUInfo getInfo() throws UnknownCPUException
{
if(!_nativeOk)
throw new UnknownCPUException("Failed to read CPU information from the system. Please verify the existence of the jcpuid dll/so.");
if(!isX86)
throw new UnknownCPUException("Failed to read CPU information from the system. The CPUID instruction exists on x86 CPU's only");
if(getCPUVendorID().equals("AuthenticAMD"))
return new AMDInfoImpl();
if(getCPUVendorID().equals("GenuineIntel"))
return new IntelInfoImpl();
throw new UnknownCPUException("Unknown CPU type: '"+getCPUVendorID()+"'");
}
protected abstract static class CPUIDCPUInfo
{
public String getVendor()
{
return getCPUVendorID();
}
public boolean hasMMX(){
return (getCPUFlags() & 0x800000) >0; //Bit 23
}
public boolean hasSSE(){
return (getCPUFlags() & 0x2000000) >0; //Bit 25
}
public boolean hasSSE2(){
return (getCPUFlags() & 0x4000000) >0; //Bit 26
}
}
protected static class AMDInfoImpl extends CPUIDCPUInfo implements AMDCPUInfo
{
public boolean IsK6Compatible()
{
return getCPUFamily() >= 5 && getCPUModel() >= 6;
}
public boolean IsK6_2_Compatible()
{
return getCPUFamily() >= 5 && getCPUModel() >= 8;
}
public boolean IsK6_3_Compatible()
{
return getCPUFamily() >= 5 && getCPUModel() >= 9;
}
public boolean IsAthlonCompatible()
{
return getCPUFamily() >= 6;
}
public boolean IsAthlon64Compatible()
{
return getCPUFamily() == 15 && getCPUExtendedFamily() == 0;
}
public String getCPUModelString() throws UnknownCPUException
{
if(getCPUFamily() == 4){
switch(getCPUModel()){
case 3:
return "486 DX/2";
case 7:
return "486 DX/2-WB";
case 8:
return "486 DX/4";
case 9:
return "486 DX/4-WB";
case 14:
return "Am5x86-WT";
case 15:
return "Am5x86-WB";
}
}
if(getCPUFamily() == 5){
switch(getCPUModel()){
case 0:
return "K5/SSA5";
case 1:
return "K5";
case 2:
return "K5";
case 3:
return "K5";
case 6:
return "K6";
case 7:
return "K6";
case 8:
return "K6-2";
case 9:
return "K6-3";
case 13:
return "K6-2+ or K6-III+";
}
}
if(getCPUFamily() == 6){
switch(getCPUModel()){
case 0:
return "Athlon (250 nm)";
case 1:
return "Athlon (250 nm)";
case 2:
return "Athlon (180 nm)";
case 3:
return "Duron";
case 4:
return "Athlon (Thunderbird)";
case 6:
return "Athlon (Palamino)";
case 7:
return "Duron (Morgan)";
case 8:
return "Athlon (Thoroughbred)";
case 10:
return "Athlon (Barton)";
}
}
if(getCPUFamily() == 15){
if(getCPUExtendedFamily() == 0){
switch(getCPUModel()){
case 4:
return "Athlon 64";
case 5:
return "Athlon 64 FX Opteron";
}
}
}
throw new UnknownCPUException("Unknown AMD CPU; Family="+getCPUFamily()+", Model="+getCPUModel());
}
}
protected static class IntelInfoImpl extends CPUIDCPUInfo implements IntelCPUInfo
{
public boolean IsPentiumCompatible()
{
return getCPUFamily() >= 5;
}
public boolean IsPentiumMMXCompatible()
{
return IsPentium2Compatible() || (getCPUFamily() == 5 && (getCPUModel() ==4 || getCPUModel() == 8));
}
public boolean IsPentium2Compatible()
{
return getCPUFamily() > 6 || (getCPUFamily() == 6 && getCPUModel() >=3);
}
public boolean IsPentium3Compatible()
{
return getCPUFamily() > 6 || (getCPUFamily() == 6 && getCPUModel() >=7);
}
public boolean IsPentium4Compatible()
{
return getCPUFamily() >= 15;
}
public String getCPUModelString() throws UnknownCPUException {
if(getCPUFamily() == 4){
switch(getCPUModel()){
case 0:
return "486 DX-25/33";
case 1:
return "486 DX-50";
case 2:
return "486 SX";
case 3:
return "486 DX/2";
case 4:
return "486 SL";
case 5:
return "486 SX/2";
case 7:
return "486 DX/2-WB";
case 8:
return "486 DX/4";
case 9:
return "486 DX/4-WB";
}
}
if(getCPUFamily() == 5){
switch(getCPUModel()){
case 0:
return "Pentium 60/66 A-step";
case 1:
return "Pentium 60/66";
case 2:
return "Pentium 75 - 200";
case 3:
return "OverDrive PODP5V83";
case 4:
return "Pentium MMX";
case 7:
return "Mobile Pentium 75 - 200";
case 8:
return "Mobile Pentium MMX";
}
}
if(getCPUFamily() == 6){
switch(getCPUModel()){
case 0:
return "Pentium Pro A-step";
case 1:
return "Pentium Pro";
case 3:
return "Pentium II (Klamath)";
case 5:
return "Pentium II (Deschutes), Celeron (Covington), Mobile Pentium II (Dixon)";
case 6:
return "Mobile Pentium II, Celeron (Mendocino)";
case 7:
return "Pentium III (Katmai)";
case 8:
return "Pentium III (Coppermine), Celeron w/SSE";
case 9:
return "Mobile Pentium III";
case 10:
return "Pentium III Xeon (Cascades)";
case 11:
return "Pentium III (130 nm)";
}
}
if(getCPUFamily() == 7){
switch(getCPUModel()){
//Itanium.. TODO
}
}
if(getCPUFamily() == 15){
if(getCPUExtendedFamily() == 0){
switch(getCPUModel()){
case 0:
return "Pentium IV (180 nm)";
case 1:
return "Pentium IV (180 nm)";
case 2:
return "Pentium IV (130 nm)";
case 3:
return "Pentium IV (90 nm)";
}
}
if(getCPUExtendedFamily() == 1){
switch(getCPUModel()){
// Itanium 2.. TODO
}
}
}
throw new UnknownCPUException("Unknown Intel CPU; Family="+getCPUFamily()+", Model="+getCPUModel());
}
}
public static void main(String args[])
{
if(!_nativeOk){
System.out.println("**Failed to retrieve CPUInfo. Please verify the existence of jcpuid dll/so**");
}
System.out.println("**CPUInfo**");
System.out.println("CPU Vendor: " + getCPUVendorID());
System.out.println("CPU Family: " + getCPUFamily());
System.out.println("CPU Model: " + getCPUModel());
System.out.println("CPU Stepping: " + getCPUStepping());
System.out.println("CPU Flags: " + getCPUFlags());
CPUInfo c = getInfo();
System.out.println(" **More CPUInfo**");
System.out.println(" CPU model string: " + c.getCPUModelString());
System.out.println(" CPU has MMX: " + c.hasMMX());
System.out.println(" CPU has SSE: " + c.hasSSE());
System.out.println(" CPU has SSE2: " + c.hasSSE2());
if(c instanceof IntelCPUInfo){
System.out.println(" **Intel-info**");
System.out.println(" Is pII-compatible: "+((IntelCPUInfo)c).IsPentium2Compatible());
System.out.println(" Is pIII-compatible: "+((IntelCPUInfo)c).IsPentium3Compatible());
System.out.println(" Is pIV-compatible: "+((IntelCPUInfo)c).IsPentium4Compatible());
}
if(c instanceof AMDCPUInfo){
System.out.println(" **AMD-info**");
System.out.println(" Is Athlon-compatible: "+((AMDCPUInfo)c).IsAthlonCompatible());
}
}
/**
* <p>Do whatever we can to load up the native library.
* If it can find a custom built jcpuid.dll / libjcpuid.so, it'll use that. Otherwise
* it'll try to look in the classpath for the correct library (see loadFromResource).
* If the user specifies -Djcpuid.enable=false it'll skip all of this.</p>
*
*/
private static final void loadNative() {
try{
String wantedProp = System.getProperty("jcpuid.enable", "true");
boolean wantNative = "true".equalsIgnoreCase(wantedProp);
if (wantNative) {
boolean loaded = loadFromResource();
if (loaded) {
_nativeOk = true;
if (_doLog)
System.err.println("INFO: Native CPUID library '"+getResourceName()+"' loaded from resource");
} else {
loaded = loadGeneric();
if (loaded) {
_nativeOk = true;
if (_doLog)
System.err.println("INFO: Native CPUID library '"+getLibraryMiddlePart()+"' loaded from somewhere in the path");
} else {
_nativeOk = false;
if (_doLog)
System.err.println("WARN: Native CPUID library jcpuid not loaded - will not be able to read CPU information using CPUID");
}
}
} else {
if (_doLog)
System.err.println("INFO: Native CPUID library jcpuid not loaded - will not be able to read CPU information using CPUID");
}
}catch(Exception e){
if (_doLog)
System.err.println("INFO: Native CPUID library jcpuid not loaded, reason: '"+e.getMessage()+"' - will not be able to read CPU information using CPUID");
}
}
/**
* <p>Try loading it from an explictly built jcpuid.dll / libjcpuid.so</p>
*
* @return true if it was loaded successfully, else false
*
*/
private static final boolean loadGeneric() {
try {
System.loadLibrary(getLibraryMiddlePart());
return true;
} catch (UnsatisfiedLinkError ule) {
return false;
}
}
/**
* <p>Check all of the jars in the classpath for the jcpuid dll/so.
* This file should be stored in the resource in the same package as this class.
*
* <p>This is a pretty ugly hack, using the general technique illustrated by the
* onion FEC libraries. It works by pulling the resource, writing out the
* byte stream to a temporary file, loading the native library from that file,
* then deleting the file.</p>
*
* @return true if it was loaded successfully, else false
*
*/
private static final boolean loadFromResource() {
String resourceName = getResourceName();
if (resourceName == null) return false;
URL resource = CPUID.class.getClassLoader().getResource(resourceName);
if (resource == null) {
if (_doLog)
System.err.println("ERROR: Resource name [" + resourceName + "] was not found");
return false;
}
File outFile = null;
try {
InputStream libStream = resource.openStream();
outFile = File.createTempFile("jcpuid", "lib.tmp");
FileOutputStream fos = new FileOutputStream(outFile);
byte buf[] = new byte[4096*1024];
while (true) {
int read = libStream.read(buf);
if (read < 0) break;
fos.write(buf, 0, read);
}
fos.close();
System.load(outFile.getAbsolutePath());//System.load requires an absolute path to the lib
return true;
} catch (UnsatisfiedLinkError ule) {
if (_doLog) {
System.err.println("ERROR: The resource " + resourceName
+ " was not a valid library for this platform");
ule.printStackTrace();
}
return false;
} catch (IOException ioe) {
if (_doLog) {
System.err.println("ERROR: Problem writing out the temporary native library data");
ioe.printStackTrace();
}
return false;
} finally {
if (outFile != null) {
outFile.deleteOnExit();
}
}
}
private static final String getResourceName()
{
String pname = CPUID.class.getPackage().getName().replace('.','/');
return pname+"/"+getLibraryPrefix()+getLibraryMiddlePart()+"."+getLibrarySuffix();
}
private static final String getLibraryPrefix()
{
boolean isWindows =System.getProperty("os.name").toLowerCase().indexOf("windows") != -1;
if(isWindows)
return "";
else
return "lib";
}
private static final String getLibraryMiddlePart(){
boolean isWindows =(System.getProperty("os.name").toLowerCase().indexOf("windows") != -1);
boolean isLinux =(System.getProperty("os.name").toLowerCase().indexOf("linux") != -1);
boolean isFreebsd =(System.getProperty("os.name").toLowerCase().indexOf("freebsd") != -1);
if(isWindows)
return "jcpuid-x86-windows"; // The convention on Windows
if(isLinux)
return "jcpuid-x86-linux"; // The convention on linux...
if(isFreebsd)
return "jcpuid-x86-freebsd"; // The convention on freebsd...
throw new RuntimeException("Dont know jcpuid library name for os type '"+System.getProperty("os.name")+"'");
}
private static final String getLibrarySuffix()
{
boolean isWindows =System.getProperty("os.name").toLowerCase().indexOf("windows") != -1;
if(isWindows)
return "dll";
else
return "so";
}
}

View File

@ -0,0 +1,45 @@
/*
* Created on Jul 16, 2004
*
*/
package freenet.support.CPUInformation;
/**
* @author Iakin
* An interface for classes that provide lowlevel information about CPU's
*
* free (adj.): unencumbered; not under the control of others
* Written by Iakin in 2004 and released into the public domain
* with no warranty of any kind, either expressed or implied.
* It probably won't make your computer catch on fire, or eat
* your children, but it might. Use at your own risk.
*/
public interface CPUInfo
{
/**
* @return A string indicating the vendor of the CPU.
*/
public String getVendor();
/**
* @return A string detailing what type of CPU that is present in the machine. I.e. 'Pentium IV' etc.
* @throws UnknownCPUException If for any reson the retrieval of the requested information
* failed. The message encapsulated in the execption indicates the
* cause of the failure.
*/
public String getCPUModelString() throws UnknownCPUException;
/**
* @return true iff the CPU support the MMX instruction set.
*/
public boolean hasMMX();
/**
* @return true iff the CPU support the SSE instruction set.
*/
public boolean hasSSE();
/**
* @return true iff the CPU support the SSE2 instruction set.
*/
public boolean hasSSE2();
}

View File

@ -0,0 +1,40 @@
/*
* Created on Jul 17, 2004
*
*/
package freenet.support.CPUInformation;
/**
* @author Iakin
* An interface for classes that provide lowlevel information about Intel CPU's
*
* free (adj.): unencumbered; not under the control of others
* Written by Iakin in 2004 and released into the public domain
* with no warranty of any kind, either expressed or implied.
* It probably won't make your computer catch on fire, or eat
* your children, but it might. Use at your own risk.
*/
public interface IntelCPUInfo extends CPUInfo {
/**
* @return true iff the CPU is at least a Pentium CPU.
*/
public boolean IsPentiumCompatible();
/**
* @return true iff the CPU is at least a Pentium which implements the MMX instruction/feature set.
*/
public boolean IsPentiumMMXCompatible();
/**
* @return true iff the CPU implements at least the p6 instruction set (Pentium II or better).
* Please note that an PentimPro CPU causes/should cause this method to return false (due to that CPU using a
* very early implementation of the p6 instruction set. No MMX etc.)
*/
public boolean IsPentium2Compatible();
/**
* @return true iff the CPU implements at least a Pentium III level of the p6 instruction/feature set.
*/
public boolean IsPentium3Compatible();
/**
* @return true iff the CPU implements at least a Pentium IV level instruction/feature set.
*/
public boolean IsPentium4Compatible();
}

View File

@ -0,0 +1,18 @@
/*
* Created on Jul 16, 2004
*/
package freenet.support.CPUInformation;
/**
* @author Iakin
*
*/
public class UnknownCPUException extends RuntimeException {
public UnknownCPUException() {
super();
}
public UnknownCPUException(String message) {
super(message);
}
}