# HG changeset patch # User Michael Spacefalcon # Date 1404027442 0 # Node ID 9d80090a9e0cfd1a00e49876abcb5b2014b5f264 # Parent 5639b4fa867287cc2fae823c2445370de7723fc8 os_tim_{fl,ir}.c: timer list concurrency interlocks redesigned to something sensible diff -r 5639b4fa8672 -r 9d80090a9e0c gsm-fw/gpf/osl/os_tim_fl.c --- a/gsm-fw/gpf/osl/os_tim_fl.c Sun Jun 29 04:06:24 2014 +0000 +++ b/gsm-fw/gpf/osl/os_tim_fl.c Sun Jun 29 07:37:22 2014 +0000 @@ -1,6 +1,7 @@ /* * This C module is a reconstruction based on the disassembly of - * os_tim.obj in frame_na7_db_fl.lib from the Leonardo package. + * os_tim.obj in frame_na7_db_fl.lib from the Leonardo package, + * subsequently reworked by Space Falcon. */ /* set of included headers from COFF symtab: */ @@ -25,8 +26,8 @@ unsigned os_time_to_tick_multiplier = TIME_TO_TICK_TDMA_FRAME_MULTIPLIER; unsigned os_tick_to_time_multiplier = TICK_TO_TIME_TDMA_FRAME_MULTIPLIER; -unsigned t_start_ticks; -T_OS_TIMER_TABLE_ENTRY * volatile t_running; +unsigned volatile t_start_ticks; +T_OS_TIMER_TABLE_ENTRY *t_running; int used_timers; int next_t_handle; int volatile t_list_access; @@ -34,6 +35,8 @@ NU_SEMAPHORE TimSemCB; NU_TIMER os_timer_cb; +#define BARRIER asm volatile ("": : :"memory") + GLOBAL LONG os_set_tick(int os_system_tick) { @@ -117,40 +120,45 @@ os_QueryTimer(OS_HANDLE TaskHandle, OS_HANDLE TimerHandle, OS_TIME *RemainingTime) { - T_OS_TIMER_TABLE_ENTRY *timer, *t_r0, *t_r3; + T_OS_TIMER_TABLE_ENTRY *timer, *t_iter; OS_TICK c_ticks, r_ticks, e_ticks; STATUS sts; - t_list_access = 1; - if (TimerHandle > MaxSimultaneousTimer) { -error_out: t_list_access = 0; + if (TimerHandle > MaxSimultaneousTimer) + return(OS_ERROR); + sts = NU_Obtain_Semaphore(&TimSemCB, NU_SUSPEND); + timer = &TimerTable[TimerHandle].entry; + if (timer->status == TMR_FREE) { + if (sts == NU_SUCCESS) + NU_Release_Semaphore(&TimSemCB); return(OS_ERROR); } - timer = &TimerTable[TimerHandle].entry; - if (!timer->status) - goto error_out; - sts = NU_Obtain_Semaphore(&TimSemCB, NU_SUSPEND); - if (sts != NU_SUCCESS) - timer_error(15); + t_list_access = 1; + BARRIER; + if (!t_running) { + r_ticks = 0; + goto out; + } c_ticks = NU_Retrieve_Clock(); e_ticks = c_ticks - t_start_ticks; - t_r0 = t_running; - *RemainingTime = 0; - t_r3 = t_running; - if (t_r0 == t_r3) - r_ticks = t_r0->r_ticks - e_ticks; + t_iter = t_running; + if (t_iter->r_ticks >= e_ticks) + r_ticks = t_iter->r_ticks - e_ticks; else - r_ticks = t_r0->r_ticks; - while (t_r0 != timer) { - t_r0 = t_r0->next; - if (t_r0 == t_r3) + r_ticks = 0; + while (t_iter != timer) { + t_iter = t_iter->next; + if (t_iter == t_running) { + r_ticks = 0; goto out; - r_ticks += t_r0->r_ticks; + } + r_ticks += t_iter->r_ticks; } +out: BARRIER; + t_list_access = 0; + if (sts == NU_SUCCESS) + NU_Release_Semaphore(&TimSemCB); *RemainingTime = SYSTEM_TICKS_TO_TIME(r_ticks); -out: if (sts == NU_SUCCESS) - NU_Release_Semaphore(&TimSemCB); - t_list_access = 0; return(OS_OK); } diff -r 5639b4fa8672 -r 9d80090a9e0c gsm-fw/gpf/osl/os_tim_ir.c --- a/gsm-fw/gpf/osl/os_tim_ir.c Sun Jun 29 04:06:24 2014 +0000 +++ b/gsm-fw/gpf/osl/os_tim_ir.c Sun Jun 29 07:37:22 2014 +0000 @@ -1,6 +1,9 @@ /* * This C module is a reconstruction based on the disassembly of - * os_tim.obj in frame_na7_db_ir.lib from the Leonardo package. + * 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: */ @@ -19,8 +22,8 @@ extern unsigned os_time_to_tick_multiplier; extern unsigned os_tick_to_time_multiplier; -extern unsigned t_start_ticks; -extern T_OS_TIMER_TABLE_ENTRY * volatile t_running; +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; @@ -28,83 +31,15 @@ extern NU_SEMAPHORE TimSemCB; extern NU_TIMER os_timer_cb; +#define BARRIER asm volatile ("": : :"memory") + void timer_error(int err) { } -/* - * The following function reconstructions have been contributed by Das Signal, - * then reviewed and fixed in a few places by Space Falcon. - */ - -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); - OS_TIME resched_time; - - if (t_list_access) { - t_start_ticks++; - NU_Reset_Timer(&os_timer_cb, os_Timeout, 1, 0, - NU_ENABLE_TIMER); - return; - } - - t_list_access = 1; - 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; - resched_time = SYSTEM_TICKS_TO_TIME(timer->p_ticks); - os_StartTimer(timer->entity_handle, timer->t_handle, - timer->t_index, resched_time, resched_time); - *t_r4 = NULL; - } - - t_list_access = 0; - return; -} +/* forward declaration */ +void os_Timeout(UNSIGNED t_handle); static int os_remove_timer_from_list(T_OS_TIMER_TABLE_ENTRY *timer) @@ -147,7 +82,7 @@ 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, r1_ticks, return_ticks; + OS_TICK c_ticks, e_ticks, r1_ticks, return_ticks; if (ticks == 0) ticks = 1; @@ -155,8 +90,9 @@ c_ticks = NU_Retrieve_Clock(); t_list = t_running; if (t_list != NULL) { - if (t_list->r_ticks >= c_ticks - t_start_ticks) { - r1_ticks = t_list->r_ticks - c_ticks + t_start_ticks; + 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; @@ -196,30 +132,91 @@ 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; - USHORT status; STATUS sts; - t_list_access = 1; + if (TimerHandle > MaxSimultaneousTimer) + return(OS_ERROR); timer = &TimerTable[TimerHandle].entry; - if (TimerHandle > MaxSimultaneousTimer || timer->status == TMR_FREE) { - t_list_access = 0; - return OS_ERROR; - } - sts = NU_Obtain_Semaphore(&TimSemCB, NU_SUSPEND); - /* Disassembly reveals this bogon in the original code: - if (sts != NU_SUCCESS) - os_MyHandle(); - */ - status = timer->status; - if (status == TMR_ACTIVE) - status = os_remove_timer_from_list(timer); + 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; @@ -229,9 +226,10 @@ 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); - t_list_access = 0; return OS_OK; } @@ -241,19 +239,23 @@ T_OS_TIMER_ENTRY *timer_e; STATUS sts; - t_list_access = 1; + if (TimerHandle > MaxSimultaneousTimer) + return(OS_ERROR); timer_e = &TimerTable[TimerHandle]; - if (TimerHandle > MaxSimultaneousTimer || - timer_e->entry.status == TMR_FREE) { - t_list_access = 0; + 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; } - sts = NU_Obtain_Semaphore(&TimSemCB, NU_SUSPEND); + 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); - t_list_access = 0; return OS_OK; } @@ -268,21 +270,19 @@ STATUS sts; T_OS_TIMER_ENTRY *timer_e; - t_list_access = 1; + if (TimerHandle > MaxSimultaneousTimer) + return(OS_ERROR); sts = NU_Obtain_Semaphore(&TimSemCB, NU_SUSPEND); timer_e = &TimerTable[TimerHandle]; - if (TimerHandle > MaxSimultaneousTimer || - timer_e->entry.status == TMR_FREE) { + if (timer_e->entry.status != TMR_USED) { if (sts == NU_SUCCESS) NU_Release_Semaphore(&TimSemCB); - t_list_access = 0; return OS_ERROR; } timer_e->next_t_handle = next_t_handle; next_t_handle = TimerHandle; timer_e->entry.status = TMR_FREE; used_timers--; - t_list_access = 0; if (sts == NU_SUCCESS) NU_Release_Semaphore(&TimSemCB); return OS_OK; @@ -296,12 +296,10 @@ STATUS sts; T_OS_TIMER_ENTRY *timer_e; - t_list_access = 1; sts = NU_Obtain_Semaphore(&TimSemCB, NU_SUSPEND); if (next_t_handle == 0) { /* no free timers left */ if (sts == NU_SUCCESS) NU_Release_Semaphore(&TimSemCB); - t_list_access = 0; return OS_ERROR; } @@ -315,6 +313,5 @@ max_used_timers = used_timers; if (sts == NU_SUCCESS) NU_Release_Semaphore(&TimSemCB); - t_list_access = 0; return OS_OK; }