OS/2, eCS & ArcaOS - Technical > Programming

OW, JNI (GCC built java 1.6) and parameters

<< < (2/3) > >>

Lars:
I think the problem he tries to catch is that some DLLs keep resetting the FPU control word to what they think is correct. So if you call a routine in those DLLs, the FPU control word will be modified when the call returns (which of course is bad,bad,bad).
Jan-Erik does set the FPU control word to what he wants (namely, to disable all FPU exceptions).
But then he wants to register an exception handler so that if something resets the FPU control word and subsequently an FPU exception occurs he can reset the FPU control word to what he wants (namely, to disable all FPU exceptions)

Gregg Young:
An exception handler for this was added to libcx 0.6.4. Simply linking to libcx should take care of this.

Jan-Erik Lärka:
This originate from http://trac.netlabs.org/java/ticket/245 and the reply to http://lvzuufx.blogspot.com/2014/09/os2-codes-prevent-sigfpe.html
I like the idea to write once and use everywhere, so the file was my interpretation of the blog post, how to to solve the problem .

OW GUI resemble Borland C++ that was taught out at school where one add the files to compile and it ... figure out how to create the exe.
The #define INITPROC(...) is what I came up with to address the limitation to call gcc built dlls from code compiled with OW.

Lars is quite right, but I can't quite grasp how/where to change the code to get it right. I also downloaded and looked at the code for XWPDeamon, but can't quite see/figure it out from there either.
I would appreciate a direct rewrite of the code to help me out.

Regards,
//Jan-Erik

Jan-Erik Lärka:
This is what I tried:

Ripped some of the code out and created reusable #define that I call with
AddFPEHandler();
...
main(...) {
    InitNoFPE( javm );
    NoFPE( javm, client\\jvm, . );
...
The problem I face now is that the fpeHandler get called twice followed by a bunch of java class loading/debug lines before it stop (but doesn't end) and use up a cpu core.

How do I get passed that?


--- Code: ---/* r = return type, f = funtion name, p = parameter(s) */
#define InitFunc( h, r, f, p )                     \
    r( __syscall *f)p;                             \
    rc = DosQueryProcAddr( h, NULL, "_"#f, (PFN *) &f ); /*GCC*/\
    if( rc != 0 )                                  \
        rc = DosQueryProcAddr( h, NULL, #f, (PFN *) &f );/*OW*/

/* v = variable name */
#define InitNoFPE( v )                             \
    EXCEPTIONREGISTRATIONRECORD ex = { 0, };       \
    LoadLib *v = new LoadLib();                    \
    _control87( 0, MCW_EM );                       \
    if( v ) {                                      \
        ex.ExceptionHandler = ( ERR )fpeHandler;   \
        DosSetExceptionHandler( &ex );             \
    }

/* v = variable name, n = name of dll, p = path to dll */
#define NoFPE( v, n, p )                           \
    v->LoadLibrary( #n, #p );                      \
    if( v->rc == NO_ERROR ) {                      \
        _control87( 0, MCW_EM );                   \
        DosSetExceptionHandler( &ex );             \
    }

// this handler was excerpted from Mozilla repository
#define AddFPEHandler()                            \
static ULONG fpeHandler( PEXCEPTIONREPORTRECORD p1,\
                   PEXCEPTIONREGISTRATIONRECORD p2,\
                   PCONTEXTRECORD p3,              \
                   PVOID p4 )                      \
{                                                  \
    switch( p1->ExceptionNum )                     \
    {                                              \
        case XCPT_FLOAT_DENORMAL_OPERAND:          \
        case XCPT_FLOAT_DIVIDE_BY_ZERO:            \
        case XCPT_FLOAT_INEXACT_RESULT:            \
        case XCPT_FLOAT_INVALID_OPERATION:         \
        case XCPT_FLOAT_OVERFLOW:                  \
        case XCPT_FLOAT_STACK_CHECK:               \
        case XCPT_FLOAT_UNDERFLOW:                 \
        {                                          \
            unsigned cw = p3->ctx_env[0];          \
            if( ( cw & MCW_EM ) != MCW_EM ) {      \
            /* Mask out all floating point exceptions */\
                p3->ctx_env[0] |= MCW_EM;          \
            /* Following two lines set precision to 53 bit mantissa. See jsnum.c */\
                p3->ctx_env[0] &= ~MCW_PC;         \
                p3->ctx_env[0] |= PC_53;           \
                printf("----- XCPT_CONTINUE_EXECUTION\n");\
                return XCPT_CONTINUE_EXECUTION;    \
            }                                      \
            break;                                 \
        }                                          \
    }                                              \
    return XCPT_CONTINUE_SEARCH;                   \
}
--- End code ---

Lars:
class LoadLib {
...

public:
    EXCEPTIONREGISTRATIONRECORD *pex;
...
    LoadLib( EXCEPTIONREGISTRATIONRECORD *prec, PSZ pszLibrName = "", PSZ pszLibrPath = ".", bool fpe = true) {
    pex = prec;
    memset(pex,0,sizeof(*pex));
    ...
    pex->ExceptionHandler = ( ERR )fpeHandler;
    DosSetExceptionHandler( pex);
    ...

    ~LoadLib() {
         if (pex->ExceptionHandler)
              DosUnsetExceptionHandler(pex);
     ....


call:

JNIEnv* create_vm(EXCEPTIONREGISTRATIONRECORD *pex) {
    javm = new LoadLib( pex,"client\\jvm" );//, ".", false ); //when used with sqlite3 and cairo
    ...


int main( int argc, char **argv ) {
    EXCEPTIONREGISTRATIONRECORD ex;
    JNIEnv* env = create_vm(&ex);
    ...
    delete javm; <---- your forgot this one ...
    return 0;
}


Just one thing to note: be aware that an exception handler can only be registered for the CURRENT stack frame (and everything called directly or indirectly from this point).
That is, you need to do "delete javm" BEFORE you return from the function where you called "new LoadLibrary". That also means you cannot pass around the LoadLibrary object and then return from the function registering it.

Also be aware that you need to set exception handlers PER THREAD. You cannot do a "new LoadLibrary" and then expect the exception handler to work from another thread (but see above, it's forbidden to pass around the object anyways).



       

Navigation

[0] Message Index

[#] Next page

[*] Previous page

Go to full version