diff options
author | Justus Winter <4winter@informatik.uni-hamburg.de> | 2015-04-26 15:47:47 +0200 |
---|---|---|
committer | Justus Winter <4winter@informatik.uni-hamburg.de> | 2015-05-20 10:56:15 +0200 |
commit | 6eb79f812ee43a4e9142de61a5821e0cc8c52bb1 (patch) | |
tree | 40bf469bc4c852bd605949d29033b46ae2fb1775 | |
parent | 3c3d3614673c93bf1b1f47d612d8067455d06920 (diff) |
kern: gracefully handle resource shortage
* kern/thread.c (stack_alloc): Report resource shortage.
* kern/sched_prim.h (stack_alloc): Adjust declaration accordingly.
* kern/thread_swap.c (thread_doswapin): Report resource shortage.
(swapin_thread_continue): If the swap-in fails, put the thread back on
the queue and go back to sleep.
* kern/thread_swap.h (thread_doswapin): Adjust declaration accordingly.
-rw-r--r-- | kern/sched_prim.h | 2 | ||||
-rw-r--r-- | kern/thread.c | 11 | ||||
-rw-r--r-- | kern/thread_swap.c | 17 | ||||
-rw-r--r-- | kern/thread_swap.h | 2 |
4 files changed, 22 insertions, 10 deletions
diff --git a/kern/sched_prim.h b/kern/sched_prim.h index fd989b6..62698dc 100644 --- a/kern/sched_prim.h +++ b/kern/sched_prim.h @@ -150,7 +150,7 @@ extern void stack_handoff( * or are defined directly by machine-dependent code. */ -extern void stack_alloc( +extern kern_return_t stack_alloc( thread_t thread, void (*resume)(thread_t)); extern boolean_t stack_alloc_try( diff --git a/kern/thread.c b/kern/thread.c index 009884c..f52c95b 100644 --- a/kern/thread.c +++ b/kern/thread.c @@ -171,7 +171,7 @@ boolean_t stack_alloc_try( * May block. */ -void stack_alloc( +kern_return_t stack_alloc( thread_t thread, void (*resume)(thread_t)) { @@ -195,15 +195,15 @@ void stack_alloc( (void) splx(s); if (stack == 0) { + kern_return_t kr; /* * Kernel stacks should be naturally aligned, * so that it is easy to find the starting/ending * addresses of a stack given an address in the middle. */ - - if (kmem_alloc_aligned(kmem_map, &stack, KERNEL_STACK_SIZE) - != KERN_SUCCESS) - panic("stack_alloc"); + kr = kmem_alloc_aligned(kmem_map, &stack, KERNEL_STACK_SIZE); + if (kr != KERN_SUCCESS) + return kr; #if MACH_DEBUG stack_init(stack); @@ -211,6 +211,7 @@ void stack_alloc( } stack_attach(thread, stack, resume); + return KERN_SUCCESS; } /* diff --git a/kern/thread_swap.c b/kern/thread_swap.c index dc2924a..20ad040 100644 --- a/kern/thread_swap.c +++ b/kern/thread_swap.c @@ -123,15 +123,18 @@ void thread_swapin(thread_t thread) * it on a run queue. No locks should be held on entry, as it is * likely that this routine will sleep (waiting for stack allocation). */ -void thread_doswapin(thread_t thread) +kern_return_t thread_doswapin(thread_t thread) { + kern_return_t kr; spl_t s; /* * Allocate the kernel stack. */ - stack_alloc(thread, thread_continue); + kr = stack_alloc(thread, thread_continue); + if (kr != KERN_SUCCESS) + return kr; /* * Place on run queue. @@ -144,6 +147,7 @@ void thread_doswapin(thread_t thread) thread_setrun(thread, TRUE); thread_unlock(thread); (void) splx(s); + return KERN_SUCCESS; } /* @@ -163,13 +167,20 @@ void __attribute__((noreturn)) swapin_thread_continue(void) while ((thread = (thread_t) dequeue_head(&swapin_queue)) != THREAD_NULL) { + kern_return_t kr; swapper_unlock(); (void) splx(s); - thread_doswapin(thread); /* may block */ + kr = thread_doswapin(thread); /* may block */ s = splsched(); swapper_lock(); + + if (kr != KERN_SUCCESS) { + enqueue_head(&swapin_queue, + (queue_entry_t) thread); + break; + } } assert_wait((event_t) &swapin_queue, FALSE); diff --git a/kern/thread_swap.h b/kern/thread_swap.h index 9d64537..d032acc 100644 --- a/kern/thread_swap.h +++ b/kern/thread_swap.h @@ -37,7 +37,7 @@ */ extern void swapper_init(void); extern void thread_swapin(thread_t thread); -extern void thread_doswapin(thread_t thread); +extern kern_return_t thread_doswapin(thread_t thread); extern void swapin_thread(void) __attribute__((noreturn)); #endif /* _KERN_THREAD_SWAP_H_ */ |