The actual code changes.

This commit is contained in:
OBattler
2026-01-10 02:25:25 +01:00
parent 3ed1ac905b
commit b857e809bf
11 changed files with 156 additions and 128 deletions

View File

@@ -8,7 +8,7 @@
#include <86box/nv/vid_nv_rivatimer.h>
uint64_t TIMER_USEC;
uint32_t timer_target;
uint64_t timer_target;
/*Enabled timers are stored in a linked list, with the first timer to expire at
the head.*/
@@ -23,68 +23,55 @@ void
timer_enable(pc_timer_t *timer)
{
pc_timer_t *timer_node = timer_head;
int ret = 0;
if (!timer_inited || (timer == NULL))
return;
if (timer->flags & TIMER_ENABLED)
timer_disable(timer);
if (timer->next || timer->prev)
fatal("timer_disable(): Attempting to enable a non-isolated "
"timer incorrectly marked as disabled\n");
fatal("timer_enable - timer->next\n");
timer->flags |= TIMER_ENABLED;
/*List currently empty - add to head*/
if (!timer_head) {
timer_head = timer;
timer_head = timer;
timer->next = timer->prev = NULL;
timer_target = timer_head->ts.ts32.integer;
ret = 1;
} else if (TIMER_LESS_THAN(timer, timer_head)) {
timer->next = timer_head;
timer->prev = NULL;
timer_head->prev = timer;
timer_head = timer;
timer_target = timer_head->ts.ts32.integer;
ret = 1;
} else if (!timer_head->next) {
timer_head->next = timer;
timer->prev = timer_head;
ret = 1;
timer_target = timer_head->ts_integer;
return;
}
if (ret == 0) {
pc_timer_t *prev = timer_head;
timer_node = timer_head->next;
timer_node = timer_head;
while (1) {
/*Timer expires before timer_node. Add to list in front of timer_node*/
if (TIMER_LESS_THAN(timer, timer_node)) {
timer->next = timer_node;
timer->prev = prev;
timer_node->prev = timer;
prev->next = timer;
ret = 1;
break;
while (1) {
/*
Timer expires before timer_node.
Add to list in front of timer_node
*/
if (TIMER_LESS_THAN(timer, timer_node)) {
timer->next = timer_node;
timer->prev = timer_node->prev;
timer_node->prev = timer;
if (timer->prev)
timer->prev->next = timer;
else {
timer_head = timer;
timer_target = timer_head->ts_integer;
}
/*timer_node is last in the list. Add timer to end of list*/
if (!timer_node->next) {
timer_node->next = timer;
timer->prev = timer_node;
ret = 1;
break;
}
prev = timer_node;
timer_node = timer_node->next;
return;
}
}
/* Do not mark it as enabled if it has failed every single condition. */
if (ret == 1)
timer->flags |= TIMER_ENABLED;
/*
timer_node is last in the list.
Add timer to end of list
*/
if (!timer_node->next) {
timer_node->next = timer;
timer->prev = timer_node;
return;
}
timer_node = timer_node->next;
}
}
void
@@ -93,9 +80,12 @@ timer_disable(pc_timer_t *timer)
if (!timer_inited || (timer == NULL) || !(timer->flags & TIMER_ENABLED))
return;
if (!timer->next && !timer->prev && timer != timer_head)
if (!timer->next && !timer->prev && timer != timer_head) {
uint32_t *p = NULL;
*p = 5; /* Crash deliberately. */
fatal("timer_disable(): Attempting to disable an isolated "
"non-head timer incorrectly marked as enabled\n");
}
timer->flags &= ~TIMER_ENABLED;
timer->in_callback = 0;
@@ -109,41 +99,60 @@ timer_disable(pc_timer_t *timer)
timer->prev = timer->next = NULL;
}
static void
timer_remove_head(void)
{
if (timer_head) {
pc_timer_t *timer = timer_head;
timer_head = timer->next;
timer_head->prev = NULL;
timer->next = timer->prev = NULL;
timer->flags &= ~TIMER_ENABLED;
}
}
void
timer_process(void)
{
pc_timer_t *timer;
int num = 0;
if (!timer_head)
return;
uint64_t old_target = timer_target;
while (1) {
timer = timer_head;
pc_timer_t *timer = timer_head;
if (!TIMER_LESS_THAN_VAL(timer, (uint32_t) tsc))
if (!TIMER_LESS_THAN_VAL(timer, (uint64_t) tsc)) {
if (num == 0)
pclog("No processing because all timers expire later\n");
break;
}
timer_head = timer->next;
if (timer_head)
timer_head->prev = NULL;
timer->next = timer->prev = NULL;
timer->flags &= ~TIMER_ENABLED;
timer_remove_head();
if (timer->flags & TIMER_SPLIT)
timer_advance_ex(timer, 0); /* We're splitting a > 1 s period into
multiple <= 1 s periods. */
multiple <= 1 s periods. */
else if (timer->callback != NULL) {
/* Make sure it's not NULL, so that we can
/*
Make sure it's not NULL, so that we can
have a NULL callback when no operation
is needed. */
is needed.
*/
timer->in_callback = 1;
timer->callback(timer->priv);
timer->in_callback = 0;
}
num++;
}
timer_target = timer_head->ts.ts32.integer;
timer_target = timer_head->ts_integer;
if (old_target > timer_target)
pclog("Timer wraparound!\n");
}
void
@@ -200,7 +209,8 @@ timer_stop(pc_timer_t *timer)
return;
timer->period = 0.0;
timer_disable(timer);
if (timer->flags & TIMER_ENABLED)
timer_disable(timer);
timer->flags &= ~TIMER_SPLIT;
timer->in_callback = 0;
}
@@ -277,11 +287,11 @@ timer_set_new_tsc(uint64_t new_tsc)
}
timer = timer_head;
timer_target = new_tsc + (int32_t)(timer_get_ts_int(timer_head) - (uint32_t)tsc);
timer_target = new_tsc + (int64_t)(timer_get_ts_int(timer_head) - (uint64_t)tsc);
while (timer) {
int32_t offset_from_current_tsc = (int32_t)(timer_get_ts_int(timer) - (uint32_t)tsc);
timer->ts.ts32.integer = new_tsc + offset_from_current_tsc;
int64_t offset_from_current_tsc = (int64_t)(timer_get_ts_int(timer) - (uint64_t)tsc);
timer->ts_integer = new_tsc + offset_from_current_tsc;
timer = timer->next;
}