Changeset 28488 in vbox
- Timestamp:
- Apr 19, 2010 6:01:22 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/SrvIntNetR0.cpp
r28438 r28488 227 227 /** Pointer to ring-3 mapping of the default exchange buffer. */ 228 228 R3PTRTYPE(PINTNETBUF) pIntBufDefaultR3; 229 /** Event semaphore which a receiver thread will sleep on while waiting for data to arrive. */ 229 /** Event semaphore which a receiver thread will sleep on while waiting 230 * for data to arrive. */ 230 231 RTSEMEVENT volatile Event; 231 232 /** Number of threads sleeping on the Event semaphore. */ … … 348 349 /** List of interfaces connected to the network. 349 350 * This is protected by the INTNET::FastMutex. */ 350 PINTNETIF pI Fs;351 PINTNETIF pIfs; 351 352 /** Pointer to the trunk interface. 352 353 * Can be NULL if there is no trunk connection. */ … … 399 400 typedef struct INTNET 400 401 { 401 /** Mutex protecting the network creation, opening and destruction.402 * (This means all operations affecting the pNetworks list.) */403 RTSEM FASTMUTEX FastMutex;402 /** Mutex protecting the creation, opening and destruction of both networks and 403 * interfaces. (This means all operations affecting the pNetworks list.) */ 404 RTSEMMUTEX hMtxCreateOpenDestroy; 404 405 /** List of networks. Protected by INTNET::Spinlock. */ 405 406 PINTNETNETWORK volatile pNetworks; … … 1068 1069 uint8_t const cbAddr, const char *pszMsg) 1069 1070 { 1070 for (PINTNETIF pIf = pNetwork->pI Fs; pIf; pIf = pIf->pNext)1071 for (PINTNETIF pIf = pNetwork->pIfs; pIf; pIf = pIf->pNext) 1071 1072 { 1072 1073 int i = intnetR0IfAddrCacheLookup(&pIf->aAddrCache[enmType], pAddr, cbAddr); … … 1092 1093 INTNETADDRTYPE const enmType, uint8_t const cbAddr, const char *pszMsg) 1093 1094 { 1094 for (PINTNETIF pIf = pNetwork->pI Fs; pIf; pIf = pIf->pNext)1095 for (PINTNETIF pIf = pNetwork->pIfs; pIf; pIf = pIf->pNext) 1095 1096 if (pIf != pIfSender) 1096 1097 { … … 1114 1115 DECLINLINE(PINTNETIF) intnetR0NetworkAddrCacheLookupIf(PINTNETNETWORK pNetwork, PCRTNETADDRU pAddr, INTNETADDRTYPE const enmType, uint8_t const cbAddr) 1115 1116 { 1116 for (PINTNETIF pIf = pNetwork->pI Fs; pIf; pIf = pIf->pNext)1117 for (PINTNETIF pIf = pNetwork->pIfs; pIf; pIf = pIf->pNext) 1117 1118 { 1118 1119 int i = intnetR0IfAddrCacheLookup(&pIf->aAddrCache[enmType], pAddr, cbAddr); … … 1325 1326 case RTNET_DHCP_MT_ACK: 1326 1327 if (intnetR0IPv4AddrIsGood(pDhcp->bp_yiaddr)) 1327 for (PINTNETIF pCur = pNetwork->pI Fs; pCur; pCur = pCur->pNext)1328 for (PINTNETIF pCur = pNetwork->pIfs; pCur; pCur = pCur->pNext) 1328 1329 if ( pCur->fMacSet 1329 1330 && !memcmp(&pCur->Mac, &pDhcp->bp_chaddr, sizeof(RTMAC))) … … 1343 1344 case RTNET_DHCP_MT_RELEASE: 1344 1345 { 1345 for (PINTNETIF pCur = pNetwork->pI Fs; pCur; pCur = pCur->pNext)1346 for (PINTNETIF pCur = pNetwork->pIfs; pCur; pCur = pCur->pNext) 1346 1347 if ( pCur->fMacSet 1347 1348 && !memcmp(&pCur->Mac, &pDhcp->bp_chaddr, sizeof(RTMAC))) … … 2270 2271 * Write the packet to all the interfaces and signal them. 2271 2272 */ 2272 for (PINTNETIF pIf = pNetwork->pI Fs; pIf; pIf = pIf->pNext)2273 for (PINTNETIF pIf = pNetwork->pIfs; pIf; pIf = pIf->pNext) 2273 2274 if (pIf != pIfSender) 2274 2275 intnetR0IfSend(pIf, pIfSender, pSG, NULL); … … 2403 2404 if (!(pNetwork->fFlags & (INTNET_OPEN_FLAGS_IGNORE_PROMISC | INTNET_OPEN_FLAGS_QUIETLY_IGNORE_PROMISC))) 2404 2405 { 2405 for (PINTNETIF pIf = pNetwork->pI Fs; pIf; pIf = pIf->pNext)2406 for (PINTNETIF pIf = pNetwork->pIfs; pIf; pIf = pIf->pNext) 2406 2407 if (pIf->fPromiscuous) 2407 2408 { … … 2418 2419 */ 2419 2420 bool fExactIntNetRecipient = false; 2420 for (PINTNETIF pIf = pNetwork->pI Fs; pIf; pIf = pIf->pNext)2421 for (PINTNETIF pIf = pNetwork->pIfs; pIf; pIf = pIf->pNext) 2421 2422 { 2422 2423 bool fIt = intnetR0IfAddrCacheLookup(&pIf->aAddrCache[enmAddrType], &Addr, cbAddr) >= 0; … … 2464 2465 */ 2465 2466 bool fExactIntNetRecipient = false; 2466 for (PINTNETIF pIf = pNetwork->pI Fs; pIf; pIf = pIf->pNext)2467 for (PINTNETIF pIf = pNetwork->pIfs; pIf; pIf = pIf->pNext) 2467 2468 { 2468 2469 bool fIt = false; … … 3312 3313 static DECLCALLBACK(void) intnetR0IfDestruct(void *pvObj, void *pvUser1, void *pvUser2) 3313 3314 { 3314 PINTNETIF pIf = (PINTNETIF)pvUser1;3315 PINTNETIF pIf = (PINTNETIF)pvUser1; 3315 3316 PINTNET pIntNet = (PINTNET)pvUser2; 3316 3317 Log(("intnetR0IfDestruct: pvObj=%p pIf=%p pIntNet=%p hIf=%RX32\n", pvObj, pIf, pIntNet, pIf->hIf)); 3317 3318 3318 RTSemFastMutexRequest(pIntNet->FastMutex); 3319 3320 /* 3321 * Mark the interface as being destroyed so the waiter 3322 * can behave appropriately (theoretical case). 3323 */ 3319 /* 3320 * We grab the INTNET create/open/destroy semaphore to make sure nobody is 3321 * adding or removing interface while we're in here. For paranoid reasons 3322 * we also mark the interface as destroyed here so any waiting threads can 3323 * take the appropriate actions (theoretical case). 3324 */ 3325 RTSemMutexRequest(pIntNet->hMtxCreateOpenDestroy, RT_INDEFINITE_WAIT); 3324 3326 ASMAtomicWriteBool(&pIf->fDestroying, true); 3325 3327 … … 3344 3346 intnetR0IfSetActive(pIf, false); 3345 3347 3346 if (pNetwork->pIFs == pIf) 3347 pNetwork->pIFs = pIf->pNext; 3348 /* unlink */ 3349 if (pNetwork->pIfs == pIf) 3350 pNetwork->pIfs = pIf->pNext; 3348 3351 else 3349 3352 { 3350 PINTNETIF pPrev = pNetwork->pI Fs;3353 PINTNETIF pPrev = pNetwork->pIfs; 3351 3354 while (pPrev) 3352 3355 { … … 3362 3365 pIf->pNext = NULL; 3363 3366 3364 /* 3365 * Release our reference to the network. 3366 */ 3367 RTSemFastMutexRelease(pIntNet->FastMutex); 3368 3367 /* Release our reference to the network. */ 3369 3368 SUPR0ObjRelease(pNetwork->pvObj, pIf->pSession); 3370 3369 pIf->pNetwork = NULL; 3371 3370 } 3372 else 3373 RTSemFastMutexRelease(pIntNet->FastMutex);3371 3372 RTSemMutexRelease(pIntNet->hMtxCreateOpenDestroy); 3374 3373 3375 3374 /* … … 3435 3434 * Creates a new network interface. 3436 3435 * 3437 * The call must have opened the network for the new interface 3438 * and is responsible for closing it on failure. On success 3439 * it must leave the network opened so the interface destructor 3440 * can close it. 3436 * The call must have opened the network for the new interface and is 3437 * responsible for closing it on failure. On success it must leave the network 3438 * opened so the interface destructor can close it. 3441 3439 * 3442 3440 * @returns VBox status code. … … 3447 3445 * @param phIf Where to store the interface handle. 3448 3446 */ 3449 static int intnetR0NetworkCreateIf(PINTNETNETWORK pNetwork, PSUPDRVSESSION pSession, unsigned cbSend, unsigned cbRecv, bool *pfCloseNetwork, PINTNETIFHANDLE phIf) 3447 static int intnetR0NetworkCreateIf(PINTNETNETWORK pNetwork, PSUPDRVSESSION pSession, unsigned cbSend, unsigned cbRecv, 3448 PINTNETIFHANDLE phIf) 3450 3449 { 3451 3450 LogFlow(("intnetR0NetworkCreateIf: pNetwork=%p pSession=%p cbSend=%u cbRecv=%u phIf=%p\n", … … 3457 3456 AssertPtr(pNetwork); 3458 3457 AssertPtr(phIf); 3459 AssertPtr(pfCloseNetwork);3460 *pfCloseNetwork = false;3461 3458 3462 3459 /* … … 3514 3511 ASMMemZero32(pIf->pIntBufDefault, cbBuf); /** @todo I thought I specified these buggers as clearing the memory... */ 3515 3512 3516 pIf->pIntBuf = pIf->pIntBufDefault;3513 pIf->pIntBuf = pIf->pIntBufDefault; 3517 3514 pIf->pIntBufR3 = pIf->pIntBufDefaultR3; 3518 3515 INTNETBufInit(pIf->pIntBuf, cbBuf, cbRecv, cbSend); … … 3524 3521 if (RT_SUCCESS(rc)) 3525 3522 { 3526 pIf->pNext = pNetwork->pI Fs;3527 pNetwork->pI Fs = pIf;3523 pIf->pNext = pNetwork->pIfs; 3524 pNetwork->pIfs = pIf; 3528 3525 RTSemFastMutexRelease(pNetwork->FastMutex2); 3529 3526 3530 3527 /* 3531 * Register the interface with the session. 3528 * Register the interface with the session, adding another 3529 * reference to the network to ease the cleanup duties of the caller. 3532 3530 */ 3533 pIf->pvObj = SUPR0ObjRegister(pSession, SUPDRVOBJTYPE_INTERNAL_NETWORK_INTERFACE, intnetR0IfDestruct, pIf, pNetwork->pIntNet);3534 if ( pIf->pvObj)3531 rc = SUPR0ObjAddRef(pNetwork->pvObj, pSession); 3532 if (RT_SUCCESS(rc)) 3535 3533 { 3536 rc = RTHandleTableAllocWithCtx(pNetwork->pIntNet->hHtIfs, pIf, pSession, (uint32_t *)&pIf->hIf);3537 if ( RT_SUCCESS(rc))3534 pIf->pvObj = SUPR0ObjRegister(pSession, SUPDRVOBJTYPE_INTERNAL_NETWORK_INTERFACE, intnetR0IfDestruct, pIf, pNetwork->pIntNet); 3535 if (pIf->pvObj) 3538 3536 { 3539 *phIf = pIf->hIf; 3540 Log(("intnetR0NetworkCreateIf: returns VINF_SUCCESS *phIf=%RX32 cbSend=%u cbRecv=%u cbBuf=%u\n", 3541 *phIf, pIf->pIntBufDefault->cbSend, pIf->pIntBufDefault->cbRecv, pIf->pIntBufDefault->cbBuf)); 3542 return VINF_SUCCESS; 3537 rc = RTHandleTableAllocWithCtx(pNetwork->pIntNet->hHtIfs, pIf, pSession, (uint32_t *)&pIf->hIf); 3538 if (RT_SUCCESS(rc)) 3539 { 3540 *phIf = pIf->hIf; 3541 Log(("intnetR0NetworkCreateIf: returns VINF_SUCCESS *phIf=%RX32 cbSend=%u cbRecv=%u cbBuf=%u\n", 3542 *phIf, pIf->pIntBufDefault->cbSend, pIf->pIntBufDefault->cbRecv, pIf->pIntBufDefault->cbBuf)); 3543 return VINF_SUCCESS; 3544 } 3545 3546 SUPR0ObjRelease(pIf->pvObj, pSession); 3547 LogFlow(("intnetR0NetworkCreateIf: returns %Rrc\n", rc)); 3548 return rc; 3543 3549 } 3544 3550 3545 SUPR0ObjRelease(pIf->pvObj, pSession); 3546 LogFlow(("intnetR0NetworkCreateIf: returns %Rrc\n", rc)); 3547 return rc; 3551 SUPR0ObjRelease(pNetwork->pvObj, pSession); 3548 3552 } 3549 3553 … … 3562 3566 RTMemFree(pIf); 3563 3567 LogFlow(("intnetR0NetworkCreateIf: returns %Rrc\n", rc)); 3564 *pfCloseNetwork = true;3565 3568 return rc; 3566 3569 } … … 3840 3843 * Free up the resources. 3841 3844 */ 3842 RTSEMFASTMUTEX FastMutex = pThis->FastMutex;3843 pThis->FastMutex = NIL_RTSEM FASTMUTEX;3845 RTSEMFASTMUTEX hFastMutex = pThis->FastMutex; 3846 pThis->FastMutex = NIL_RTSEMMUTEX; 3844 3847 pThis->pNetwork = NULL; 3845 RTSemFastMutexRelease( FastMutex);3846 RTSemFastMutexDestroy( FastMutex);3848 RTSemFastMutexRelease(hFastMutex); 3849 RTSemFastMutexDestroy(hFastMutex); 3847 3850 RTMemFree(pThis); 3848 3851 } … … 3953 3956 3954 3957 /** 3955 * Close a network which was opened/created using intnetR0OpenNetwork()/intnetR0CreateNetwork().3956 *3957 * @param pNetwork The network to close.3958 * @param pSession The session handle.3959 */3960 static int intnetR0NetworkClose(PINTNETNETWORK pNetwork, PSUPDRVSESSION pSession)3961 {3962 LogFlow(("intnetR0NetworkClose: pNetwork=%p pSession=%p\n", pNetwork, pSession));3963 AssertPtrReturn(pSession, VERR_INVALID_PARAMETER);3964 AssertPtrReturn(pNetwork, VERR_INVALID_PARAMETER);3965 3966 int rc = SUPR0ObjRelease(pNetwork->pvObj, pSession);3967 LogFlow(("intnetR0NetworkClose: return %Rrc\n", rc));3968 return rc;3969 }3970 3971 3972 /**3973 3958 * Object destructor callback. 3974 3959 * This is called for reference counted objectes when the count reaches 0. … … 3986 3971 3987 3972 /* take the create/destroy sem. */ 3988 RTSem FastMutexRequest(pIntNet->FastMutex);3973 RTSemMutexRequest(pIntNet->hMtxCreateOpenDestroy, RT_INDEFINITE_WAIT); 3989 3974 3990 3975 /* … … 4014 3999 4015 4000 /* 4016 * Because of the undefined order of the per session object dereferencing when closing a session, 4017 * we have to handle the case where the network is destroyed before the interfaces. We'll 4018 * deal with this by simply orphaning the interfaces. 4001 * Because of the undefined order of the per session object dereferencing 4002 * when closing a session, we have to handle the case where the network is 4003 * destroyed before the interfaces. 4004 * We deal with this simply by orphaning the interfaces. 4019 4005 */ 4020 4006 RTSemFastMutexRequest(pNetwork->FastMutex2); 4021 4007 4022 PINTNETIF pCur = pNetwork->pI Fs;4008 PINTNETIF pCur = pNetwork->pIfs; 4023 4009 while (pCur) 4024 4010 { … … 4050 4036 4051 4037 /* release the create/destroy sem. (can be done before trunk destruction.) */ 4052 RTSem FastMutexRelease(pIntNet->FastMutex);4038 RTSemMutexRelease(pIntNet->hMtxCreateOpenDestroy); 4053 4039 } 4054 4040 … … 4056 4042 /** 4057 4043 * Opens an existing network. 4044 * 4045 * The call must own the INTNET::hMtxCreateOpenDestroy. 4058 4046 * 4059 4047 * @returns VBox status code. … … 4137 4125 return rc; 4138 4126 } 4127 4139 4128 pCur = pCur->pNext; 4140 4129 } … … 4148 4137 * Creates a new network. 4149 4138 * 4150 * The call must own the INTNET:: FastMutexand has already attempted4139 * The call must own the INTNET::hMtxCreateOpenDestroy and has already attempted 4151 4140 * opening the network and found it to be non-existing. 4152 4141 * … … 4159 4148 * @param pszTrunk The trunk name. Its meaning is specfic to the type. 4160 4149 * @param fFlags Flags, see INTNET_OPEN_FLAGS_*. 4161 * @param ppNetwork Where to store the network. In the case of failure whatever is returned 4162 * here should be dereferenced outside the INTNET::FastMutex. 4150 * @param ppNetwork Where to store the network. In the case of failure 4151 * whatever is returned here should be dereferenced 4152 * outside the INTNET::hMtxCreateOpenDestroy. 4163 4153 */ 4164 4154 static int intnetR0CreateNetwork(PINTNET pIntNet, PSUPDRVSESSION pSession, const char *pszNetwork, INTNETTRUNKTYPE enmTrunkType, … … 4190 4180 if (RT_SUCCESS(rc)) 4191 4181 { 4192 //pNew->pI Fs= NULL;4193 pNew->pIntNet = pIntNet;4194 //pNew->cActiveIFs = 0;4195 pNew->fFlags = fFlags;4196 size_t cchName = strlen(pszNetwork);4197 pNew->cchName = (uint8_t)cchName;4182 //pNew->pIfs = NULL; 4183 pNew->pIntNet = pIntNet; 4184 //pNew->cActiveIFs = 0; 4185 pNew->fFlags = fFlags; 4186 size_t cchName = strlen(pszNetwork); 4187 pNew->cchName = (uint8_t)cchName; 4198 4188 Assert(cchName && cchName < sizeof(pNew->szName)); /* caller's responsibility. */ 4199 4189 memcpy(pNew->szName, pszNetwork, cchName); /* '\0' by alloc. */ 4200 pNew->enmTrunkType = enmTrunkType;4190 pNew->enmTrunkType = enmTrunkType; 4201 4191 Assert(strlen(pszTrunk) < sizeof(pNew->szTrunk)); /* caller's responsibility. */ 4202 4192 strcpy(pNew->szTrunk, pszTrunk); 4203 4193 if (fFlags & INTNET_OPEN_FLAGS_SHARED_MAC_ON_WIRE) 4204 pNew->pbTmp = RT_ALIGN_PT(pNew + 1, 64, uint8_t *);4194 pNew->pbTmp = RT_ALIGN_PT(pNew + 1, 64, uint8_t *); 4205 4195 //else 4206 // pNew->pbTmp = NULL;4196 // pNew->pbTmp = NULL; 4207 4197 4208 4198 /* … … 4216 4206 4217 4207 /* 4218 * Check if the current session is actually allowed to create and open 4219 * the network. It is possible to implement network name based policies 4220 * and these must be checked now. SUPR0ObjRegister does no such checks. 4208 * Check if the current session is actually allowed to create and 4209 * open the network. It is possible to implement network name 4210 * based policies and these must be checked now. SUPR0ObjRegister 4211 * does no such checks. 4221 4212 */ 4222 4213 rc = SUPR0ObjVerifyAccess(pNew->pvObj, pSession, pNew->szName); … … 4235 4226 } 4236 4227 4237 /* 4238 * We unlink it here so it cannot be opened when the caller leaves 4239 * INTNET::FastMutex before dereferencing it. 4240 */ 4241 Assert(pIntNet->pNetworks == pNew); 4242 pIntNet->pNetworks = pNew->pNext; 4243 pNew->pNext = NULL; 4244 4245 *ppNetwork = pNew; 4228 SUPR0ObjRelease(pNew->pvObj, pSession); 4246 4229 LogFlow(("intnetR0CreateNetwork: returns %Rrc\n", rc)); 4247 4230 return rc; … … 4324 4307 4325 4308 /* 4326 * Acquire the mutex to serialize open/create .4327 */ 4328 int rc = RTSem FastMutexRequest(pIntNet->FastMutex);4309 * Acquire the mutex to serialize open/create/close. 4310 */ 4311 int rc = RTSemMutexRequest(pIntNet->hMtxCreateOpenDestroy, RT_INDEFINITE_WAIT); 4329 4312 if (RT_FAILURE(rc)) 4330 4313 return rc; … … 4333 4316 * Try open / create the network and create an interface on it for the 4334 4317 * caller to use. 4335 *4336 * Note! Because of the destructors grabbing INTNET::FastMutex and us being4337 * required to own this semaphore for the entire network opening / creation4338 * and interface creation sequence, intnetR0CreateNetwork will have to4339 * defer the network cleanup to us on failure.4340 4318 */ 4341 4319 PINTNETNETWORK pNetwork = NULL; 4342 4320 rc = intnetR0OpenNetwork(pIntNet, pSession, pszNetwork, enmTrunkType, pszTrunk, fFlags, &pNetwork); 4343 if (RT_SUCCESS(rc) || rc == VERR_NOT_FOUND) 4344 { 4345 bool fCloseNetwork = true; 4346 bool fNewNet = rc == VERR_NOT_FOUND; 4347 if (fNewNet) 4348 rc = intnetR0CreateNetwork(pIntNet, pSession, pszNetwork, enmTrunkType, pszTrunk, fFlags, &pNetwork); 4321 if (RT_SUCCESS(rc)) 4322 { 4323 rc = intnetR0NetworkCreateIf(pNetwork, pSession, cbSend, cbRecv, phIf); 4349 4324 if (RT_SUCCESS(rc)) 4350 rc = intnetR0NetworkCreateIf(pNetwork, pSession, cbSend, cbRecv, &fCloseNetwork, phIf); 4351 4352 RTSemFastMutexRelease(pIntNet->FastMutex); 4353 4354 if (RT_FAILURE(rc)) 4325 rc = VINF_ALREADY_INITIALIZED; 4326 SUPR0ObjRelease(pNetwork->pvObj, pSession); 4327 } 4328 else if (rc == VERR_NOT_FOUND) 4329 { 4330 rc = intnetR0CreateNetwork(pIntNet, pSession, pszNetwork, enmTrunkType, pszTrunk, fFlags, &pNetwork); 4331 if (RT_SUCCESS(rc)) 4355 4332 { 4356 if(pNetwork && fCloseNetwork)4357 intnetR0NetworkClose(pNetwork, pSession);4333 rc = intnetR0NetworkCreateIf(pNetwork, pSession, cbSend, cbRecv, phIf); 4334 SUPR0ObjRelease(pNetwork->pvObj, pSession); 4358 4335 } 4359 else if(!fNewNet) 4360 rc = VINF_ALREADY_INITIALIZED; 4361 } 4362 else 4363 RTSemFastMutexRelease(pIntNet->FastMutex); 4364 4336 } 4337 4338 RTSemMutexRelease(pIntNet->hMtxCreateOpenDestroy); 4365 4339 LogFlow(("INTNETR0Open: return %Rrc *phIf=%RX32\n", rc, *phIf)); 4366 4340 return rc; … … 4405 4379 */ 4406 4380 Assert(pIntNet->pNetworks == NULL); 4407 if (pIntNet-> FastMutex != NIL_RTSEMFASTMUTEX)4408 { 4409 RTSem FastMutexDestroy(pIntNet->FastMutex);4410 pIntNet-> FastMutex = NIL_RTSEMFASTMUTEX;4381 if (pIntNet->hMtxCreateOpenDestroy != NIL_RTSEMMUTEX) 4382 { 4383 RTSemMutexDestroy(pIntNet->hMtxCreateOpenDestroy); 4384 pIntNet->hMtxCreateOpenDestroy = NIL_RTSEMMUTEX; 4411 4385 } 4412 4386 if (pIntNet->hHtIfs != NIL_RTHANDLETABLE) … … 4436 4410 //pIntNet->pNetworks = NULL; 4437 4411 4438 rc = RTSem FastMutexCreate(&pIntNet->FastMutex);4412 rc = RTSemMutexCreate(&pIntNet->hMtxCreateOpenDestroy); 4439 4413 if (RT_SUCCESS(rc)) 4440 4414 { … … 4448 4422 } 4449 4423 4450 RTSem FastMutexDestroy(pIntNet->FastMutex);4424 RTSemMutexDestroy(pIntNet->hMtxCreateOpenDestroy); 4451 4425 } 4452 4426 RTMemFree(pIntNet);
Note:
See TracChangeset
for help on using the changeset viewer.