void syscall_DriverStandardCall(const _OS_Syscall_Args * param_info, const void * arg, void * ret) { const UINT32 * uint_args = (const UINT32 *)arg; UINT32 * uint_ret = (UINT32 *)ret; OS_Return result = SYSCALL_ARGUMENT_ERROR; Klog32(KLOG_SYSCALL, "Syscall SubId - ", param_info->sub_id); switch(param_info->sub_id) { case SUBCALL_DRIVER_LOOKUP: if((param_info->arg_count >= 1) && (param_info->ret_count >= 2)) { result = _OS_DriverLookup((const INT8 *)uint_args[0], (OS_Driver_t *)(uint_ret+1)); } break; case SUBCALL_DRIVER_OPEN: if(param_info->arg_count >= 2) { result = _OS_DriverOpen((OS_Driver_t) uint_args[0], (OS_DriverAccessMode) uint_args[1]); } break; case SUBCALL_DRIVER_CLOSE: if(param_info->arg_count >= 1) { result = _OS_DriverClose((OS_Driver_t) uint_args[0]); } break; case SUBCALL_DRIVER_READ: if((param_info->arg_count >= 4) && (param_info->ret_count >= 2)) { uint_ret[1] = uint_args[2]; result = _OS_DriverRead((OS_Driver_t) uint_args[0], (void *) uint_args[1], &uint_ret[1], (BOOL) uint_args[3]); } break; case SUBCALL_DRIVER_WRITE: if((param_info->arg_count >= 4) && (param_info->ret_count >= 2)) { uint_ret[1] = uint_args[2]; result = _OS_DriverWrite((OS_Driver_t) uint_args[0], (const void *) uint_args[1], &uint_ret[1], (BOOL) uint_args[3]); } break; case SUBCALL_DRIVER_CONFIGURE: break; } if(uint_ret) uint_ret[0] = result; }
/////////////////////////////////////////////////////////////////////////////// // Kernel Side of the Syscall function /////////////////////////////////////////////////////////////////////////////// void _OS_KernelSyscall(const _OS_Syscall_Args * param_info, const void * arg, void * ret) { if(!param_info || (param_info->id >= SYSCALL_MAX_COUNT) || !_syscall_handlers[param_info->id]) { KlogStr(KLOG_WARNING, "Error occurred in Kernel function %s", __FUNCTION__); if(ret) ((UINT32 *)ret)[0] = SYSCALL_ARGUMENT_ERROR; return; } Klog32(KLOG_SYSCALL, "Syscall Id - ", param_info->id); // Note down the return pointer which may be needed to update the output parameters if(g_current_task) g_current_task->syscall_result = (UINT32 *)ret; _syscall_handlers[param_info->id](param_info, arg, ret); }
OS_Return _OS_SemWait(OS_Sem_t sem) { OS_Return status; #if OS_ENABLE_CPU_STATS==1 g_sched_starting_counter_value = _OS_Timer_GetCount(PERIODIC_TIMER); #endif if((status = assert_open(sem)) != SUCCESS) { goto exit; } // Get the Semaphore object OS_SemaphoreCB * semobj = (OS_SemaphoreCB *)&g_semaphore_pool[sem]; // Make sure that the current process owns the Semaphore. if(semobj->owner != (OS_Process *) g_current_process) { status = RESOURCE_NOT_OWNED; goto exit; } // Get the task execution time UINT32 budget_spent = _OS_Timer_GetTimeElapsed_us(BUDGET_TIMER); g_current_task->accumulated_budget += budget_spent; if(IS_PERIODIC_TASK(g_current_task->attributes)) { // Adjust the remaining budget for the current task ASSERT(budget_spent <= ((OS_PeriodicTask *)g_current_task)->remaining_budget); ((OS_PeriodicTask *)g_current_task)->remaining_budget -= budget_spent; } // If the semaphore count is 0, then block the thread if(semobj->count == 0) { // Block the thread if(IS_PERIODIC_TASK(g_current_task->attributes)) { // Delete the current task from ready tasks queue _OS_QueueDelete(&g_ready_q, (void*)g_current_task); // Add the current task to the semaphore's blocked queue for periodic tasks _OS_QueueInsert(&semobj->periodic_task_queue, (void*)g_current_task, ((OS_PeriodicTask *)g_current_task)->alarm_time); } else { // Delete the current task from ready tasks queue _OS_QueueDelete(&g_ap_ready_q, (void*)g_current_task); // Add the current task to the semaphore's blocked queue for aperiodic tasks _OS_QueueInsert(&semobj->aperiodic_task_queue, (void*)g_current_task, ((OS_AperiodicTask *)g_current_task)->priority); } Klog32(KLOG_SEMAPHORE_DEBUG, "Semaphore :- ", semobj->count); } else { // Decrement the semaphore count in order to acquire it semobj->count--; Klog32(KLOG_SEMAPHORE_DEBUG, "Semaphore - ", semobj->count); // The return path for this function is through _OS_Schedule, so it is important to // update the result in the syscall_result if(g_current_task->syscall_result) g_current_task->syscall_result[0] = SUCCESS; } _OS_Schedule(); exit: return status; }
OS_Return _OS_SemPost(OS_Sem_t sem) { OS_GenericTask* task = NULL; OS_Return status; UINT64 key = 0; #if OS_ENABLE_CPU_STATS==1 g_sched_starting_counter_value = _OS_Timer_GetCount(PERIODIC_TIMER); #endif if((status = assert_open(sem)) != SUCCESS) { goto exit; } // Get the Semaphore object OS_SemaphoreCB * semobj = (OS_SemaphoreCB *)&g_semaphore_pool[sem]; // Make sure that the current process owns the Semaphore. if(semobj->owner != (OS_Process *) g_current_process) { status = RESOURCE_NOT_OWNED; goto exit; } // Get the task execution time UINT32 budget_spent = _OS_Timer_GetTimeElapsed_us(BUDGET_TIMER); g_current_task->accumulated_budget += budget_spent; if(IS_PERIODIC_TASK(g_current_task->attributes)) { // Adjust the remaining budget for the current task ASSERT(budget_spent <= ((OS_PeriodicTask *)g_current_task)->remaining_budget); ((OS_PeriodicTask *)g_current_task)->remaining_budget -= budget_spent; } if(semobj->count == 0) { // Unblock a waiting task. First check the periodic queue _OS_QueueGet(&semobj->periodic_task_queue, (void**)&task, &key); if(task) { // Place this task in the periodic task ready queue _OS_QueueInsert(&g_ready_q,(void*)task, key); } else { // Now check the Aperiodic queue _OS_QueueGet(&semobj->aperiodic_task_queue, (void**)&task, &key); if(task) { // Insert this task into Aperiodic task queue _OS_QueueInsert(&g_ap_ready_q,(void*)task,key); } } } if(task) { // If a task is getting ready, then there is no need to increment the semaphore count // The return path for this function is through _OS_Schedule, so it is important to // update the result in the syscall_result if(task->syscall_result) task->syscall_result[0] = SUCCESS; Klog32(KLOG_SEMAPHORE_DEBUG, "Semaphore :+ ", semobj->count); } else { // Increment the resource count semobj->count++; Klog32(KLOG_SEMAPHORE_DEBUG, "Semaphore + ", semobj->count); } _OS_Schedule(); exit: return status; }