Both old and new L3LogicalChannel point to the same MMContext. The message arrives on the new channel, but we run this function on the old channel because we have not changed the LogicalChannel that the Context points to yet. mNextChan still points to the new channel. Beware that the two channels are serviced by different threads.
| 250 | // mNextChan still points to the new channel. |
| 251 | // Beware that the two channels are serviced by different threads. |
| 252 | void L3LogicalChannel::reassignComplete() |
| 253 | { |
| 254 | ScopedLock lock(gMMLock,__FILE__,__LINE__); |
| 255 | //timerStop(TChReassignment); // Handled by assignTCHFProcedure, which is notified after us. |
| 256 | |
| 257 | if (!mChContext) { |
| 258 | // Logic error. |
| 259 | LOG(ERR) << "received channel reassignment complete on dead channel:"<<this; |
| 260 | l3sendm(GSM::L3ChannelRelease(L3RRCause::NormalEvent)); |
| 261 | chanSetState(chRequestRelease); |
| 262 | return; |
| 263 | } |
| 264 | if (!mNextChan) { |
| 265 | // Logic error. |
| 266 | LOG(ERR) << "received channel reassignment complete with no nextchan allocated"<<this; |
| 267 | l3sendm(GSM::L3ChannelRelease(L3RRCause::NormalEvent)); |
| 268 | chanSetState(chRequestRelease); |
| 269 | return; |
| 270 | } |
| 271 | if (mNextChan->mChState != chEstablished) { |
| 272 | // The nextChan was supposed to get an ESTABLISH primitive then the L3AssignComplete command in order to get here. |
| 273 | // There could be a logic error or the MS may have dropped the channel at this inopportune moment, |
| 274 | // so it is not necessarily an error. |
| 275 | LOG(NOTICE)<< "Next channel in unexpected state, dropping channel"<<LOGVARM(mNextChan); |
| 276 | chanSetState(chRequestRelease); |
| 277 | return; |
| 278 | } |
| 279 | mChContext->mmSetChannel(mNextChan); |
| 280 | LOG(INFO) <<"successful channel reassignment" <<LOGVAR2("from-channel",this) <<LOGVAR2("to-channel",mNextChan); |
| 281 | mNextChan = NULL; |
| 282 | // FIXME: There is a race for the new channel to get its ESTABLISH before this old one gets this hardrelease. |
| 283 | sleep(1); |
| 284 | chanSetState(chRequestHardRelease); // Done with this channel. |
| 285 | //chanSetState(L3LogicalChannel::chReassignComplete); // Redundant with sending the HARDRELEASE, this will cause the service loop to exit. |
| 286 | } |
| 287 | |
| 288 | #if UNUSED |
| 289 | void L3LogicalChannel::chanLost() |
no test coverage detected