1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
#ifdef AMOEBA
/*
* iopreader.c
*
* $XFree86: mit/server/os/iopreader.c,v 1.1 1993/03/20 04:31:22 dawes Exp $
*
*/
#include <amoeba.h>
#include <ampolicy.h>
#include <cmdreg.h>
#include <stdcom.h>
#include <stderr.h>
#include <server/iop/iop.h>
#include "osdep.h"
#define MAXEVENTQUEUE 32
capability iopcap;
static mutex lock;
static semaphore empty, filled;
static IOPEvent event_queue[MAXEVENTQUEUE];
static int event_qin, event_qout;
void IOPCleanUp();
static void IOPServerReader();
/*
* Initialize the IOP server
*/
void
InitializeIOPServerReader()
{
char host[100];
errstat err;
/*
* Initialize event queue
*/
event_qin = event_qout = 0;
sema_init(&empty, MAXEVENTQUEUE);
sema_init(&filled, 0);
mu_init(&lock);
/*
* Get IOP capability, and enable the server
*/
if (AuServerHostName == NULL)
FatalError("No hostname, no screen\n");
snprintf(host, sizeof host, "%s/%s/%s", HOST_DIR, AuServerHostName,
DEF_IOPSVRNAME);
if ((err = name_lookup(host, &iopcap)) != STD_OK)
FatalError("Cannot find IOP server %s: %s\n", host, err_why(err));
/*
* Enable IOP server
*/
if ((err = iop_enable(&iopcap)) != STD_OK)
FatalError("iop_enable failed (%s)\n", err_why(err));
/*
* Start IOP reader thread
*/
atexit(IOPCleanUp);
if (thread_newthread(IOPServerReader, DEVREADER_STACK, 0, 0) <= 0)
FatalError("Cannot start IOP reader thread\n");
}
/*
* IOP clean up, actuall disable the IOP server. Its the IOP's own choice
* what do do (perhaps restore the screen?).
*/
void
IOPCleanUp()
{
errstat err;
if ((err = iop_disable(&iopcap)) != STD_OK)
ErrorF("iop_disable failed (%s)\n", err_why(err));
}
/*
* This threads polls the IOP server for events. Once an event (or a
* number of events) are read, they are queued up using a traditional
* producer/consumer approach.
*/
static void
IOPServerReader()
{
IOPEvent queue[MAXEVENTQUEUE - 1];
int nevents, i;
errstat err;
WaitForInitialization();
#ifdef XDEBUG
if (amDebug)
ErrorF("IOPServerReader() running ...\n");
#endif
for (;;) {
do {
nevents = MAXEVENTQUEUE - 1;
err = iop_getevents(&iopcap, queue, &nevents);
if (err != STD_OK) {
if (err != RPC_FAILURE) {
ErrorF("iop_getevents failed (%s)\n", err_why(err));
}
nevents = 0;
}
} while (nevents <= 0);
/* store event(s) in the global event queue */
sema_mdown(&empty, nevents);
mu_lock(&lock);
for (i = 0; i < nevents; i++) {
event_queue[event_qin] = queue[i];
event_qin = (event_qin + 1) % MAXEVENTQUEUE;
}
mu_unlock(&lock);
sema_mup(&filled, nevents);
WakeUpMainThread();
}
}
/*
* Return the number of IOP events waiting
*/
int
AmoebaEventsAvailable()
{
return sema_level(&filled);
}
/*
* Get the IOP events from the queue. ``size'' is the maximum the
* requestor cares to handle, the actual size read is returned as
* result.
*/
int
AmoebaGetEvents(queue, size)
IOPEvent *queue;
int size;
{
int nevents, i;
if (sema_level(&filled) <= 0)
return 0;
if ((nevents = sema_level(&filled)) > size)
nevents = size;
sema_mdown(&filled, nevents);
mu_lock(&lock);
for (i = 0; i < nevents; i++) {
queue[i] = event_queue[event_qout];
event_qout = (event_qout + 1) % MAXEVENTQUEUE;
}
mu_unlock(&lock);
sema_mup(&empty, nevents);
return nevents;
}
#endif /* AMOEBA */
|