Changeset 64674 in vbox for trunk/src/VBox/Devices/Storage
- Timestamp:
- Nov 15, 2016 2:09:23 PM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/IOBufMgmt.cpp
r64411 r64674 77 77 void *pvMem; 78 78 /** Number of bins for free objects. */ 79 unsigned cBins; 79 uint32_t cBins; 80 /** Flag whether allocation is on hold waiting for everything to be free 81 * to be able to defragment the memory. */ 82 bool fAllocSuspended; 80 83 /** Array of bins. */ 81 84 PIOBUFMGRBIN paBins; … … 88 91 #include "IOBufMgmt.h" 89 92 90 DECLINLINE(unsigned) iobufMgrGetBinCount(size_t cbMin, size_t cbMax) 91 { 92 unsigned u32Max = ASMBitLastSetU32((uint32_t)cbMax); 93 unsigned u32Min = ASMBitLastSetU32((uint32_t)cbMin); 93 /** 94 * Gets the number of bins required between the given minimum and maximum size 95 * to have a bin for every power of two size inbetween. 96 * 97 * @returns The number of bins required. 98 * @param cbMin The size of the smallest bin. 99 * @param cbMax The size of the largest bin. 100 */ 101 DECLINLINE(uint32_t) iobufMgrGetBinCount(uint32_t cbMin, uint32_t cbMax) 102 { 103 uint32_t u32Max = ASMBitLastSetU32(cbMax); 104 uint32_t u32Min = ASMBitLastSetU32(cbMin); 94 105 95 106 Assert(cbMax >= cbMin && cbMax != 0 && cbMin != 0); … … 97 108 } 98 109 110 /** 111 * Returns the number of entries required in the object array to cover all bins. 112 * 113 * @returns Number of entries required in the object array. 114 * @param cbMem Size of the memory buffer. 115 * @param cBins Number of bins available. 116 * @param cbBinMin Minimum object size. 117 */ 99 118 DECLINLINE(uint32_t) iobufMgrGetObjCount(size_t cbMem, unsigned cBins, size_t cbMinBin) 100 119 { … … 112 131 } 113 132 114 DECLHIDDEN(int) IOBUFMgrCreate(PIOBUFMGR phIoBufMgr, size_t cbMax, uint32_t fFlags) 115 { 116 int rc = VINF_SUCCESS; 117 118 AssertPtrReturn(phIoBufMgr, VERR_INVALID_POINTER); 119 AssertReturn(cbMax, VERR_NOT_IMPLEMENTED); 120 121 /* Allocate the basic structure in one go. */ 122 unsigned cBins = iobufMgrGetBinCount(IOBUFMGR_BIN_SIZE_MIN, IOBUFMGR_BIN_SIZE_MAX); 123 uint32_t cObjs = iobufMgrGetObjCount(cbMax, cBins, IOBUFMGR_BIN_SIZE_MIN); 124 PIOBUFMGRINT pThis = (PIOBUFMGRINT)RTMemAllocZ(RT_OFFSETOF(IOBUFMGRINT, apvObj[cObjs]) + cBins * sizeof(IOBUFMGRBIN)); 125 if (RT_LIKELY(pThis)) 126 { 127 pThis->fFlags = fFlags; 128 pThis->cbMax = cbMax; 129 pThis->cbFree = cbMax; 130 pThis->cBins = cBins; 131 pThis->u32OrderMin = ASMBitLastSetU32(IOBUFMGR_BIN_SIZE_MIN) - 1; 132 pThis->u32OrderMax = ASMBitLastSetU32(IOBUFMGR_BIN_SIZE_MAX) - 1; 133 pThis->paBins = (PIOBUFMGRBIN)((uint8_t *)pThis + RT_OFFSETOF(IOBUFMGRINT, apvObj[cObjs])); 134 135 rc = RTCritSectInit(&pThis->CritSectAlloc); 136 if (RT_SUCCESS(rc)) 137 { 138 if (pThis->fFlags & IOBUFMGR_F_REQUIRE_NOT_PAGABLE) 139 rc = RTMemSaferAllocZEx(&pThis->pvMem, RT_ALIGN_Z(pThis->cbMax, _4K), 140 RTMEMSAFER_F_REQUIRE_NOT_PAGABLE); 141 else 142 pThis->pvMem = RTMemPageAllocZ(RT_ALIGN_Z(pThis->cbMax, _4K)); 143 144 if ( RT_LIKELY(pThis->pvMem) 145 && RT_SUCCESS(rc)) 133 /** 134 * Resets the bins to factory default (memory resigin in the largest bin). 135 * 136 * @returns nothing. 137 * @param pThis The I/O buffer manager instance. 138 */ 139 static void iobufMgrResetBins(PIOBUFMGRINT pThis) 140 { 141 /* Init the bins. */ 142 size_t cbMax = pThis->cbMax; 143 size_t iObj = 0; 144 uint32_t cbBin = IOBUFMGR_BIN_SIZE_MIN; 145 for (unsigned i = 0; i < pThis->cBins; i++) 146 { 147 PIOBUFMGRBIN pBin = &pThis->paBins[i]; 148 pBin->iFree = 0; 149 pBin->papvFree = &pThis->apvObj[iObj]; 150 iObj += cbMax / cbBin; 151 152 /* Init the biggest possible bin with the free objects. */ 153 if ( (cbBin << 1) > cbMax 154 || i == pThis->cBins - 1) 155 { 156 uint8_t *pbMem = (uint8_t *)pThis->pvMem; 157 while (cbMax) 146 158 { 147 /* Init the bins. */ 148 size_t iObj = 0; 149 uint32_t cbBin = IOBUFMGR_BIN_SIZE_MIN; 150 for (unsigned i = 0; i < cBins; i++) 151 { 152 PIOBUFMGRBIN pBin = &pThis->paBins[i]; 153 pBin->iFree = 0; 154 pBin->papvFree = &pThis->apvObj[iObj]; 155 iObj += cbMax / cbBin; 156 157 /* Init the biggest possible bin with the free objects. */ 158 if ( (cbBin << 1) > cbMax 159 || i == cBins - 1) 160 { 161 uint8_t *pbMem = (uint8_t *)pThis->pvMem; 162 while (cbMax) 163 { 164 pBin->papvFree[pBin->iFree] = pbMem; 165 cbMax -= cbBin; 166 pbMem += cbBin; 167 pBin->iFree++; 168 169 if (cbMax < cbBin) /** @todo Populate smaller bins and don't waste memory. */ 170 break; 171 } 172 173 /* Limit the number of available bins. */ 174 pThis->cBins = i + 1; 175 break; 176 } 177 178 cbBin <<= 1; 179 } 180 181 *phIoBufMgr = pThis; 182 return VINF_SUCCESS; 159 pBin->papvFree[pBin->iFree] = pbMem; 160 cbMax -= cbBin; 161 pbMem += cbBin; 162 pBin->iFree++; 163 164 if (cbMax < cbBin) /** @todo Populate smaller bins and don't waste memory. */ 165 break; 183 166 } 184 else 185 rc = VERR_NO_MEMORY; 186 187 RTCritSectDelete(&pThis->CritSectAlloc); 188 } 189 190 RTMemFree(pThis); 191 } 192 else 193 rc = VERR_NO_MEMORY; 194 195 return rc; 196 } 197 198 DECLHIDDEN(int) IOBUFMgrDestroy(IOBUFMGR hIoBufMgr) 199 { 200 PIOBUFMGRINT pThis = hIoBufMgr; 201 202 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 203 204 int rc = RTCritSectEnter(&pThis->CritSectAlloc); 205 if (RT_SUCCESS(rc)) 206 { 207 if (pThis->cbFree == pThis->cbMax) 208 { 209 if (pThis->fFlags & IOBUFMGR_F_REQUIRE_NOT_PAGABLE) 210 RTMemSaferFree(pThis->pvMem, RT_ALIGN_Z(pThis->cbMax, _4K)); 211 else 212 RTMemPageFree(pThis->pvMem, RT_ALIGN_Z(pThis->cbMax, _4K)); 213 214 RTCritSectLeave(&pThis->CritSectAlloc); 215 RTCritSectDelete(&pThis->CritSectAlloc); 216 RTMemFree(pThis); 217 } 218 else 219 { 220 rc = VERR_INVALID_STATE; 221 RTCritSectLeave(&pThis->CritSectAlloc); 222 } 223 } 224 225 return rc; 226 } 227 167 168 /* Limit the number of available bins. */ 169 pThis->cBins = i + 1; 170 break; 171 } 172 173 cbBin <<= 1; 174 } 175 } 176 177 /** 178 * Allocate one segment from the manager. 179 * 180 * @returns Number of bytes allocated, 0 if there is no free memory. 181 * @param pThis The I/O buffer manager instance. 182 * @param pSeg The segment to fill in on success. 183 * @param cb Maximum number of bytes to allocate. 184 */ 228 185 static size_t iobufMgrAllocSegment(PIOBUFMGRINT pThis, PRTSGSEG pSeg, size_t cb) 229 186 { … … 282 239 * If we didn't find something in the higher bins try to accumulate as much as possible from the smaller bins. 283 240 */ 284 /** @todo Defragment in case there is enough memory free but we can't find something in our bin. */285 241 if ( pBin->iFree == 0 286 242 && iBin > 0) 287 243 { 244 #if 1 245 pThis->fAllocSuspended = true; 246 #else 288 247 do 289 248 { … … 302 261 } 303 262 while (iBin > 0); 263 #endif 304 264 } 305 265 else if (pBin->iFree != 0) … … 315 275 } 316 276 277 DECLHIDDEN(int) IOBUFMgrCreate(PIOBUFMGR phIoBufMgr, size_t cbMax, uint32_t fFlags) 278 { 279 int rc = VINF_SUCCESS; 280 281 AssertPtrReturn(phIoBufMgr, VERR_INVALID_POINTER); 282 AssertReturn(cbMax, VERR_NOT_IMPLEMENTED); 283 284 /* Allocate the basic structure in one go. */ 285 unsigned cBins = iobufMgrGetBinCount(IOBUFMGR_BIN_SIZE_MIN, IOBUFMGR_BIN_SIZE_MAX); 286 uint32_t cObjs = iobufMgrGetObjCount(cbMax, cBins, IOBUFMGR_BIN_SIZE_MIN); 287 PIOBUFMGRINT pThis = (PIOBUFMGRINT)RTMemAllocZ(RT_OFFSETOF(IOBUFMGRINT, apvObj[cObjs]) + cBins * sizeof(IOBUFMGRBIN)); 288 if (RT_LIKELY(pThis)) 289 { 290 pThis->fFlags = fFlags; 291 pThis->cbMax = cbMax; 292 pThis->cbFree = cbMax; 293 pThis->cBins = cBins; 294 pThis->fAllocSuspended = false; 295 pThis->u32OrderMin = ASMBitLastSetU32(IOBUFMGR_BIN_SIZE_MIN) - 1; 296 pThis->u32OrderMax = ASMBitLastSetU32(IOBUFMGR_BIN_SIZE_MAX) - 1; 297 pThis->paBins = (PIOBUFMGRBIN)((uint8_t *)pThis + RT_OFFSETOF(IOBUFMGRINT, apvObj[cObjs])); 298 299 rc = RTCritSectInit(&pThis->CritSectAlloc); 300 if (RT_SUCCESS(rc)) 301 { 302 if (pThis->fFlags & IOBUFMGR_F_REQUIRE_NOT_PAGABLE) 303 rc = RTMemSaferAllocZEx(&pThis->pvMem, RT_ALIGN_Z(pThis->cbMax, _4K), 304 RTMEMSAFER_F_REQUIRE_NOT_PAGABLE); 305 else 306 pThis->pvMem = RTMemPageAllocZ(RT_ALIGN_Z(pThis->cbMax, _4K)); 307 308 if ( RT_LIKELY(pThis->pvMem) 309 && RT_SUCCESS(rc)) 310 { 311 iobufMgrResetBins(pThis); 312 313 *phIoBufMgr = pThis; 314 return VINF_SUCCESS; 315 } 316 else 317 rc = VERR_NO_MEMORY; 318 319 RTCritSectDelete(&pThis->CritSectAlloc); 320 } 321 322 RTMemFree(pThis); 323 } 324 else 325 rc = VERR_NO_MEMORY; 326 327 return rc; 328 } 329 330 DECLHIDDEN(int) IOBUFMgrDestroy(IOBUFMGR hIoBufMgr) 331 { 332 PIOBUFMGRINT pThis = hIoBufMgr; 333 334 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 335 336 int rc = RTCritSectEnter(&pThis->CritSectAlloc); 337 if (RT_SUCCESS(rc)) 338 { 339 if (pThis->cbFree == pThis->cbMax) 340 { 341 if (pThis->fFlags & IOBUFMGR_F_REQUIRE_NOT_PAGABLE) 342 RTMemSaferFree(pThis->pvMem, RT_ALIGN_Z(pThis->cbMax, _4K)); 343 else 344 RTMemPageFree(pThis->pvMem, RT_ALIGN_Z(pThis->cbMax, _4K)); 345 346 RTCritSectLeave(&pThis->CritSectAlloc); 347 RTCritSectDelete(&pThis->CritSectAlloc); 348 RTMemFree(pThis); 349 } 350 else 351 { 352 rc = VERR_INVALID_STATE; 353 RTCritSectLeave(&pThis->CritSectAlloc); 354 } 355 } 356 357 return rc; 358 } 359 317 360 DECLHIDDEN(int) IOBUFMgrAllocBuf(IOBUFMGR hIoBufMgr, PIOBUFDESC pIoBufDesc, size_t cbIoBuf, 318 361 size_t *pcbIoBufAllocated) … … 388 431 pThis->cbFree += (size_t)RT_BIT_32(u32Order); 389 432 } 433 434 if ( pThis->cbFree == pThis->cbMax 435 && pThis->fAllocSuspended) 436 { 437 iobufMgrResetBins(pThis); 438 pThis->fAllocSuspended = false; 439 } 440 390 441 RTCritSectLeave(&pThis->CritSectAlloc); 391 442 }
Note:
See TracChangeset
for help on using the changeset viewer.