Wiley.Symbian.OS.Internals.Real.time.Kernel.Programming.Dec.2005.eBook-DDU (779891), страница 19
Текст из файла (страница 19)
This statedoes not necessarily imply that the thread is actually ready to run – this isindicated by the N-state. For example, a thread that is explicitly suspendedor waiting on a nanokernel wait object (generally a fast semaphore) hasiMState==EReady, if it is not attached to any Symbian OS wait object.iMState==EWaitSemaphoreThis state indicates that the thread is currently blocked waiting fora Symbian OS semaphore and is enqueued on the semaphore’s waitqueue.
The thread’s iWaitObj field points to the semaphore.iMState==EWaitSemaphoreSuspendedThis state indicates that another thread has explicitly suspended thisthread after it blocked on a Symbian OS semaphore and was enqueuedon the semaphore’s suspended queue. The thread’s iWaitObj fieldpoints to the semaphore.iMState==EWaitMutexThis state indicates that the thread is currently blocked waiting for a Symbian OS mutex and is enqueued on the mutex wait queue.
The thread’siWaitObj field points to the mutex.iMState==EWaitMutexSuspendedThis state indicates that another thread has explicitly suspended thisthread after it blocked on a Symbian OS mutex and was enqueued onthe mutex suspended queue. The thread’s iWaitObj field points tothe mutex.iMState==EHoldMutexPendingThis state indicates that the thread has been woken up from the EWaitMutex state but has not yet claimed the mutex. The thread is enqueuedon the mutex pending queue and the thread’s iWaitObj field points tothe mutex.74THREADS, PROCESSES AND LIBRARIESiMState==EWaitCondVarThis state indicates that the thread is waiting on a condition variable. Thethread is enqueued on the condition variable’s wait queue, iWaitQ, andits iWaitObj field points to the condition variable.iMState==EWaitCondVarSuspendedThis state indicates that the thread has been suspended while waiting ona condition variable.
The thread is removed from the condition variable’siWaitQ, and enqueued on iSuspendQ. The thread’s iWaitObj fieldpoints to the condition variable.M-state changesA thread’s M-state can change because of any of the following operations:1.The thread blocks on a wait object2.The thread is released from a wait object3.The thread is suspended4.The thread is resumed5.The thread’s priority is changed.
This can cause a transition fromEWaitMutex to EHoldMutexPending if the mutex is free and thethread’s priority is increased6.The thread is killed. Multiple state changes can occur in this case asthe thread proceeds through the exit handler. The first state changewill occur as a result of a ReleaseWait() call at the beginning ofthe exit handler. This call cancels the thread’s wait on any SymbianOS wait object and detaches the thread from the wait object, that is itremoves it from any queues related to the wait object.
The final statechange will be to the EDead state at the end of the exit handler.The first five of these operations are protected by the system lock mutex.In the case of thread exit, the initial call to make the thread exit isprotected by the system lock, as is the ReleaseWait() call, but the exithandler runs without the system lock for some of the time.3.3.4.2 Other M-statesRTOS personality layers can add new M-states to indicate that threadsare waiting on non-Symbian OS wait objects. To make this easier toimplement, each Symbian OS thread has an unknown state handler,iUnknownStateHandler.
Let’s see how it works.Assume that a thread is in an M-state unknown to the kernel (that is,not one of those I have discussed above). Then the kernel will call theunknown state handler after the kernel suspends, resumes, kills or changesSYMBIAN OS THREADS75the priority of that thread. The unknown state handler can then adjust theRTOS wait object’s queues and transition the M-state if necessary.The unknown state handler is not involved in all state transitions: theRTOS personality layer code will block and release threads from an RTOSwait object directly.It is worth noting that the Symbian OS thread unknown state handler,iUnknownStateHandler, is completely different to the nanokernel thread unknown state handler, iNThread->iHandlers->iStateHandler.
Which you use depends on exactly how you implement yourRTOS personality layer. Clearly there are two choices:Over the nanokernelThis is the usual method, described in Chapter 17, Real Time. Personalitylayer threads are bare NThreads and you use NThread::iHandlers>iStateHandler to add extra wait states for new wait objects.Over the Symbian OS kernelIn this case, personality layer threads are Symbian OS kernel threads, andDThread::iUnknownStateHandler would be used to add extra waitstates for new wait objects. The advantage of using this method is thatyou can make use of Symbian OS kernel services in your personality layerthreads (for example semaphores, mutexes and memory allocation).
Thedisadvantage is that Symbian OS threads use a lot more memory – over800 bytes per DThread, plus 4 KB of stack.3.3.5 Cleanup queuesEach Symbian OS thread has a cleanup queue, iCleanup. Thisqueue holds thread cleanup items, which are TThreadCleanup-derivedobjects.TThreadCleanupclass TThreadCleanup : public TPriListLink{public:IMPORT_C TThreadCleanup();void ChangePriority(TInt aNewPriority);IMPORT_C void Remove();virtual void Cleanup()=0;public:DThread* iThread;public:friend class Monitor;};The cleanup queue is a priority queue, with each of the cleanup items on ithaving a priority between 0 and 63.
Each cleanup item also has a callback76THREADS, PROCESSES AND LIBRARIESfunction. When the Symbian OS thread terminates, its thread exit handlercalls the callback functions in descending order of priority – it alwaysholds the system lock while it does this. It is, however, permissible for acleanup item’s callback to release the system lock, for example to deletethe cleanup item itself or to perform some other long-running operation.(The kernel also locks the system when it modifies the cleanup queue.)The kernel sets the priority of cleanup items that are used purely toprovide notification of thread exit to zero.Currently the Symbian OS kernel uses thread cleanup items for twopurposes:1.It associates a TThreadMutexCleanup object with every SymbianOS mutex.
The kernel adds this item to the cleanup queue of themutex-holding thread so that it can release the mutex if the threadterminates2.The kernel uses cleanup items with non-zero priority to implementpriority inheritance for Symbian OS mutexes; it does this by adjustingthe priority of the TThreadMutexCleanupItem.3.3.5.1 Priority inheritenceHow does this priority inheritence work? We define the priority of aSymbian OS thread to be the maximum of its own priority, and that ofany cleanup item on its queue.
Now suppose that a low-priority threadowns a mutex when a higher-priority thread comes along and blocks onthat mutex. The kernel will then adjust the priority of the cleanup itemassociated with the mutex to be equal to the priority of the high-prioritythread. Thus the low-priority thread’s priority, which is the maximumof its own priority and any cleanup item it owns, is also boosted, sinceit owns the cleanup item associated with the mutex. If there are nohigher-priority ready threads in the system, it will continue to run until itreleases the mutex, at which point its priority drops to its normal level.3.3.5.2 Notification of device driver client terminationThere is a third use for thread cleanup items: device drivers can usethem to get notification of their clients terminating unexpectedly.
Forexample, the local media sub-system uses this mechanism to ensurethat the resources held by the driver on behalf of the client thread arecleaned up if the client thread terminates. It has to use this method, sincemultiple threads in the same process may use a single logical channelto communicate with the driver, meaning that the channel Close()method will not necessarily be called when a client thread terminates.SYMBIAN OS THREADS3.3.677Thread logon and rendezvousThread logon is a mechanism that allows a thread to request notificationthat another thread has reached a given point in its execution or hasterminated. The first form of notification is known as a rendezvous.Each thread has two doubly linked lists: one of target logons (iTargetLogons – representing threads which are requesting notification ofa rendezvous with or the termination of this thread) and one of ownedlogons (iOwnedLogons – representing requests by this thread to be notified of a rendezvous with other threads or when other threads terminate).Rendezvous requests are stored at the head of iOwnedLogons and logon(termination) requests are stored at the tail of this list.The kernel handles process rendezvous and logon using an identicalmechanism.The TLogon::LogonLock fast mutex protects all these lists (overall the threads and processes in the system).
When a rendezvous issignaled by a thread, the target logon list is iterated from the head and allrendezvous requests completed. When a thread terminates, the thread exithandler completes all the logons on its target logon list (both rendezvousand termination) with the exit reason and discards any remaining logonson its owned logon list.We use the iExiting field to prevent a new logon from being addedto a thread after it has completed all its target logons, which would resultin the new logon never being completed. The iExiting flag is set toETrue at the beginning of the thread exit handler. Any attempt to add anew logon to (or rendezvous with) a thread whose iExiting flag is setwill fail and will complete immediately with KErrDied.Since thread logons need notification of thread exit just as cleanupitems do, why do we need a separate mechanism for them rather thanjust adding them to the thread cleanup list? This is because the kernelprotects thread cleanup queues with the system lock held and so theymust be fast, with a bounded execution time.