diff options
-rw-r--r-- | kern/mutex_i.h | 2 | ||||
-rw-r--r-- | kern/sref.c | 2 | ||||
-rw-r--r-- | kern/task.c | 18 | ||||
-rw-r--r-- | kern/thread.c | 24 | ||||
-rw-r--r-- | kern/thread.h | 19 | ||||
-rw-r--r-- | kern/thread_i.h | 2 | ||||
-rw-r--r-- | kern/work.c | 4 |
7 files changed, 62 insertions, 9 deletions
diff --git a/kern/mutex_i.h b/kern/mutex_i.h index aaaf7cad..5e78a4da 100644 --- a/kern/mutex_i.h +++ b/kern/mutex_i.h @@ -77,7 +77,7 @@ mutex_wait(struct mutex *mutex, struct mutex_waiter *waiter) unsigned int state; do { - thread_sleep(&mutex->lock); + thread_sleep(&mutex->lock, mutex, "mutex"); state = mutex_tryacquire_slow(mutex); } while (state != MUTEX_UNLOCKED); diff --git a/kern/sref.c b/kern/sref.c index e1368c30..9bffbe9a 100644 --- a/kern/sref.c +++ b/kern/sref.c @@ -803,7 +803,7 @@ sref_manage(void *arg) cpu_intr_save(&flags); while (!sref_cache_is_dirty(cache)) { - thread_sleep(NULL); + thread_sleep(NULL, cache, "sref"); } cpu_intr_restore(flags); diff --git a/kern/task.c b/kern/task.c index e415cb65..f4586eed 100644 --- a/kern/task.c +++ b/kern/task.c @@ -29,6 +29,12 @@ #include <vm/vm_kmem.h> #include <vm/vm_map.h> +#ifdef __LP64__ +#define TASK_INFO_ADDR_FMT "%016lx" +#else /* __LP64__ */ +#define TASK_INFO_ADDR_FMT "%08lx" +#endif /* __LP64__ */ + /* * Kernel task and storage. */ @@ -138,9 +144,15 @@ task_info(struct task *task) printk("task: name: %s, threads:\n", task->name); list_for_each_entry(&task->threads, thread, task_node) { - printk("task: %s: %p %c %.2s:%02hu %s\n", task->name, thread, - thread_state_to_chr(thread), thread_schedclass_to_str(thread), - thread_priority(thread), thread->name); + printk("task: " TASK_INFO_ADDR_FMT " %c %8s:" TASK_INFO_ADDR_FMT + " %.2s:%02hu %s\n", + (unsigned long)thread, + thread_state_to_chr(thread), + thread_wchan_desc(thread), + (unsigned long)thread_wchan_addr(thread), + thread_schedclass_to_str(thread), + thread_priority(thread), + thread->name); } spinlock_unlock(&task->lock); diff --git a/kern/thread.c b/kern/thread.c index 9c3a01be..239bbcfb 100644 --- a/kern/thread.c +++ b/kern/thread.c @@ -338,6 +338,20 @@ struct thread_zombie { struct thread *thread; }; +static void +thread_set_wchan(struct thread *thread, const void *wchan_addr, + const char *wchan_desc) +{ + thread->wchan_addr = wchan_addr; + thread->wchan_desc = wchan_desc; +} + +static void +thread_clear_wchan(struct thread *thread) +{ + thread_set_wchan(thread, NULL, NULL); +} + static const struct thread_sched_ops * thread_get_sched_ops(const struct thread *thread) { @@ -551,6 +565,7 @@ thread_runq_wakeup_balancer(struct thread_runq *runq) return; } + thread_clear_wchan(runq->balancer); runq->balancer->state = THREAD_RUNNING; thread_runq_wakeup(runq, runq->balancer); } @@ -1680,6 +1695,7 @@ thread_init(struct thread *thread, void *stack, const struct thread_attr *attr, thread->flags = 0; thread->runq = NULL; + thread_set_wchan(thread, thread, "init"); thread->state = THREAD_SLEEPING; thread->preempt = THREAD_SUSPEND_PREEMPT_LEVEL; thread->pinned = 0; @@ -1862,6 +1878,7 @@ thread_balance(void *arg) for (;;) { runq->idle_balance_ticks = THREAD_IDLE_BALANCE_TICKS; + thread_set_wchan(self, runq, "runq"); self->state = THREAD_SLEEPING; runq = thread_runq_schedule(runq); assert(runq == arg); @@ -1992,6 +2009,7 @@ thread_setup_idler(struct thread_runq *runq) cpumap_destroy(cpumap); /* An idler thread needs special tuning */ + thread_clear_wchan(idler); idler->state = THREAD_RUNNING; idler->runq = runq; runq->idler = idler; @@ -2129,7 +2147,8 @@ thread_join(struct thread *thread) } void -thread_sleep(struct spinlock *interlock) +thread_sleep(struct spinlock *interlock, const void *wchan_addr, + const char *wchan_desc) { struct thread_runq *runq; struct thread *thread; @@ -2146,6 +2165,7 @@ thread_sleep(struct spinlock *interlock) spinlock_unlock(interlock); } + thread_set_wchan(thread, wchan_addr, wchan_desc); thread->state = THREAD_SLEEPING; runq = thread_runq_schedule(runq); @@ -2173,6 +2193,7 @@ thread_wakeup(struct thread *thread) */ if (thread->runq == NULL) { assert(thread->state != THREAD_RUNNING); + thread_clear_wchan(thread); thread->state = THREAD_RUNNING; } else { /* @@ -2192,6 +2213,7 @@ thread_wakeup(struct thread *thread) return; } + thread_clear_wchan(thread); thread->state = THREAD_RUNNING; thread_unlock_runq(runq, flags); } diff --git a/kern/thread.h b/kern/thread.h index 074963de..c5405d7f 100644 --- a/kern/thread.h +++ b/kern/thread.h @@ -192,12 +192,17 @@ void thread_join(struct thread *thread); * In any case, the preemption nesting level must strictly be one when calling * this function. * + * The wait channel describes the reason why the thread is sleeping. The + * address should refer to a relevant synchronization object, normally + * containing the interlock, but not necessarily. + * * This is a low level thread control primitive that should only be called by * higher thread synchronization functions. * * Implies a memory barrier. */ -void thread_sleep(struct spinlock *interlock); +void thread_sleep(struct spinlock *interlock, const void *wchan_addr, + const char *wchan_desc); /* * Schedule a thread for execution on a processor. @@ -242,6 +247,18 @@ void thread_tick_intr(void); void thread_setscheduler(struct thread *thread, unsigned char policy, unsigned short priority); +static inline const void * +thread_wchan_addr(const struct thread *thread) +{ + return thread->wchan_addr; +} + +static inline const char * +thread_wchan_desc(const struct thread *thread) +{ + return thread->wchan_desc; +} + /* * Return a character representation of the state of a thread. */ diff --git a/kern/thread_i.h b/kern/thread_i.h index d004298f..eeee417c 100644 --- a/kern/thread_i.h +++ b/kern/thread_i.h @@ -94,6 +94,8 @@ struct thread { /* Sleep/wakeup synchronization members */ struct thread_runq *runq; + const void *wchan_addr; + const char *wchan_desc; unsigned short state; /* Thread-local members */ diff --git a/kern/work.c b/kern/work.c index 6c798fbb..3ba6d2b2 100644 --- a/kern/work.c +++ b/kern/work.c @@ -315,7 +315,7 @@ work_process(void *arg) pool->nr_available_threads++; do { - thread_sleep(lock); + thread_sleep(lock, pool, "work_spr"); } while (pool->manager != NULL); list_remove(&self->node); @@ -351,7 +351,7 @@ work_process(void *arg) pool->manager = self; do { - thread_sleep(lock); + thread_sleep(lock, pool, "work_mgr"); } while (work_pool_nr_works(pool) == 0); pool->manager = NULL; |