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.5 by gbeauche, 2005-03-15T20:46:50Z 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 74 | Line 74 | static bool timer_thread_active = false;
74   static volatile bool timer_thread_cancel = false;
75   static tm_time_t wakeup_time_max = { 0x7fffffff, 999999999 };
76   static tm_time_t wakeup_time = wakeup_time_max;
77 < static sem_t wakeup_time_sem;
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
# Line 185 | Line 194 | static void sigresume_handler(int sig)
194   static bool timer_thread_init(void)
195   {
196          // Install suspend signal handler
197 <        sigfillset(&sigsuspend_action.sa_mask);
197 >        sigemptyset(&sigsuspend_action.sa_mask);
198 >        sigaddset(&sigsuspend_action.sa_mask, SIGRESUME);
199          sigsuspend_action.sa_handler = sigsuspend_handler;
200          sigsuspend_action.sa_flags = SA_RESTART;
201   #ifdef HAVE_SIGNAL_SA_RESTORER
# Line 195 | Line 205 | static bool timer_thread_init(void)
205                  return false;
206  
207          // Install resume signal handler
208 <        sigfillset(&sigresume_action.sa_mask);
208 >        sigemptyset(&sigresume_action.sa_mask);
209          sigresume_action.sa_handler = sigresume_handler;
210          sigresume_action.sa_flags = SA_RESTART;
211   #ifdef HAVE_SIGNAL_SA_RESTORER
# Line 271 | 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
276        sem_init(&wakeup_time_sem, 0, 1);
293          timer_thread_active = timer_thread_init();
294   #endif
295   #endif
# 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();
302                sem_destroy(&wakeup_time_sem);
322   #endif
323          }
324   #endif
# Line 357 | 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
361        sem_wait(&wakeup_time_sem);
384          timer_thread_suspend();
385 +        pthread_mutex_lock(&wakeup_time_lock);
386   #endif
387          if (ReadMacInt16(tm + qType) & 0x8000) {
388  
# Line 392 | 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 <        sem_post(&wakeup_time_sem);
424 >        pthread_mutex_unlock(&wakeup_time_lock);
425          timer_thread_resume();
426          assert(suspend_count == 0);
427   #endif
# Line 429 | 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");
436 <                                return 0;
465 >                                timer_mac2host_time(delay, ReadMacInt16(tm + tmCount));
466                          }
467  
468                          // Yes, calculate wakeup time relative to last scheduled time
# Line 465 | 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
469        sem_wait(&wakeup_time_sem);
502          timer_thread_suspend();
503 +        pthread_mutex_lock(&wakeup_time_lock);
504   #endif
505          WriteMacInt16(tm + qType, ReadMacInt16(tm + qType) | 0x8000);
506          enqueue_tm(tm);
# Line 487 | 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 <        sem_post(&wakeup_time_sem);
529 >        pthread_mutex_unlock(&wakeup_time_lock);
530          timer_thread_resume();
531          assert(suspend_count == 0);
532   #endif
# Line 523 | 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) {
530
591                  // Wait until time specified by wakeup_time
592                  clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &wakeup_time, NULL);
593  
534                sem_wait(&wakeup_time_sem);
594                  tm_time_t system_time;
595                  timer_current_time(system_time);
596                  if (timer_cmp_time(wakeup_time, system_time) < 0) {
597  
598                          // Timer expired, trigger interrupt
599 +                        pthread_mutex_lock(&wakeup_time_lock);
600                          wakeup_time = wakeup_time_max;
601 +                        pthread_mutex_unlock(&wakeup_time_lock);
602                          SetInterruptFlag(INTFLAG_TIMER);
603                          TriggerInterrupt();
604                  }
544                sem_post(&wakeup_time_sem);
605          }
606          return NULL;
607   }
# Line 587 | 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
591        sem_wait(&wakeup_time_sem);
655          timer_thread_suspend();
656 +        pthread_mutex_lock(&wakeup_time_lock);
657   #endif
658          wakeup_time = wakeup_time_max;
659          for (int j=0; j<NUM_DESCS; j++) {
# Line 605 | 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 <        sem_post(&wakeup_time_sem);
678 >        pthread_mutex_unlock(&wakeup_time_lock);
679          timer_thread_resume();
680          assert(suspend_count == 0);
681   #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines