There's no two ways about it. This shit is definitely not safe.
git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@2556 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -0,0 +1,90 @@
|
|||||||
|
//
|
||||||
|
// $Id: Unsafe.java,v 1.1 2003/05/08 21:25:20 mdb Exp $
|
||||||
|
|
||||||
|
package com.threerings.util.unsafe;
|
||||||
|
|
||||||
|
import com.threerings.util.Log;
|
||||||
|
import com.samskivert.util.RunAnywhere;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A native library for doing unsafe things. Don't use this library. If
|
||||||
|
* you must ignore that warning, then be sure you use it sparingly and
|
||||||
|
* only in very well considered cases.
|
||||||
|
*/
|
||||||
|
public class Unsafe
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Enables or disables garbage collection. <em>Warning:</em> you will
|
||||||
|
* be fucked if you leave it disabled for too long. Do not do this
|
||||||
|
* unless you are dang sure about what you're doing and are prepared
|
||||||
|
* to test your code on every platform this side of Nantucket.
|
||||||
|
*
|
||||||
|
* <p> Calls to this method do not nest. Regardless of how many times
|
||||||
|
* you disable GC, only one call is required to reenable it.
|
||||||
|
*/
|
||||||
|
public static void setGCEnabled (boolean enabled)
|
||||||
|
{
|
||||||
|
// we don't support nesting, NOOP if the state doesn't change
|
||||||
|
if (_loaded && enabled != _gcEnabled) {
|
||||||
|
if (_gcEnabled = enabled) {
|
||||||
|
enableGC();
|
||||||
|
} else {
|
||||||
|
disableGC();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Causes the current thread to block for the specified number of
|
||||||
|
* milliseconds. This exists primarily to work around the fact that on
|
||||||
|
* Linux, {@link Thread#sleep} is only accurate to around 12ms which
|
||||||
|
* is wholly unacceptable.
|
||||||
|
*/
|
||||||
|
public static void sleep (int millis)
|
||||||
|
{
|
||||||
|
if (_loaded && RunAnywhere.isLinux()) {
|
||||||
|
nativeSleep(millis);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
Thread.sleep(millis);
|
||||||
|
} catch (InterruptedException ie) {
|
||||||
|
Log.info("Thread.sleep(" + millis + ") interrupted.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reenable garbage collection after a call to {@link #disableGC}.
|
||||||
|
*/
|
||||||
|
protected static native void enableGC ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disables garbage collection.
|
||||||
|
*/
|
||||||
|
protected static native void disableGC ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sleeps the current thread for the specified number of milliseconds.
|
||||||
|
*/
|
||||||
|
protected static native void nativeSleep (int millis);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called to initialize our library.
|
||||||
|
*/
|
||||||
|
protected static native boolean init ();
|
||||||
|
|
||||||
|
/** The current state of GC enablement. */
|
||||||
|
protected static boolean _gcEnabled = true;
|
||||||
|
|
||||||
|
/** Whether or not we were able to load and initialize our library. */
|
||||||
|
protected static boolean _loaded;
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
System.loadLibrary("unsafe");
|
||||||
|
_loaded = init();
|
||||||
|
} catch (UnsatisfiedLinkError e) {
|
||||||
|
Log.warning("Failed to load 'unsafe' library: " + e + ".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||||
|
#include <jni.h>
|
||||||
|
/* Header for class com_threerings_util_unsafe_Unsafe */
|
||||||
|
|
||||||
|
#ifndef _Included_com_threerings_util_unsafe_Unsafe
|
||||||
|
#define _Included_com_threerings_util_unsafe_Unsafe
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* Inaccessible static: _gcEnabled */
|
||||||
|
/* Inaccessible static: _loaded */
|
||||||
|
/*
|
||||||
|
* Class: com_threerings_util_unsafe_Unsafe
|
||||||
|
* Method: enableGC
|
||||||
|
* Signature: ()V
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL Java_com_threerings_util_unsafe_Unsafe_enableGC
|
||||||
|
(JNIEnv *, jclass);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: com_threerings_util_unsafe_Unsafe
|
||||||
|
* Method: disableGC
|
||||||
|
* Signature: ()V
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL Java_com_threerings_util_unsafe_Unsafe_disableGC
|
||||||
|
(JNIEnv *, jclass);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: com_threerings_util_unsafe_Unsafe
|
||||||
|
* Method: nativeSleep
|
||||||
|
* Signature: (I)V
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL Java_com_threerings_util_unsafe_Unsafe_nativeSleep
|
||||||
|
(JNIEnv *, jclass, jint);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: com_threerings_util_unsafe_Unsafe
|
||||||
|
* Method: init
|
||||||
|
* Signature: ()Z
|
||||||
|
*/
|
||||||
|
JNIEXPORT jboolean JNICALL Java_com_threerings_util_unsafe_Unsafe_init
|
||||||
|
(JNIEnv *, jclass);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
#
|
||||||
|
# $Id: Makefile,v 1.1 2003/05/08 21:25:20 mdb Exp $
|
||||||
|
|
||||||
|
#
|
||||||
|
# Executable definitions
|
||||||
|
|
||||||
|
CC=gcc
|
||||||
|
RM=rm
|
||||||
|
CP=cp
|
||||||
|
MKDIR=mkdir
|
||||||
|
|
||||||
|
#
|
||||||
|
# Directory definitions
|
||||||
|
|
||||||
|
ROOT=../../../../../../..
|
||||||
|
LIBRARIES_PATH=-L/usr/X11R6/lib
|
||||||
|
INSTALL_PATH=${ROOT}/dist/lib/i686-Linux
|
||||||
|
|
||||||
|
#
|
||||||
|
# Parameter and file definitions
|
||||||
|
|
||||||
|
INCLUDES=-I.. -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux
|
||||||
|
LIBRARIES=-lX11
|
||||||
|
TARGET=libunsafe.so
|
||||||
|
INSTALL_TARGET=${INSTALL_PATH}/${TARGET}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Target definitions
|
||||||
|
|
||||||
|
all: ${INSTALL_TARGET}
|
||||||
|
|
||||||
|
${INSTALL_TARGET}: com_threerings_util_unsafe_Unsafe.c
|
||||||
|
@echo Compiling Unsafe.c
|
||||||
|
@${CC} ${INCLUDES} -c com_threerings_util_unsafe_Unsafe.c \
|
||||||
|
-o com_threerings_util_unsafe_Unsafe.o
|
||||||
|
@echo Creating ${TARGET}
|
||||||
|
@${MKDIR} -p ${INSTALL_PATH}
|
||||||
|
@${CC} -o ${INSTALL_TARGET} com_threerings_util_unsafe_Unsafe.o \
|
||||||
|
${LIBRARIES} ${LIBRARIES_PATH} -shared
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-${RM} *.o
|
||||||
|
-${RM} ${INSTALL_TARGET}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* $Id: com_threerings_util_unsafe_Unsafe.c,v 1.1 2003/05/08 21:25:20 mdb Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <jni.h>
|
||||||
|
#include <jvmpi.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "com_threerings_util_unsafe_Unsafe.h"
|
||||||
|
|
||||||
|
/* global jvmpi interface pointer */
|
||||||
|
static JVMPI_Interface* jvmpi;
|
||||||
|
|
||||||
|
/** A sleep method that uses select(). This seems to have about 10ms
|
||||||
|
* granularity where nanosleep() has about 20ms. Sigh. */
|
||||||
|
static int select_sleep (int millisecs)
|
||||||
|
{
|
||||||
|
fd_set dummy;
|
||||||
|
struct timeval toWait;
|
||||||
|
FD_ZERO(&dummy);
|
||||||
|
toWait.tv_sec = millisecs / 1000;
|
||||||
|
toWait.tv_usec = (millisecs % 1000) * 1000;
|
||||||
|
return select(0, &dummy, NULL, NULL, &toWait);
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
Java_com_threerings_util_unsafe_Unsafe_enableGC (JNIEnv* env, jclass clazz)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Reenabling GC.\n");
|
||||||
|
jvmpi->EnableGC();
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
Java_com_threerings_util_unsafe_Unsafe_disableGC (JNIEnv* env, jclass clazz)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Disabling GC.\n");
|
||||||
|
jvmpi->DisableGC();
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
Java_com_threerings_util_unsafe_Unsafe_nativeSleep (
|
||||||
|
JNIEnv* env, jclass clazz, jint millis)
|
||||||
|
{
|
||||||
|
/* struct timespec tmspec; */
|
||||||
|
/* tmspec.tv_sec = millis/1000; */
|
||||||
|
/* tmspec.tv_nsec = (millis%1000)*1000000; */
|
||||||
|
/* if (nanosleep(&tmspec, NULL) < 0) { */
|
||||||
|
/* fprintf(stderr, "nanosleep() failed: %s\n", strerror(errno)); */
|
||||||
|
/* } */
|
||||||
|
if (select_sleep(millis) < 0) {
|
||||||
|
fprintf(stderr, "select_sleep() failed: %s\n", strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jboolean JNICALL
|
||||||
|
Java_com_threerings_util_unsafe_Unsafe_init (JNIEnv* env, jclass clazz)
|
||||||
|
{
|
||||||
|
JavaVM* jvm;
|
||||||
|
|
||||||
|
if ((*env)->GetJavaVM(env, &jvm) > 0) {
|
||||||
|
fprintf(stderr, "Failed to get JavaVM from env.\n");
|
||||||
|
return JNI_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get jvmpi interface pointer */
|
||||||
|
if (((*jvm)->GetEnv(jvm, (void**)&jvmpi, JVMPI_VERSION_1)) < 0) {
|
||||||
|
fprintf(stderr, "Failed to get JVMPI from JavaVM.\n");
|
||||||
|
return JNI_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return JNI_TRUE;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user