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.7 by gbeauche, 2005-07-01T23:15:11Z vs.
Revision 1.12 by asvitkine, 2009-08-17T20:44:30Z

# Line 1 | Line 1
1   /*
2   *  timer.cpp - Time Manager emulation
3   *
4 < *  SheepShaver (C) 1997-2005 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"
# Line 33 | Line 29
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  
# Line 77 | Line 77 | static tm_time_t wakeup_time = wakeup_ti
77   static pthread_mutex_t wakeup_time_lock = PTHREAD_MUTEX_INITIALIZER;
78   static void *timer_func(void *arg);
79   #endif
80 + #ifdef PRECISE_TIMING_MACH
81 + static clock_serv_t system_clock;
82 + static thread_act_t timer_thread;
83 + static bool timer_thread_active = false;
84 + static tm_time_t wakeup_time_max = { 0x7fffffff, 999999999 };
85 + static tm_time_t wakeup_time = wakeup_time_max;
86 + static semaphore_t wakeup_time_sem;
87 + static void *timer_func(void *arg);
88 + #endif
89   #endif
90  
91  
# Line 272 | Line 281 | void TimerInit(void)
281          wakeup_time_sem = create_sem(1, "Wakeup Time");
282          timer_thread = spawn_thread(timer_func, "Time Manager", B_REAL_TIME_PRIORITY, NULL);
283          resume_thread(timer_thread);
284 + #elif PRECISE_TIMING_MACH
285 +        pthread_t pthread;
286 +        
287 +        host_get_clock_service(mach_host_self(), REALTIME_CLOCK, &system_clock);
288 +        semaphore_create(mach_task_self(), &wakeup_time_sem, SYNC_POLICY_FIFO, 1);
289 +
290 +        pthread_create(&pthread, NULL, &timer_func, NULL);
291   #endif
292   #ifdef PRECISE_TIMING_POSIX
293          timer_thread_active = timer_thread_init();
# Line 297 | Line 313 | void TimerExit(void)
313                  wait_for_thread(timer_thread, &l);
314                  delete_sem(wakeup_time_sem);
315   #endif
316 + #ifdef PRECISE_TIMING_MACH
317 +                timer_thread_active = false;
318 +                semaphore_destroy(mach_task_self(), wakeup_time_sem);
319 + #endif
320   #ifdef PRECISE_TIMING_POSIX
321                  timer_thread_kill();
322   #endif
# Line 356 | Line 376 | int16 RmvTime(uint32 tm)
376          while (acquire_sem(wakeup_time_sem) == B_INTERRUPTED) ;
377          suspend_thread(timer_thread);
378   #endif
379 + #ifdef PRECISE_TIMING_MACH
380 +        semaphore_wait(wakeup_time_sem);
381 +        thread_suspend(timer_thread);
382 + #endif
383   #if PRECISE_TIMING_POSIX
384          timer_thread_suspend();
385          pthread_mutex_lock(&wakeup_time_lock);
# Line 391 | Line 415 | int16 RmvTime(uint32 tm)
415                  get_thread_info(timer_thread, &info);
416          } while (info.state == B_THREAD_SUSPENDED);     // Sometimes, resume_thread() doesn't work (BeOS bug?)
417   #endif
418 + #ifdef PRECISE_TIMING_MACH
419 +        semaphore_signal(wakeup_time_sem);
420 +        thread_abort(timer_thread);
421 +        thread_resume(timer_thread);
422 + #endif
423   #if PRECISE_TIMING_POSIX
424          pthread_mutex_unlock(&wakeup_time_lock);
425          timer_thread_resume();
# Line 428 | Line 457 | int16 PrimeTime(uint32 tm, int32 time)
457                  // Yes, tmWakeUp set?
458                  if (ReadMacInt32(tm + tmWakeUp)) {
459  
460 <                        //!! PrimeTime(0) means continue previous delay
461 <                        // (save wakeup time in RmvTime?)
460 >                        // PrimeTime(0) can either mean (a) "the task runs as soon as interrupts are enabled"
461 >                        // or (b) "continue previous delay" if an expired task was stopped via RmvTime() and
462 >                        // then re-installed using InsXTime(). Since tmWakeUp was set, this is case (b).
463 >                        // The remaining time was saved in tmCount by RmvTime().
464                          if (time == 0) {
465 <                                printf("FATAL: Unsupported PrimeTime(0)\n");
435 <                                return 0;
465 >                                timer_mac2host_time(delay, ReadMacInt16(tm + tmCount));
466                          }
467  
468                          // Yes, calculate wakeup time relative to last scheduled time
# Line 464 | Line 494 | int16 PrimeTime(uint32 tm, int32 time)
494          while (acquire_sem(wakeup_time_sem) == B_INTERRUPTED) ;
495          suspend_thread(timer_thread);
496   #endif
497 + #ifdef PRECISE_TIMING_MACH
498 +        semaphore_wait(wakeup_time_sem);
499 +        thread_suspend(timer_thread);
500 + #endif
501   #if PRECISE_TIMING_POSIX
502          timer_thread_suspend();
503          pthread_mutex_lock(&wakeup_time_lock);
# Line 486 | Line 520 | int16 PrimeTime(uint32 tm, int32 time)
520                  get_thread_info(timer_thread, &info);
521          } while (info.state == B_THREAD_SUSPENDED);     // Sometimes, resume_thread() doesn't work (BeOS bug?)
522   #endif
523 + #ifdef PRECISE_TIMING_MACH
524 +        semaphore_signal(wakeup_time_sem);
525 +        thread_abort(timer_thread);
526 +        thread_resume(timer_thread);
527 + #endif
528   #ifdef PRECISE_TIMING_POSIX
529          pthread_mutex_unlock(&wakeup_time_lock);
530          timer_thread_resume();
# Line 522 | Line 561 | static int32 timer_func(void *arg)
561   }
562   #endif
563  
564 + #ifdef PRECISE_TIMING_MACH
565 + static void *timer_func(void *arg)
566 + {
567 +        timer_thread = mach_thread_self();
568 +        timer_thread_active = true;
569 +        
570 +        while (timer_thread_active) {
571 +                clock_sleep(system_clock, TIME_ABSOLUTE, wakeup_time, NULL);
572 +                semaphore_wait(wakeup_time_sem);
573 +          
574 +                tm_time_t system_time;
575 +                
576 +                timer_current_time(system_time);
577 +                if (timer_cmp_time(wakeup_time, system_time) < 0) {
578 +                        wakeup_time = wakeup_time_max;
579 +                        SetInterruptFlag(INTFLAG_TIMER);
580 +                        TriggerInterrupt();
581 +                }
582 +                semaphore_signal(wakeup_time_sem);
583 +        }
584 + }
585 + #endif
586 +
587   #ifdef PRECISE_TIMING_POSIX
588   static void *timer_func(void *arg)
589   {
590          while (!timer_thread_cancel) {
529
591                  // Wait until time specified by wakeup_time
592                  clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &wakeup_time, NULL);
593  
# Line 586 | Line 647 | void TimerInterrupt(void)
647          while (acquire_sem(wakeup_time_sem) == B_INTERRUPTED) ;
648          suspend_thread(timer_thread);
649   #endif
650 + #if PRECISE_TIMING_MACH
651 +        semaphore_wait(wakeup_time_sem);
652 +        thread_suspend(timer_thread);
653 + #endif
654   #if PRECISE_TIMING_POSIX
655          timer_thread_suspend();
656          pthread_mutex_lock(&wakeup_time_lock);
# Line 604 | Line 669 | void TimerInterrupt(void)
669                  get_thread_info(timer_thread, &info);
670          } while (info.state == B_THREAD_SUSPENDED);     // Sometimes, resume_thread() doesn't work (BeOS bug?)
671   #endif
672 + #if PRECISE_TIMING_MACH
673 +        semaphore_signal(wakeup_time_sem);
674 +        thread_abort(timer_thread);
675 +        thread_resume(timer_thread);
676 + #endif
677   #if PRECISE_TIMING_POSIX
678          pthread_mutex_unlock(&wakeup_time_lock);
679          timer_thread_resume();

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines