This document describes porting problems related to asynchronous services.
The client-server framework used on Symbian platform assumes that a client thread stops running after passing an asynchronous request to a server and does not resume until the server has finished handling the request. In SMP there is no guarantee that this will happen, and consequently there is an impact on the way in which you pass variables between client and server threads.
On a single core system it is common for client code to assume that the client thread will be pre-empted by the server thread since the server thread has higher priority. On SMP this is not so, as the two threads may be running on separate cores. It is therefore quite possible for a client thread to continue running while an asynchronous request is being serviced and might unwind its own stack before the server has written to that stack in response to the request.
One way round this problem is to force the client thread to wait until the request has been serviced, but then the request is no longer asynchronous.
On SMP a client thread should not pass stack variables to a server thread when making an asynchronous request. Instead, the data should be held in class members of the client class, since member variables are stored on the heap. This principle applies to all temporary variables in a client thread.
The following code examples illustrate the problem.
Example 1:
108 inline TInt RWlanLogicalChannel::ManagementCommand( 109 const TDesC8& aInBuffer, 110 TDes8* aOutBuffer, 111 TRequestStatus* aStatus) 112 { … 114 SOidMsgStrorage* pdu( new SOidMsgStrorage ); 116 SOutputBuffer output = { NULL, 0 }; … 141 // Execute command asynchronously 142 DoRequest(EWlanCommand, *aStatus, pdu, 143 (output.iData ? &output : NULL) 144 ); … 146 ret = KErrNone; ... 149 // always remember to deallocate 150 151 } 154 } …
Example 2:
108 inline TInt RWlanLogicalChannel::ManagementCommand( 109 const TDesC8& aInBuffer, 110 TDes8* aOutBuffer, 111 TRequestStatus* aStatus) 112 { … 147 iAsyncOidCommandMsg = *pdu; 148 iAsyncOidCommandOutput = output; 149 DoRequest( 150 EWlanCommand, 151 *aStatus, 152 &iAsyncOidCommandMsg, 153 (output.iData ? &iAsyncOidCommandOutput : NULL) ); 146 ret = KErrNone; ... 149 // always remember to deallocate 150 151 } 154 } …
In the first example, the variables pdu and output are stack variables declared within the function ManagementCommand() and there is a danger that the stack will have been unwound before the server tries to write to those variables. In the second example, pdu and output have the same function as before but are class members of RWlanLogicalChannel. They are therefore stored on the heap and will persist until the request is completed regardless of the state of the stack.
Copyright ©2010 Nokia Corporation and/or its subsidiary(-ies).
All rights
reserved. Unless otherwise stated, these materials are provided under the terms of the Eclipse Public License
v1.0.