diff src/gpf/osl/os_tim_ir.c @ 0:4e78acac3d88

src/{condat,cs,gpf,nucleus}: import from Selenite
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 16 Oct 2020 06:23:26 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gpf/osl/os_tim_ir.c	Fri Oct 16 06:23:26 2020 +0000
@@ -0,0 +1,320 @@
+/*
+ * This C module is a reconstruction based on the disassembly of
+ * os_tim.obj in frame_na7_db_ir.lib from the Leonardo package,
+ * subsequently reworked by Space Falcon.
+ *
+ * The original decompilation has been contributed by Das Signal.
+ */
+
+/* set of included headers from COFF symtab: */
+#include <stdio.h>
+#include "nucleus.h"
+#include "typedefs.h"
+#include "os.h"
+#include "gdi.h"
+#include "os_types.h"
+#include "os_glob.h"
+
+extern T_OS_TIMER_ENTRY TimerTable[];
+extern T_OS_TIMER_TABLE_ENTRY *p_list[];
+
+extern unsigned os_time_to_tick_multiplier;
+extern unsigned os_tick_to_time_multiplier;
+
+extern unsigned volatile t_start_ticks;
+extern T_OS_TIMER_TABLE_ENTRY *t_running;
+extern int used_timers;
+extern int next_t_handle;
+extern int volatile t_list_access;
+extern int max_used_timers;
+extern NU_SEMAPHORE TimSemCB;
+extern NU_TIMER os_timer_cb;
+
+#ifdef __GNUC__
+#define	BARRIER	asm volatile ("": : :"memory")
+#else
+#define	BARRIER	/* prayer */
+#endif
+
+void
+timer_error(int err)
+{
+}
+
+/* forward declaration */
+void os_Timeout(UNSIGNED t_handle);
+
+static int
+os_remove_timer_from_list(T_OS_TIMER_TABLE_ENTRY *timer)
+{
+	OS_TICK c_ticks;
+
+	if (timer != t_running) {
+		if (timer->next != t_running)
+			timer->next->r_ticks += timer->r_ticks;
+	} else {
+		c_ticks = NU_Retrieve_Clock();
+		if (timer->next == timer) {
+			t_running = 0;
+		} else {
+			timer->next->r_ticks =
+			    t_start_ticks + timer->r_ticks +
+			    timer->next->r_ticks - c_ticks;
+			t_running = timer->next;
+		}
+		NU_Control_Timer(&os_timer_cb, NU_DISABLE_TIMER);
+		if (t_running != NULL) {
+			t_start_ticks = c_ticks;
+			if (t_running->r_ticks != 0)
+				NU_Reset_Timer(&os_timer_cb, os_Timeout,
+						t_running->r_ticks, 0,
+						NU_ENABLE_TIMER);
+		}
+	}
+	if (timer->next != timer) {
+		timer->prev->next = timer->next;
+		timer->next->prev = timer->prev;
+	}
+	timer->next = NULL;
+	timer->prev = NULL;
+	timer->status = TMR_USED;
+	return TMR_USED;
+}
+
+static unsigned
+os_add_timer_to_list(T_OS_TIMER_TABLE_ENTRY *timer, OS_TICK ticks)
+{
+	T_OS_TIMER_TABLE_ENTRY *t_list;
+	OS_TICK c_ticks, e_ticks, r1_ticks, return_ticks;
+
+	if (ticks == 0)
+		ticks = 1;
+
+	c_ticks = NU_Retrieve_Clock();
+	t_list = t_running;
+	if (t_list != NULL) {
+		e_ticks = c_ticks - t_start_ticks;
+		if (t_list->r_ticks >= e_ticks) {
+			r1_ticks = t_list->r_ticks - e_ticks;
+			t_list->r_ticks = r1_ticks;
+		} else {
+			r1_ticks = 0;
+			t_list->r_ticks = 0;
+		}
+		t_start_ticks = c_ticks;
+		return_ticks = 0;
+		while (ticks >= r1_ticks) {
+			ticks -= r1_ticks;
+			t_list = t_list->next;
+			if (t_list == t_running)
+				goto out;
+			r1_ticks = t_list->r_ticks;
+		}
+		t_list->r_ticks -= ticks;
+		if (t_list == t_running) {
+			t_running = timer;
+			t_start_ticks = c_ticks;
+			NU_Control_Timer(&os_timer_cb, NU_DISABLE_TIMER);
+			return_ticks = ticks;
+		}
+out:
+		timer->next = t_list;
+		timer->prev = t_list->prev;
+		t_list->prev->next = timer;
+		t_list->prev = timer;
+		timer->r_ticks = ticks;
+	} else {
+		timer->next = timer;
+		timer->prev = timer;
+		timer->r_ticks = ticks;
+		t_start_ticks = c_ticks;
+		t_running = timer;
+		return_ticks = ticks;
+	}
+	timer->status = TMR_ACTIVE;
+	return return_ticks;
+}
+
+void
+os_Timeout(UNSIGNED t_handle)	/* argument is unused */
+{
+	ULONG s_ticks;
+	OS_HANDLE task_handle, e_handle;
+	USHORT t_index;
+	int i, done;
+	T_OS_TIMER_TABLE_ENTRY **t_r4;
+	T_OS_TIMER_TABLE_ENTRY *timer;
+	void (*timeout_func) (OS_HANDLE, OS_HANDLE, USHORT);
+
+	if (t_list_access) {
+		t_start_ticks++;
+		NU_Reset_Timer(&os_timer_cb, os_Timeout, 1, 0,
+				NU_ENABLE_TIMER);
+		return;
+	}
+
+	timer = t_running;
+	if (timer) {
+		s_ticks = 0;
+		done = 0;
+		i = 0;
+		do {
+			timeout_func = timer->TimeoutProc;
+			if (timer->p_ticks)
+				p_list[i++] = timer;
+			task_handle = timer->task_handle;
+			e_handle = timer->entity_handle;
+			t_index = timer->t_index;
+			timer->status = TMR_USED;
+			if (timer->next == timer) {
+				t_running = NULL;
+				done = 1;
+			} else {
+				timer->prev->next = timer->next;
+				timer->next->prev = timer->prev;
+				if (timer->next->r_ticks) {
+					t_running = timer->next;
+					s_ticks = timer->next->r_ticks;
+					done = 1;
+				} else
+					timer = timer->next;
+			}
+			timeout_func(task_handle, e_handle, t_index);
+		}
+		while (!done);
+
+		if (s_ticks) {
+			t_start_ticks = NU_Retrieve_Clock();
+			NU_Reset_Timer(&os_timer_cb, os_Timeout, s_ticks, 0,
+				       NU_ENABLE_TIMER);
+		}
+	}
+	for (t_r4 = p_list; *t_r4; t_r4++) {
+		timer = *t_r4;
+		s_ticks = os_add_timer_to_list(timer, timer->p_ticks);
+		if (s_ticks)
+			NU_Reset_Timer(&os_timer_cb, os_Timeout, s_ticks, 0,
+					NU_ENABLE_TIMER);
+		*t_r4 = NULL;
+	}
+}
+
+GLOBAL LONG os_StartTimer(OS_HANDLE TaskHandle, OS_HANDLE TimerHandle,
+				USHORT Index, OS_TIME InitialTime,
+				OS_TIME RescheduleTime)
+{
+	T_OS_TIMER_TABLE_ENTRY *timer;
+	OS_TICK ticks;
+	STATUS sts;
+
+	if (TimerHandle > MaxSimultaneousTimer)
+		return(OS_ERROR);
+	timer = &TimerTable[TimerHandle].entry;
+	sts = NU_Obtain_Semaphore(&TimSemCB, NU_SUSPEND);
+	if (timer->status == TMR_FREE) {
+		if (sts == NU_SUCCESS)
+			NU_Release_Semaphore(&TimSemCB);
+		return(OS_ERROR);
+	}
+	t_list_access = 1;
+	BARRIER;
+	if (timer->status == TMR_ACTIVE)
+		os_remove_timer_from_list(timer);
+	timer->t_handle = TimerHandle;
+	timer->task_handle = os_MyHandle();
+	timer->entity_handle = TaskHandle;
+	timer->t_index = Index;
+	timer->p_ticks = TIME_TO_SYSTEM_TICKS(RescheduleTime);
+	ticks = os_add_timer_to_list(timer, TIME_TO_SYSTEM_TICKS(InitialTime));
+	if (ticks)
+		NU_Reset_Timer(&os_timer_cb, os_Timeout, ticks, 0,
+				NU_ENABLE_TIMER);
+	BARRIER;
+	t_list_access = 0;
+	if (sts == NU_SUCCESS)
+		NU_Release_Semaphore(&TimSemCB);
+	return OS_OK;
+}
+
+GLOBAL LONG os_StopTimer(OS_HANDLE TaskHandle, OS_HANDLE TimerHandle)
+	/* TaskHandle argument is unused */
+{
+	T_OS_TIMER_ENTRY *timer_e;
+	STATUS sts;
+
+	if (TimerHandle > MaxSimultaneousTimer)
+		return(OS_ERROR);
+	timer_e = &TimerTable[TimerHandle];
+	sts = NU_Obtain_Semaphore(&TimSemCB, NU_SUSPEND);
+	if (timer_e->entry.status == TMR_FREE) {
+		if (sts == NU_SUCCESS)
+			NU_Release_Semaphore(&TimSemCB);
+		return OS_ERROR;
+	}
+	t_list_access = 1;
+	BARRIER;
+	if (timer_e->entry.status == TMR_ACTIVE)
+		os_remove_timer_from_list(&timer_e->entry);
+	BARRIER;
+	t_list_access = 0;
+	if (sts == NU_SUCCESS)
+		NU_Release_Semaphore(&TimSemCB);
+	return OS_OK;
+}
+
+GLOBAL LONG os_IncrementTick(OS_TICK ticks)
+{
+	return OS_OK;
+}
+
+GLOBAL LONG os_DestroyTimer(OS_HANDLE TaskHandle, OS_HANDLE TimerHandle)
+	/* TaskHandle argument is unused */
+{
+	STATUS sts;
+	T_OS_TIMER_ENTRY *timer_e;
+
+	if (TimerHandle > MaxSimultaneousTimer)
+		return(OS_ERROR);
+	sts = NU_Obtain_Semaphore(&TimSemCB, NU_SUSPEND);
+	timer_e = &TimerTable[TimerHandle];
+	if (timer_e->entry.status != TMR_USED) {
+		if (sts == NU_SUCCESS)
+			NU_Release_Semaphore(&TimSemCB);
+		return OS_ERROR;
+	}
+	timer_e->next_t_handle = next_t_handle;
+	next_t_handle = TimerHandle;
+	timer_e->entry.status = TMR_FREE;
+	used_timers--;
+	if (sts == NU_SUCCESS)
+		NU_Release_Semaphore(&TimSemCB);
+	return OS_OK;
+}
+
+GLOBAL LONG os_CreateTimer(OS_HANDLE TaskHandle,
+			   void (*TimeoutProc) (OS_HANDLE, OS_HANDLE, USHORT),
+			   OS_HANDLE *TimerHandle, OS_HANDLE MemPoolHandle)
+	/* TaskHandle and MemPoolHandle arguments are unused */
+{
+	STATUS sts;
+	T_OS_TIMER_ENTRY *timer_e;
+
+	sts = NU_Obtain_Semaphore(&TimSemCB, NU_SUSPEND);
+	if (next_t_handle == 0) { /* no free timers left */
+		if (sts == NU_SUCCESS)
+			NU_Release_Semaphore(&TimSemCB);
+		return OS_ERROR;
+	}
+
+	timer_e = &TimerTable[next_t_handle];
+	timer_e->entry.status = TMR_USED;
+	timer_e->entry.TimeoutProc = TimeoutProc;
+	*TimerHandle = next_t_handle;
+	next_t_handle = timer_e->next_t_handle;
+	used_timers++;
+	if (max_used_timers < used_timers)
+		max_used_timers = used_timers;
+	if (sts == NU_SUCCESS)
+		NU_Release_Semaphore(&TimSemCB);
+	return OS_OK;
+}