ogre线程及其死锁问题
问题一:
OGRE_THREAD_SUPPORT == 1, 在多个线程中创建entity或调用resource的load
OGRE_THREAD_SUPPORT == 2,在多个线程中调用resource的prepare(包括在主线程中调用createEntity并在其它线程中调用prepare)
死锁情况:
case:
Thread 1
MeshManager::load
Ogre::ResourceGroupManager::openResource()
lock - grp->OGRE_AUTO_MUTEX_NAME //lock grp,锁定传入的group
Ogre::Resource::changeGroupOwnership() //改变资源的group为资源实际所在的group
Ogre::ResourceGroupManager::_notifyResourceGroupChanged()
lock - ResourceGroupManager::mutex //lock rgm //锁定实际的group
Ogre::ResourceGroupManager::addCreatedResource()
wait - grp->OGRE_AUTO_MUTEX_NAME //lock grp
Thread 2
MeshManager::load
OgreMain_d.dll!Ogre::ResourceGroupManager::openResource()
lock grp->OGRE_AUTO_MUTEX_NAME //lock grp,锁定传入的group
OgreMain_d.dll!Ogre::ResourceGroupManager::findGroupContainingResourceImpl()
wait - ResourceGroupManager::mutex //lock rgm
总结:只有当两个线程调用openResource并传入不同的group,但资源实际的group又相同时才会出现这种情况
例1:
线程1调用openResource("test.png", group1),线程2调用openResource("test1.mesh", group2);
如果test1.mesh存在于group2中,test.png实际上也存在于group2中,就会发生上面的死锁情况
例2:
一个线程调用MeshManager::getsingleton().load("test1.mesh", "group1")
另一个线程调用MeshManager::getsingleton().load("pig.mesh", "group2")
如果test1.mesh和pig.mesh都存在于group1或者group2中就会发生死锁
createEntity调用传入的groupname始终是AutoDetect,不会有问题
问题二:
OGRE_THREAD_SUPPORT == 2
I've recently enabled the THREAD_SUPPORT=2 to play around with it. Unfortunately, I'm actually running into massive deadlocking problems with ResourceGroupManager.
Here's a description of what I'm running in to.
Legend:
RM1 = ResourceManager from preparation thread
RGM1 = ResourceGroupManager from preparation thread
RM2 = ResourceManager from rendering/primary thread
RGM2 = ResourceGroupManager from rendering/primary thread
The problematic sequence (typical situation, I'm sure there's tons of similar situations):
Code:
RGM1->prepareResourceGroup("G") (locks RGM)
...
在主线程里调createEntity
RM2->createOrRetrieve("Tex in group X") (locks RM)
RGM2->_notifyResourceCreated("Tex in group X")
RGM2->getResourceGroup (waits for lock of RGM)
...
RM1->createOrRetrieve("Tex in G") (waits for lock of RM) <-- Deadlocked here
也就是说createOrRetrieve不能在preparation thread 里调用,只能在主线程里调用(对于OGRE_THREAD_SUPPORT == 2,本来就不应该嘛?)
不过这样看来对于OGRE_THREAD_SUPPORT == 1, createEntity如果被两个线程同时调用不会发生死锁(因为RM,RGM加锁的顺利一样)
In this case these calls are resulting from the normal course of resource loading and come up due to the various calls to resource->load() throughout the rendering process.
The problem seems to be the mCurrentGroup and having to lock ResourceGroupManager for long periods of time, for example when calling prepareResourceGroup(). Unfortunately, removing this restriction is a lot of refactoring to RGM. What are you guys' thoughts here?
I'm also not sure if this only limited to the new HP threading or not. My gut is telling me this situation exists with THREAD_SUPPORT=1 as well, but I've not researched it.
问题三:
ogre的线程还存在一些问题:
* zziplib 在多线程下有问题
* Fonts were not safe for prepare()
* animations/skeletons 没有提供prepare机制.