we no longer use timers with setitimer and SIGVTALRM, that's so nineties...

instead spin off a cpu_thread and have it ping the main render thread as needed
This commit is contained in:
Aaron Culliney 2013-07-02 01:10:57 -07:00
parent c51018a2bb
commit 18c3f5f698
5 changed files with 51 additions and 31 deletions

View File

@ -352,9 +352,7 @@ void c_periodic_update(int dummysig) {
*/ */
void enter_debugger(void) void enter_debugger(void)
{ {
setitimer(ITIMER_VIRTUAL,&timer_off,0);
c_do_debugging(); c_do_debugging();
setitimer(ITIMER_VIRTUAL,&timer_on,0);
} }
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------

View File

@ -73,8 +73,6 @@
#define kPGDN 164 #define kPGDN 164
#define kEND 165 #define kEND 165
#define TIMER_DELAY 30000L
#ifdef PC_JOYSTICK #ifdef PC_JOYSTICK
extern int js_fd; extern int js_fd;

View File

@ -19,6 +19,8 @@
#include <ctype.h> #include <ctype.h>
#include <stdlib.h> #include <stdlib.h>
#include <signal.h> #include <signal.h>
#include <time.h>
#include <pthread.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/io.h> #include <sys/io.h>
@ -32,9 +34,7 @@
#include "cpu.h" #include "cpu.h"
#include "glue.h" #include "glue.h"
#include "prefs.h" #include "prefs.h"
#include "timing.h"
const struct itimerval timer_off = {{0,0},{0,0}};
const struct itimerval timer_on = {{0,TIMER_DELAY},{0,TIMER_DELAY}};
/* ---------------------------------- /* ----------------------------------
internal apple2 variables internal apple2 variables
@ -45,6 +45,9 @@ static unsigned char apple_ii_rom[12288];
static unsigned char apple_iie_rom[32768]; /* //e */ static unsigned char apple_iie_rom[32768]; /* //e */
#endif #endif
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
/* in debugger.c */ /* in debugger.c */
extern int breakpoints[]; extern int breakpoints[];
extern int watchpoints[]; extern int watchpoints[];
@ -704,10 +707,6 @@ static void c_initialize_firsttime()
/* initialize the video system */ /* initialize the video system */
video_init(); video_init();
/* Enable periodic updates */
signal(SIGVTALRM,c_periodic_update);
setitimer(ITIMER_VIRTUAL,&timer_on,0);
reinitialize(); reinitialize();
} }
@ -715,29 +714,38 @@ void c_read_random() {
random_value = (unsigned char)(rand() >> 8); random_value = (unsigned char)(rand() >> 8);
} }
static void cpu_thread (void *dummyptr) {
do {
cpu65_run();
reinitialize();
} while (1);
}
static void main_thread (void *dummyptr) {
do {
// sleep waiting for the cpu thread to ping us that it's sleeping...
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
c_periodic_update(0);
} while (1);
}
int main(int sargc, char *sargv[]) int main(int sargc, char *sargv[])
{ {
int i;
argc = sargc; argc = sargc;
argv = sargv; argv = sargv;
for (i = 1; i < argc; i++)
{
/*
if (strcmp(argv[i], "-vga") == 0)
force_vga_mode = 1;
*/
}
load_settings(); /* user prefs */ load_settings(); /* user prefs */
c_initialize_firsttime(); /* init svga graphics and vm */ c_initialize_firsttime(); /* init svga graphics and vm */
timing_initialize();
for (;;) { // spin off cpu thread
/* execute the emulator */ pthread_t thread1;
cpu65_run(); pthread_create(&thread1, NULL, (void *) &cpu_thread, (void *)NULL);
reinitialize(); // enter main render thread
} main_thread(NULL);
/* never reached */
} }

View File

@ -39,8 +39,6 @@
#define SW_IOUDIS 0xC07E #define SW_IOUDIS 0xC07E
#endif #endif
extern const struct itimerval timer_on,timer_off;
/* Text characters */ /* Text characters */
extern const unsigned char ucase_glyphs[0x200]; extern const unsigned char ucase_glyphs[0x200];
extern const unsigned char lcase_glyphs[0x100]; extern const unsigned char lcase_glyphs[0x100];

View File

@ -15,8 +15,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <time.h> #include <time.h>
#include <pthread.h>
#define DEFAULT_SLEEP 60 #define DEFAULT_SLEEP 120
static unsigned int sleep_hz = DEFAULT_SLEEP; // sleep intervals per sec static unsigned int sleep_hz = DEFAULT_SLEEP; // sleep intervals per sec
static unsigned long cpu_target_hz = APPLE2_HZ; // target clock speed static unsigned long cpu_target_hz = APPLE2_HZ; // target clock speed
@ -28,6 +29,9 @@ static unsigned long cycle=0;
static long sleep_adjust=0; static long sleep_adjust=0;
static long sleep_adjust_inc=0; static long sleep_adjust_inc=0;
extern pthread_mutex_t mutex;
extern pthread_cond_t cond;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// assuming end > start, returns end - start // assuming end > start, returns end - start
@ -66,16 +70,30 @@ void timing_set_sleep_hz (unsigned int hz) {
/* /*
* Throttles the 65c02 CPU down to a target frequency of X. * Throttles the 65c02 CPU down to a target frequency of X.
* Currently set to target the Apple //e @ 1.02MHz * Currently set to target the Apple //e @ 1.02MHz
*
* This is called from cpu65_run() on the cpu-thread
*/ */
void timing_throttle () { void timing_throttle () {
++cycle; ++cycle;
static time_t severe_lag=0;
if ((cycle%cycles_interval) == 0) { if ((cycle%cycles_interval) == 0) {
// wake render thread as we go to sleep
pthread_mutex_lock(&mutex);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
clock_gettime(CLOCK_MONOTONIC, &tj); clock_gettime(CLOCK_MONOTONIC, &tj);
deltat = timespec_diff(ti, tj); deltat = timespec_diff(ti, tj);
ti=tj; ti=tj;
if (deltat.tv_sec != 0) { if (deltat.tv_sec != 0) {
// severely lagging ... // severely lagging, don't bother sleeping ...
if (severe_lag < time(NULL)) {
severe_lag = time(NULL)+2;
fprintf(stderr, "Severe lag detected...\n");
}
} else { } else {
deltat.tv_nsec = processing_interval - deltat.tv_nsec + sleep_adjust_inc; deltat.tv_nsec = processing_interval - deltat.tv_nsec + sleep_adjust_inc;
nanosleep(&deltat, NULL); // NOTE: spec says will return right away if deltat.tv_nsec value < 0 ... nanosleep(&deltat, NULL); // NOTE: spec says will return right away if deltat.tv_nsec value < 0 ...