Skip to content
File

Blob: src/workerd/io/tracked-wasm-instance.c++

3.6 KB
1// Copyright (c) 2017-2022 Cloudflare, Inc.
2// Licensed under the Apache 2.0 license found in the LICENSE file or at:
3// https://opensource.org/licenses/Apache-2.0
4 
5#include "tracked-wasm-instance.h"
6 
7namespace workerd {
8 
9kj::Maybe<TrackedWasmInstance&> TrackedWasmInstanceList::registerSignal(jsg::Lock&,
10 kj::Array<kj::byte> memory,
11 kj::Maybe<uint32_t> signalOffset,
12 kj::Maybe<uint32_t> terminatedOffset) const {
13 // At least one offset must be provided — there's nothing to register otherwise.
14 if (signalOffset == kj::none && terminatedOffset == kj::none) {
15 return kj::none;
16 }
17 
18 // If a terminated offset was provided, validate it fits in memory.
19 KJ_IF_SOME(offset, terminatedOffset) {
20 if (static_cast<size_t>(offset) + WASM_SIGNAL_FIELD_BYTES > memory.size()) {
21 return kj::none;
22 }
23 }
24 // If a signal offset was provided, validate it fits in memory too.
25 KJ_IF_SOME(offset, signalOffset) {
26 if (static_cast<size_t>(offset) + WASM_SIGNAL_FIELD_BYTES > memory.size()) {
27 return kj::none;
28 }
29 // Zero the signal address to clear any stale signals.
30 uint32_t value = 0;
31 memory.asPtr().slice(offset, offset + WASM_SIGNAL_FIELD_BYTES).copyFrom(kj::asBytes(&value, 1));
32 }
33 
34 // Safe to const_cast: the jsg::Lock& parameter proves we hold the isolate lock, which is the
35 // synchronization required by the signal-safe list for mutations.
36 auto& entry = const_cast<SignalSafeList<TrackedWasmInstance>&>(list).pushFront(
37 TrackedWasmInstance{.memory = kj::mv(memory),
38 .signalByteOffset = signalOffset,
39 .terminatedByteOffset = terminatedOffset});
40 return entry;
41}
42 
43void TrackedWasmInstanceList::filter(jsg::Lock&) const {
44 // Safe to const_cast: the jsg::Lock& parameter proves we hold the isolate lock.
45 const_cast<SignalSafeList<TrackedWasmInstance>&>(list).filter(
46 [](const TrackedWasmInstance& signal) { return signal.shouldRetain(); });
47}
48 
49void TrackedWasmInstanceList::clear(jsg::Lock&) const {
50 // Safe to const_cast: the jsg::Lock& parameter proves we hold the isolate lock.
51 const_cast<SignalSafeList<TrackedWasmInstance>&>(list).clear();
52}
53 
54void TrackedWasmInstanceList::writeShutdownSignal() const {
55 // Safe to const_cast: this is called from a signal handler on the same thread that holds the
56 // isolate lock, so there is no concurrent mutation of the list structure.
57 const_cast<SignalSafeList<TrackedWasmInstance>&>(list).iterate([](TrackedWasmInstance& signal) {
58 KJ_IF_SOME(offset, signal.signalByteOffset) {
59 uint32_t value = WASM_SIGNAL_SIGXCPU;
60 signal.memory.asPtr().slice(offset, offset + sizeof(value)).copyFrom(kj::asBytes(&value, 1));
61 }
62 });
63}
64 
65void TrackedWasmInstanceList::clearShutdownSignal() const {
66 // Safe to const_cast: same-thread signal-handler context, no concurrent list mutation.
67 const_cast<SignalSafeList<TrackedWasmInstance>&>(list).iterate([](TrackedWasmInstance& signal) {
68 KJ_IF_SOME(offset, signal.signalByteOffset) {
69 uint32_t value = 0;
70 signal.memory.asPtr().slice(offset, offset + sizeof(value)).copyFrom(kj::asBytes(&value, 1));
71 }
72 });
73}
74 
75void TrackedWasmInstanceList::writeTerminatedSignal() const {
76 // Safe to const_cast: same-thread signal-handler context, no concurrent list mutation.
77 const_cast<SignalSafeList<TrackedWasmInstance>&>(list).iterate([](TrackedWasmInstance& signal) {
78 // Skip entries that have no terminated address (signal-only modules).
79 KJ_IF_SOME(offset, signal.terminatedByteOffset) {
80 uint32_t value = 1;
81 signal.memory.asPtr().slice(offset, offset + sizeof(value)).copyFrom(kj::asBytes(&value, 1));
82 }
83 });
84}
85 
86} // namespace workerd