ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/timer.cpp
(Generate patch)

Comparing SheepShaver/src/timer.cpp (file contents):
Revision 1.1.1.1 by cebix, 2002-02-04T16:58:13Z vs.
Revision 1.15 by asvitkine, 2011-12-28T18:14:58Z

# Line 1 | Line 1
1   /*
2   *  timer.cpp - Time Manager emulation
3   *
4 < *  SheepShaver (C) 1997-2002 Christian Bauer and Marc Hellwig
4 > *  SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
# Line 18 | Line 18
18   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19   */
20  
21 /*
22 * TODO: Prime(0)
23 */
24
21   #include "sysdeps.h"
22   #include "timer.h"
23   #include "macos_util.h"
24   #include "main.h"
25   #include "cpu_emulation.h"
26  
27 + #ifdef PRECISE_TIMING_POSIX
28 + #include <pthread.h>
29 + #include <semaphore.h>
30 + #endif
31 +
32 + #ifdef PRECISE_TIMING_MACH
33 + #include <mach/mach.h>
34 + #endif
35 +
36   #define DEBUG 0
37   #include "debug.h"
38  
39  
35 #if __BEOS__
36 #define PRECISE_TIMING 1
37 #else
38 #define PRECISE_TIMING 0
39 #endif
40
40   #define TM_QUEUE 0                      // Enable TMQueue management (doesn't work)
41  
42  
# Line 54 | Line 53 | enum { // TMTask struct
53   struct TMDesc {
54          uint32 task;            // Mac address of associated TMTask
55          tm_time_t wakeup;       // Time this task is scheduled for execution
56 <        bool in_use;            // Flag: descriptor in use
56 >        TMDesc *next;
57   };
58  
59 < const int NUM_DESCS = 64;               // Maximum number of descriptors
61 < static TMDesc desc[NUM_DESCS];
59 > static TMDesc *tmDescList;
60  
61   #if PRECISE_TIMING
62 + #ifdef PRECISE_TIMING_BEOS
63   static thread_id timer_thread = -1;
64   static bool thread_active = true;
65 < static volatile tm_time_t wakeup_time = 0x7fffffffffffffff;
65 > static const tm_time_t wakeup_time_max = 0x7fffffffffffffff;
66 > static volatile tm_time_t wakeup_time = wakeup_time_max;
67   static sem_id wakeup_time_sem = -1;
68   static int32 timer_func(void *arg);
69   #endif
70 + #ifdef PRECISE_TIMING_POSIX
71 + static pthread_t timer_thread;
72 + static bool timer_thread_active = false;
73 + static volatile bool timer_thread_cancel = false;
74 + static tm_time_t wakeup_time_max = { 0x7fffffff, 999999999 };
75 + static tm_time_t wakeup_time = wakeup_time_max;
76 + static pthread_mutex_t wakeup_time_lock = PTHREAD_MUTEX_INITIALIZER;
77 + static void *timer_func(void *arg);
78 + #endif
79 + #ifdef PRECISE_TIMING_MACH
80 + static clock_serv_t system_clock;
81 + static thread_act_t timer_thread;
82 + static bool timer_thread_active = false;
83 + static tm_time_t wakeup_time_max = { 0x7fffffff, 999999999 };
84 + static tm_time_t wakeup_time = wakeup_time_max;
85 + static semaphore_t wakeup_time_sem;
86 + static void *timer_func(void *arg);
87 + #endif
88 + #endif
89  
90  
91 < /*
73 < *  Allocate descriptor for given TMTask in list
74 < */
75 <
76 < static int alloc_desc(uint32 tm)
91 > inline static void free_desc(TMDesc *desc)
92   {
93 <        // Search for first free descriptor
94 <        for (int i=0; i<NUM_DESCS; i++)
95 <                if (!desc[i].in_use) {
96 <                        desc[i].task = tm;
97 <                        desc[i].in_use = true;
98 <                        return i;
93 >        if (desc == tmDescList) {
94 >                tmDescList = desc->next;
95 >        } else {
96 >                for (TMDesc *d = tmDescList; d; d = d->next) {
97 >                        if (d->next == desc) {
98 >                                d->next = desc->next;
99 >                                break;
100 >                        }
101                  }
102 <        return -1;
103 < }
87 <
88 <
89 < /*
90 < *  Free descriptor in list
91 < */
92 <
93 < inline static void free_desc(int i)
94 < {
95 <        desc[i].in_use = false;
102 >        }
103 >        delete desc;
104   }
105  
98
106   /*
107   *  Find descriptor associated with given TMTask
108   */
109  
110 < inline static int find_desc(uint32 tm)
110 > inline static TMDesc *find_desc(uint32 tm)
111   {
112 <        for (int i=0; i<NUM_DESCS; i++)
113 <                if (desc[i].in_use && desc[i].task == tm)
114 <                        return i;
115 <        return -1;
112 >        TMDesc *desc = tmDescList;
113 >        while (desc) {
114 >                if (desc->task == tm) {
115 >                        return desc;
116 >                }
117 >                desc = desc->next;
118 >        }
119 >        return NULL;
120   }
121  
122  
# Line 143 | Line 154 | static void dequeue_tm(uint32 tm)
154  
155  
156   /*
157 + *  Timer thread operations
158 + */
159 +
160 + #ifdef PRECISE_TIMING_POSIX
161 + const int SIGSUSPEND = SIGRTMIN + 6;
162 + const int SIGRESUME  = SIGRTMIN + 7;
163 + static struct sigaction sigsuspend_action;
164 + static struct sigaction sigresume_action;
165 +
166 + static int suspend_count = 0;
167 + static pthread_mutex_t suspend_count_lock = PTHREAD_MUTEX_INITIALIZER;
168 + static sem_t suspend_ack_sem;
169 + static sigset_t suspend_handler_mask;
170 +
171 + // Signal handler for suspended thread
172 + static void sigsuspend_handler(int sig)
173 + {
174 +        sem_post(&suspend_ack_sem);
175 +        sigsuspend(&suspend_handler_mask);
176 + }
177 +
178 + // Signal handler for resumed thread
179 + static void sigresume_handler(int sig)
180 + {
181 +        /* simply trigger a signal to stop clock_nanosleep() */
182 + }
183 +
184 + // Initialize timer thread
185 + static bool timer_thread_init(void)
186 + {
187 +        // Install suspend signal handler
188 +        sigemptyset(&sigsuspend_action.sa_mask);
189 +        sigaddset(&sigsuspend_action.sa_mask, SIGRESUME);
190 +        sigsuspend_action.sa_handler = sigsuspend_handler;
191 +        sigsuspend_action.sa_flags = SA_RESTART;
192 + #ifdef HAVE_SIGNAL_SA_RESTORER
193 +        sigsuspend_action.sa_restorer = NULL;
194 + #endif
195 +        if (sigaction(SIGSUSPEND, &sigsuspend_action, NULL) < 0)
196 +                return false;
197 +
198 +        // Install resume signal handler
199 +        sigemptyset(&sigresume_action.sa_mask);
200 +        sigresume_action.sa_handler = sigresume_handler;
201 +        sigresume_action.sa_flags = SA_RESTART;
202 + #ifdef HAVE_SIGNAL_SA_RESTORER
203 +        sigresume_action.sa_restorer = NULL;
204 + #endif
205 +        if (sigaction(SIGRESUME, &sigresume_action, NULL) < 0)
206 +                return false;
207 +
208 +        // Initialize semaphore
209 +        if (sem_init(&suspend_ack_sem, 0, 0) < 0)
210 +                return false;
211 +
212 +        // Initialize suspend_handler_mask, it excludes SIGRESUME
213 +        if (sigfillset(&suspend_handler_mask) != 0)
214 +                return false;
215 +        if (sigdelset(&suspend_handler_mask, SIGRESUME) != 0)
216 +                return false;
217 +
218 +        // Create thread in running state
219 +        suspend_count = 0;
220 +        return (pthread_create(&timer_thread, NULL, timer_func, NULL) == 0);
221 + }
222 +
223 + // Kill timer thread
224 + static void timer_thread_kill(void)
225 + {
226 +        timer_thread_cancel = true;
227 + #ifdef HAVE_PTHREAD_CANCEL
228 +        pthread_cancel(timer_thread);
229 + #endif
230 +        pthread_join(timer_thread, NULL);
231 + }
232 +
233 + // Suspend timer thread
234 + static void timer_thread_suspend(void)
235 + {
236 +        pthread_mutex_lock(&suspend_count_lock);
237 +        if (suspend_count == 0) {
238 +                suspend_count ++;
239 +                if (pthread_kill(timer_thread, SIGSUSPEND) == 0)
240 +                        sem_wait(&suspend_ack_sem);
241 +        }
242 +        pthread_mutex_unlock(&suspend_count_lock);
243 + }
244 +
245 + // Resume timer thread
246 + static void timer_thread_resume(void)
247 + {
248 +        pthread_mutex_lock(&suspend_count_lock);
249 +        assert(suspend_count > 0);
250 +        if (suspend_count == 1) {
251 +                suspend_count = 0;
252 +                pthread_kill(timer_thread, SIGRESUME);
253 +        }
254 +        pthread_mutex_unlock(&suspend_count_lock);
255 + }
256 + #endif
257 +
258 +
259 + /*
260   *  Initialize Time Manager
261   */
262  
263   void TimerInit(void)
264   {
265 <        // Mark all descriptors as inactive
152 <        for (int i=0; i<NUM_DESCS; i++)
153 <                free_desc(i);
265 >        TimerReset();
266  
267   #if PRECISE_TIMING
268          // Start timer thread
269 + #ifdef PRECISE_TIMING_BEOS
270          wakeup_time_sem = create_sem(1, "Wakeup Time");
271          timer_thread = spawn_thread(timer_func, "Time Manager", B_REAL_TIME_PRIORITY, NULL);
272          resume_thread(timer_thread);
273 + #elif PRECISE_TIMING_MACH
274 +        pthread_t pthread;
275 +        
276 +        host_get_clock_service(mach_host_self(), REALTIME_CLOCK, &system_clock);
277 +        semaphore_create(mach_task_self(), &wakeup_time_sem, SYNC_POLICY_FIFO, 1);
278 +
279 +        pthread_create(&pthread, NULL, &timer_func, NULL);
280 + #endif
281 + #ifdef PRECISE_TIMING_POSIX
282 +        timer_thread_active = timer_thread_init();
283 + #endif
284   #endif
285   }
286  
# Line 170 | Line 294 | void TimerExit(void)
294   #if PRECISE_TIMING
295          // Quit timer thread
296          if (timer_thread > 0) {
297 + #ifdef PRECISE_TIMING_BEOS
298                  status_t l;
299                  thread_active = false;
300                  suspend_thread(timer_thread);
301                  resume_thread(timer_thread);
302                  wait_for_thread(timer_thread, &l);
303                  delete_sem(wakeup_time_sem);
304 + #endif
305 + #ifdef PRECISE_TIMING_MACH
306 +                timer_thread_active = false;
307 +                semaphore_destroy(mach_task_self(), wakeup_time_sem);
308 + #endif
309 + #ifdef PRECISE_TIMING_POSIX
310 +                timer_thread_kill();
311 + #endif
312          }
313   #endif
314   }
# Line 187 | Line 320 | void TimerExit(void)
320  
321   void TimerReset(void)
322   {
323 <        // Mark all descriptors as inactive
324 <        for (int i=0; i<NUM_DESCS; i++)
325 <                free_desc(i);
323 >        TMDesc *desc = tmDescList;
324 >        while (desc) {
325 >                TMDesc *next = desc->next;
326 >                delete desc;
327 >                desc = next;
328 >        }
329 >        tmDescList = NULL;
330   }
331  
332  
# Line 201 | Line 338 | int16 InsTime(uint32 tm, uint16 trap)
338   {
339          D(bug("InsTime %08lx, trap %04x\n", tm, trap));
340          WriteMacInt16((uint32)tm + qType, ReadMacInt16((uint32)tm + qType) & 0x1fff | (trap << 4) & 0x6000);
341 <        if (find_desc(tm) >= 0)
342 <                printf("WARNING: InsTime(): Task re-inserted\n");
341 >        if (find_desc(tm))
342 >                printf("WARNING: InsTime(%08lx): Task re-inserted\n", tm);
343          else {
344 <                int i = alloc_desc(tm);
345 <                if (i < 0)
346 <                        printf("FATAL: InsTime(): No free Time Manager descriptor\n");
344 >                TMDesc *desc = new TMDesc;
345 >                desc->task = tm;
346 >                desc->next = tmDescList;
347 >                tmDescList = desc;
348          }
349          return 0;
350   }
# Line 221 | Line 359 | int16 RmvTime(uint32 tm)
359          D(bug("RmvTime %08lx\n", tm));
360  
361          // Find descriptor
362 <        int i = find_desc(tm);
363 <        if (i < 0) {
362 >        TMDesc *desc = find_desc(tm);
363 >        if (!desc) {
364                  printf("WARNING: RmvTime(%08lx): Descriptor not found\n", tm);
365                  return 0;
366          }
367  
368          // Task active?
369 < #if PRECISE_TIMING
369 > #if PRECISE_TIMING_BEOS
370          while (acquire_sem(wakeup_time_sem) == B_INTERRUPTED) ;
371          suspend_thread(timer_thread);
372   #endif
373 + #ifdef PRECISE_TIMING_MACH
374 +        semaphore_wait(wakeup_time_sem);
375 +        thread_suspend(timer_thread);
376 + #endif
377 + #if PRECISE_TIMING_POSIX
378 +        timer_thread_suspend();
379 +        pthread_mutex_lock(&wakeup_time_lock);
380 + #endif
381          if (ReadMacInt16(tm + qType) & 0x8000) {
382  
383                  // Yes, make task inactive and remove it from the Time Manager queue
# Line 239 | Line 385 | int16 RmvTime(uint32 tm)
385                  dequeue_tm(tm);
386   #if PRECISE_TIMING
387                  // Look for next task to be called and set wakeup_time
388 <                wakeup_time = 0x7fffffffffffffff;
389 <                for (int j=0; j<NUM_DESCS; j++) {
390 <                        if (desc[j].in_use && (ReadMacInt16(desc[j].task + qType) & 0x8000))
391 <                                if (desc[j].wakeup < wakeup_time)
392 <                                        wakeup_time = desc[j].wakeup;
247 <                }
388 >                wakeup_time = wakeup_time_max;
389 >                for (TMDesc *d = tmDescList; d; d = d->next)
390 >                        if ((ReadMacInt16(d->task + qType) & 0x8000))
391 >                                if (timer_cmp_time(d->wakeup, wakeup_time) < 0)
392 >                                        wakeup_time = d->wakeup;
393   #endif
394  
395                  // Compute remaining time
396                  tm_time_t remaining, current;
397                  timer_current_time(current);
398 <                timer_sub_time(remaining, desc[i].wakeup, current);
398 >                timer_sub_time(remaining, desc->wakeup, current);
399                  WriteMacInt32(tm + tmCount, timer_host2mac_time(remaining));
400          } else
401                  WriteMacInt32(tm + tmCount, 0);
402          D(bug(" tmCount %ld\n", ReadMacInt32(tm + tmCount)));
403 < #if PRECISE_TIMING
403 > #if PRECISE_TIMING_BEOS
404          release_sem(wakeup_time_sem);
405          thread_info info;
406          do {
# Line 263 | Line 408 | int16 RmvTime(uint32 tm)
408                  get_thread_info(timer_thread, &info);
409          } while (info.state == B_THREAD_SUSPENDED);     // Sometimes, resume_thread() doesn't work (BeOS bug?)
410   #endif
411 + #ifdef PRECISE_TIMING_MACH
412 +        semaphore_signal(wakeup_time_sem);
413 +        thread_abort(timer_thread);
414 +        thread_resume(timer_thread);
415 + #endif
416 + #if PRECISE_TIMING_POSIX
417 +        pthread_mutex_unlock(&wakeup_time_lock);
418 +        timer_thread_resume();
419 +        assert(suspend_count == 0);
420 + #endif
421  
422          // Free descriptor
423 <        free_desc(i);
423 >        free_desc(desc);
424          return 0;
425   }
426  
# Line 279 | Line 434 | int16 PrimeTime(uint32 tm, int32 time)
434          D(bug("PrimeTime %08lx, time %ld\n", tm, time));
435  
436          // Find descriptor
437 <        int i = find_desc(tm);
438 <        if (i < 0) {
439 <                printf("FATAL: PrimeTime(): Descriptor not found\n");
437 >        TMDesc *desc = find_desc(tm);
438 >        if (!desc) {
439 >                printf("FATAL: PrimeTime(%08lx): Descriptor not found\n", tm);
440                  return 0;
441          }
442  
# Line 295 | Line 450 | int16 PrimeTime(uint32 tm, int32 time)
450                  // Yes, tmWakeUp set?
451                  if (ReadMacInt32(tm + tmWakeUp)) {
452  
453 <                        //!! PrimeTime(0) means continue previous delay
454 <                        // (save wakeup time in RmvTime?)
453 >                        // PrimeTime(0) can either mean (a) "the task runs as soon as interrupts are enabled"
454 >                        // or (b) "continue previous delay" if an expired task was stopped via RmvTime() and
455 >                        // then re-installed using InsXTime(). Since tmWakeUp was set, this is case (b).
456 >                        // The remaining time was saved in tmCount by RmvTime().
457                          if (time == 0) {
458 <                                printf("FATAL: Unsupported PrimeTime(0)\n");
302 <                                return 0;
458 >                                timer_mac2host_time(delay, ReadMacInt16(tm + tmCount));
459                          }
460  
461                          // Yes, calculate wakeup time relative to last scheduled time
462                          tm_time_t wakeup;
463 <                        timer_add_time(wakeup, desc[i].wakeup, delay);
464 <                        desc[i].wakeup = wakeup;
463 >                        timer_add_time(wakeup, desc->wakeup, delay);
464 >                        desc->wakeup = wakeup;
465  
466                  } else {
467  
468                          // No, calculate wakeup time relative to current time
469                          tm_time_t now;
470                          timer_current_time(now);
471 <                        timer_add_time(desc[i].wakeup, now, delay);
471 >                        timer_add_time(desc->wakeup, now, delay);
472                  }
473  
474                  // Set tmWakeUp to indicate that task was scheduled
# Line 323 | Line 479 | int16 PrimeTime(uint32 tm, int32 time)
479                  // Not extended task, calculate wakeup time relative to current time
480                  tm_time_t now;
481                  timer_current_time(now);
482 <                timer_add_time(desc[i].wakeup, now, delay);
482 >                timer_add_time(desc->wakeup, now, delay);
483          }
484  
485          // Make task active and enqueue it in the Time Manager queue
486 < #if PRECISE_TIMING
486 > #if PRECISE_TIMING_BEOS
487          while (acquire_sem(wakeup_time_sem) == B_INTERRUPTED) ;
488          suspend_thread(timer_thread);
489   #endif
490 + #ifdef PRECISE_TIMING_MACH
491 +        semaphore_wait(wakeup_time_sem);
492 +        thread_suspend(timer_thread);
493 + #endif
494 + #if PRECISE_TIMING_POSIX
495 +        timer_thread_suspend();
496 +        pthread_mutex_lock(&wakeup_time_lock);
497 + #endif
498          WriteMacInt16(tm + qType, ReadMacInt16(tm + qType) | 0x8000);
499          enqueue_tm(tm);
500   #if PRECISE_TIMING
501          // Look for next task to be called and set wakeup_time
502 <        wakeup_time = 0x7fffffffffffffff;
503 <        for (int j=0; j<NUM_DESCS; j++) {
504 <                if (desc[j].in_use && (ReadMacInt16(desc[j].task + qType) & 0x8000))
505 <                        if (desc[j].wakeup < wakeup_time)
506 <                                wakeup_time = desc[j].wakeup;
507 <        }
502 >        wakeup_time = wakeup_time_max;
503 >        for (TMDesc *d = tmDescList; d; d = d->next)
504 >                if ((ReadMacInt16(d->task + qType) & 0x8000))
505 >                        if (timer_cmp_time(d->wakeup, wakeup_time) < 0)
506 >                                wakeup_time = d->wakeup;
507 > #ifdef PRECISE_TIMING_BEOS
508          release_sem(wakeup_time_sem);
509          thread_info info;
510          do {
# Line 348 | Line 512 | int16 PrimeTime(uint32 tm, int32 time)
512                  get_thread_info(timer_thread, &info);
513          } while (info.state == B_THREAD_SUSPENDED);     // Sometimes, resume_thread() doesn't work (BeOS bug?)
514   #endif
515 + #ifdef PRECISE_TIMING_MACH
516 +        semaphore_signal(wakeup_time_sem);
517 +        thread_abort(timer_thread);
518 +        thread_resume(timer_thread);
519 + #endif
520 + #ifdef PRECISE_TIMING_POSIX
521 +        pthread_mutex_unlock(&wakeup_time_lock);
522 +        timer_thread_resume();
523 +        assert(suspend_count == 0);
524 + #endif
525 + #endif
526          return 0;
527   }
528  
529  
355 #if PRECISE_TIMING
530   /*
531   *  Time Manager thread
532   */
533  
534 + #ifdef PRECISE_TIMING_BEOS
535   static int32 timer_func(void *arg)
536   {
537          while (thread_active) {
# Line 378 | Line 553 | static int32 timer_func(void *arg)
553   }
554   #endif
555  
556 + #ifdef PRECISE_TIMING_MACH
557 + static void *timer_func(void *arg)
558 + {
559 +        timer_thread = mach_thread_self();
560 +        timer_thread_active = true;
561 +        
562 +        while (timer_thread_active) {
563 +                clock_sleep(system_clock, TIME_ABSOLUTE, wakeup_time, NULL);
564 +                semaphore_wait(wakeup_time_sem);
565 +          
566 +                tm_time_t system_time;
567 +                
568 +                timer_current_time(system_time);
569 +                if (timer_cmp_time(wakeup_time, system_time) < 0) {
570 +                        wakeup_time = wakeup_time_max;
571 +                        SetInterruptFlag(INTFLAG_TIMER);
572 +                        TriggerInterrupt();
573 +                }
574 +                semaphore_signal(wakeup_time_sem);
575 +        }
576 +        return NULL;
577 + }
578 + #endif
579 +
580 + #ifdef PRECISE_TIMING_POSIX
581 + static void *timer_func(void *arg)
582 + {
583 +        while (!timer_thread_cancel) {
584 +                // Wait until time specified by wakeup_time
585 +                clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &wakeup_time, NULL);
586 +
587 +                tm_time_t system_time;
588 +                timer_current_time(system_time);
589 +                if (timer_cmp_time(wakeup_time, system_time) < 0) {
590 +
591 +                        // Timer expired, trigger interrupt
592 +                        pthread_mutex_lock(&wakeup_time_lock);
593 +                        wakeup_time = wakeup_time_max;
594 +                        pthread_mutex_unlock(&wakeup_time_lock);
595 +                        SetInterruptFlag(INTFLAG_TIMER);
596 +                        TriggerInterrupt();
597 +                }
598 +        }
599 +        return NULL;
600 + }
601 + #endif
602 +
603  
604   /*
605   *  Timer interrupt function (executed as part of 60Hz interrupt)
# Line 390 | Line 612 | void TimerInterrupt(void)
612          // Look for active TMTasks that have expired
613          tm_time_t now;
614          timer_current_time(now);
615 <        for (int i=0; i<NUM_DESCS; i++)
616 <                if (desc[i].in_use) {
617 <                        uint32 tm = desc[i].task;
618 <                        if ((ReadMacInt16(tm + qType) & 0x8000) && timer_cmp_time(desc[i].wakeup, now) <= 0) {
619 <
620 <                                // Found one, mark as inactive and remove it from the Time Manager queue
621 <                                WriteMacInt16(tm + qType, ReadMacInt16(tm + qType) & 0x7fff);
622 <                                dequeue_tm(tm);
623 <
624 <                                // Call timer function
625 <                                uint32 addr = ReadMacInt32(tm + tmAddr);
626 <                                if (addr) {
627 <                                        D(bug("Calling TimeTask %08lx, addr %08lx\n", tm, addr));
628 <                                        M68kRegisters r;
629 <                                        r.a[0] = addr;
630 <                                        r.a[1] = tm;
631 <                                        Execute68k(r.a[0], &r);
632 <                                        D(bug(" returned from TimeTask\n"));
633 <                                }
615 >        TMDesc *desc = tmDescList;
616 >        while (desc) {
617 >                TMDesc *next = desc->next;
618 >                uint32 tm = desc->task;
619 >                if ((ReadMacInt16(tm + qType) & 0x8000) && timer_cmp_time(desc->wakeup, now) <= 0) {
620 >
621 >                        // Found one, mark as inactive and remove it from the Time Manager queue
622 >                        WriteMacInt16(tm + qType, ReadMacInt16(tm + qType) & 0x7fff);
623 >                        dequeue_tm(tm);
624 >
625 >                        // Call timer function
626 >                        uint32 addr = ReadMacInt32(tm + tmAddr);
627 >                        if (addr) {
628 >                                D(bug("Calling TimeTask %08lx, addr %08lx\n", tm, addr));
629 >                                M68kRegisters r;
630 >                                r.a[0] = addr;
631 >                                r.a[1] = tm;
632 >                                Execute68k(r.a[0], &r);
633 >                                D(bug(" returned from TimeTask\n"));
634                          }
635                  }
636 +                desc = next;
637 +        }
638  
639   #if PRECISE_TIMING
640          // Look for next task to be called and set wakeup_time
641 + #if PRECISE_TIMING_BEOS
642          while (acquire_sem(wakeup_time_sem) == B_INTERRUPTED) ;
643          suspend_thread(timer_thread);
644 <        wakeup_time = 0x7fffffffffffffff;
645 <        for (int j=0; j<NUM_DESCS; j++) {
646 <                if (desc[j].in_use && (ReadMacInt16(desc[j].task + qType) & 0x8000))
647 <                        if (desc[j].wakeup < wakeup_time)
648 <                                wakeup_time = desc[j].wakeup;
649 <        }
644 > #endif
645 > #if PRECISE_TIMING_MACH
646 >        semaphore_wait(wakeup_time_sem);
647 >        thread_suspend(timer_thread);
648 > #endif
649 > #if PRECISE_TIMING_POSIX
650 >        timer_thread_suspend();
651 >        pthread_mutex_lock(&wakeup_time_lock);
652 > #endif
653 >        wakeup_time = wakeup_time_max;
654 >        for (TMDesc *d = tmDescList; d; d = d->next)
655 >                if ((ReadMacInt16(d->task + qType) & 0x8000))
656 >                        if (timer_cmp_time(d->wakeup, wakeup_time) < 0)
657 >                                wakeup_time = d->wakeup;
658 > #if PRECISE_TIMING_BEOS
659          release_sem(wakeup_time_sem);
660          thread_info info;
661          do {
# Line 429 | Line 663 | void TimerInterrupt(void)
663                  get_thread_info(timer_thread, &info);
664          } while (info.state == B_THREAD_SUSPENDED);     // Sometimes, resume_thread() doesn't work (BeOS bug?)
665   #endif
666 + #if PRECISE_TIMING_MACH
667 +        semaphore_signal(wakeup_time_sem);
668 +        thread_abort(timer_thread);
669 +        thread_resume(timer_thread);
670 + #endif
671 + #if PRECISE_TIMING_POSIX
672 +        pthread_mutex_unlock(&wakeup_time_lock);
673 +        timer_thread_resume();
674 +        assert(suspend_count == 0);
675 + #endif
676 + #endif
677   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines