#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; inhandle; 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; ine; 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; ilk); 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); }