#3718, #3717: Add check for SSE 4.2 and PCLMUL support to native zlib

This commit is contained in:
lax1dude 2024-08-08 18:19:20 +10:00 committed by md_5
parent e49759025f
commit 6b612302e1
No known key found for this signature in database
GPG Key ID: E8E901AC7C617C11
10 changed files with 73 additions and 3 deletions

View File

@ -3,6 +3,7 @@
#include <zlib.h> #include <zlib.h>
#include "shared.h" #include "shared.h"
#include "cpuid_helper.h"
#include "net_md_5_bungee_jni_zlib_NativeCompressImpl.h" #include "net_md_5_bungee_jni_zlib_NativeCompressImpl.h"
typedef unsigned char byte; typedef unsigned char byte;
@ -26,6 +27,10 @@ jint throwException(JNIEnv *env, const char* message, int err) {
return (*env)->Throw(env, throwable); return (*env)->Throw(env, throwable);
} }
JNIEXPORT jboolean JNICALL Java_net_md_15_bungee_jni_zlib_NativeCompressImpl_checkSupported(JNIEnv* env, jobject obj) {
return (jboolean) checkCompressionNativesSupport();
}
void JNICALL Java_net_md_15_bungee_jni_zlib_NativeCompressImpl_reset(JNIEnv* env, jobject obj, jlong ctx, jboolean compress) { void JNICALL Java_net_md_15_bungee_jni_zlib_NativeCompressImpl_reset(JNIEnv* env, jobject obj, jlong ctx, jboolean compress) {
z_stream* stream = (z_stream*) ctx; z_stream* stream = (z_stream*) ctx;
int ret = (compress) ? deflateReset(stream) : inflateReset(stream); int ret = (compress) ? deflateReset(stream) : inflateReset(stream);

View File

@ -0,0 +1,22 @@
// Header to check for SSE 4.2 support in compression natives
// GCC only!
#ifndef _INCLUDE_CPUID_HELPER_H
#define _INCLUDE_CPUID_HELPER_H
#include <stdbool.h>
#include <cpuid.h>
static inline bool checkCompressionNativesSupport() {
unsigned int eax;
unsigned int ebx;
unsigned int ecx;
unsigned int edx;
if(__get_cpuid(1, &eax, &ebx, &ecx, &edx)) {
return (ecx & bit_PCLMUL) != 0 && (ecx & bit_SSE4_2) != 0;
}else {
return false;
}
}
#endif // _INCLUDE_CPUID_HELPER_H

View File

@ -15,6 +15,14 @@ extern "C" {
JNIEXPORT void JNICALL Java_net_md_15_bungee_jni_zlib_NativeCompressImpl_initFields JNIEXPORT void JNICALL Java_net_md_15_bungee_jni_zlib_NativeCompressImpl_initFields
(JNIEnv *, jclass); (JNIEnv *, jclass);
/*
* Class: net_md_5_bungee_jni_zlib_NativeCompressImpl
* Method: checkSupported
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_net_md_15_bungee_jni_zlib_NativeCompressImpl_checkSupported
(JNIEnv *, jobject);
/* /*
* Class: net_md_5_bungee_jni_zlib_NativeCompressImpl * Class: net_md_5_bungee_jni_zlib_NativeCompressImpl
* Method: end * Method: end

View File

@ -15,14 +15,23 @@ public final class NativeCode<T>
private final String name; private final String name;
private final Supplier<? extends T> javaImpl; private final Supplier<? extends T> javaImpl;
private final Supplier<? extends T> nativeImpl; private final Supplier<? extends T> nativeImpl;
private final boolean enableNativeFlag;
private final boolean extendedSupportCheck;
// //
private boolean loaded; private boolean loaded;
public NativeCode(String name, Supplier<? extends T> javaImpl, Supplier<? extends T> nativeImpl) public NativeCode(String name, Supplier<? extends T> javaImpl, Supplier<? extends T> nativeImpl)
{
this( name, javaImpl, nativeImpl, false );
}
public NativeCode(String name, Supplier<? extends T> javaImpl, Supplier<? extends T> nativeImpl, boolean extendedSupportCheck)
{ {
this.name = name; this.name = name;
this.javaImpl = javaImpl; this.javaImpl = javaImpl;
this.nativeImpl = nativeImpl; this.nativeImpl = nativeImpl;
this.enableNativeFlag = Boolean.parseBoolean( System.getProperty( "net.md_5.bungee.jni." + name + ".enable", "true" ) );
this.extendedSupportCheck = extendedSupportCheck;
} }
public T newInstance() public T newInstance()
@ -32,7 +41,7 @@ public final class NativeCode<T>
public boolean load() public boolean load()
{ {
if ( !loaded && isSupported() ) if ( enableNativeFlag && !loaded && isSupported() )
{ {
String fullName = "bungeecord-" + name; String fullName = "bungeecord-" + name;
@ -59,6 +68,13 @@ public final class NativeCode<T>
} }
System.load( temp.getPath() ); System.load( temp.getPath() );
if ( extendedSupportCheck )
{
// Should throw NativeCodeException if incompatible
nativeImpl.get();
}
loaded = true; loaded = true;
} catch ( IOException ex ) } catch ( IOException ex )
{ {
@ -66,6 +82,9 @@ public final class NativeCode<T>
} catch ( UnsatisfiedLinkError ex ) } catch ( UnsatisfiedLinkError ex )
{ {
System.out.println( "Could not load native library: " + ex.getMessage() ); System.out.println( "Could not load native library: " + ex.getMessage() );
} catch ( NativeCodeException ex )
{
System.out.println( "Native library " + name + " is incompatible: " + ex.getMessage() );
} }
} }
} }

View File

@ -7,4 +7,10 @@ public class NativeCodeException extends RuntimeException
{ {
super( message + " : " + reason ); super( message + " : " + reason );
} }
public NativeCodeException(String message)
{
super( message );
}
} }

View File

@ -15,6 +15,8 @@ public class NativeCompressImpl
static native void initFields(); static native void initFields();
native boolean checkSupported();
native void end(long ctx, boolean compress); native void end(long ctx, boolean compress);
native void reset(long ctx, boolean compress); native void reset(long ctx, boolean compress);

View File

@ -15,6 +15,14 @@ public class NativeZlib implements BungeeZlib
private boolean compress; private boolean compress;
private long ctx; private long ctx;
public NativeZlib()
{
if ( !nativeCompress.checkSupported() )
{
throw new NativeCodeException( "This CPU does not support the required SSE 4.2 and/or PCLMUL extensions!" );
}
}
@Override @Override
public void init(boolean compress, int level) public void init(boolean compress, int level)
{ {

View File

@ -15,7 +15,7 @@ import org.junit.jupiter.api.Test;
public class NativeZlibTest public class NativeZlibTest
{ {
private final NativeCode<BungeeZlib> factory = new NativeCode<>( "native-compress", JavaZlib::new, NativeZlib::new ); private final NativeCode<BungeeZlib> factory = new NativeCode<>( "native-compress", JavaZlib::new, NativeZlib::new, true );
@Test @Test
public void doTest() throws DataFormatException public void doTest() throws DataFormatException

View File

@ -8,5 +8,5 @@ import net.md_5.bungee.jni.zlib.NativeZlib;
public class CompressFactory public class CompressFactory
{ {
public static final NativeCode<BungeeZlib> zlib = new NativeCode<>( "native-compress", JavaZlib::new, NativeZlib::new ); public static final NativeCode<BungeeZlib> zlib = new NativeCode<>( "native-compress", JavaZlib::new, NativeZlib::new, true );
} }