Changeset 1741 in vbox
- Timestamp:
- Mar 27, 2007 4:29:56 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Serial/DrvChar.cpp
r1736 r1741 31 31 32 32 #include <VBox/log.h> 33 #include <iprt/asm.h> 33 34 #include <iprt/assert.h> 34 35 #include <iprt/stream.h> 36 #include <iprt/semaphore.h> 35 37 36 38 #include "Builtins.h" 37 39 40 41 /** Size of the send fifo queue (in bytes) */ 42 #define CHAR_MAX_SEND_QUEUE 0x80 43 #define CHAR_MAX_SEND_QUEUE_MASK 0x7f 38 44 39 45 /******************************************************************************* … … 58 64 /** Receive thread ID. */ 59 65 RTTHREAD ReceiveThread; 66 /** Send thread ID. */ 67 RTTHREAD SendThread; 68 /** Send event semephore */ 69 RTSEMEVENT SendSem; 70 71 /** Internal send FIFO queue */ 72 uint8_t aSendQueue[CHAR_MAX_SEND_QUEUE]; 73 uint32_t iSendQueueHead; 74 uint32_t iSendQueueTail; 60 75 } DRVCHAR, *PDRVCHAR; 61 76 … … 97 112 { 98 113 PDRVCHAR pData = PDMICHAR_2_DRVCHAR(pInterface); 114 const char *pBuffer = (const char *)pvBuf; 99 115 int rc = VINF_SUCCESS; 100 116 101 117 LogFlow(("%s: pvBuf=%#p cbWrite=%d\n", __FUNCTION__, pvBuf, cbWrite)); 102 118 103 /* 104 * Write the character to the attached stream (if present). 105 */ 106 if (pData->pDrvStream) 119 for (uint32_t i=0;i<cbWrite;i++) 107 120 { 108 const char *pBuffer = (const char *)pvBuf; 109 size_t cbProcessed = cbWrite; 110 111 while (cbWrite) 121 uint32_t idx = pData->iSendQueueHead; 122 123 pData->aSendQueue[idx] = pBuffer[i]; 124 idx = (idx + 1) & CHAR_MAX_SEND_QUEUE_MASK; 125 126 ASMAtomicXchgU32(&pData->iSendQueueHead, idx); 127 } 128 RTSemEventSignal(pData->SendSem); 129 return VINF_SUCCESS; 130 } 131 132 133 /* -=-=-=-=- receive thread -=-=-=-=- */ 134 135 /** 136 * Send thread loop. 137 * 138 * @returns 0 on success. 139 * @param ThreadSelf Thread handle to this thread. 140 * @param pvUser User argument. 141 */ 142 static DECLCALLBACK(int) drvCharSendLoop(RTTHREAD ThreadSelf, void *pvUser) 143 { 144 PDRVCHAR pData = (PDRVCHAR)pvUser; 145 146 for(;;) 147 { 148 int rc = RTSemEventWait(pData->SendSem, RT_INDEFINITE_WAIT); 149 if (VBOX_FAILURE(rc)) 150 break; 151 152 /* 153 * Write the character to the attached stream (if present). 154 */ 155 if ( !pData->fShutdown 156 && pData->pDrvStream) 112 157 { 113 rc = pData->pDrvStream->pfnWrite(pData->pDrvStream, pBuffer, &cbProcessed); 114 if (VBOX_SUCCESS(rc)) 115 { 116 Assert(cbProcessed); 117 cbWrite -= cbProcessed; 118 pBuffer += cbProcessed; 119 } 120 else if (rc == VERR_TIMEOUT) 121 { 122 /* Normal case, just means that the stream didn't accept a new 123 * character before the timeout elapsed. Just retry. */ 124 rc = VINF_SUCCESS; 125 } 126 else 127 { 128 Log(("Write failed with %Vrc; skipping\n", rc)); 129 break; 158 while (pData->iSendQueueTail != pData->iSendQueueHead) 159 { 160 size_t cbProcessed = 1; 161 162 rc = pData->pDrvStream->pfnWrite(pData->pDrvStream, &pData->aSendQueue[pData->iSendQueueTail], &cbProcessed); 163 if (VBOX_SUCCESS(rc)) 164 { 165 Assert(cbProcessed); 166 pData->iSendQueueTail++; 167 pData->iSendQueueTail &= CHAR_MAX_SEND_QUEUE_MASK; 168 } 169 else if (rc == VERR_TIMEOUT) 170 { 171 /* Normal case, just means that the stream didn't accept a new 172 * character before the timeout elapsed. Just retry. */ 173 rc = VINF_SUCCESS; 174 } 175 else 176 { 177 Log(("Write failed with %Vrc; skipping\n", rc)); 178 break; 179 } 130 180 } 131 181 } 182 else 183 break; 132 184 } 133 else 134 rc = VERR_PDM_NO_ATTACHED_DRIVER; 135 136 LogFlow(("%s: returns rc=%Vrc\n", __FUNCTION__, rc)); 137 return rc; 185 186 pData->SendThread = NIL_RTTHREAD; 187 188 return VINF_SUCCESS; 138 189 } 139 190 … … 251 302 return PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_MISSING_INTERFACE_BELOW, RT_SRC_POS, N_("Char#%d has no stream interface below"), pDrvIns->iInstance); 252 303 253 rc = RTThreadCreate(&pData->ReceiveThread, drvCharReceiveLoop, (void *)pData, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "Char ");304 rc = RTThreadCreate(&pData->ReceiveThread, drvCharReceiveLoop, (void *)pData, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "Char Receive"); 254 305 if (VBOX_FAILURE(rc)) 255 306 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("Char#%d cannot create receive thread"), pDrvIns->iInstance); 256 307 308 rc = RTSemEventCreate(&pData->SendSem); 309 AssertRC(rc); 310 311 rc = RTThreadCreate(&pData->SendThread, drvCharSendLoop, (void *)pData, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "Char Send"); 312 if (VBOX_FAILURE(rc)) 313 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("Char#%d cannot create send thread"), pDrvIns->iInstance); 314 257 315 return VINF_SUCCESS; 258 316 } … … 274 332 275 333 pData->fShutdown = true; 276 RTThreadWait(pData->ReceiveThread, 5000, NULL);334 RTThreadWait(pData->ReceiveThread, 1000, NULL); 277 335 if (pData->ReceiveThread != NIL_RTTHREAD) 278 336 LogRel(("Char%d: receive thread did not terminate\n", pDrvIns->iInstance)); 337 338 /* Empty the send queue */ 339 pData->iSendQueueTail = pData->iSendQueueHead = 0; 340 341 RTSemEventDestroy(pData->SendSem); 342 pData->SendSem = NIL_RTSEMEVENT; 343 344 RTThreadWait(pData->SendThread, 1000, NULL); 345 if (pData->SendThread != NIL_RTTHREAD) 346 LogRel(("Char%d: send thread did not terminate\n", pDrvIns->iInstance)); 279 347 } 280 348
Note:
See TracChangeset
for help on using the changeset viewer.