#include <9pm/windows.h>
#include <9pm/u.h>
#include <9pm/libc.h>
#include <9pm/fcall.h>
#include "dat.h"
#include "fns.h"
#include "syscall.h"
enum
{
MaxHandle = MAXIMUM_WAIT_OBJECTS,
};
typedef struct Hproc Hproc;
struct Hproc
{
Lock lk;
HANDLE h[MaxHandle];
Hwait *w[MaxHandle];
int nhandle, nahandle;
Hwait *add;
Hwait *remove;
};
Lock hproclk;
Lock halloclk;
Hproc *hproc[64];
static void
removew(Hproc *hp, Hwait *w)
{
int i, ne;
Hwait *ww;
ne = w->ne;
hp->nhandle -= ne;
hp->nahandle -= ne;
for(i=w->first; i<hp->nhandle; i++){
hp->h[i] = hp->h[i+ne];
hp->w[i] = ww = hp->w[i+ne];
if(i+ne == ww->first)
ww->first = i;
}
}
static void
addw(Hproc *hp, Hwait *w)
{
int i;
if(hp->nhandle+w->ne > MaxHandle)
panic("addw");
w->first = hp->nhandle;
for(i=0; i<w->ne; i++, hp->nhandle++){
hp->h[hp->nhandle] = w->e[i].h;
hp->w[hp->nhandle] = w;
}
}
DWORD WINAPI
hwaitthread(void *a)
{
int s, ret;
Hproc *hp;
Hwait *w, *wnext;
setmach(&nomach);
hp = a;
for(;;){
ret = WaitForMultipleObjects(hp->nhandle, hp->h, 0, INFINITE);
if(ret < WAIT_OBJECT_0 || ret >= WAIT_OBJECT_0+hp->nhandle)
panic("hwaitthread");
// print("WaitForMultipleObjects woke up\n");
ret -= WAIT_OBJECT_0;
s = splhi();
lock(&hp->lk);
splx(s);
if(ret == 0){
for(w=hp->remove; w; w=wnext){
wnext = w->nextremove;
removew(hp, w);
w->removed = 1;
}
hp->remove = nil;
for(w=hp->add; w; w=wnext){
wnext = w->nextadd;
addw(hp, w);
}
hp->add = nil;
if(hp->nahandle != hp->nhandle)
panic("hwaitproc nahandle");
}else{
w = hp->w[ret];
w->alt = ret - w->first;
removew(hp, w);
rendwakeup(&w->r);
}
unlock(&hp->lk);
}
return 0; /* not reached */
}
Hproc*
hwaitproc(Hwait *w)
{
int i, s;
Hproc *hp;
if(w->ne > MaxHandle-1)
panic("hwaitproc");
s = splhi();
Again:
lock(&hproclk);
for(i=0; i<nelem(hproc); i++){
hp = hproc[i];
if(hp == nil)
break;
lock(&hp->lk);
if(hp->nahandle+w->ne < MaxHandle)
break;
unlock(&hp->lk);
}
splx(s);
if(i == nelem(hproc))
panic("hwaitproc");
if(hp == nil){
lock(&halloclk);
unlock(&hproclk);
if(hproc[i] != nil){
unlock(&halloclk);
goto Again;
}
hp = smalloc(sizeof(Hproc));
hp->nhandle = 1;
hp->nahandle = 1;
hp->h[0] = CreateSemaphore(nil, 0, 1, nil);
if(hp->h[0] == nil)
panic("hwaitproc create semaphore");
CreateThread(nil, 8192, hwaitthread, hp, 0, nil);
hproc[i] = hp;
unlock(&halloclk);
goto Again;
}
unlock(&hproclk);
w->alt = -1;
w->nextadd = hp->add;
hp->add = w;
hp->nahandle += w->ne;
unlock(&hp->lk);
ReleaseSemaphore(hp->h[0], 1, nil);
return hp;
}
static int
fired(Hwait *w)
{
return w->alt >= 0;
}
void
handlewait(Hwait *w)
{
Hproc *hp;
hp = hwaitproc(w);
rendsleep(&w->r, fired, w);
if(w->alt != -1)
return;
lock(&hp->lk);
if(w->alt != -1){
unlock(&hp->lk);
return;
}
w->nextremove = hp->remove;
hp->remove = w;
w->removed = 0;
unlock(&hp->lk);
ReleaseSemaphore(hp->h[0], 1, nil);
while(!w->removed)
Sleep(0);
}
syntax highlighted by Code2HTML, v. 0.9.1