Question on thread and critical section on Windows Vista

Started by
6 comments, last by cubicwang 16 years, 2 months ago
Hi Now my program have a second task thread for update the animation and particles, On windowsXP it run well, but on vista , the task thread always failed to lock the critical section and waiting, I Dont know why. The task thread and main thread have two critical sections, one is the task critical section, this CS is used for the main thread and task thread to push and pop the task. When main thread want to push a task into the task queue, it enter the taskCS,push a task and then leave, the task thread will loop and try to enter the taskCS , pop a task and then leave. There also another CS for the task thread to make it suspend if no task to do. The task critical section is the XwTask::g_taskMutex and the task suspend critical section is the XwTask::g_taskSuspendMutex In main thread we tick the object and may call the pushTask. ///Push new task to the task queue. XWBOOL XwTask::pushTask(XwTask* task) { if(XwTask::g_taskThread != 0) { task->taskState = TS_WAITPROCESS; CwOSystem::lockMutex(XwTask::g_taskMutex); if(XwTask::g_taskQueueTail) { XwTask::g_taskQueueTail->pNext = task; XwTask::g_taskQueueTail = task; } else { XW_ASSERT(XwTask::g_taskQueueHeader == NULL); XwTask::g_taskQueueHeader = XwTask::g_taskQueueTail = task; } CwOSystem::unlockMutex(XwTask::g_taskMutex); //Make the task thread run. CwOSystem::unlockMutex(XwTask::g_taskSuspendMutex); CwOSystem::lockMutex(XwTask::g_taskSuspendMutex); return TRUE; } CWARNFMT(LT_ENGINE, XW_T("Push task failed! task thread have not been start!")); return FALSE; } Below is the task main function and I hope it can suspend if no task, by XwTask::g_taskSuspendMutex.The main thread will enter this CS most of the time, and if we push a task, the main thread will leave this CS and the task thread will enter it, and when the taskThread wake up it will leave this CS imidiatley and run until no task in the queue and then try to enter the CS and then suspend untill the main thread leave it. ///The task thread. XWBOOL XwTask::taskThread() { XwTask* pTask = NULL; while(!XwTask::g_taskQuit) { //Get a task from task list. CwOSystem::lockMutex(XwTask::g_taskMutex); if(XwTask::g_taskQueueHeader) { pTask = XwTask::g_taskQueueHeader; XwTask::g_taskQueueHeader = (XwTask*)pTask->pNext; if(!XwTask::g_taskQueueHeader) { XwTask::g_taskQueueTail = NULL; } pTask->pNext = NULL; } else { pTask = NULL; } CwOSystem::unlockMutex(XwTask::g_taskMutex); if(pTask) { pTask->taskState = TS_PROCESSING; if(pTask->process()) { pTask->taskState = TS_FINISH; } else { pTask->taskState = TS_FAILED; } } else { //Make the task thread waiting. CwOSystem::lockMutex(XwTask::g_taskSuspendMutex); CwOSystem::unlockMutex(XwTask::g_taskSuspendMutex); } } return TRUE; } I dont konw why the task thread alway waiting it ,seems that it can not enter the task critical sections. It difficult to trace the program, Anybody know is there any different for critical section between the windows vista and windows xp. Please help ,thank you! Can you give me some sugestion for how to debug it? the multithread programe is too difficult to trace.
Advertisement
Quote:Anybody know is there any different for critical section between the windows vista and windows xp.

There are many differences.

Just a few of the changes that might be an issue:

*The scheduler was modified, which can expose existing race conditions.
*Vista has different internal objects: undocumented structure use and improper initialization are known (and well documented) to cause compatibility issues.
*Vista and Windows Server no longer use a fifo for handing out synchronization objects.
*Vista and Windows Server use more complex (but better performing) processor-specific synchronization objects including simple semaphores, mutexes, and critical sections, spinlocks, etc.

There are many other differences.

Note that nearly all applications work perfectly without changes.

Most likely you are just discovering an existing bug that was present but not discovered earlier.
Quote:Can you give me some sugestion for how to debug it? the multithread programe is too difficult to trace.

It seems your answer is right there.

I've seen this type of problem too often when back I did consulting work. You *must* design large programs with debugging in mind, otherwise you get problems like this late in development that can shut down the product. Synchronization is something that takes both experience and caution.
Quote:Can you give me some sugestion for how to debug it?

Sure.

First, find out exactly where everything is at the time of the lock. (If it isn't actually locking but just never entering, replace the call with a blocking lock and it should stop with the appropriate debugging information.) Read this article (and countless similar ones discovered by searching for "debugging deadlock thread") to help you figure that out.

Next, go through your designs to figure out what would cause that particular set of locks to be enabled.

Ideally your own threading libraries should provide information on the state of the different locks. If you don't have such a thing in your libraries or designs, I'd suggest you get a tool like the one in this MSDN magazine article to help you figure out the code owners of all locks and critical sections. If your libraries don't, and you can't use that tool, the Windows Debugger (comes with the Platform SDK) has several thread debugging functions can also help you track it down. But really, if you have to go that far to find the information, you've got more serious problems with your design that you should fix.

From there, you have to backtrack and figure out what got you into the incorrect state. This can range from trivially easy to painfully hard, depending on the complexity of the system, the design, and your own experience.

Good luck. :-)
Thank you.
I will try it.
Never ever rely on explicit unlocking for mutexes / critical sections! Always use scoped locks instead. If you can't or don't want to use a higher level threading API such as boost::thread, at least write your own ScopedLock class and use that instead of explicitely calling unlockMutex() or LeaveCriticalSection().

class SimpleScopedLock{private:    MyMutex& m_theMutex;    bool m_isLocked;    // disable copy constructor and assignment operator    SimpleScopedLock( const SimpleScopedLock& );    SimpleScopedLock& operator = ( const SimpleScopedLock& );public:    explicit SimpleScopedLock( MyMutex& theMutex ) : m_theMutex( theMutex ), m_isLocked( true )    {        // Lock the mutex.        m_theMutex.lock();        // or BlaBla::lockMutex( m_theMutex ) or whatever    }    ~SimpleScopedLock()    {        // automatically releases the mutex the moment the scoped lock goes out of scope        unlock();    }}    void unlock()    {        if ( m_isLocked == true )        {            m_theMutex.unlock();            m_isLocked = false;        }    }};// Usage examplevoid SomeClass::acquireMutexAndDoSomething(){    // acquire mutex    SimpleScopedLock myLock( m_someSynchronizationMutex );    // do lots of interesting stuff ...    // no explicit unlocking required ... the mutex as released as soon as the current scope (i.e. the acquireMutexAndDoSomething() method, in this case) is left}


This should help to eliminate a lot of silly race conditions.
Thank you so much!
How the scoped lock work?
There seems no system mutex or critical section calls in the function, the MyMutex is the interface of the system mutex?
Why not explicit unlock mutex or leave critical section , I dont know what the different between the call of leaveCriticalSection() and the unlock of the scopedlock. is the bool m_isLocked is the key word?
We must handle a flag for if the critical section is enter or not?
I try to add a isLock flag to my mutex but seems no help.
The enter critical section and leave critical section is not the same to the WindowsXP on Vista, It seems the enter and leave may have no effect,
When I call enter critical section, it always work, but when I can leaveCriticalSection, it may not leave or the other thread can not be wakeup, I dont know why.
Can anybody explain it for me?
Thank you!

This topic is closed to new replies.

Advertisement