/** * @file tpl_as_counter_kernel.c * * @internal * * @section desc File description * * Trampoline autosar extension software counters functions * * @section copyright Copyright * * Trampoline OS * * Trampoline is copyright (c) IRCCyN 2005-2007 * Autosar extension is copyright (c) IRCCyN and ESEO 2007 * Trampoline and its Autosar extension are protected by the * French intellectual property law. * * This software is distributed under the Lesser GNU Public Licence * * @section infos File informations * * $Date$ * $Rev$ * $Author$ * $URL$ */ #include "tpl_as_spinlock_kernel.h" #include "tpl_os_kernel.h" #include "tpl_os_errorhook.h" #include "tpl_machine_interface.h" #include "tpl_as_error.h" #include "tpl_os_error.h" #include "tpl_os_definitions.h" #include "tpl_as_definitions.h" #define OS_START_SEC_CODE #include "tpl_memmap.h" /** * FIXME : Ugly but we need this until the SPINLOCK_RESUME and SPINLOCK_SUSPEND * macros are corrected. */ tpl_bool tpl_spinlock_resscheduler_taken[NUMBER_OF_CORES] = {FALSE}; /* * */ FUNC(tpl_status, OS_CODE) tpl_get_spinlock_service( VAR(tpl_spinlock_id, AUTOMATIC) spinlock_id) { GET_CURRENT_CORE_ID(core_id) VAR(tpl_status, AUTOMATIC) result = E_OK; P2VAR(tpl_lock, AUTOMATIC, OS_VAR) lock = NULL_PTR; /* store information for error hook routine */ STORE_SERVICE(OSServiceId_GetSpinlock) STORE_SPINLOCK_ID(spinlock_id) /* check a spinlock_id error */ CHECK_SPINLOCK_ID_ERROR(spinlock_id, result) /* check access rights */ CHECK_ACCESS_RIGHTS_SPINLOCK_ID(core_id, spinlock_id, result) /* check spinlock interference deadlock error */ CHECK_SPINLOCK_INTERFERENCE_DEADLOCK_ERROR(core_id, spinlock_id, result) /* check spinlock nesting order error */ CHECK_SPINLOCK_NESTING_ORDER_ERROR(core_id, spinlock_id, result) IF_NO_EXTENDED_ERROR(result) { /* increase the tolerance level of interrupts following the spinlock's * lock method */ SPINLOCK_SUSPEND_INTERRUPTS(core_id, spinlock_id) /* get the lock descriptor */ lock = &(tpl_spinlock_table[spinlock_id]->state); /* get the lock, this call is blocking */ tpl_get_lock(lock); /* get the resscheduler if the spinlock has the associated method */ SPINLOCK_GET_RESSCHEDULER(core_id, spinlock_id) /* store id of last taken spinlock, so we can check later the nesting order */ SET_LAST_TAKEN_SPINLOCK(core_id, spinlock_id) } PROCESS_ERROR(result) return result; } /* * */ FUNC(tpl_status, OS_CODE) tpl_release_spinlock_service( VAR(tpl_spinlock_id, AUTOMATIC) spinlock_id) { GET_CURRENT_CORE_ID(core_id) VAR(tpl_status, AUTOMATIC) result = E_OK; P2VAR(tpl_lock, AUTOMATIC, OS_VAR) lock = NULL_PTR; /* store information for error hook routine */ STORE_SERVICE(OSServiceId_ReleaseSpinlock) STORE_SPINLOCK_ID(spinlock_id) /* check a spinlock_id error */ CHECK_SPINLOCK_ID_ERROR(spinlock_id, result) /* check access rights */ CHECK_ACCESS_RIGHTS_SPINLOCK_ID(core_id, spinlock_id, result) /* check spinlock not taken error */ CHECK_SPINLOCK_NOT_TAKEN_ERROR(core_id, spinlock_id, result) /* check spinlock nesting order error */ CHECK_SPINLOCK_UNNESTING_ORDER_ERROR(core_id, spinlock_id, result) IF_NO_EXTENDED_ERROR(result) { /* get the lock descriptor */ lock = &(tpl_spinlock_table[spinlock_id]->state); /* get the lock, this call is blocking */ tpl_release_lock(lock); /* store id of last released spinlock, so we can check later the nesting order */ REMOVE_LAST_TAKEN_SPINLOCK(core_id) /* lower the tolerance level of interrupts. Release res_scheduler */ SPINLOCK_RESUME_INTERRUPTS(core_id) } PROCESS_ERROR(result) return result; } /* * */ FUNC(tpl_status, OS_CODE) tpl_try_to_get_spinlock_service( VAR(tpl_spinlock_id, AUTOMATIC) spinlock_id, P2VAR(tpl_try_to_get_spinlock_type, AUTOMATIC, OS_VAR) success) { GET_CURRENT_CORE_ID(core_id) VAR(tpl_status, AUTOMATIC) result = E_OK; P2VAR(tpl_lock, AUTOMATIC, OS_VAR) lock = NULL_PTR; /* store information for error hook routine */ STORE_SERVICE(OSServiceId_TryToGetSpinlock) STORE_SPINLOCK_ID(spinlock_id) /* check a spinlock_id error */ CHECK_SPINLOCK_ID_ERROR(spinlock_id, result) /* check access rights */ CHECK_ACCESS_RIGHTS_SPINLOCK_ID(core_id, spinlock_id, result) /* check spinlock interference deadlock error */ CHECK_SPINLOCK_INTERFERENCE_DEADLOCK_ERROR(core_id, spinlock_id, result) /* check spinlock nesting order error */ CHECK_SPINLOCK_NESTING_ORDER_ERROR(core_id, spinlock_id, result) IF_NO_EXTENDED_ERROR(result) { /* increase the tolerance level of interrupts following the spinlock's * lock method */ SPINLOCK_SUSPEND_INTERRUPTS(core_id, spinlock_id) /* get the lock descriptor */ lock = &(tpl_spinlock_table[spinlock_id]->state); /* get the lock, this call is not blocking */ tpl_try_to_get_lock(lock, success); if (*success == TRYTOGETSPINLOCK_SUCCESS) { /* get the resscheduler if the spinlock has the associated method */ SPINLOCK_GET_RESSCHEDULER(core_id, spinlock_id) /* store id of last taken spinlock */ SET_LAST_TAKEN_SPINLOCK(core_id, spinlock_id) } else { /* restore the tolerance level of interrupts if the lock has not been * taken */ SPINLOCK_RESUME_INTERRUPTS(core_id) } } PROCESS_ERROR(result) return result; } #define OS_STOP_SEC_CODE #include "tpl_memmap.h" #include "Os.h" #define API_START_SEC_CODE #include "tpl_memmap.h" /* * Trampoline extra * GetSpinlock_IE : GetSpinlock with Interrupts Enabled */ FUNC(tpl_status, OS_CODE) GetSpinlock_IE( VAR(tpl_spinlock_id, AUTOMATIC) spinlock_id) { VAR(tpl_status, AUTOMATIC) result = E_OK; VAR(TryToGetSpinlockType, AUTOMATIC) success = TRYTOGETSPINLOCK_NOSUCCESS; do { result = TryToGetSpinlock(spinlock_id, &success); } while((result == E_OK) && (success == TRYTOGETSPINLOCK_NOSUCCESS)); return result; } #define API_STOP_SEC_CODE #include "tpl_memmap.h" /* End of file tpl_as_counter_kernel.c */