comparison gsm-fw/gpf/osl/os_tim_ir.c @ 482:9d80090a9e0c

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