1 /*
2  * Copyright 2014, General Dynamics C4 Systems
3  *
4  * SPDX-License-Identifier: GPL-2.0-only
5  */
6 
7 #include <api/failures.h>
8 #include <model/preemption.h>
9 #include <model/statedata.h>
10 #include <plat/machine/hardware.h>
11 #include <config.h>
12 
13 /*
14  * Possibly preempt the current thread to allow an interrupt to be handled.
15  */
preemptionPoint(void)16 exception_t preemptionPoint(void)
17 {
18     /* Record that we have performed some work. */
19     ksWorkUnitsCompleted++;
20 
21     /*
22      * If we have performed a non-trivial amount of work since last time we
23      * checked for preemption, and there is an interrupt pending, handle the
24      * interrupt.
25      *
26      * We avoid checking for pending IRQs every call, as our callers tend to
27      * call us in a tight loop and checking for pending IRQs can be quite slow.
28      */
29     if (ksWorkUnitsCompleted >= CONFIG_MAX_NUM_WORK_UNITS_PER_PREEMPTION) {
30         ksWorkUnitsCompleted = 0;
31 #ifdef CONFIG_KERNEL_MCS
32         updateTimestamp();
33         if (!(sc_active(NODE_STATE(ksCurSC)) && refill_sufficient(NODE_STATE(ksCurSC), NODE_STATE(ksConsumed)))
34             || isCurDomainExpired() || isIRQPending()) {
35 #else
36         if (isIRQPending()) {
37 #endif
38             return EXCEPTION_PREEMPTED;
39         }
40     }
41 
42     return EXCEPTION_NONE;
43 }
44 
45