summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kern/thread.c2
-rw-r--r--kern/thread.h43
-rw-r--r--kern/thread_i.h3
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; /* (-) */