comparison 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
comparison
equal deleted inserted replaced
-1:000000000000 0:4e78acac3d88
1 /*
2 * This C module is a reconstruction based on the disassembly of
3 * os_tim.obj in frame_na7_db_ir.lib from the Leonardo package,
4 * subsequently reworked by Space Falcon.
5 *
6 * The original decompilation has been contributed by Das Signal.
7 */
8
9 /* set of included headers from COFF symtab: */
10 #include <stdio.h>
11 #include "nucleus.h"
12 #include "typedefs.h"
13 #include "os.h"
14 #include "gdi.h"
15 #include "os_types.h"
16 #include "os_glob.h"
17
18 extern T_OS_TIMER_ENTRY TimerTable[];
19 extern T_OS_TIMER_TABLE_ENTRY *p_list[];
20
21 extern unsigned os_time_to_tick_multiplier;
22 extern unsigned os_tick_to_time_multiplier;
23
24 extern unsigned volatile t_start_ticks;
25 extern T_OS_TIMER_TABLE_ENTRY *t_running;
26 extern int used_timers;
27 extern int next_t_handle;
28 extern int volatile t_list_access;
29 extern int max_used_timers;
30 extern NU_SEMAPHORE TimSemCB;
31 extern NU_TIMER os_timer_cb;
32
33 #ifdef __GNUC__
34 #define BARRIER asm volatile ("": : :"memory")
35 #else
36 #define BARRIER /* prayer */
37 #endif
38
39 void
40 timer_error(int err)
41 {
42 }
43
44 /* forward declaration */
45 void os_Timeout(UNSIGNED t_handle);
46
47 static int
48 os_remove_timer_from_list(T_OS_TIMER_TABLE_ENTRY *timer)
49 {
50 OS_TICK c_ticks;
51
52 if (timer != t_running) {
53 if (timer->next != t_running)
54 timer->next->r_ticks += timer->r_ticks;
55 } else {
56 c_ticks = NU_Retrieve_Clock();
57 if (timer->next == timer) {
58 t_running = 0;
59 } else {
60 timer->next->r_ticks =
61 t_start_ticks + timer->r_ticks +
62 timer->next->r_ticks - c_ticks;
63 t_running = timer->next;
64 }
65 NU_Control_Timer(&os_timer_cb, NU_DISABLE_TIMER);
66 if (t_running != NULL) {
67 t_start_ticks = c_ticks;
68 if (t_running->r_ticks != 0)
69 NU_Reset_Timer(&os_timer_cb, os_Timeout,
70 t_running->r_ticks, 0,
71 NU_ENABLE_TIMER);
72 }
73 }
74 if (timer->next != timer) {
75 timer->prev->next = timer->next;
76 timer->next->prev = timer->prev;
77 }
78 timer->next = NULL;
79 timer->prev = NULL;
80 timer->status = TMR_USED;
81 return TMR_USED;
82 }
83
84 static unsigned
85 os_add_timer_to_list(T_OS_TIMER_TABLE_ENTRY *timer, OS_TICK ticks)
86 {
87 T_OS_TIMER_TABLE_ENTRY *t_list;
88 OS_TICK c_ticks, e_ticks, r1_ticks, return_ticks;
89
90 if (ticks == 0)
91 ticks = 1;
92
93 c_ticks = NU_Retrieve_Clock();
94 t_list = t_running;
95 if (t_list != NULL) {
96 e_ticks = c_ticks - t_start_ticks;
97 if (t_list->r_ticks >= e_ticks) {
98 r1_ticks = t_list->r_ticks - e_ticks;
99 t_list->r_ticks = r1_ticks;
100 } else {
101 r1_ticks = 0;
102 t_list->r_ticks = 0;
103 }
104 t_start_ticks = c_ticks;
105 return_ticks = 0;
106 while (ticks >= r1_ticks) {
107 ticks -= r1_ticks;
108 t_list = t_list->next;
109 if (t_list == t_running)
110 goto out;
111 r1_ticks = t_list->r_ticks;
112 }
113 t_list->r_ticks -= ticks;
114 if (t_list == t_running) {
115 t_running = timer;
116 t_start_ticks = c_ticks;
117 NU_Control_Timer(&os_timer_cb, NU_DISABLE_TIMER);
118 return_ticks = ticks;
119 }
120 out:
121 timer->next = t_list;
122 timer->prev = t_list->prev;
123 t_list->prev->next = timer;
124 t_list->prev = timer;
125 timer->r_ticks = ticks;
126 } else {
127 timer->next = timer;
128 timer->prev = timer;
129 timer->r_ticks = ticks;
130 t_start_ticks = c_ticks;
131 t_running = timer;
132 return_ticks = ticks;
133 }
134 timer->status = TMR_ACTIVE;
135 return return_ticks;
136 }
137
138 void
139 os_Timeout(UNSIGNED t_handle) /* argument is unused */
140 {
141 ULONG s_ticks;
142 OS_HANDLE task_handle, e_handle;
143 USHORT t_index;
144 int i, done;
145 T_OS_TIMER_TABLE_ENTRY **t_r4;
146 T_OS_TIMER_TABLE_ENTRY *timer;
147 void (*timeout_func) (OS_HANDLE, OS_HANDLE, USHORT);
148
149 if (t_list_access) {
150 t_start_ticks++;
151 NU_Reset_Timer(&os_timer_cb, os_Timeout, 1, 0,
152 NU_ENABLE_TIMER);
153 return;
154 }
155
156 timer = t_running;
157 if (timer) {
158 s_ticks = 0;
159 done = 0;
160 i = 0;
161 do {
162 timeout_func = timer->TimeoutProc;
163 if (timer->p_ticks)
164 p_list[i++] = timer;
165 task_handle = timer->task_handle;
166 e_handle = timer->entity_handle;
167 t_index = timer->t_index;
168 timer->status = TMR_USED;
169 if (timer->next == timer) {
170 t_running = NULL;
171 done = 1;
172 } else {
173 timer->prev->next = timer->next;
174 timer->next->prev = timer->prev;
175 if (timer->next->r_ticks) {
176 t_running = timer->next;
177 s_ticks = timer->next->r_ticks;
178 done = 1;
179 } else
180 timer = timer->next;
181 }
182 timeout_func(task_handle, e_handle, t_index);
183 }
184 while (!done);
185
186 if (s_ticks) {
187 t_start_ticks = NU_Retrieve_Clock();
188 NU_Reset_Timer(&os_timer_cb, os_Timeout, s_ticks, 0,
189 NU_ENABLE_TIMER);
190 }
191 }
192 for (t_r4 = p_list; *t_r4; t_r4++) {
193 timer = *t_r4;
194 s_ticks = os_add_timer_to_list(timer, timer->p_ticks);
195 if (s_ticks)
196 NU_Reset_Timer(&os_timer_cb, os_Timeout, s_ticks, 0,
197 NU_ENABLE_TIMER);
198 *t_r4 = NULL;
199 }
200 }
201
202 GLOBAL LONG os_StartTimer(OS_HANDLE TaskHandle, OS_HANDLE TimerHandle,
203 USHORT Index, OS_TIME InitialTime,
204 OS_TIME RescheduleTime)
205 {
206 T_OS_TIMER_TABLE_ENTRY *timer;
207 OS_TICK ticks;
208 STATUS sts;
209
210 if (TimerHandle > MaxSimultaneousTimer)
211 return(OS_ERROR);
212 timer = &TimerTable[TimerHandle].entry;
213 sts = NU_Obtain_Semaphore(&TimSemCB, NU_SUSPEND);
214 if (timer->status == TMR_FREE) {
215 if (sts == NU_SUCCESS)
216 NU_Release_Semaphore(&TimSemCB);
217 return(OS_ERROR);
218 }
219 t_list_access = 1;
220 BARRIER;
221 if (timer->status == TMR_ACTIVE)
222 os_remove_timer_from_list(timer);
223 timer->t_handle = TimerHandle;
224 timer->task_handle = os_MyHandle();
225 timer->entity_handle = TaskHandle;
226 timer->t_index = Index;
227 timer->p_ticks = TIME_TO_SYSTEM_TICKS(RescheduleTime);
228 ticks = os_add_timer_to_list(timer, TIME_TO_SYSTEM_TICKS(InitialTime));
229 if (ticks)
230 NU_Reset_Timer(&os_timer_cb, os_Timeout, ticks, 0,
231 NU_ENABLE_TIMER);
232 BARRIER;
233 t_list_access = 0;
234 if (sts == NU_SUCCESS)
235 NU_Release_Semaphore(&TimSemCB);
236 return OS_OK;
237 }
238
239 GLOBAL LONG os_StopTimer(OS_HANDLE TaskHandle, OS_HANDLE TimerHandle)
240 /* TaskHandle argument is unused */
241 {
242 T_OS_TIMER_ENTRY *timer_e;
243 STATUS sts;
244
245 if (TimerHandle > MaxSimultaneousTimer)
246 return(OS_ERROR);
247 timer_e = &TimerTable[TimerHandle];
248 sts = NU_Obtain_Semaphore(&TimSemCB, NU_SUSPEND);
249 if (timer_e->entry.status == TMR_FREE) {
250 if (sts == NU_SUCCESS)
251 NU_Release_Semaphore(&TimSemCB);
252 return OS_ERROR;
253 }
254 t_list_access = 1;
255 BARRIER;
256 if (timer_e->entry.status == TMR_ACTIVE)
257 os_remove_timer_from_list(&timer_e->entry);
258 BARRIER;
259 t_list_access = 0;
260 if (sts == NU_SUCCESS)
261 NU_Release_Semaphore(&TimSemCB);
262 return OS_OK;
263 }
264
265 GLOBAL LONG os_IncrementTick(OS_TICK ticks)
266 {
267 return OS_OK;
268 }
269
270 GLOBAL LONG os_DestroyTimer(OS_HANDLE TaskHandle, OS_HANDLE TimerHandle)
271 /* TaskHandle argument is unused */
272 {
273 STATUS sts;
274 T_OS_TIMER_ENTRY *timer_e;
275
276 if (TimerHandle > MaxSimultaneousTimer)
277 return(OS_ERROR);
278 sts = NU_Obtain_Semaphore(&TimSemCB, NU_SUSPEND);
279 timer_e = &TimerTable[TimerHandle];
280 if (timer_e->entry.status != TMR_USED) {
281 if (sts == NU_SUCCESS)
282 NU_Release_Semaphore(&TimSemCB);
283 return OS_ERROR;
284 }
285 timer_e->next_t_handle = next_t_handle;
286 next_t_handle = TimerHandle;
287 timer_e->entry.status = TMR_FREE;
288 used_timers--;
289 if (sts == NU_SUCCESS)
290 NU_Release_Semaphore(&TimSemCB);
291 return OS_OK;
292 }
293
294 GLOBAL LONG os_CreateTimer(OS_HANDLE TaskHandle,
295 void (*TimeoutProc) (OS_HANDLE, OS_HANDLE, USHORT),
296 OS_HANDLE *TimerHandle, OS_HANDLE MemPoolHandle)
297 /* TaskHandle and MemPoolHandle arguments are unused */
298 {
299 STATUS sts;
300 T_OS_TIMER_ENTRY *timer_e;
301
302 sts = NU_Obtain_Semaphore(&TimSemCB, NU_SUSPEND);
303 if (next_t_handle == 0) { /* no free timers left */
304 if (sts == NU_SUCCESS)
305 NU_Release_Semaphore(&TimSemCB);
306 return OS_ERROR;
307 }
308
309 timer_e = &TimerTable[next_t_handle];
310 timer_e->entry.status = TMR_USED;
311 timer_e->entry.TimeoutProc = TimeoutProc;
312 *TimerHandle = next_t_handle;
313 next_t_handle = timer_e->next_t_handle;
314 used_timers++;
315 if (max_used_timers < used_timers)
316 max_used_timers = used_timers;
317 if (sts == NU_SUCCESS)
318 NU_Release_Semaphore(&TimSemCB);
319 return OS_OK;
320 }