/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __ISR_H #define __ISR_H #include #include #include #include #include #include struct ChainedInterrupt { link_t isrs; void (*const enable)(struct ChainedInterrupt *); void (*const disable)(struct ChainedInterrupt *); }; struct ChainedIsr { link_t node; uint32_t maxLatencyNs; bool (*func)(struct ChainedIsr *); uint16_t tid; }; static inline void chainIsr(struct ChainedInterrupt *interrupt, struct ChainedIsr *isr) { interrupt->disable(interrupt); isr->tid = osGetCurrentTid(); list_add_tail(&interrupt->isrs, &isr->node); interrupt->enable(interrupt); } static inline void unchainIsr(struct ChainedInterrupt *interrupt, struct ChainedIsr *isr) { interrupt->disable(interrupt); isr->tid = 0; list_delete(&isr->node); if (!list_is_empty(&interrupt->isrs)) interrupt->enable(interrupt); } static inline bool dispatchIsr(struct ChainedInterrupt *interrupt) { struct link_t *cur, *tmp; bool handled = false; uint16_t oldTid = osGetCurrentTid(); list_iterate(&interrupt->isrs, cur, tmp) { struct ChainedIsr *curIsr = container_of(cur, struct ChainedIsr, node); osSetCurrentTid(curIsr->tid); handled = curIsr->func(curIsr); if (handled) break; } osSetCurrentTid(oldTid); return handled; } static inline int unchainIsrAll(struct ChainedInterrupt *interrupt, uint32_t tid) { int count = 0; struct link_t *cur, *tmp; list_iterate(&interrupt->isrs, cur, tmp) { struct ChainedIsr *curIsr = container_of(cur, struct ChainedIsr, node); if (curIsr->tid == tid) { unchainIsr(interrupt, curIsr); count++; } } return count; } static inline uint32_t maxLatencyIsr(struct ChainedInterrupt *interrupt) { struct link_t *cur, *tmp; uint32_t latency = 0; list_iterate(&interrupt->isrs, cur, tmp) { struct ChainedIsr *curIsr = container_of(cur, struct ChainedIsr, node); if (!latency || (curIsr->maxLatencyNs && curIsr->maxLatencyNs < latency)) latency = curIsr->maxLatencyNs; } return latency; } #endif /* __ISR_H */