source: trunk/src/winmm/os2timer.cpp@ 763

Last change on this file since 763 was 763, checked in by phaller, 26 years ago

Fix: debug version doesn't initialize memory with 0

File size: 11.1 KB
Line 
1/* $Id: os2timer.cpp,v 1.12 1999-08-31 20:22:27 phaller Exp $ */
2
3/*
4 * OS/2 Timer class
5 *
6 * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
7 * Copyright 1999 Patrick Haller (phaller@gmx.net)
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12
13
14/****************************************************************************
15 * Includes *
16 ****************************************************************************/
17
18#define INCL_DOSPROCESS
19#define INCL_DOSDATETIME
20#define INCL_DOSSEMAPHORES
21#include <os2wrap.h> //Odin32 OS/2 api wrappers
22#include <process.h>
23#include <win32type.h>
24#include <wprocess.h>
25#include <misc.h>
26
27#include "time.h"
28#include "os2timer.h"
29
30
31
32/****************************************************************************
33 * Structures *
34 ****************************************************************************/
35
36
37/***********************************
38 * PH: fixups for missing os2win.h *
39 ***********************************/
40
41extern "C"
42{
43 typedef DWORD (* CALLBACK LPTHREAD_START_ROUTINE)(LPVOID);
44
45 HANDLE WIN32API CreateThread(LPSECURITY_ATTRIBUTES lpsa,
46 DWORD cbStack,
47 LPTHREAD_START_ROUTINE lpStartAddr,
48 LPVOID lpvThreadParm,
49 DWORD fdwCreate,
50 LPDWORD lpIDThread);
51}
52
53/****************************************************************************
54 * Local Prototypes *
55 ****************************************************************************/
56
57static DWORD _System TimerHlpHandler(LPVOID timer);
58
59
60
61/****************************************************************************
62 * Class: OS2TimerResolution *
63 ****************************************************************************/
64
65
66/*****************************************************************************
67 * Name : OS2TimerResolution::OS2TimerResolution
68 * Purpose : create a new entry in the resolution stack
69 * Parameters: -
70 * Variables :
71 * Result :
72 * Remark :
73 * Status : UNTESTED STUB
74 *
75 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
76 *****************************************************************************/
77
78OS2TimerResolution::OS2TimerResolution(int dwPeriod)
79 : next(NULL)
80{
81 // add to linked list
82 OS2TimerResolution *timeRes = OS2TimerResolution::sTimerResolutions;
83
84 if(timeRes != NULL)
85 {
86 while(timeRes->next != NULL)
87 {
88 timeRes = timeRes->next;
89 }
90 timeRes->next = this;
91 }
92 else
93 OS2TimerResolution::sTimerResolutions = this;
94
95 this->dwPeriod = dwPeriod;
96}
97
98
99/*****************************************************************************
100 * Name : OS2TimerResolution::~OS2TimerResolution
101 * Purpose : remove entry from the linked list
102 * Parameters:
103 * Variables :
104 * Result :
105 * Remark :
106 * Status : UNTESTED STUB
107 *
108 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
109 *****************************************************************************/
110
111OS2TimerResolution::~OS2TimerResolution()
112{
113 // remove from linked list
114 OS2TimerResolution *timeRes = OS2TimerResolution::sTimerResolutions;
115
116 // leaveResolutionScope() if still entered???
117
118 if(timeRes != this)
119 {
120 while(timeRes->next != this)
121 {
122 timeRes = timeRes->next;
123 }
124 timeRes->next = this->next;
125 }
126 else
127 OS2TimerResolution::sTimerResolutions = timeRes->next;
128}
129
130
131/*****************************************************************************
132 * Name : OS2TimerResolution::enterResolutionScope
133 * Purpose : set the currently requested timer resolution for this entry
134 * Parameters:
135 * Variables :
136 * Result :
137 * Remark :
138 * Status : UNTESTED STUB
139 *
140 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
141 *****************************************************************************/
142
143BOOL OS2TimerResolution::enterResolutionScope(int dwPeriod)
144{
145 OS2TimerResolution* timeRes = new OS2TimerResolution(dwPeriod);
146 if (timeRes != NULL)
147 return TRUE;
148 else
149 return FALSE;
150}
151
152
153/*****************************************************************************
154 * Name : OS2TimerResolution::leaveResolutionScope
155 * Purpose : remove specified entry from the list if periods match
156 * Parameters: int dwPeriod
157 * Variables :
158 * Result : TRUE or FALSE
159 * Remark :
160 * Status : UNTESTED STUB
161 *
162 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
163 *****************************************************************************/
164
165BOOL OS2TimerResolution::leaveResolutionScope(int dwPeriod)
166{
167 OS2TimerResolution* timeRes = OS2TimerResolution::sTimerResolutions;
168
169 if (timeRes != NULL)
170 {
171 for(; // walk to the end of the list
172 timeRes->next != NULL;
173 timeRes = timeRes->next)
174 ;
175
176 if (timeRes->dwPeriod == dwPeriod) // do the requested period match?
177 {
178 delete timeRes; // so delete that object
179 return TRUE; // OK, can remove the entry
180 }
181 }
182 return FALSE; // nope, mismatch !
183}
184
185
186/*****************************************************************************
187 * Name : OS2TimerResolution::queryCurrentResolution
188 * Purpose : determine the minimum resolution currently requested
189 * Parameters:
190 * Variables :
191 * Result :
192 * Remark :
193 * Status : UNTESTED STUB
194 *
195 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
196 *****************************************************************************/
197
198int OS2TimerResolution::queryCurrentResolution()
199{
200 OS2TimerResolution *timeRes = OS2TimerResolution::sTimerResolutions;
201 int iMin = -1;
202
203 if (timeRes != NULL) // do we have an entry yet?
204 for (; // walk the linked list
205 timeRes->next != NULL;
206 timeRes = timeRes->next)
207 {
208 if (timeRes->dwPeriod < iMin) // determine minimum time period
209 iMin = timeRes->dwPeriod;
210 }
211
212 return iMin;
213}
214
215
216
217
218
219/******************************************************************************/
220/******************************************************************************/
221OS2Timer::OS2Timer() : TimerSem(0), TimerHandle(0), TimerThreadID(0),
222 clientCallback(NULL), TimerStatus(Stopped), fFatal(FALSE),
223 next(NULL)
224{
225 OS2Timer *timer = OS2Timer::timers;
226
227 if(timer != NULL)
228 {
229 while(timer->next != NULL)
230 {
231 timer = timer->next;
232 }
233 timer->next = this;
234 }
235 else
236 timers = this;
237
238 //TimerThreadID = _beginthread(TimerHlpHandler, NULL, 0x4000, (void *)this);
239 hTimerThread = CreateThread(NULL,
240 0x1000,
241 (LPTHREAD_START_ROUTINE)TimerHlpHandler,
242 (LPVOID)this,
243 0, // thread creation flags
244 &TimerThreadID);
245
246
247 //@@@PH: CreateThread() should be used instead
248 //@@@PH: logic sux ... waits for creation of semaphores
249 DosSleep(100);
250}
251/******************************************************************************/
252/******************************************************************************/
253OS2Timer::~OS2Timer()
254{
255 OS2Timer *timer = OS2Timer::timers;
256
257 KillTimer();
258
259 if(timer != this)
260 {
261 while(timer->next != this)
262 {
263 timer = timer->next;
264 }
265 timer->next = this->next;
266 }
267 else
268 timers = timer->next;
269}
270/******************************************************************************/
271/******************************************************************************/
272BOOL OS2Timer::StartTimer(int period,
273 int resolution,
274 LPTIMECALLBACK lptc,
275 int dwUser,
276 int fuEvent)
277{
278 APIRET rc;
279
280 if(TimerThreadID == -1)
281 {
282 return(FALSE);
283 }
284
285 if(TimerStatus == Stopped)
286 {
287 clientCallback = lptc;
288 userData = dwUser;
289
290 if(fuEvent == TIME_PERIODIC)
291 rc = DosStartTimer(period, (HSEM)TimerSem, &TimerHandle);
292 else
293 rc = DosAsyncTimer(period, (HSEM)TimerSem, &TimerHandle);
294
295 if(rc)
296 {
297
298#ifdef DEBUG
299 if(fuEvent == TIME_PERIODIC)
300 WriteLog("DosStartTimer failed %d\n", rc);
301 else
302 WriteLog("DosAsyncTimer failed %d\n", rc);
303#endif
304
305 return(FALSE);
306 }
307
308 TimerStatus = Running;
309 }
310 else
311 return(FALSE); //already running (must use timeKillEvent first)
312
313 return(TRUE);
314}
315/******************************************************************************/
316/******************************************************************************/
317void OS2Timer::StopTimer()
318{
319 if(TimerStatus == Running)
320 {
321 DosStopTimer(TimerHandle);
322 TimerStatus = Stopped;
323 }
324}
325/******************************************************************************/
326/******************************************************************************/
327void OS2Timer::KillTimer()
328{
329 fFatal = TRUE;
330 DosStopTimer(TimerHandle);
331 if(DosPostEventSem(TimerSem))
332 { //something went wrong
333 DosKillThread(TimerThreadID);
334 DosCloseEventSem(TimerSem);
335 }
336 TimerStatus = InActive;
337}
338/******************************************************************************/
339//******************************************************************************
340void OS2Timer::TimerHandler()
341{
342 ULONG Count = 0;
343 APIRET rc = 0; /* Return code */
344 USHORT selTIB;
345
346 dprintf(("WINMM: TimerHandler thread created\n"));
347
348 rc = DosSetPriority (PRTYS_THREAD, /* Change a single thread */
349 PRTYC_TIMECRITICAL, /* Time critical class */
350 0L, /* Increase by 15 */
351 0L); /* Assume current thread */
352
353 rc = DosCreateEventSem(NULL, &TimerSem, DC_SEM_SHARED, 0);
354 if(rc != 0)
355 {
356 dprintf(("WINMM: OS2Timer: DosCreateEventSem failed rc=#%08xh\n", rc));
357 return; // terminate thread
358 }
359
360 TimerStatus = Stopped;
361
362 while(!fFatal)
363 {
364 DosWaitEventSem(TimerSem, SEM_INDEFINITE_WAIT);
365 DosResetEventSem(TimerSem, &Count);
366 if(!fFatal)
367 {
368 // @@@PH: we're calling the client with PRTYC_TIMECRITICAL !!!
369 // It'd be much nicer to call with original priority!
370
371 selTIB = SetWin32TIB();
372 clientCallback((UINT)this, 0, userData, 0, 0);
373 SetFS(selTIB);
374 }
375 }
376 DosCloseEventSem(TimerSem);
377}
378//******************************************************************************
379//******************************************************************************
380//static void _Optlink TimerHlpHandler(void *timer)
381static DWORD _System TimerHlpHandler(LPVOID timer)
382{
383 ((OS2Timer *)timer)->TimerHandler();
384
385 //_endthread(); isn't really required
386 return 0;
387}
388
389
390//******************************************************************************
391//******************************************************************************
392OS2TimerResolution *OS2TimerResolution::sTimerResolutions = NULL;
393OS2Timer *OS2Timer::timers = NULL;
394int OS2Timer::timerPeriod = 0;
395
Note: See TracBrowser for help on using the repository browser.