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

Last change on this file since 2812 was 2812, checked in by sandervl, 26 years ago

Added new logging feature + fixed waveout query format bug

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