Use `ssize_t` return value for `heap_quota_remaining` and `heap_claim`. In both cases we need to be able to encode error codes. `heap_quota_remaining` already does that, casting -1 into `size_t` which is not intuitive to use. Address this by using a `ssize_t` return value for both. Although this halves the sizes that we can represent, this shouldn't matter in practice because we will never have a heap that is larger than a few GBs anyways (and that already would be very large). The queue compartment is missing a return value check for `heap_claim`, leave that for later because this may require some rework in the function to gracefully handle errors. Signed-off-by: Hugo Lefeuvre <hugo.lefeuvre@scisemi.com>
diff --git a/benchmarks/allocation/alloc.cc b/benchmarks/allocation/alloc.cc index 7185f86..4f41652 100644 --- a/benchmarks/allocation/alloc.cc +++ b/benchmarks/allocation/alloc.cc
@@ -31,7 +31,7 @@ } auto end = rdcycle(); printf(__XSTRING(BOARD) "\t%ld\t%ld\n", static_cast<int>(size), end - start); - size_t quota = heap_quota_remaining(MALLOC_CAPABILITY); + auto quota = heap_quota_remaining(MALLOC_CAPABILITY); Debug::Invariant(quota == MALLOC_QUOTA, "Quota remaining {}, should be {}", quota, MALLOC_QUOTA); Debug::log("Flushing quarantine"); heap_quarantine_empty();
diff --git a/sdk/core/allocator/main.cc b/sdk/core/allocator/main.cc index 58b6ea1..29a652b 100644 --- a/sdk/core/allocator/main.cc +++ b/sdk/core/allocator/main.cc
@@ -803,7 +803,7 @@ } // namespace -__cheriot_minimum_stack(0x80) size_t +__cheriot_minimum_stack(0x80) ssize_t heap_quota_remaining(struct SObjStruct *heapCapability) { STACK_CHECK(0x80); @@ -856,7 +856,7 @@ return malloc_internal(bytes, std::move(g), cap, timeout); } -__cheriot_minimum_stack(0x1b0) size_t +__cheriot_minimum_stack(0x1b0) ssize_t heap_claim(SObj heapCapability, void *pointer) { STACK_CHECK(0x1b0);
diff --git a/sdk/include/stdlib.h b/sdk/include/stdlib.h index 6b2e069..d60e4e4 100644 --- a/sdk/include/stdlib.h +++ b/sdk/include/stdlib.h
@@ -154,7 +154,7 @@ * (if `heapCapability` or `pointer` is not valid, etc.), or `-ENOTENOUGHSTACK` * if the stack is insufficiently large to run the function. */ -size_t __cheri_compartment("alloc") +ssize_t __cheri_compartment("alloc") heap_claim(struct SObjStruct *heapCapability, void *pointer); /** @@ -211,7 +211,7 @@ * `heapCapability` is not valid or if the stack is insufficient to run the * function. */ -size_t __cheri_compartment("alloc") +ssize_t __cheri_compartment("alloc") heap_quota_remaining(struct SObjStruct *heapCapability); /**
diff --git a/sdk/lib/queue/queue_compartment.cc b/sdk/lib/queue/queue_compartment.cc index e43876b..96f4845 100644 --- a/sdk/lib/queue/queue_compartment.cc +++ b/sdk/lib/queue/queue_compartment.cc
@@ -78,6 +78,7 @@ receive->allocation = freeBuffer; // Add a second claim on the buffer so that we can free the queue by freeing // it twice, once in each endpoint. + // TODO we should check the return value of `heap_claim` heap_claim(heapCapability, freeBuffer); if (int claimed = heap_claim_fast(timeout, outQueueSend, outQueueReceive);
diff --git a/tests/allocator-test.cc b/tests/allocator-test.cc index 2a8c26a..c206f35 100644 --- a/tests/allocator-test.cc +++ b/tests/allocator-test.cc
@@ -261,20 +261,20 @@ void test_claims() { debug_log("Beginning tests on claims"); - size_t quotaLeft = heap_quota_remaining(MALLOC_CAPABILITY); + auto quotaLeft = heap_quota_remaining(MALLOC_CAPABILITY); TEST(quotaLeft == MALLOC_QUOTA, "After claim and free from {}-byte quota, {} bytes left before " "running claims tests", MALLOC_QUOTA, quotaLeft); size_t allocSize = 128; - size_t mallocQuotaLeft = heap_quota_remaining(MALLOC_CAPABILITY); + auto mallocQuotaLeft = heap_quota_remaining(MALLOC_CAPABILITY); CHERI::Capability alloc{ heap_allocate(&noWait, MALLOC_CAPABILITY, allocSize)}; TEST(alloc.is_valid(), "Allocation failed"); int claimCount = 0; auto claim = [&]() { - size_t claimSize = heap_claim(SECOND_HEAP, alloc); + ssize_t claimSize = heap_claim(SECOND_HEAP, alloc); claimCount++; TEST(claimSize == allocSize, "{}-byte allocation claimed as {} bytes (claim number {})", @@ -293,7 +293,7 @@ claim(); quotaLeft = heap_quota_remaining(SECOND_HEAP); claim(); - size_t quotaLeftAfterSecondClaim = heap_quota_remaining(SECOND_HEAP); + auto quotaLeftAfterSecondClaim = heap_quota_remaining(SECOND_HEAP); TEST(quotaLeft == quotaLeftAfterSecondClaim, "Claiming twice reduced quota from {} to {}", quotaLeft, @@ -301,7 +301,7 @@ debug_log("Freeing object on malloc capability: {}", alloc); ret = heap_free(MALLOC_CAPABILITY, alloc); TEST(ret == 0, "Failed to free claimed object, return: {}", ret); - size_t mallocQuota2 = heap_quota_remaining(MALLOC_CAPABILITY); + auto mallocQuota2 = heap_quota_remaining(MALLOC_CAPABILITY); TEST(mallocQuotaLeft == mallocQuota2, "Freeing claimed object did not restore quota to {}, quota is {}", mallocQuotaLeft, @@ -411,7 +411,8 @@ // The next test requires all memory allocated from the malloc // capability to be freed before it starts. int sleeps = 0; - while (heap_quota_remaining(MALLOC_CAPABILITY) < MALLOC_QUOTA) + while (heap_quota_remaining(MALLOC_CAPABILITY) < MALLOC_QUOTA && + heap_quota_remaining(MALLOC_CAPABILITY) > 0) { Timeout t{1}; thread_sleep(&t); @@ -538,7 +539,7 @@ TEST(ret == 0, "Heap free with the correct capability returned failed with {}.", ret); - size_t quotaLeft = heap_quota_remaining(STATIC_SEALED_VALUE(secondHeap)); + auto quotaLeft = heap_quota_remaining(STATIC_SEALED_VALUE(secondHeap)); TEST(quotaLeft == 1024, "After alloc and free from 1024-byte quota, {} bytes left", quotaLeft);
diff --git a/tests/queue-test.cc b/tests/queue-test.cc index 3b1fd05..5239f19 100644 --- a/tests/queue-test.cc +++ b/tests/queue-test.cc
@@ -104,7 +104,7 @@ void test_queue_sealed() { - size_t heapSpace = heap_quota_remaining(MALLOC_CAPABILITY); + auto heapSpace = heap_quota_remaining(MALLOC_CAPABILITY); Timeout t{1}; SObj receiveHandle; SObj sendHandle;