diff options
-rw-r--r-- | kern/thread.c | 2 | ||||
-rw-r--r-- | kern/thread.h | 43 | ||||
-rw-r--r-- | kern/thread_i.h | 3 |
3 files changed, 48 insertions, 0 deletions
diff --git a/kern/thread.c b/kern/thread.c index 1a078fea..550de7ee 100644 --- a/kern/thread.c +++ b/kern/thread.c @@ -1700,6 +1700,7 @@ thread_bootstrap_common(unsigned int cpu) booter = &thread_booters[cpu]; booter->nr_refs = 0; /* Make sure booters aren't destroyed */ booter->flags = 0; + booter->intr = 0; booter->preempt = 1; cpumap_fill(&booter->cpumap); thread_set_user_sched_policy(booter, THREAD_SCHED_POLICY_IDLE); @@ -1817,6 +1818,7 @@ thread_init(struct thread *thread, void *stack, turnstile_td_init(&thread->turnstile_td); thread->last_cond = NULL; thread->propagate_priority = false; + thread->intr = 0; thread->preempt = THREAD_SUSPEND_PREEMPT_LEVEL; thread->pinned = 0; thread->llsync_read = 0; diff --git a/kern/thread.h b/kern/thread.h index 28404fb4..486d6fae 100644 --- a/kern/thread.h +++ b/kern/thread.h @@ -600,6 +600,49 @@ thread_preempt_disable(void) } /* + * Interrupt level control functions. + * + * Functions that change the interrupt level are implicit compiler barriers. + */ + +static inline bool +thread_interrupted(void) +{ + return (thread_self()->intr != 0); +} + +static inline void +thread_intr_enter(void) +{ + struct thread *thread; + + thread = thread_self(); + + if (thread->intr == 0) { + thread_preempt_disable(); + } + + thread->intr++; + assert(thread->intr != 0); + barrier(); +} + +static inline void +thread_intr_leave(void) +{ + struct thread *thread; + + barrier(); + thread = thread_self(); + assert(thread->intr != 0); + thread->intr--; + + if (thread->intr == 0) { + thread_preempt_enable_no_resched(); + } +} + +/* * Lockless synchronization read-side critical section nesting counter * control functions. */ diff --git a/kern/thread_i.h b/kern/thread_i.h index 0490f928..b0e0074f 100644 --- a/kern/thread_i.h +++ b/kern/thread_i.h @@ -135,6 +135,9 @@ struct thread { /* Pinning counter, migration is allowed if 0 */ unsigned short pinned; /* (-) */ + /* Interrupt level counter, in thread context if 0 */ + unsigned short intr; /* (-) */ + /* Read-side critical section counter, not in any if 0 */ unsigned short llsync_read; /* (-) */ |