aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/runtime.c29
-rw-r--r--core/runtime.h4
2 files changed, 33 insertions, 0 deletions
diff --git a/core/runtime.c b/core/runtime.c
index 4a857c7..19ff215 100644
--- a/core/runtime.c
+++ b/core/runtime.c
@@ -201,6 +201,35 @@ unsigned char *pure_runtime_ingress(PureTicket ticket, size_t *size) {
return (unsigned char *)w->resource.body.data;
}
+PureResult pure_runtime_grow(PureTicket ticket, size_t size) {
+ PureWork *w = lookup(ticket, true);
+ PureRuntime *r = ticket.runtime;
+ if (!w || r->running || w->state != RECEIVING || w->input != PURE_INPUT_WRITE || w->parent.runtime)
+ return PURE_INVALID;
+ size_t had = w->resource.body.size;
+ if (size <= had) return PURE_OK;
+ if (size - had > r->budget - r->retained) {
+ METRIC(++r->budget_rejections);
+ return PURE_BUDGET;
+ }
+ if (!r->host.allocate) return PURE_ALLOCATION;
+ PureResource grown = {0};
+ r->running = true;
+ bool ok = r->host.allocate(r->host.context, size, &grown);
+ r->running = false;
+ if (!ok || !grown.body.data || grown.body.size != size || !grown.release) {
+ dispose(r, &grown);
+ return PURE_ALLOCATION;
+ }
+ if (had) memcpy((unsigned char *)grown.body.data, w->resource.body.data, had);
+ dispose(r, &w->resource);
+ w->resource = grown;
+ w->charged += size - had;
+ r->retained += size - had;
+ METRIC(if (r->retained > r->peak_retained) r->peak_retained = r->retained);
+ return PURE_OK;
+}
+
bool pure_runtime_step(PureRuntime *r) {
if (!r || r->running || r->ready_head == NONE) return false;
#ifdef PURE_ASYNC_EFFECTS
diff --git a/core/runtime.h b/core/runtime.h
index 70f5d08..fd19525 100644
--- a/core/runtime.h
+++ b/core/runtime.h
@@ -110,6 +110,10 @@ bool pure_runtime_bind(PureRuntime *, PureWork *, size_t capacity);
PureResult pure_runtime_accept(PureRuntime *, PureInput, const char *key,
int64_t expected, size_t input_size, PureTicket *out);
unsigned char *pure_runtime_ingress(PureTicket, size_t *size);
+/* A WRITE input still being filled grows to size with its bytes kept (the
+ * ingress moves: take it again), charged to the budget as its admission was;
+ * BUDGET or ALLOCATION leave it as it was. */
+PureResult pure_runtime_grow(PureTicket, size_t size);
bool pure_runtime_ready(PureTicket);
bool pure_runtime_step(PureRuntime *); /* execute at most one ready job */
bool pure_runtime_result(PureTicket, PureOutcome *out);