static void CALLBACK hal_timeproc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) { struct TNode *node, *nnode; if (TryEnterCriticalSection(&g_hws->hsp_DevLock)) { TTIME curtime; hal_getsystime(g_hal, &curtime); node = g_hws->hsp_ReqList.tlh_Head.tln_Succ; for (; (nnode = node->tln_Succ); node = nnode) { struct TTimeRequest *tr = (struct TTimeRequest *) node; if (TCmpTime(&curtime, &tr->ttr_Data.ttr_Time) >= 0) { TRemove(node); TAddTail(&g_ReplyList, node); } } node = g_ReplyList.tlh_Head.tln_Succ; for (; (nnode = node->tln_Succ); node = nnode) { struct TTimeRequest *tr = (struct TTimeRequest *) node; TRemove(node); if (!hal_replytimereq(tr)) TAddHead(&g_ReplyList, node); } LeaveCriticalSection(&g_hws->hsp_DevLock); } }
static void TTASKENTRY hal_devfunc(struct TTask *task) { TAPTR exec = TGetExecBase(task); struct THALBase *hal = TExecGetHALBase(exec); struct HALSpecific *hps = hal->hmb_Specific; struct HALThread *thread = TlsGetValue(hps->hsp_TLSIndex); TAPTR port = TExecGetUserPort(exec, task); struct TTimeRequest *msg; TUINT sig = 0; TTIME waittime, curtime; struct TNode *nnode, *node; waittime.ttm_Sec = 2000000000; waittime.ttm_USec = 0; for (;;) { sig = hal_timedwaitevent(hal, thread, &waittime, TTASK_SIG_ABORT | TTASK_SIG_USER); if (sig & TTASK_SIG_ABORT) break; EnterCriticalSection(&hps->hsp_DevLock); hal_getsystime(hal, &curtime); while ((msg = TExecGetMsg(exec, port))) { TAddTime(&msg->ttr_Data.ttr_Time, &curtime); TAddTail(&hps->hsp_ReqList, (struct TNode *) msg); } waittime.ttm_Sec = 2000000000; waittime.ttm_USec = 0; node = hps->hsp_ReqList.tlh_Head; for (; (nnode = node->tln_Succ); node = nnode) { struct TTimeRequest *tr = (struct TTimeRequest *) node; TTIME *tm = &tr->ttr_Data.ttr_Time; if (TCmpTime(&curtime, tm) >= 0) { TRemove(node); tr->ttr_Req.io_Error = 0; TExecReplyMsg(exec, node); continue; } if (TCmpTime(tm, &waittime) < 0) waittime = *tm; } LeaveCriticalSection(&hps->hsp_DevLock); } TDBPRINTF(2,("goodbye from HAL device\n")); }
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); } }