static int tek_lib_exec_waitmsg(lua_State *L) { struct LuaExecTask *lexec = tek_lib_exec_check(L); struct TExecBase *TExecBase = lexec->exec; TTIME dt, *pdt = TNULL, destt, nowt; int narg; TAPTR hal = TExecBase->texb_HALBase; struct TMsgPort *port = TGetUserPort(TNULL); struct TNode *node; TUINT sig = TSetSignal(0, 0) & (TTASK_SIG_USER | TTASK_SIG_ABORT); tek_lib_exec_checkabort(L, lexec->exec, sig); dt.tdt_Int64 = luaL_optnumber(L, 1, 0) * 1000; if (dt.tdt_Int64) { TGetSystemTime(&destt); TAddTime(&destt, &dt); pdt = &dt; } for (;;) { THALLock(hal, &port->tmp_Lock); node = port->tmp_MsgList.tlh_Head.tln_Succ; if (node->tln_Succ == TNULL) node = TNULL; THALUnlock(hal, &port->tmp_Lock); if (node) break; sig = TWaitTime(pdt, TTASK_SIG_USER | TTASK_SIG_ABORT); tek_lib_exec_checkabort(L, lexec->exec, sig); if (sig == 0) break; if (pdt) { dt = destt; TGetSystemTime(&nowt); TSubTime(&dt, &nowt); } } narg = tek_lib_exec_getmsg(L); return tek_lib_exec_return_sig2string(L, sig, narg); }
static TUINT hal_timedwaitevent(struct THALBase *hal, struct HALThread *t, TTIME *tektime, TUINT sigmask) { struct HALSpecific *hws = hal->hmb_Specific; struct HALThread *wth = TlsGetValue(hws->hsp_TLSIndex); TTIME waitt, curt; TUINT millis; TUINT sig; for (;;) { #ifndef HAL_USE_ATOMICS EnterCriticalSection(&wth->hth_SigLock); sig = wth->hth_SigState & sigmask; wth->hth_SigState &= ~sigmask; LeaveCriticalSection(&wth->hth_SigLock); #else sig = InterlockedAnd(&wth->hth_SigState, ~sigmask) & sigmask; #endif if (sig) break; waitt = *tektime; hal_getsystime(hal, &curt); TSubTime(&waitt, &curt); if (waitt.tdt_Int64 < 0) break; if (waitt.tdt_Int64 > 1000000000000LL) millis = 1000000000; else millis = waitt.tdt_Int64 / 1000; if (millis > 0) WaitForSingleObject(wth->hth_SigEvent, millis); } return sig; }
static TUINT hal_timedwaitevent(struct THALBase *hal, struct HALThread *t, TTIME *tektime, TUINT sigmask) { struct HALSpecific *hws = hal->hmb_Specific; struct HALThread *wth = TlsGetValue(hws->hsp_TLSIndex); TTIME waitt, curt; TUINT millis; TUINT sig; for (;;) { EnterCriticalSection(&wth->hth_SigLock); sig = wth->hth_SigState & sigmask; wth->hth_SigState &= ~sigmask; LeaveCriticalSection(&wth->hth_SigLock); if (sig) break; waitt = *tektime; hal_getsystime(hal, &curt); TSubTime(&waitt, &curt); if (waitt.ttm_Sec < 0) break; if (waitt.ttm_Sec > 1000000) millis = 1000000000; else { millis = waitt.ttm_Sec * 1000; millis += waitt.ttm_USec / 1000; } if (millis > 0) WaitForSingleObject(wth->hth_SigEvent, millis); } return sig; }
EXPORT void hal_beginio(struct THALBase *hal, struct TTimeRequest *req) { struct HALSpecific *hws = hal->hmb_Specific; TAPTR exec = hws->hsp_ExecBase; TTIME curtime; TINT64 x = 0; switch (req->ttr_Req.io_Command) { /* execute asynchronously */ case TTREQ_WAITLOCALDATE: /* microseconds west of GMT: */ x = hal_getdstfromlocaldate(hal, &req->ttr_Data.ttr_Date); x *= 1000000; case TTREQ_WAITUNIVERSALDATE: x += req->ttr_Data.ttr_Date.tdt_Int64; x -= 11644473600000000ULL; req->ttr_Data.ttr_Date.tdt_Int64 = x; #ifndef USE_MMTIMER hal_getsystime(hal, &curtime); TSubTime(&req->ttr_Data.ttr_Time, &curtime); #endif goto addtimereq; case TTREQ_WAITTIME: #ifdef USE_MMTIMER hal_getsystime(hal, &curtime); TAddTime(&req->ttr_Data.ttr_Time, &curtime); #endif addtimereq: { #ifdef USE_MMTIMER struct TMessage *msg = TGETMSGPTR(req); EnterCriticalSection(&hws->hsp_DevLock); msg->tmsg_Flags = TMSG_STATUS_SENT | TMSGF_QUEUED; msg->tmsg_RPort = req->ttr_Req.io_ReplyPort; TAddTail(&hws->hsp_ReqList, (struct TNode *) req); LeaveCriticalSection(&hws->hsp_DevLock); #else TExecPutMsg(exec, TExecGetUserPort(exec, hws->hsp_DevTask), req->ttr_Req.io_ReplyPort, req); #endif return; } /* execute synchronously */ default: case TTREQ_GETUNIVERSALDATE: { TINT timezone_bias; hal_getsysdate(hal, &req->ttr_Data.ttr_Date, &timezone_bias); break; } case TTREQ_GETLOCALDATE: hal_getsysdate(hal, &req->ttr_Data.ttr_Date, TNULL); break; case TTREQ_GETSYSTEMTIME: hal_getsystime(hal, &req->ttr_Data.ttr_Time); break; #if 0 case TTREQ_GETDSFROMDATE: req->ttr_Data.ttr_DSSec = hal_dsfromdate(hal, &req->ttr_Data.ttr_Date.ttr_Date); break; #endif } req->ttr_Req.io_Error = 0; if (!(req->ttr_Req.io_Flags & TIOF_QUICK)) { /* async operation indicated; reply to self */ TExecReplyMsg(exec, req); } }
static void fb_runinstance(TAPTR task) { struct TExecBase *TExecBase = TGetExecBase(task); WINDISPLAY *mod = TGetTaskData(task); struct TVRequest *req; TUINT sig; /* interval time: 1/50s: */ TTIME intt = { 20000 }; /* next absolute time to send interval message: */ TTIME nextt; TTIME waitt, nowt; TGetSystemTime(&nextt); TAddTime(&nextt, &intt); TDBPRINTF(TDB_INFO,("Device instance running\n")); do { TBOOL do_interval = TFALSE; while ((req = TGetMsg(mod->fbd_CmdPort))) { fb_docmd(mod, req); TReplyMsg(req); } fb_notifywindows(mod); /* calculate new delta to wait: */ TGetSystemTime(&nowt); waitt = nextt; TSubTime(&waitt, &nowt); TWaitTime(&waitt, mod->fbd_CmdPortSignal); /* check if time interval has expired: */ TGetSystemTime(&nowt); if (TCmpTime(&nowt, &nextt) > 0) { /* expired; send interval: */ do_interval = TTRUE; TAddTime(&nextt, &intt); if (TCmpTime(&nowt, &nextt) >= 0) { /* nexttime expired already; create new time from now: */ nextt = nowt; TAddTime(&nextt, &intt); } } /* send out input messages: */ fb_sendimessages(mod, do_interval); /* get signal state: */ sig = TSetSignal(0, TTASK_SIG_ABORT); } while (!(sig & TTASK_SIG_ABORT)); TDBPRINTF(TDB_INFO,("Device instance closedown\n")); fb_exitinstance(mod); }
static void rfb_runtask(struct TTask *task) { TAPTR TExecBase = TGetExecBase(task); RFBDISPLAY *mod = TGetTaskData(task); struct TVRequest *req; TUINT sig; TTIME intt = { RAWFB_INTERVAL_MICROS }; /* next absolute time to send interval message: */ TTIME nextt; TTIME waitt, nowt; TAPTR cmdport = TGetUserPort(task); TUINT cmdportsignal = TGetPortSignal(cmdport); TUINT imsgportsignal = TGetPortSignal(mod->rfb_RndIMsgPort); TDBPRINTF(TDB_INFO,("RawFB device context running\n")); TGetSystemTime(&nowt); nextt = nowt; TAddTime(&nextt, &intt); do { /* process input messages: */ rfb_processevent(mod); /* do draw commands: */ while ((req = TGetMsg(cmdport))) { rfb_docmd(mod, req); TReplyMsg(req); } /* check if time interval has expired: */ TGetSystemTime(&nowt); if (TCmpTime(&nowt, &nextt) > 0) { /* expired; send intervals: */ TLock(mod->rfb_InstanceLock); struct TNode *next, *node = mod->rfb_VisualList.tlh_Head; for (; (next = node->tln_Succ); node = next) { RFBWINDOW *v = (RFBWINDOW *) node; TIMSG *imsg; if ((v->rfbw_InputMask & TITYPE_INTERVAL) && rfb_getimsg(mod, v, &imsg, TITYPE_INTERVAL)) TPutMsg(v->rfbw_IMsgPort, TNULL, imsg); } TUnlock(mod->rfb_InstanceLock); TAddTime(&nextt, &intt); } /* calculate new wait time: */ waitt = nextt; TGetSystemTime(&nowt); TSubTime(&waitt, &nowt); if (waitt.tdt_Int64 <= 0 || waitt.tdt_Int64 > RAWFB_INTERVAL_MICROS) { /* something's wrong with the clock, recalculate */ TDBPRINTF(TDB_INFO,("clock problem: %lld\n", waitt.tdt_Int64)); nextt = nowt; TAddTime(&nextt, &intt); waitt = nextt; TSubTime(&waitt, &nowt); } sig = TWaitTime(&waitt, cmdportsignal | imsgportsignal | TTASK_SIG_ABORT); } while (!(sig & TTASK_SIG_ABORT)); TDBPRINTF(TDB_INFO,("RawFB device context closedown\n")); rfb_exittask(mod); }
static void rfb_runtask(struct TTask *task) { TAPTR TExecBase = TGetExecBase(task); struct rfb_Display *mod = TGetTaskData(task); struct TVRequest *req; TUINT sig = 0; TTIME intt = { 20000 }; /* next absolute time to send interval message: */ TTIME nextt; TTIME waitt, nowt, *pwaitt; TAPTR cmdport = TGetUserPort(task); TUINT cmdportsignal = TGetPortSignal(cmdport); TUINT imsgportsignal = TGetPortSignal(mod->rfb_RndIMsgPort); TUINT waitsigs = cmdportsignal | imsgportsignal | TTASK_SIG_ABORT; TDBPRINTF(TDB_INFO, ("RawFB device context running\n")); TGetSystemTime(&nowt); nextt = nowt; TAddTime(&nextt, &intt); do { if (sig & cmdportsignal) { TBOOL checkrect = mod->rfb_Flags & RFBFL_PTR_VISIBLE; TINT arec[4]; while ((req = TGetMsg(cmdport))) { if (checkrect) { TINT res = rfb_cmdrectaffected(mod, req, arec, TTRUE); if (res < 0 || (res > 0 && REGION_OVERLAPRECT(mod->rfb_PtrBackBuffer.rect, arec))) { rfb_restoreptrbg(mod); checkrect = TFALSE; } } rfb_docmd(mod, req); TReplyMsg(req); } } if (mod->rfb_Flags & RFBFL_SHOWPTR) rfb_drawpointer(mod); /* check if time interval has expired: */ TGetSystemTime(&nowt); /* do interval timers */ if (mod->rfb_NumInterval > 0) { if (TCmpTime(&nowt, &nextt) >= 0) { /* expired; send intervals: */ TLock(mod->rfb_InstanceLock); struct TNode *next, *node = mod->rfb_VisualList.tlh_Head.tln_Succ; for (; (next = node->tln_Succ); node = next) { struct rfb_Window *v = (struct rfb_Window *) node; TIMSG *imsg; if ((v->rfbw_InputMask & TITYPE_INTERVAL) && rfb_getimsg(mod, v, &imsg, TITYPE_INTERVAL)) TPutMsg(v->rfbw_IMsgPort, TNULL, imsg); } TUnlock(mod->rfb_InstanceLock); TAddTime(&nextt, &intt); } /* calculate new wait time: */ waitt = nextt; TSubTime(&waitt, &nowt); if (waitt.tdt_Int64 <= 0 || waitt.tdt_Int64 > 20000) { nextt = nowt; TAddTime(&nextt, &intt); waitt = nextt; TSubTime(&waitt, &nowt); } pwaitt = &waitt; } else pwaitt = TNULL; #if defined(ENABLE_LINUXFB) rfb_linux_wait(mod, pwaitt); sig = TSetSignal(0, waitsigs); #else sig = TWaitTime(pwaitt, waitsigs); #endif if (sig & imsgportsignal) rfb_processevent(mod); } while (!(sig & TTASK_SIG_ABORT)); TDBPRINTF(TDB_INFO, ("RawFB device context closedown\n")); rfb_exittask(mod); }
LOCAL void x11_taskfunc(struct TTask *task) { TAPTR TExecBase = TGetExecBase(task); struct X11Display *inst = TGetTaskData(task); TUINT sig = 0; fd_set rset; struct TVRequest *req; TIMSG *imsg; char buf[256]; struct timeval tv, *ptv; struct TMsgPort *cmdport = TGetUserPort(task); TUINT cmdportsignal = TGetPortSignal(cmdport); TUINT ireplysignal = TGetPortSignal(inst->x11_IReplyPort); TUINT waitsigs = cmdportsignal | ireplysignal | TTASK_SIG_ABORT; /* interval time: 1/50s: */ TTIME intt = { 20000 }; /* next absolute time to send interval message: */ TTIME nextt; TTIME waitt, nowt; TDBPRINTF(TDB_INFO, ("Device instance running\n")); TGetSystemTime(&nowt); nextt = nowt; TAddTime(&nextt, &intt); do { if (sig & ireplysignal) { while ((imsg = TGetMsg(inst->x11_IReplyPort))) { /* returned input message */ if (imsg->timsg_Type == TITYPE_REQSELECTION) { XSelectionEvent *reply = (XSelectionEvent *) imsg->timsg_Requestor; struct TTagItem *replytags = (struct TTagItem *) imsg->timsg_ReplyData; size_t len = TGetTag(replytags, TIMsgReply_UTF8SelectionLen, 0); TUINT8 *xdata = (TUINT8 *) TGetTag(replytags, TIMsgReply_UTF8Selection, TNULL); XChangeProperty(inst->x11_Display, reply->requestor, reply->property, XA_ATOM, 8, PropModeReplace, (unsigned char *) xdata, len); XSendEvent(inst->x11_Display, reply->requestor, 0, NoEventMask, (XEvent *) reply); XSync(inst->x11_Display, False); TFree((TAPTR) imsg->timsg_Requestor); TFree(xdata); /* reqselect roundtrip ended */ } TFree(imsg); } } if (sig & cmdportsignal) { while (inst->x11_RequestInProgress == TNULL && (req = TGetMsg(cmdport))) { x11_docmd(inst, req); if (inst->x11_RequestInProgress) break; TReplyMsg(req); } } XFlush(inst->x11_Display); FD_ZERO(&rset); FD_SET(inst->x11_fd_display, &rset); FD_SET(inst->x11_fd_sigpipe_read, &rset); TGetSystemTime(&nowt); if (inst->x11_NumInterval > 0 || inst->x11_RequestInProgress) { if (TCmpTime(&nowt, &nextt) >= 0) { /* expired; send interval: */ struct TNode *next, *node = inst->x11_vlist.tlh_Head.tln_Succ; for (; (next = node->tln_Succ); node = next) { struct X11Window *v = (struct X11Window *) node; TIMSG *imsg; if ((v->eventmask & TITYPE_INTERVAL) && x11_getimsg(inst, v, &imsg, TITYPE_INTERVAL)) TPutMsg(v->imsgport, TNULL, imsg); } TAddTime(&nextt, &intt); } /* calculate new wait time: */ waitt = nextt; TSubTime(&waitt, &nowt); if (waitt.tdt_Int64 <= 0 || waitt.tdt_Int64 > 20000) { nextt = nowt; TAddTime(&nextt, &intt); waitt = nextt; TSubTime(&waitt, &nowt); } tv.tv_sec = waitt.tdt_Int64 / 1000000; tv.tv_usec = waitt.tdt_Int64 % 1000000; ptv = &tv; } else ptv = NULL; /* wait for display, signal fd and timeout: */ if (select(inst->x11_fd_max, &rset, NULL, NULL, ptv) > 0) { int nbytes; /* consume signal: */ if (FD_ISSET(inst->x11_fd_sigpipe_read, &rset)) { ioctl(inst->x11_fd_sigpipe_read, FIONREAD, &nbytes); if (nbytes > 0) if (read(inst->x11_fd_sigpipe_read, buf, TMIN(sizeof(buf), (size_t) nbytes)) != nbytes) TDBPRINTF(TDB_ERROR, ("could not read wakeup signal\n")); } } /* process input messages: */ x11_processevent(inst); /* send out input messages to owners: */ x11_sendimessages(inst); /* get signal state: */ sig = TSetSignal(0, waitsigs); } while (!(sig & TTASK_SIG_ABORT)); TDBPRINTF(TDB_INFO, ("Device instance exit\n")); x11_exitinstance(inst); }