Changeset 27932 in vbox
- Timestamp:
- Apr 1, 2010 12:39:15 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Serial/DrvChar.cpp
r26173 r27932 1 1 /* $Id$ */ 2 2 /** @file 3 * VBox stream I/O devices: Generic char driver 3 * Driver that PDMISTREAM into PDMICHARCONNECTOR / PDMICHARPORT. 4 * 5 * Converts synchronous calls (PDMICHARCONNECTOR::pfnWrite, PDMISTREAM::pfnRead) 6 * into asynchronous ones. 4 7 */ 5 8 6 9 /* 7 * Copyright (C) 2006-20 07Sun Microsystems, Inc.10 * Copyright (C) 2006-2010 Sun Microsystems, Inc. 8 11 * 9 12 * This file is part of VirtualBox Open Source Edition (OSE), as … … 76 79 /** Internal send FIFO queue */ 77 80 uint8_t aSendQueue[CHAR_MAX_SEND_QUEUE]; 78 uint32_t 81 uint32_t volatile iSendQueueHead; 79 82 uint32_t iSendQueueTail; 80 83 … … 142 145 143 146 /** 144 * Send thread loop .147 * Send thread loop - pushes data down thru the driver chain. 145 148 * 146 149 * @returns 0 on success. … … 152 155 PDRVCHAR pThis = (PDRVCHAR)pvUser; 153 156 154 for(;;)157 while (!pThis->fShutdown) 155 158 { 156 159 int rc = RTSemEventWait(pThis->SendSem, RT_INDEFINITE_WAIT); … … 161 164 * Write the character to the attached stream (if present). 162 165 */ 163 if ( !pThis->fShutdown 164 && pThis->pDrvStream) 166 if ( pThis->fShutdown 167 || !pThis->pDrvStream) 168 break; 169 170 while ( pThis->iSendQueueTail != pThis->iSendQueueHead 171 && !pThis->fShutdown) 165 172 { 166 while (pThis->iSendQueueTail != pThis->iSendQueueHead) 167 { 168 size_t cbProcessed = 1; 169 170 rc = pThis->pDrvStream->pfnWrite(pThis->pDrvStream, &pThis->aSendQueue[pThis->iSendQueueTail], &cbProcessed); 171 if (RT_SUCCESS(rc)) 172 { 173 Assert(cbProcessed); 174 pThis->iSendQueueTail++; 175 pThis->iSendQueueTail &= CHAR_MAX_SEND_QUEUE_MASK; 176 } 177 else if (rc == VERR_TIMEOUT) 178 { 179 /* Normal case, just means that the stream didn't accept a new 180 * character before the timeout elapsed. Just retry. */ 181 rc = VINF_SUCCESS; 182 } 183 else 184 { 185 LogFlow(("Write failed with %Rrc; skipping\n", rc)); 186 break; 187 } 173 size_t cbProcessed = 1; 174 175 rc = pThis->pDrvStream->pfnWrite(pThis->pDrvStream, &pThis->aSendQueue[pThis->iSendQueueTail], &cbProcessed); 176 if (RT_SUCCESS(rc)) 177 { 178 Assert(cbProcessed); 179 pThis->iSendQueueTail++; 180 pThis->iSendQueueTail &= CHAR_MAX_SEND_QUEUE_MASK; 181 } 182 else if (rc == VERR_TIMEOUT) 183 { 184 /* Normal case, just means that the stream didn't accept a new 185 * character before the timeout elapsed. Just retry. */ 186 rc = VINF_SUCCESS; 187 } 188 else 189 { 190 LogFlow(("Write failed with %Rrc; skipping\n", rc)); 191 break; 188 192 } 189 193 } 190 else 191 break; 192 } 193 194 pThis->SendThread = NIL_RTTHREAD; 194 } 195 195 196 196 return VINF_SUCCESS; … … 263 263 } 264 264 265 pThis->ReceiveThread = NIL_RTTHREAD;266 267 265 return VINF_SUCCESS; 268 266 } … … 312 310 PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns); 313 311 312 /* 313 * Tell the threads to shut down. 314 */ 314 315 pThis->fShutdown = true; 315 if (pThis->ReceiveThread) 316 { 317 RTThreadWait(pThis->ReceiveThread, 1000, NULL); 318 if (pThis->ReceiveThread != NIL_RTTHREAD) 319 LogRel(("Char%d: receive thread did not terminate\n", pDrvIns->iInstance)); 320 } 321 322 /* Empty the send queue */ 323 pThis->iSendQueueTail = pThis->iSendQueueHead = 0; 324 325 RTSemEventSignal(pThis->SendSem); 326 RTSemEventDestroy(pThis->SendSem); 327 pThis->SendSem = NIL_RTSEMEVENT; 328 329 if (pThis->SendThread) 330 { 331 RTThreadWait(pThis->SendThread, 1000, NULL); 332 if (pThis->SendThread != NIL_RTTHREAD) 333 LogRel(("Char%d: send thread did not terminate\n", pDrvIns->iInstance)); 316 if (pThis->SendSem != NIL_RTSEMEVENT) 317 { 318 RTSemEventSignal(pThis->SendSem); 319 RTSemEventDestroy(pThis->SendSem); 320 pThis->SendSem = NIL_RTSEMEVENT; 321 } 322 323 /* 324 * Wait for the threads. 325 * ASSUMES that PDM destroys the driver chain from the the bottom and up. 326 */ 327 if (pThis->ReceiveThread != NIL_RTTHREAD) 328 { 329 int rc = RTThreadWait(pThis->ReceiveThread, 300000, NULL); 330 if (RT_SUCCESS(rc)) 331 pThis->ReceiveThread = NIL_RTTHREAD; 332 else 333 LogRel(("Char%d: receive thread did not terminate (%Rrc)\n", pDrvIns->iInstance, rc)); 334 } 335 336 if (pThis->SendThread != NIL_RTTHREAD) 337 { 338 int rc = RTThreadWait(pThis->SendThread, 30000, NULL); 339 if (RT_SUCCESS(rc)) 340 pThis->SendThread = NIL_RTTHREAD; 341 else 342 LogRel(("Char%d: send thread did not terminate (%Rrc)\n", pDrvIns->iInstance, rc)); 334 343 } 335 344 } … … 350 359 * Init basic data members and interfaces. 351 360 */ 361 pThis->fShutdown = false; 352 362 pThis->ReceiveThread = NIL_RTTHREAD; 353 pThis->fShutdown = false; 363 pThis->SendThread = NIL_RTTHREAD; 364 pThis->SendSem = NIL_RTSEMEVENT; 354 365 /* IBase. */ 355 366 pDrvIns->IBase.pfnQueryInterface = drvCharQueryInterface; … … 383 394 if (pThis->pDrvStream->pfnRead) 384 395 { 385 rc = RTThreadCreate(&pThis->ReceiveThread, drvCharReceiveLoop, (void *)pThis, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "CharRecv"); 396 rc = RTThreadCreate(&pThis->ReceiveThread, drvCharReceiveLoop, (void *)pThis, 0, 397 RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "CharRecv"); 386 398 if (RT_FAILURE(rc)) 387 399 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("Char#%d cannot create receive thread"), pDrvIns->iInstance); … … 389 401 390 402 rc = RTSemEventCreate(&pThis->SendSem); 391 AssertRC(rc); 392 393 rc = RTThreadCreate(&pThis->SendThread, drvCharSendLoop, (void *)pThis, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "CharSend"); 403 AssertRCReturn(rc, rc); 404 405 rc = RTThreadCreate(&pThis->SendThread, drvCharSendLoop, (void *)pThis, 0, 406 RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "CharSend"); 394 407 if (RT_FAILURE(rc)) 395 408 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("Char#%d cannot create send thread"), pDrvIns->iInstance);
Note:
See TracChangeset
for help on using the changeset viewer.