1 /*-------------------------------------------------------------------------
5 * Copyright (c) 2015 Google Inc.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and/or associated documentation files (the
9 * "Materials"), to deal in the Materials without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sublicense, and/or sell copies of the Materials, and to
12 * permit persons to whom the Materials are furnished to do so, subject to
13 * the following conditions:
15 * The above copyright notice(s) and this permission notice shall be
16 * included in all copies or substantial portions of the Materials.
18 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
28 * \brief Memory allocation callback utilities.
29 *//*--------------------------------------------------------------------*/
31 #include "vkAllocationCallbackUtil.hpp"
32 #include "tcuFormatUtil.hpp"
33 #include "tcuTestLog.hpp"
34 #include "deSTLUtil.hpp"
42 // System default allocator
44 static VKAPI_ATTR void* VKAPI_CALL systemAllocate (void*, size_t size, size_t alignment, VkSystemAllocationScope)
47 return deAlignedMalloc(size, (deUint32)alignment);
52 static VKAPI_ATTR void VKAPI_CALL systemFree (void*, void* pMem)
57 static VKAPI_ATTR void* VKAPI_CALL systemReallocate (void*, void* pOriginal, size_t size, size_t alignment, VkSystemAllocationScope)
59 return deAlignedRealloc(pOriginal, size, alignment);
62 static VKAPI_ATTR void VKAPI_CALL systemInternalAllocationNotification (void*, size_t, VkInternalAllocationType, VkSystemAllocationScope)
66 static VKAPI_ATTR void VKAPI_CALL systemInternalFreeNotification (void*, size_t, VkInternalAllocationType, VkSystemAllocationScope)
70 static const VkAllocationCallbacks s_systemAllocator =
76 systemInternalAllocationNotification,
77 systemInternalFreeNotification,
80 const VkAllocationCallbacks* getSystemAllocator (void)
82 return &s_systemAllocator;
85 // AllocationCallbacks
87 static VKAPI_ATTR void* VKAPI_CALL allocationCallback (void* pUserData, size_t size, size_t alignment, VkSystemAllocationScope allocationScope)
89 return reinterpret_cast<AllocationCallbacks*>(pUserData)->allocate(size, alignment, allocationScope);
92 static VKAPI_ATTR void* VKAPI_CALL reallocationCallback (void* pUserData, void* pOriginal, size_t size, size_t alignment, VkSystemAllocationScope allocationScope)
94 return reinterpret_cast<AllocationCallbacks*>(pUserData)->reallocate(pOriginal, size, alignment, allocationScope);
97 static VKAPI_ATTR void VKAPI_CALL freeCallback (void* pUserData, void* pMem)
99 reinterpret_cast<AllocationCallbacks*>(pUserData)->free(pMem);
102 static VKAPI_ATTR void VKAPI_CALL internalAllocationNotificationCallback (void* pUserData, size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope)
104 reinterpret_cast<AllocationCallbacks*>(pUserData)->notifyInternalAllocation(size, allocationType, allocationScope);
107 static VKAPI_ATTR void VKAPI_CALL internalFreeNotificationCallback (void* pUserData, size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope)
109 reinterpret_cast<AllocationCallbacks*>(pUserData)->notifyInternalFree(size, allocationType, allocationScope);
112 static VkAllocationCallbacks makeCallbacks (AllocationCallbacks* object)
114 const VkAllocationCallbacks callbacks =
116 reinterpret_cast<void*>(object),
118 reallocationCallback,
120 internalAllocationNotificationCallback,
121 internalFreeNotificationCallback
126 AllocationCallbacks::AllocationCallbacks (void)
127 : m_callbacks(makeCallbacks(this))
131 AllocationCallbacks::~AllocationCallbacks (void)
135 // AllocationCallbackRecord
137 AllocationCallbackRecord AllocationCallbackRecord::allocation (size_t size, size_t alignment, VkSystemAllocationScope scope, void* returnedPtr)
139 AllocationCallbackRecord record;
141 record.type = TYPE_ALLOCATION;
142 record.data.allocation.size = size;
143 record.data.allocation.alignment = alignment;
144 record.data.allocation.scope = scope;
145 record.data.allocation.returnedPtr = returnedPtr;
150 AllocationCallbackRecord AllocationCallbackRecord::reallocation (void* original, size_t size, size_t alignment, VkSystemAllocationScope scope, void* returnedPtr)
152 AllocationCallbackRecord record;
154 record.type = TYPE_REALLOCATION;
155 record.data.reallocation.original = original;
156 record.data.reallocation.size = size;
157 record.data.reallocation.alignment = alignment;
158 record.data.reallocation.scope = scope;
159 record.data.reallocation.returnedPtr = returnedPtr;
164 AllocationCallbackRecord AllocationCallbackRecord::free (void* mem)
166 AllocationCallbackRecord record;
168 record.type = TYPE_FREE;
169 record.data.free.mem = mem;
174 AllocationCallbackRecord AllocationCallbackRecord::internalAllocation (size_t size, VkInternalAllocationType type, VkSystemAllocationScope scope)
176 AllocationCallbackRecord record;
178 record.type = TYPE_INTERNAL_ALLOCATION;
179 record.data.internalAllocation.size = size;
180 record.data.internalAllocation.type = type;
181 record.data.internalAllocation.scope = scope;
186 AllocationCallbackRecord AllocationCallbackRecord::internalFree (size_t size, VkInternalAllocationType type, VkSystemAllocationScope scope)
188 AllocationCallbackRecord record;
190 record.type = TYPE_INTERNAL_FREE;
191 record.data.internalAllocation.size = size;
192 record.data.internalAllocation.type = type;
193 record.data.internalAllocation.scope = scope;
200 ChainedAllocator::ChainedAllocator (const VkAllocationCallbacks* nextAllocator)
201 : m_nextAllocator(nextAllocator)
205 ChainedAllocator::~ChainedAllocator (void)
209 void* ChainedAllocator::allocate (size_t size, size_t alignment, VkSystemAllocationScope allocationScope)
211 return m_nextAllocator->pfnAllocation(m_nextAllocator->pUserData, size, alignment, allocationScope);
214 void* ChainedAllocator::reallocate (void* original, size_t size, size_t alignment, VkSystemAllocationScope allocationScope)
216 return m_nextAllocator->pfnReallocation(m_nextAllocator->pUserData, original, size, alignment, allocationScope);
219 void ChainedAllocator::free (void* mem)
221 m_nextAllocator->pfnFree(m_nextAllocator->pUserData, mem);
224 void ChainedAllocator::notifyInternalAllocation (size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope)
226 m_nextAllocator->pfnInternalAllocation(m_nextAllocator->pUserData, size, allocationType, allocationScope);
229 void ChainedAllocator::notifyInternalFree (size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope)
231 m_nextAllocator->pfnInternalFree(m_nextAllocator->pUserData, size, allocationType, allocationScope);
234 // AllocationCallbackRecorder
236 AllocationCallbackRecorder::AllocationCallbackRecorder (const VkAllocationCallbacks* allocator, deUint32 callCountHint)
237 : ChainedAllocator (allocator)
238 , m_records (callCountHint)
242 AllocationCallbackRecorder::~AllocationCallbackRecorder (void)
246 void* AllocationCallbackRecorder::allocate (size_t size, size_t alignment, VkSystemAllocationScope allocationScope)
248 void* const ptr = ChainedAllocator::allocate(size, alignment, allocationScope);
250 m_records.append(AllocationCallbackRecord::allocation(size, alignment, allocationScope, ptr));
255 void* AllocationCallbackRecorder::reallocate (void* original, size_t size, size_t alignment, VkSystemAllocationScope allocationScope)
257 void* const ptr = ChainedAllocator::reallocate(original, size, alignment, allocationScope);
259 m_records.append(AllocationCallbackRecord::reallocation(original, size, alignment, allocationScope, ptr));
264 void AllocationCallbackRecorder::free (void* mem)
266 ChainedAllocator::free(mem);
268 m_records.append(AllocationCallbackRecord::free(mem));
271 void AllocationCallbackRecorder::notifyInternalAllocation (size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope)
273 ChainedAllocator::notifyInternalAllocation(size, allocationType, allocationScope);
275 m_records.append(AllocationCallbackRecord::internalAllocation(size, allocationType, allocationScope));
278 void AllocationCallbackRecorder::notifyInternalFree (size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope)
280 ChainedAllocator::notifyInternalFree(size, allocationType, allocationScope);
282 m_records.append(AllocationCallbackRecord::internalFree(size, allocationType, allocationScope));
285 // DeterministicFailAllocator
287 DeterministicFailAllocator::DeterministicFailAllocator (const VkAllocationCallbacks* allocator, deUint32 numPassingAllocs)
288 : ChainedAllocator (allocator)
289 , m_numPassingAllocs(numPassingAllocs)
290 , m_allocationNdx (0)
294 DeterministicFailAllocator::~DeterministicFailAllocator (void)
298 void* DeterministicFailAllocator::allocate (size_t size, size_t alignment, VkSystemAllocationScope allocationScope)
300 if (deAtomicIncrementUint32(&m_allocationNdx) <= m_numPassingAllocs)
301 return ChainedAllocator::allocate(size, alignment, allocationScope);
306 void* DeterministicFailAllocator::reallocate (void* original, size_t size, size_t alignment, VkSystemAllocationScope allocationScope)
308 if (deAtomicIncrementUint32(&m_allocationNdx) <= m_numPassingAllocs)
309 return ChainedAllocator::reallocate(original, size, alignment, allocationScope);
316 AllocationCallbackValidationResults::AllocationCallbackValidationResults (void)
318 deMemset(internalAllocationTotal, 0, sizeof(internalAllocationTotal));
321 void AllocationCallbackValidationResults::clear (void)
323 liveAllocations.clear();
325 deMemset(internalAllocationTotal, 0, sizeof(internalAllocationTotal));
331 struct AllocationSlot
333 AllocationCallbackRecord record;
336 AllocationSlot (void)
340 AllocationSlot (const AllocationCallbackRecord& record_, bool isLive_)
346 size_t getAlignment (const AllocationCallbackRecord& record)
348 if (record.type == AllocationCallbackRecord::TYPE_ALLOCATION)
349 return record.data.allocation.alignment;
350 else if (record.type == AllocationCallbackRecord::TYPE_REALLOCATION)
351 return record.data.reallocation.alignment;
361 void validateAllocationCallbacks (const AllocationCallbackRecorder& recorder, AllocationCallbackValidationResults* results)
363 std::vector<AllocationSlot> allocations;
364 std::map<void*, size_t> ptrToSlotIndex;
366 DE_ASSERT(results->liveAllocations.empty() && results->violations.empty());
368 for (AllocationCallbackRecorder::RecordIterator callbackIter = recorder.getRecordsBegin();
369 callbackIter != recorder.getRecordsEnd();
372 const AllocationCallbackRecord& record = *callbackIter;
376 const VkSystemAllocationScope* const scopePtr = record.type == AllocationCallbackRecord::TYPE_ALLOCATION ? &record.data.allocation.scope
377 : record.type == AllocationCallbackRecord::TYPE_REALLOCATION ? &record.data.reallocation.scope
378 : record.type == AllocationCallbackRecord::TYPE_INTERNAL_ALLOCATION ? &record.data.internalAllocation.scope
379 : record.type == AllocationCallbackRecord::TYPE_INTERNAL_FREE ? &record.data.internalAllocation.scope
382 if (scopePtr && !de::inBounds(*scopePtr, (VkSystemAllocationScope)0, VK_SYSTEM_ALLOCATION_SCOPE_LAST))
383 results->violations.push_back(AllocationCallbackViolation(record, AllocationCallbackViolation::REASON_INVALID_ALLOCATION_SCOPE));
386 // Validate alignment
387 if (record.type == AllocationCallbackRecord::TYPE_ALLOCATION ||
388 record.type == AllocationCallbackRecord::TYPE_REALLOCATION)
390 if (!deIsPowerOfTwoSize(getAlignment(record)))
391 results->violations.push_back(AllocationCallbackViolation(record, AllocationCallbackViolation::REASON_INVALID_ALIGNMENT));
394 // Validate actual allocation behavior
397 case AllocationCallbackRecord::TYPE_ALLOCATION:
399 if (record.data.allocation.returnedPtr)
401 if (!de::contains(ptrToSlotIndex, record.data.allocation.returnedPtr))
403 ptrToSlotIndex[record.data.allocation.returnedPtr] = allocations.size();
404 allocations.push_back(AllocationSlot(record, true));
408 const size_t slotNdx = ptrToSlotIndex[record.data.allocation.returnedPtr];
409 if (!allocations[slotNdx].isLive)
411 allocations[slotNdx].isLive = true;
412 allocations[slotNdx].record = record;
416 // we should not have multiple live allocations with the same pointer
425 case AllocationCallbackRecord::TYPE_REALLOCATION:
427 if (de::contains(ptrToSlotIndex, record.data.reallocation.original))
429 const size_t origSlotNdx = ptrToSlotIndex[record.data.reallocation.original];
430 AllocationSlot& origSlot = allocations[origSlotNdx];
432 DE_ASSERT(record.data.reallocation.original != DE_NULL);
434 if (record.data.reallocation.size > 0)
436 if (getAlignment(origSlot.record) != record.data.reallocation.alignment)
437 results->violations.push_back(AllocationCallbackViolation(record, AllocationCallbackViolation::REASON_REALLOC_DIFFERENT_ALIGNMENT));
439 if (record.data.reallocation.original == record.data.reallocation.returnedPtr)
441 if (!origSlot.isLive)
443 results->violations.push_back(AllocationCallbackViolation(record, AllocationCallbackViolation::REASON_REALLOC_FREED_PTR));
444 origSlot.isLive = true; // Mark live to suppress further errors
447 // Just update slot record
448 allocations[origSlotNdx].record = record;
452 if (record.data.reallocation.returnedPtr)
454 allocations[origSlotNdx].isLive = false;
455 if (!de::contains(ptrToSlotIndex, record.data.reallocation.returnedPtr))
457 ptrToSlotIndex[record.data.reallocation.returnedPtr] = allocations.size();
458 allocations.push_back(AllocationSlot(record, true));
462 const size_t slotNdx = ptrToSlotIndex[record.data.reallocation.returnedPtr];
463 if (!allocations[slotNdx].isLive)
465 allocations[slotNdx].isLive = true;
466 allocations[slotNdx].record = record;
470 // we should not have multiple live allocations with the same pointer
475 // else original ptr remains valid and live
480 DE_ASSERT(!record.data.reallocation.returnedPtr);
482 origSlot.isLive = false;
487 if (record.data.reallocation.original)
488 results->violations.push_back(AllocationCallbackViolation(record, AllocationCallbackViolation::REASON_REALLOC_NOT_ALLOCATED_PTR));
490 if (record.data.reallocation.returnedPtr)
492 DE_ASSERT(!de::contains(ptrToSlotIndex, record.data.reallocation.returnedPtr));
493 ptrToSlotIndex[record.data.reallocation.returnedPtr] = allocations.size();
494 allocations.push_back(AllocationSlot(record, true));
501 case AllocationCallbackRecord::TYPE_FREE:
503 if (record.data.free.mem != DE_NULL) // Freeing null pointer is valid and ignored
505 if (de::contains(ptrToSlotIndex, record.data.free.mem))
507 const size_t slotNdx = ptrToSlotIndex[record.data.free.mem];
509 if (allocations[slotNdx].isLive)
510 allocations[slotNdx].isLive = false;
512 results->violations.push_back(AllocationCallbackViolation(record, AllocationCallbackViolation::REASON_DOUBLE_FREE));
515 results->violations.push_back(AllocationCallbackViolation(record, AllocationCallbackViolation::REASON_FREE_NOT_ALLOCATED_PTR));
521 case AllocationCallbackRecord::TYPE_INTERNAL_ALLOCATION:
522 case AllocationCallbackRecord::TYPE_INTERNAL_FREE:
524 if (de::inBounds(record.data.internalAllocation.type, (VkInternalAllocationType)0, VK_INTERNAL_ALLOCATION_TYPE_LAST))
526 size_t* const totalAllocSizePtr = &results->internalAllocationTotal[record.data.internalAllocation.type][record.data.internalAllocation.scope];
527 const size_t size = record.data.internalAllocation.size;
529 if (record.type == AllocationCallbackRecord::TYPE_INTERNAL_FREE)
531 if (*totalAllocSizePtr < size)
533 results->violations.push_back(AllocationCallbackViolation(record, AllocationCallbackViolation::REASON_NEGATIVE_INTERNAL_ALLOCATION_TOTAL));
534 *totalAllocSizePtr = 0; // Reset to 0 to suppress compound errors
537 *totalAllocSizePtr -= size;
540 *totalAllocSizePtr += size;
543 results->violations.push_back(AllocationCallbackViolation(record, AllocationCallbackViolation::REASON_INVALID_INTERNAL_ALLOCATION_TYPE));
553 DE_ASSERT(!de::contains(ptrToSlotIndex, DE_NULL));
555 // Collect live allocations
556 for (std::vector<AllocationSlot>::const_iterator slotIter = allocations.begin();
557 slotIter != allocations.end();
560 if (slotIter->isLive)
561 results->liveAllocations.push_back(slotIter->record);
565 bool checkAndLog (tcu::TestLog& log, const AllocationCallbackValidationResults& results, deUint32 allowedLiveAllocScopeBits)
571 if (!results.violations.empty())
573 for (size_t violationNdx = 0; violationNdx < results.violations.size(); ++violationNdx)
575 log << TestLog::Message << "VIOLATION " << (violationNdx+1)
576 << ": " << results.violations[violationNdx]
577 << " (" << results.violations[violationNdx].record << ")"
578 << TestLog::EndMessage;
581 log << TestLog::Message << "ERROR: Found " << results.violations.size() << " invalid allocation callbacks!" << TestLog::EndMessage;
584 // Verify live allocations
585 for (size_t liveNdx = 0; liveNdx < results.liveAllocations.size(); ++liveNdx)
587 const AllocationCallbackRecord& record = results.liveAllocations[liveNdx];
588 const VkSystemAllocationScope scope = record.type == AllocationCallbackRecord::TYPE_ALLOCATION ? record.data.allocation.scope
589 : record.type == AllocationCallbackRecord::TYPE_REALLOCATION ? record.data.reallocation.scope
590 : VK_SYSTEM_ALLOCATION_SCOPE_LAST;
592 DE_ASSERT(de::inBounds(scope, (VkSystemAllocationScope)0, VK_SYSTEM_ALLOCATION_SCOPE_LAST));
594 if ((allowedLiveAllocScopeBits & (1u << scope)) == 0)
596 log << TestLog::Message << "LEAK " << (numLeaks+1) << ": " << record << TestLog::EndMessage;
601 // Verify internal allocations
602 for (int internalAllocTypeNdx = 0; internalAllocTypeNdx < VK_INTERNAL_ALLOCATION_TYPE_LAST; ++internalAllocTypeNdx)
604 for (int scopeNdx = 0; scopeNdx < VK_SYSTEM_ALLOCATION_SCOPE_LAST; ++scopeNdx)
606 const VkInternalAllocationType type = (VkInternalAllocationType)internalAllocTypeNdx;
607 const VkSystemAllocationScope scope = (VkSystemAllocationScope)scopeNdx;
608 const size_t totalAllocated = results.internalAllocationTotal[type][scope];
610 if ((allowedLiveAllocScopeBits & (1u << scopeNdx)) == 0 &&
613 log << TestLog::Message << "LEAK " << (numLeaks+1) << ": " << totalAllocated
614 << " bytes of (" << type << ", " << scope << ") internal memory is still allocated"
615 << TestLog::EndMessage;
622 log << TestLog::Message << "ERROR: Found " << numLeaks << " memory leaks!" << TestLog::EndMessage;
624 return results.violations.empty() && numLeaks == 0;
627 bool validateAndLog (tcu::TestLog& log, const AllocationCallbackRecorder& recorder, deUint32 allowedLiveAllocScopeBits)
629 AllocationCallbackValidationResults validationResults;
631 validateAllocationCallbacks(recorder, &validationResults);
633 return checkAndLog(log, validationResults, allowedLiveAllocScopeBits);
636 std::ostream& operator<< (std::ostream& str, const AllocationCallbackRecord& record)
640 case AllocationCallbackRecord::TYPE_ALLOCATION:
641 str << "ALLOCATION: size=" << record.data.allocation.size
642 << ", alignment=" << record.data.allocation.alignment
643 << ", scope=" << record.data.allocation.scope
644 << ", returnedPtr=" << tcu::toHex(record.data.allocation.returnedPtr);
647 case AllocationCallbackRecord::TYPE_REALLOCATION:
648 str << "REALLOCATION: original=" << tcu::toHex(record.data.reallocation.original)
649 << ", size=" << record.data.reallocation.size
650 << ", alignment=" << record.data.reallocation.alignment
651 << ", scope=" << record.data.reallocation.scope
652 << ", returnedPtr=" << tcu::toHex(record.data.reallocation.returnedPtr);
655 case AllocationCallbackRecord::TYPE_FREE:
656 str << "FREE: mem=" << tcu::toHex(record.data.free.mem);
659 case AllocationCallbackRecord::TYPE_INTERNAL_ALLOCATION:
660 case AllocationCallbackRecord::TYPE_INTERNAL_FREE:
661 str << "INTERNAL_" << (record.type == AllocationCallbackRecord::TYPE_INTERNAL_ALLOCATION ? "ALLOCATION" : "FREE")
662 << ": size=" << record.data.internalAllocation.size
663 << ", type=" << record.data.internalAllocation.type
664 << ", scope=" << record.data.internalAllocation.scope;
674 std::ostream& operator<< (std::ostream& str, const AllocationCallbackViolation& violation)
676 switch (violation.reason)
678 case AllocationCallbackViolation::REASON_DOUBLE_FREE:
680 DE_ASSERT(violation.record.type == AllocationCallbackRecord::TYPE_FREE);
681 str << "Double free of " << tcu::toHex(violation.record.data.free.mem);
685 case AllocationCallbackViolation::REASON_FREE_NOT_ALLOCATED_PTR:
687 DE_ASSERT(violation.record.type == AllocationCallbackRecord::TYPE_FREE);
688 str << "Attempt to free " << tcu::toHex(violation.record.data.free.mem) << " which has not been allocated";
692 case AllocationCallbackViolation::REASON_REALLOC_NOT_ALLOCATED_PTR:
694 DE_ASSERT(violation.record.type == AllocationCallbackRecord::TYPE_REALLOCATION);
695 str << "Attempt to reallocate " << tcu::toHex(violation.record.data.reallocation.original) << " which has not been allocated";
699 case AllocationCallbackViolation::REASON_REALLOC_FREED_PTR:
701 DE_ASSERT(violation.record.type == AllocationCallbackRecord::TYPE_REALLOCATION);
702 str << "Attempt to reallocate " << tcu::toHex(violation.record.data.reallocation.original) << " which has been freed";
706 case AllocationCallbackViolation::REASON_NEGATIVE_INTERNAL_ALLOCATION_TOTAL:
708 DE_ASSERT(violation.record.type == AllocationCallbackRecord::TYPE_INTERNAL_FREE);
709 str << "Internal allocation total for (" << violation.record.data.internalAllocation.type << ", " << violation.record.data.internalAllocation.scope << ") is negative";
713 case AllocationCallbackViolation::REASON_INVALID_INTERNAL_ALLOCATION_TYPE:
715 DE_ASSERT(violation.record.type == AllocationCallbackRecord::TYPE_INTERNAL_ALLOCATION ||
716 violation.record.type == AllocationCallbackRecord::TYPE_INTERNAL_FREE);
717 str << "Invalid internal allocation type " << tcu::toHex(violation.record.data.internalAllocation.type);
721 case AllocationCallbackViolation::REASON_INVALID_ALLOCATION_SCOPE:
723 str << "Invalid allocation scope";
727 case AllocationCallbackViolation::REASON_INVALID_ALIGNMENT:
729 str << "Invalid alignment";
733 case AllocationCallbackViolation::REASON_REALLOC_DIFFERENT_ALIGNMENT:
735 str << "Reallocation with different alignment";