/*
- * PC/HW routine collection v1.4 for DOS/DJGPP
+ * PC/HW routine collection v1.5 for DOS/DJGPP
*
* Copyright (C) 2002 - Borca Daniel
* Email : dborca@yahoo.com
-/* Desc: install timer engine
- *
- * In : -
- * Out : 0 for success
- *
- * Note: initial frequency is 18.2 Hz
- */
-static int install_timer (void)
-{
- if (timer_installed || pc_install_irq(TIMER_IRQ, timer)) {
- return -1;
- } else {
- memset(timer_func, 0, sizeof(timer_func));
-
- LOCKDATA(timer_func);
- LOCKDATA(timer_main);
- LOCKFUNC(timer);
-
- timer_main.counter = 0x10000;
-
- DISABLE();
- outportb(0x43, 0x34);
- outportb(0x40, 0);
- outportb(0x40, 0);
- timer_main.clock_ticks = 0;
- ENABLE();
-
- pc_atexit(pc_remove_timer);
- timer_installed = TRUE;
- return 0;
- }
-}
-
-
-
-/* Desc: install timerfunc
- *
- * In : callback function, opaque pointer to be passed to callee, freq (Hz)
- * Out : timerfunc id (0 .. MAX_TIMERS-1)
- *
- * Note: returns -1 if error
- */
-int pc_install_int (PFUNC func, void *parm, unsigned int freq)
-{
- int i;
- TIMER *t = NULL;
-
- /* ensure the timer engine is set up */
- if (!timer_installed) {
- if (install_timer()) {
- return -1;
- }
- }
-
- /* find an empty slot */
- for (i = 0; i < MAX_TIMERS; i++) {
- if (!timer_func[i].func) {
- t = &timer_func[i];
- break;
- }
- }
- if (t == NULL) {
- return -1;
- }
-
- DISABLE();
-
- t->func = func;
- t->parm = parm;
- t->freq = freq;
- t->clock_ticks = 0;
-
- /* update main timer / sons to match highest frequency */
- if (freq > timer_main.freq) {
- unsigned int new_counter = PIT_FREQ / freq;
-
- for (i = 0; i < MAX_TIMERS; i++) {
- if (timer_func[i].func) {
- ADJUST(timer_func[i], freq);
- }
- }
-
- outportb(0x43, 0x34);
- outportb(0x40, (unsigned char)new_counter);
- outportb(0x40, (unsigned char)(new_counter>>8));
- timer_main.clock_ticks = 0;
- timer_main.counter = new_counter;
- timer_main.freq = freq;
- } else {
- /* t == &timer_func[i] */
- ADJUST(timer_func[i], timer_main.freq);
- }
-
- ENABLE();
-
- return t - timer_func;
-}
-
-
-
/* Desc: remove timerfunc
*
* In : timerfunc id
}
return 0;
-}
+} ENDOFUNC(pc_remove_int)
ENABLE();
return 0;
+} ENDOFUNC(pc_adjust_int)
+
+
+
+/* Desc: install timer engine
+ *
+ * In : -
+ * Out : 0 for success
+ *
+ * Note: initial frequency is 18.2 Hz
+ */
+static int install_timer (void)
+{
+ if (timer_installed || pc_install_irq(TIMER_IRQ, timer)) {
+ return -1;
+ } else {
+ memset(timer_func, 0, sizeof(timer_func));
+
+ LOCKDATA(timer_func);
+ LOCKDATA(timer_main);
+ LOCKFUNC(timer);
+ LOCKFUNC(pc_adjust_int);
+ LOCKFUNC(pc_remove_int);
+
+ timer_main.counter = 0x10000;
+
+ DISABLE();
+ outportb(0x43, 0x34);
+ outportb(0x40, 0);
+ outportb(0x40, 0);
+ timer_main.clock_ticks = 0;
+ ENABLE();
+
+ pc_atexit(pc_remove_timer);
+ timer_installed = TRUE;
+ return 0;
+ }
+}
+
+
+
+/* Desc: install timerfunc
+ *
+ * In : callback function, opaque pointer to be passed to callee, freq (Hz)
+ * Out : timerfunc id (0 .. MAX_TIMERS-1)
+ *
+ * Note: returns -1 if error
+ */
+int pc_install_int (PFUNC func, void *parm, unsigned int freq)
+{
+ int i;
+ TIMER *t = NULL;
+
+ /* ensure the timer engine is set up */
+ if (!timer_installed) {
+ if (install_timer()) {
+ return -1;
+ }
+ }
+
+ /* find an empty slot */
+ for (i = 0; i < MAX_TIMERS; i++) {
+ if (!timer_func[i].func) {
+ t = &timer_func[i];
+ break;
+ }
+ }
+ if (t == NULL) {
+ return -1;
+ }
+
+ DISABLE();
+
+ t->func = func;
+ t->parm = parm;
+ t->freq = freq;
+ t->clock_ticks = 0;
+
+ /* update main timer / sons to match highest frequency */
+ if (freq > timer_main.freq) {
+ unsigned int new_counter = PIT_FREQ / freq;
+
+ for (i = 0; i < MAX_TIMERS; i++) {
+ if (timer_func[i].func) {
+ ADJUST(timer_func[i], freq);
+ }
+ }
+
+ outportb(0x43, 0x34);
+ outportb(0x40, (unsigned char)new_counter);
+ outportb(0x40, (unsigned char)(new_counter>>8));
+ timer_main.clock_ticks = 0;
+ timer_main.counter = new_counter;
+ timer_main.freq = freq;
+ } else {
+ /* t == &timer_func[i] */
+ ADJUST(timer_func[i], timer_main.freq);
+ }
+
+ i = t - timer_func;
+
+ ENABLE();
+
+ return i;
}
*/
/*
- * DOS/DJGPP glut driver v1.4 for Mesa
+ * DOS/DJGPP glut driver v1.5 for Mesa
*
* Copyright (C) 2002 - Borca Daniel
* Email : dborca@yahoo.com
int fid; /* func-id as returned from PCHW */
} GLUTSShotCB;
-static GLboolean g_sscb_semaphore;
-
GLUTidleCB g_idle_func = NULL;
static void g_single_shot_callback (void *opaque)
{
GLUTSShotCB *cb = (GLUTSShotCB *)opaque;
- while (g_sscb_semaphore) {
- }
if (!--cb->ttl) {
cb->func(cb->value);
pc_remove_int(cb->fid);
+ /* We won't be needing this slot anymore, so free it. This operation
+ * must be the last thing, and must be atomic, to mutex `glutTimerFunc'
+ */
cb->func = NULL;
}
} ENDOFUNC(g_single_shot_callback)
if (virgin) {
virgin = GL_FALSE;
LOCKDATA(g_sscb);
- LOCKDATA(g_sscb_semaphore);
LOCKFUNC(g_single_shot_callback);
/* we should lock the callee also... */
}
freq = 1000 / millis;
ttl = 1;
}
- g_sscb_semaphore++;
for (i = 0; i < MAX_SSHOT_CB; i++) {
if (g_sscb[i].func == NULL) {
- int fid = pc_install_int((PFUNC)func, &g_sscb[i], freq);
- if (fid >= 0) {
- g_sscb[i].func = func;
- g_sscb[i].value = value;
- g_sscb[i].ttl = ttl;
- g_sscb[i].fid = fid;
+ /* We will be needing this slot, so alloc it. This operation
+ * must be the first thing, and must be atomic, to mutex callbacks!
+ */
+ g_sscb[i].func = func;
+ g_sscb[i].value = value;
+ g_sscb[i].ttl = ttl;
+ /* There is a very small gap here: `pc_install_int' enables
+ * interrupts just before returning FID value (which will be
+ * used inside callback). The critical gap is 1 millisecond
+ * - which I'm sure we won't overrun...
+ */
+ g_sscb[i].fid = pc_install_int((PFUNC)func, &g_sscb[i], freq);
+ if (g_sscb[i].fid < 0) {
+ /* Interrupt could not be set! Release the slot back */
+ g_sscb[i].func = NULL;
}
break;
}
}
- g_sscb_semaphore--;
}
}