diff options
author | Patrick Williams <iawillia@us.ibm.com> | 2012-01-03 11:10:42 -0600 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2012-01-05 00:57:01 -0600 |
commit | 048789fdce6b406de3b7149f8171afd63eea1829 (patch) | |
tree | 2291287f0fd3cb05441a96e72346e27436ebbba1 | |
parent | a001b92d6d5ab2383a7c8c51f1ee43f8095d1d56 (diff) | |
download | talos-hostboot-048789fdce6b406de3b7149f8171afd63eea1829.tar.gz talos-hostboot-048789fdce6b406de3b7149f8171afd63eea1829.zip |
Fix race condition between stackmanager and vmmmanager.
Change-Id: Ie3f3fb2050428af1fc398b1577dfc090cd7d26cf
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/591
Tested-by: Jenkins Server
Reviewed-by: MIKE J. JONES <mjjones@us.ibm.com>
Reviewed-by: Melissa J. Connell <missyc@us.ibm.com>
Reviewed-by: Douglas R. Gilbert <dgilbert@us.ibm.com>
Reviewed-by: MATTHEW S. BARTH <msbarth@us.ibm.com>
-rw-r--r-- | src/include/kernel/stacksegment.H | 2 | ||||
-rw-r--r-- | src/include/kernel/taskmgr.H | 3 | ||||
-rw-r--r-- | src/include/kernel/vmmmgr.H | 1 | ||||
-rw-r--r-- | src/kernel/msghandler.C | 13 | ||||
-rw-r--r-- | src/kernel/stacksegment.C | 4 |
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; } |