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.4 by gbeauche, 2005-03-05T19:07:35Z 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 70 | Line 66 | static int32 timer_func(void *arg);
66   #endif
67   #ifdef PRECISE_TIMING_POSIX
68   static pthread_t timer_thread;
69 < static volatile bool thread_active = false;
69 > 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 165 | Line 162 | static struct sigaction sigresume_action
162   static int suspend_count = 0;
163   static pthread_mutex_t suspend_count_lock = PTHREAD_MUTEX_INITIALIZER;
164   static sem_t suspend_ack_sem;
165 + static sigset_t suspend_handler_mask;
166  
167   // Signal handler for suspended thread
168   static void sigsuspend_handler(int sig)
169   {
170          sem_post(&suspend_ack_sem);
171 <
174 <        sigset_t mask;
175 <        sigfillset(&mask);
176 <        sigdelset(&mask, SIGRESUME);
177 <        sigsuspend(&mask);
171 >        sigsuspend(&suspend_handler_mask);
172   }
173  
174   // Signal handler for resumed thread
# Line 187 | 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 197 | 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 210 | Line 205 | static bool timer_thread_init(void)
205          if (sem_init(&suspend_ack_sem, 0, 0) < 0)
206                  return false;
207  
208 +        // Initialize suspend_handler_mask, it excludes SIGRESUME
209 +        if (sigfillset(&suspend_handler_mask) != 0)
210 +                return false;
211 +        if (sigdelset(&suspend_handler_mask, SIGRESUME) != 0)
212 +                return false;
213 +
214          // Create thread in running state
215          suspend_count = 0;
216          return (pthread_create(&timer_thread, NULL, timer_func, NULL) == 0);
# Line 218 | Line 219 | static bool timer_thread_init(void)
219   // Kill timer thread
220   static void timer_thread_kill(void)
221   {
222 +        timer_thread_cancel = true;
223   #ifdef HAVE_PTHREAD_CANCEL
224          pthread_cancel(timer_thread);
225   #endif
# Line 268 | Line 270 | void TimerInit(void)
270          resume_thread(timer_thread);
271   #endif
272   #ifdef PRECISE_TIMING_POSIX
273 <        sem_init(&wakeup_time_sem, 0, 1);
272 <        thread_active = timer_thread_init();
273 >        timer_thread_active = timer_thread_init();
274   #endif
275   #endif
276   }
# Line 293 | Line 294 | void TimerExit(void)
294                  delete_sem(wakeup_time_sem);
295   #endif
296   #ifdef PRECISE_TIMING_POSIX
296                thread_active = false;
297                  timer_thread_kill();
298                sem_destroy(&wakeup_time_sem);
298   #endif
299          }
300   #endif
# Line 354 | Line 353 | int16 RmvTime(uint32 tm)
353          suspend_thread(timer_thread);
354   #endif
355   #if PRECISE_TIMING_POSIX
357        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 389 | 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 425 | 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;
433 <                        }
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 462 | Line 460 | int16 PrimeTime(uint32 tm, int32 time)
460          suspend_thread(timer_thread);
461   #endif
462   #if PRECISE_TIMING_POSIX
465        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 484 | 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 522 | Line 520 | static int32 timer_func(void *arg)
520   #ifdef PRECISE_TIMING_POSIX
521   static void *timer_func(void *arg)
522   {
523 <        while (thread_active) {
523 >        while (!timer_thread_cancel) {
524  
525                  // Wait until time specified by wakeup_time
526                  clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &wakeup_time, NULL);
527  
530                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                  }
540                sem_post(&wakeup_time_sem);
539          }
540          return NULL;
541   }
# Line 584 | Line 582 | void TimerInterrupt(void)
582          suspend_thread(timer_thread);
583   #endif
584   #if PRECISE_TIMING_POSIX
587        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 602 | 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