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.10 by asvitkine, 2009-07-31T20:43:28Z

# 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 74 | Line 70 | static bool timer_thread_active = false;
70   static volatile bool timer_thread_cancel = false;
71   static tm_time_t wakeup_time_max = { 0x7fffffff, 999999999 };
72   static tm_time_t wakeup_time = wakeup_time_max;
73 < static sem_t wakeup_time_sem;
73 > static pthread_mutex_t wakeup_time_lock = PTHREAD_MUTEX_INITIALIZER;
74   static void *timer_func(void *arg);
75   #endif
76   #endif
# Line 185 | Line 181 | static void sigresume_handler(int sig)
181   static bool timer_thread_init(void)
182   {
183          // Install suspend signal handler
184 <        sigfillset(&sigsuspend_action.sa_mask);
184 >        sigemptyset(&sigsuspend_action.sa_mask);
185 >        sigaddset(&sigsuspend_action.sa_mask, SIGRESUME);
186          sigsuspend_action.sa_handler = sigsuspend_handler;
187          sigsuspend_action.sa_flags = SA_RESTART;
188   #ifdef HAVE_SIGNAL_SA_RESTORER
# Line 195 | Line 192 | static bool timer_thread_init(void)
192                  return false;
193  
194          // Install resume signal handler
195 <        sigfillset(&sigresume_action.sa_mask);
195 >        sigemptyset(&sigresume_action.sa_mask);
196          sigresume_action.sa_handler = sigresume_handler;
197          sigresume_action.sa_flags = SA_RESTART;
198   #ifdef HAVE_SIGNAL_SA_RESTORER
# Line 273 | Line 270 | void TimerInit(void)
270          resume_thread(timer_thread);
271   #endif
272   #ifdef PRECISE_TIMING_POSIX
276        sem_init(&wakeup_time_sem, 0, 1);
273          timer_thread_active = timer_thread_init();
274   #endif
275   #endif
# Line 299 | Line 295 | void TimerExit(void)
295   #endif
296   #ifdef PRECISE_TIMING_POSIX
297                  timer_thread_kill();
302                sem_destroy(&wakeup_time_sem);
298   #endif
299          }
300   #endif
# Line 358 | Line 353 | int16 RmvTime(uint32 tm)
353          suspend_thread(timer_thread);
354   #endif
355   #if PRECISE_TIMING_POSIX
361        sem_wait(&wakeup_time_sem);
356          timer_thread_suspend();
357 +        pthread_mutex_lock(&wakeup_time_lock);
358   #endif
359          if (ReadMacInt16(tm + qType) & 0x8000) {
360  
# Line 393 | Line 388 | int16 RmvTime(uint32 tm)
388          } while (info.state == B_THREAD_SUSPENDED);     // Sometimes, resume_thread() doesn't work (BeOS bug?)
389   #endif
390   #if PRECISE_TIMING_POSIX
391 <        sem_post(&wakeup_time_sem);
391 >        pthread_mutex_unlock(&wakeup_time_lock);
392          timer_thread_resume();
393          assert(suspend_count == 0);
394   #endif
# Line 429 | Line 424 | int16 PrimeTime(uint32 tm, int32 time)
424                  // Yes, tmWakeUp set?
425                  if (ReadMacInt32(tm + tmWakeUp)) {
426  
427 <                        //!! PrimeTime(0) means continue previous delay
428 <                        // (save wakeup time in RmvTime?)
429 <                        if (time == 0) {
430 <                                printf("FATAL: Unsupported PrimeTime(0)\n");
431 <                                return 0;
437 <                        }
427 >                        // PrimeTime(0) can either mean (a) "the task runs as soon as interrupts are enabled"
428 >                        // or (b) "continue previous delay" if an expired task was stopped via RmvTime() and
429 >                        // then re-installed using InsXTime(). Since tmWakeUp was set, this is case (b).
430 >                        // The remaining time was saved in tmCount by RmvTime().
431 >                        timer_mac2host_time(delay, ReadMacInt16(tm + tmCount));
432  
433                          // Yes, calculate wakeup time relative to last scheduled time
434                          tm_time_t wakeup;
# Line 466 | Line 460 | int16 PrimeTime(uint32 tm, int32 time)
460          suspend_thread(timer_thread);
461   #endif
462   #if PRECISE_TIMING_POSIX
469        sem_wait(&wakeup_time_sem);
463          timer_thread_suspend();
464 +        pthread_mutex_lock(&wakeup_time_lock);
465   #endif
466          WriteMacInt16(tm + qType, ReadMacInt16(tm + qType) | 0x8000);
467          enqueue_tm(tm);
# Line 488 | Line 482 | int16 PrimeTime(uint32 tm, int32 time)
482          } while (info.state == B_THREAD_SUSPENDED);     // Sometimes, resume_thread() doesn't work (BeOS bug?)
483   #endif
484   #ifdef PRECISE_TIMING_POSIX
485 <        sem_post(&wakeup_time_sem);
485 >        pthread_mutex_unlock(&wakeup_time_lock);
486          timer_thread_resume();
487          assert(suspend_count == 0);
488   #endif
# Line 531 | Line 525 | static void *timer_func(void *arg)
525                  // Wait until time specified by wakeup_time
526                  clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &wakeup_time, NULL);
527  
534                sem_wait(&wakeup_time_sem);
528                  tm_time_t system_time;
529                  timer_current_time(system_time);
530                  if (timer_cmp_time(wakeup_time, system_time) < 0) {
531  
532                          // Timer expired, trigger interrupt
533 +                        pthread_mutex_lock(&wakeup_time_lock);
534                          wakeup_time = wakeup_time_max;
535 +                        pthread_mutex_unlock(&wakeup_time_lock);
536                          SetInterruptFlag(INTFLAG_TIMER);
537                          TriggerInterrupt();
538                  }
544                sem_post(&wakeup_time_sem);
539          }
540          return NULL;
541   }
# Line 588 | Line 582 | void TimerInterrupt(void)
582          suspend_thread(timer_thread);
583   #endif
584   #if PRECISE_TIMING_POSIX
591        sem_wait(&wakeup_time_sem);
585          timer_thread_suspend();
586 +        pthread_mutex_lock(&wakeup_time_lock);
587   #endif
588          wakeup_time = wakeup_time_max;
589          for (int j=0; j<NUM_DESCS; j++) {
# Line 606 | Line 600 | void TimerInterrupt(void)
600          } while (info.state == B_THREAD_SUSPENDED);     // Sometimes, resume_thread() doesn't work (BeOS bug?)
601   #endif
602   #if PRECISE_TIMING_POSIX
603 <        sem_post(&wakeup_time_sem);
603 >        pthread_mutex_unlock(&wakeup_time_lock);
604          timer_thread_resume();
605          assert(suspend_count == 0);
606   #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines