|
11 | 11 | #include <iostream>
|
12 | 12 | #include <cassert>
|
13 | 13 | #include <cstring>
|
| 14 | +#include <algorithm> |
14 | 15 |
|
15 | 16 | #include "globals.h"
|
16 | 17 |
|
@@ -44,25 +45,55 @@ get_min_stk_size(size_t default_size) {
|
44 | 45 | }
|
45 | 46 | }
|
46 | 47 |
|
| 48 | +static size_t |
| 49 | +get_next_stk_size(rust_scheduler *sched, rust_task *task, |
| 50 | + size_t min, size_t current, size_t requested) { |
| 51 | + LOG(task, mem, "calculating new stack size for 0x%" PRIxPTR, task); |
| 52 | + LOG(task, mem, |
| 53 | + "min: %" PRIdPTR " current: %" PRIdPTR " requested: %" PRIdPTR, |
| 54 | + min, current, requested); |
| 55 | + |
| 56 | + // Allocate at least enough to accomodate the next frame |
| 57 | + size_t sz = std::max(min, requested); |
| 58 | + |
| 59 | + // And double the stack size each allocation |
| 60 | + const size_t max = 1024 * 1024; |
| 61 | + size_t next = std::min(max, current * 2); |
| 62 | + |
| 63 | + sz = std::max(sz, next); |
| 64 | + |
| 65 | + LOG(task, mem, "next stack size: %" PRIdPTR, sz); |
| 66 | + return sz; |
| 67 | +} |
47 | 68 |
|
48 | 69 | // Task stack segments. Heap allocated and chained together.
|
49 | 70 |
|
50 | 71 | static stk_seg*
|
51 |
| -new_stk(rust_scheduler *sched, rust_task *task, size_t minsz) |
| 72 | +new_stk(rust_scheduler *sched, rust_task *task, size_t requested_sz) |
52 | 73 | {
|
53 |
| - size_t min_stk_bytes = get_min_stk_size(sched->min_stack_size); |
54 |
| - if (minsz < min_stk_bytes) |
55 |
| - minsz = min_stk_bytes; |
56 |
| - size_t sz = sizeof(stk_seg) + minsz + RED_ZONE_SIZE; |
| 74 | + // The minimum stack size, in bytes, of a Rust stack, excluding red zone |
| 75 | + size_t min_sz = get_min_stk_size(sched->min_stack_size); |
| 76 | + // The size of the current stack segment, excluding red zone |
| 77 | + size_t current_sz = 0; |
| 78 | + if (task->stk != NULL) { |
| 79 | + current_sz = (size_t)(task->stk->end |
| 80 | + - (uintptr_t)&task->stk->data[0] |
| 81 | + - RED_ZONE_SIZE); |
| 82 | + } |
| 83 | + // The calculated size of the new stack, excluding red zone |
| 84 | + size_t rust_stk_sz = get_next_stk_size(sched, task, min_sz, |
| 85 | + current_sz, requested_sz); |
| 86 | + |
| 87 | + size_t sz = sizeof(stk_seg) + rust_stk_sz + RED_ZONE_SIZE; |
57 | 88 | stk_seg *stk = (stk_seg *)task->malloc(sz, "stack");
|
58 | 89 | LOGPTR(task->sched, "new stk", (uintptr_t)stk);
|
59 | 90 | memset(stk, 0, sizeof(stk_seg));
|
60 | 91 | stk->next = task->stk;
|
61 |
| - stk->end = (uintptr_t) &stk->data[minsz + RED_ZONE_SIZE]; |
| 92 | + stk->end = (uintptr_t) &stk->data[rust_stk_sz + RED_ZONE_SIZE]; |
62 | 93 | LOGPTR(task->sched, "stk end", stk->end);
|
63 | 94 | stk->valgrind_id =
|
64 | 95 | VALGRIND_STACK_REGISTER(&stk->data[0],
|
65 |
| - &stk->data[minsz + RED_ZONE_SIZE]); |
| 96 | + &stk->data[rust_stk_sz + RED_ZONE_SIZE]); |
66 | 97 | #ifndef NVALGRIND
|
67 | 98 | VALGRIND_MAKE_MEM_NOACCESS(stk->data, STACK_NOACCESS_SIZE);
|
68 | 99 | #endif
|
|
0 commit comments