/*
 * $Header: /p/sss/cvs/OpenVM/src/native/common/include/eventmanager.h,v 1.19 2004/09/02 00:42:10 pizlofj Exp $
 * eventmanager.c -- C-land code for the event manager.  this here code
 *                   helps facilitate our fast poll check that happens once
 *                   every couple instructions.  it also helps the VM
 *                   block for events whenever it needs to do so.
 *                   if you wish to learn how the Java code works that
 *                   actually makes this code useful, look at
 *                   ovm.services.events.EventManager and
 *                   s3.services.events.EventManagerImpl.
 * by Filip and David.
 */

#ifndef _EVENTMANAGER_H
#define _EVENTMANAGER_H

#include "jtypes.h"
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>


typedef void (*VOID_FPTR)(void);
extern volatile VOID_FPTR signal_event;
extern volatile VOID_FPTR signal_event_from_thread;

#ifndef OLDE_STYLE_POLLCHECK

typedef union {
    struct {
        /* these flags are 'reversed' to ensure that the pollcheck involves
           a compare-to-zero, which can be easier to do on some platforms. */
        volatile jshort notSignaled;
        volatile jshort notEnabled;
    } _;
    volatile jint oneTrueWord;
} eventUnion_t;

extern eventUnion_t eventUnion;

#define CHECK_EVENTS() (!eventUnion.oneTrueWord)
#define CHECK_EVENT_SIGNALED() (!eventUnion._.notSignaled)
#define SIGNAL_EVENT_FOR_POLL_CHECK() (eventUnion._.notSignaled=0)
#define RESET_EVENTS() (eventUnion._.notSignaled=1)
#define EVENTS_SET_ENABLED(value) (eventUnion._.notEnabled=!value)

#else

#warning "Using the Olde-Style Pollcheck"

extern volatile sig_atomic_t eventSignaled;
extern volatile jboolean eventsEnabled;

#define CHECK_EVENTS() (eventSignaled&&eventsEnabled)
#define CHECK_EVENT_SIGNALED() (eventSignaled)
#define SIGNAL_EVENT_FOR_POLL_CHECK() (eventSignaled=1)
#define RESET_EVENTS() (eventSignaled=0)
#define EVENTS_SET_ENABLED(value) (eventsEnabled=enabled)

#endif

#define SIGNAL_EVENT() do {\
    if (signal_event!=NULL) {\
        signal_event();\
    }\
} while (0)

#define SIGNAL_EVENT_FROM_THREAD() do {\
    if (signal_event_from_thread!=NULL) {\
        signal_event_from_thread();\
    }\
} while (0)

#ifdef IN_EVENTMANAGER_C
# define EVENTMANAGER_INLINE
#else 
# define EVENTMANAGER_INLINE static inline
#endif

/** enable/disable event processing */
/* Warning: this is hand-inlined in SimpleJIT. If you change this
 * function, turn off the hand inlinig or update SimpleJIT */
EVENTMANAGER_INLINE void eventsSetEnabled(jboolean enabled) {
    EVENTS_SET_ENABLED(enabled);
}

/* Warning: this is hand-inlined in SimpleJIT. If you change this
 * function, turn off the hand inlinig or update SimpleJIT */
EVENTMANAGER_INLINE jboolean eventPollcheck() {
    if (CHECK_EVENTS()) {
        RESET_EVENTS();
        eventsSetEnabled(0);
        return 1;
    }
    return 0;
}

/* wait for events to happen.  will not return until there
 * is an event. */
extern void waitForEvents();

/* functions for setting up the two trivial signal event implementations */
void makeSignalEventSimple();
void makeSignalEventBroken();
void makeSignalEventFromThreadSimple();
void makeSignalEventFromThreadBroken();

#endif


