source: trunk/dll/tmrsvcs.c@ 1570

Last change on this file since 1570 was 1570, checked in by Gregg Young, 14 years ago

Added IdleIfNeeded to place load and free loops to idle priority when dealing with large numbers of items. Used SleepIfNeeded more places for a similar purpose.

  • Property svn:keywords set to Author Date Id Revision
File size: 3.3 KB
Line 
1
2/***********************************************************************
3
4 $Id: tmrsvcs.c 1570 2011-06-12 22:09:19Z gyoung $
5
6 Timer services
7
8 Copyright (c) 2008 Steven H. Levine
9
10 05 Jan 08 SHL Baseline
11 12 Jun 11 GKY Added IdleIfNeeded to the container/list fill and free loops to improve system
12 responsiveness when dealing with large numbers of items
13
14***********************************************************************/
15
16#define INCL_DOS // QSV_MS_COUNT
17
18// #include "errutil.h" // DbgMsg // 05 Jan 08 SHL fixme debug
19#include "tmrsvcs.h"
20
21// static PSZ pszSrcFile = __FILE__; // 05 Jan 08 SHL fixme debug
22
23/**
24 * Prepare interval timer descriptor for use
25 * Call with interval 0 to to reset internal estimators
26 * @param pTD point to interval timer descriptor
27 * @param interval_msec is the timer interval in msec or 0 to retain existing value
28 */
29
30VOID InitITimer(ITIMER_DESC *pitd, UINT interval_msec)
31{
32 if (interval_msec) {
33 // Assume starting new loop at similar rate
34 pitd->interval_msec = interval_msec;
35 pitd->remaining = pitd->estimated;
36 }
37 else {
38 // Assume loop rate is changing to a significantly lower value
39 pitd->remaining = 0;
40 pitd->estimated = 1; // Force rate recalc
41 }
42 DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &pitd->start_msec, sizeof(pitd->start_msec));
43}
44
45/**
46 * Check timer interval expired
47 * Attempts to optimize calls to fetch QSV_MS_COUNT
48 * Caller should reinit if processing rate changes
49 * @return TRUE if expired
50 */
51
52BOOL IsITimerExpired(ITIMER_DESC *pitd)
53{
54 INT err_msec;
55 ULONG cur_msec;
56 UINT elapsed_msec;
57 INT cnt;
58
59 if (--pitd->remaining < 0) {
60
61 DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &cur_msec, sizeof(cur_msec));
62 elapsed_msec = cur_msec - pitd->start_msec;
63 if (elapsed_msec == pitd->interval_msec) {
64 pitd->remaining = pitd->estimated;
65 pitd->start_msec = cur_msec;
66 pitd->misses = 0;
67 return TRUE; // Say interval expired
68 }
69
70 pitd->misses++;
71 err_msec = (cur_msec - pitd->start_msec) - pitd->interval_msec;
72 // Estimate counts per msec
73 if (err_msec > 0) {
74 // Late - need to reduce estimated count
75 if (elapsed_msec)
76 pitd->estimated = pitd->estimated * pitd->interval_msec / elapsed_msec;
77 else {
78 // Should not occur
79 if (pitd->estimated)
80 pitd->estimated--;
81 }
82 // Calc counts for next interval
83 pitd->remaining = pitd->estimated -
84 (pitd->estimated * err_msec / pitd->interval_msec);
85 pitd->start_msec += pitd->interval_msec;
86 return TRUE;
87 }
88
89 // Early - need to increase estimated count
90 cnt = pitd->estimated * (-err_msec) / pitd->interval_msec;
91 if (!cnt) {
92 if (pitd->estimated)
93 cnt = pitd->estimated * 2;
94 else
95 cnt = 1;
96 }
97 pitd->estimated += cnt;
98 pitd->remaining = cnt;
99 }
100 return FALSE; // Keep waiting
101}
102
103VOID SleepIfNeeded(ITIMER_DESC *pitd, UINT sleepTime)
104{
105 if (IsITimerExpired(pitd)) {
106 DosSleep(sleepTime);
107 InitITimer(pitd, 0);
108 }
109}
110
111ULONG IdleIfNeeded(ITIMER_DESC *pitd, LONG delta)
112{
113 APIRET rc;
114
115 if (IsITimerExpired(pitd)) {
116 rc = DosSetPriority(PRTYS_THREAD,PRTYC_IDLETIME,delta,0L);
117 InitITimer(pitd, 0);
118 return rc;
119 }
120 return 1;
121}
122
123#pragma alloc_text(TMRSVCS,InitITimer,IsITimerExpired,SleepIfNeeded,IdleIfNeeded)
Note: See TracBrowser for help on using the repository browser.