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

Comparing BasiliskII/src/Unix/main_unix.cpp (file contents):
Revision 1.38 by gbeauche, 2001-07-07T09:07:38Z vs.
Revision 1.39 by cebix, 2001-07-09T11:22:00Z

# Line 475 | Line 475 | int main(int argc, char **argv)
475          sigaction(SIGINT, &sigint_sa, NULL);
476   #endif
477  
478 < #if defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
478 > #if defined(HAVE_PTHREADS)
479 >
480 >        // POSIX threads available, start 60Hz thread
481 >        pthread_attr_init(&tick_thread_attr);
482 > #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
483 >        if (geteuid() == 0) {
484 >                pthread_attr_setinheritsched(&tick_thread_attr, PTHREAD_EXPLICIT_SCHED);
485 >                pthread_attr_setschedpolicy(&tick_thread_attr, SCHED_FIFO);
486 >                struct sched_param fifo_param;
487 >                fifo_param.sched_priority = (sched_get_priority_min(SCHED_FIFO) + sched_get_priority_max(SCHED_FIFO)) / 2;
488 >                pthread_attr_setschedparam(&tick_thread_attr, &fifo_param);
489 >        }
490 > #endif
491 >        tick_thread_active = (pthread_create(&tick_thread, &tick_thread_attr, tick_func, NULL) == 0);
492 >        if (!tick_thread_active) {
493 >                sprintf(str, GetString(STR_TICK_THREAD_ERR), strerror(errno));
494 >                ErrorAlert(str);
495 >                QuitEmulator();
496 >        }
497 >        D(bug("60Hz thread started\n"));
498 >
499 > #elif defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
500  
501          // POSIX.4 timers and real-time signals available, start 60Hz timer
502          sigemptyset(&timer_sa.sa_mask);
# Line 506 | Line 527 | int main(int argc, char **argv)
527          }
528          D(bug("60Hz timer started\n"));
529  
509 #elif defined(HAVE_PTHREADS)
510
511        // POSIX threads available, start 60Hz thread
512        pthread_attr_init(&tick_thread_attr);
513 #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
514        if (geteuid() == 0) {
515                pthread_attr_setinheritsched(&tick_thread_attr, PTHREAD_EXPLICIT_SCHED);
516                pthread_attr_setschedpolicy(&tick_thread_attr, SCHED_FIFO);
517                struct sched_param fifo_param;
518                fifo_param.sched_priority = (sched_get_priority_min(SCHED_FIFO) + sched_get_priority_max(SCHED_FIFO)) / 2;
519                pthread_attr_setschedparam(&tick_thread_attr, &fifo_param);
520        }
521 #endif
522        tick_thread_active = (pthread_create(&tick_thread, &tick_thread_attr, tick_func, NULL) == 0);
523        if (!tick_thread_active) {
524                sprintf(str, GetString(STR_TICK_THREAD_ERR), strerror(errno));
525                ErrorAlert(str);
526                QuitEmulator();
527        }
528        D(bug("60Hz thread started\n"));
529
530   #else
531  
532          // Start 60Hz timer
# Line 575 | Line 575 | void QuitEmulator(void)
575          Exit680x0();
576   #endif
577  
578 < #if defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
579 <        // Stop 60Hz timer
580 <        timer_delete(timer);
581 < #elif defined(HAVE_PTHREADS)
578 > #if defined(HAVE_PTHREADS)
579          // Stop 60Hz thread
580          if (tick_thread_active) {
581                  tick_thread_cancel = true;
# Line 587 | Line 584 | void QuitEmulator(void)
584   #endif
585                  pthread_join(tick_thread, NULL);
586          }
587 + #elif defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
588 +        // Stop 60Hz timer
589 +        timer_delete(timer);
590   #else
591          struct itimerval req;
592          req.it_interval.tv_sec = req.it_value.tv_sec = 0;
# Line 849 | Line 849 | static void one_tick(...)
849   #ifdef HAVE_PTHREADS
850   static void *tick_func(void *arg)
851   {
852 +        uint64 start = GetTicks_usec();
853 +        int64 ticks = 0;
854          uint64 next = GetTicks_usec();
855          while (!tick_thread_cancel) {
856                  one_tick();
# Line 858 | Line 860 | static void *tick_func(void *arg)
860                          Delay_usec(delay);
861                  else if (delay < -16625)
862                          next = GetTicks_usec();
863 +                ticks++;
864          }
865 +        uint64 end = GetTicks_usec();
866 +        D(bug("%Ld ticks in %Ld usec = %f ticks/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start)));
867          return NULL;
868   }
869   #endif
870  
871  
867 /*
868 *  Get current value of microsecond timer
869 */
870
871 uint64 GetTicks_usec(void)
872 {
873 #ifdef HAVE_CLOCK_GETTIME
874        struct timespec t;
875        clock_gettime(CLOCK_REALTIME, &t);
876        return (uint64)t.tv_sec * 1000000 + t.tv_nsec / 1000;
877 #else
878        struct timeval t;
879        gettimeofday(&t, NULL);
880        return (uint64)t.tv_sec * 1000000 + t.tv_usec;
881 #endif
882 }
883
884
885 /*
886 *  Delay by specified number of microseconds (<1 second)
887 *  (adapted from SDL_Delay() source; this function is designed to provide
888 *  the highest accuracy possible)
889 */
890
891 #if defined(linux)
892 // Linux select() changes its timeout parameter upon return to contain
893 // the remaining time. Most other unixen leave it unchanged or undefined.
894 #define SELECT_SETS_REMAINING
895 #elif defined(__FreeBSD__) || defined(__sun__)
896 #define USE_NANOSLEEP
897 #elif defined(HAVE_PTHREADS) && defined(sgi)
898 // SGI pthreads has a bug when using pthreads+signals+nanosleep,
899 // so instead of using nanosleep, wait on a CV which is never signalled.
900 #define USE_COND_TIMEDWAIT
901 #endif
902
903 void Delay_usec(uint32 usec)
904 {
905        int was_error;
906
907 #if defined(USE_NANOSLEEP)
908        struct timespec elapsed, tv;
909 #elif defined(USE_COND_TIMEDWAIT)
910        // Use a local mutex and cv, so threads remain independent
911        pthread_cond_t delay_cond = PTHREAD_COND_INITIALIZER;
912        pthread_mutex_t delay_mutex = PTHREAD_MUTEX_INITIALIZER;
913        struct timespec elapsed;
914        uint64 future;
915 #else
916        struct timeval tv;
917 #ifndef SELECT_SETS_REMAINING
918        uint64 then, now, elapsed;
919 #endif
920 #endif
921
922        // Set the timeout interval - Linux only needs to do this once
923 #if defined(SELECT_SETS_REMAINING)
924    tv.tv_sec = 0;
925    tv.tv_usec = usec;
926 #elif defined(USE_NANOSLEEP)
927    elapsed.tv_sec = 0;
928    elapsed.tv_nsec = usec * 1000;
929 #elif defined(USE_COND_TIMEDWAIT)
930        future = GetTicks_usec() + usec;
931        elapsed.tv_sec = future / 1000000;
932        elapsed.tv_nsec = (future % 1000000) * 1000;
933 #else
934    then = GetTicks_usec();
935 #endif
936
937        do {
938                errno = 0;
939 #if defined(USE_NANOSLEEP)
940                tv.tv_sec = elapsed.tv_sec;
941                tv.tv_nsec = elapsed.tv_nsec;
942                was_error = nanosleep(&tv, &elapsed);
943 #elif defined(USE_COND_TIMEDWAIT)
944                was_error = pthread_mutex_lock(&delay_mutex);
945                was_error = pthread_cond_timedwait(&delay_cond, &delay_mutex, &elapsed);
946                was_error = pthread_mutex_unlock(&delay_mutex);
947 #else
948 #ifndef SELECT_SETS_REMAINING
949                // Calculate the time interval left (in case of interrupt)
950                now = GetTicks_usec();
951                elapsed = now - then;
952                then = now;
953                if (elapsed >= usec)
954                        break;
955                usec -= elapsed;
956                tv.tv_sec = 0;
957                tv.tv_usec = usec;
958 #endif
959                was_error = select(0, NULL, NULL, NULL, &tv);
960 #endif
961        } while (was_error && (errno == EINTR));
962 }
963
964
872   #if !EMULATED_68K
873   /*
874   *  Virtual 68k interrupt handler

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines