summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/include/kernel/stacksegment.H2
-rw-r--r--src/include/kernel/taskmgr.H3
-rw-r--r--src/include/kernel/vmmmgr.H1
-rw-r--r--src/kernel/msghandler.C13
-rw-r--r--src/kernel/stacksegment.C4
5 files changed, 22 insertions, 1 deletions
diff --git a/src/include/kernel/stacksegment.H b/src/include/kernel/stacksegment.H
index 2d3474dc6..460a61b49 100644
--- a/src/include/kernel/stacksegment.H
+++ b/src/include/kernel/stacksegment.H
@@ -108,6 +108,8 @@ class StackSegment : public Segment
* @brief Delete previously created stack for a task.
*
* @param i_task - Task ID of task owning the stack.
+ *
+ * @note This function obtains the VMM-subsystem spinlock.
*/
static void deleteStack(tid_t i_task);
diff --git a/src/include/kernel/taskmgr.H b/src/include/kernel/taskmgr.H
index 63aa76484..b38618d22 100644
--- a/src/include/kernel/taskmgr.H
+++ b/src/include/kernel/taskmgr.H
@@ -125,6 +125,9 @@ class TaskManager
* @param[in] t - The task to end.
* @param[in] retval - Return value from the task.
* @param[in] status - TASK_STATUS_* enumeration of how the task ended.
+ *
+ * @note This function obtains the VMM-subsystem spinlock as part of
+ * releasing the task stack.
*/
static void endTask(task_t* t, void* retval, int status);
diff --git a/src/include/kernel/vmmmgr.H b/src/include/kernel/vmmmgr.H
index 845066229..3782bb762 100644
--- a/src/include/kernel/vmmmgr.H
+++ b/src/include/kernel/vmmmgr.H
@@ -200,6 +200,7 @@ class VmmManager
public:
friend class Block;
+ friend class StackSegment;
};
diff --git a/src/kernel/msghandler.C b/src/kernel/msghandler.C
index 82dab7f8f..08859633a 100644
--- a/src/kernel/msghandler.C
+++ b/src/kernel/msghandler.C
@@ -22,6 +22,7 @@
// IBM_PROLOG_END
#include <assert.h>
#include <errno.h>
+#include <util/locked/queue.H>
#include <kernel/msghandler.H>
#include <kernel/task.H>
#include <kernel/cpu.H>
@@ -96,6 +97,11 @@ int MessageHandler::recvMessage(msg_t* i_msg)
// Lock subsystem spinlock.
if (iv_lock) iv_lock->lock();
+ // List of tasks to end due to errors.
+ // Ending the task must happen outside of the spinlock due to
+ // requirements of TaskManager::endTask.
+ Util::Locked::Queue<task_t> endTaskList;
+
// Get <key, rc> from response.
MessageHandler_Pending::key_type key =
reinterpret_cast<MessageHandler_Pending::key_type>(i_msg->data[0]);
@@ -141,7 +147,7 @@ int MessageHandler::recvMessage(msg_t* i_msg)
// Unsuccessful, unhandled response. Kill task.
printk("Unhandled msg rc %d for key %p on task %d @ %p\n",
msg_rc, key, deferred_task->tid, deferred_task->context.nip);
- TaskManager::endTask(deferred_task, NULL, TASK_STATUS_CRASHED);
+ endTaskList.insert(deferred_task);
}
else if (CONTINUE_DEFER == rc)
{
@@ -157,6 +163,11 @@ int MessageHandler::recvMessage(msg_t* i_msg)
// Finished handling the response, unlock subsystem.
if (iv_lock) iv_lock->unlock();
+ while(task_t* end_task = endTaskList.remove())
+ {
+ TaskManager::endTask(end_task, NULL, TASK_STATUS_CRASHED);
+ }
+
// Release memory for message (created from sendMsg).
delete(i_msg);
diff --git a/src/kernel/stacksegment.C b/src/kernel/stacksegment.C
index 0ea3e24a8..f7ced0f1f 100644
--- a/src/kernel/stacksegment.C
+++ b/src/kernel/stacksegment.C
@@ -149,6 +149,8 @@ void* StackSegment::_createStack(tid_t i_task)
void StackSegment::_deleteStack(tid_t i_task)
{
+ VmmManager::getLock()->lock();
+
uint64_t l_addr_8mb = i_task * (8*MEGABYTE) + VMM_VADDR_STACK_SEGMENT;
StackBlockNode* l_node = iv_blockList.find(l_addr_8mb);
@@ -159,5 +161,7 @@ void StackSegment::_deleteStack(tid_t i_task)
delete l_node->block;
delete l_node;
+ VmmManager::getLock()->unlock();
+
return;
}
OpenPOWER on IntegriCloud