summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustus Winter <4winter@informatik.uni-hamburg.de>2015-04-26 15:47:47 +0200
committerJustus Winter <4winter@informatik.uni-hamburg.de>2015-05-20 10:56:15 +0200
commit6eb79f812ee43a4e9142de61a5821e0cc8c52bb1 (patch)
tree40bf469bc4c852bd605949d29033b46ae2fb1775
parent3c3d3614673c93bf1b1f47d612d8067455d06920 (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.h2
-rw-r--r--kern/thread.c11
-rw-r--r--kern/thread_swap.c17
-rw-r--r--kern/thread_swap.h2
4 files changed, 22 insertions, 10 deletions
diff --git a/kern/sched_prim.h b/kern/sched_prim.h
index fd989b6c..62698dc2 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 009884ce..f52c95b8 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 dc2924a9..20ad0409 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 9d645373..d032accf 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_ */