nodejs/deps/v8/test/mjsunit/shared-memory/mutex-async-lock-realm-disposed.js
Michaël Zasso 9d7cd9b864
deps: update V8 to 12.8.374.13
PR-URL: https://github.com/nodejs/node/pull/54077
Reviewed-By: Jiawen Geng <technicalcute@gmail.com>
Reviewed-By: Richard Lau <rlau@redhat.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
2024-08-16 16:03:01 +02:00

90 lines
3.2 KiB
JavaScript

// Copyright 2024 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Flags: --harmony-struct --allow-natives-syntax --expose-gc
// Flags: --no-lazy-compile-dispatcher --no-concurrent-recompilation
if (this.Worker) {
(function TestRealmWithAsyncWaiterDisposed() {
let workerLockScript = `onmessage = function({data:msg}) {
let {mutex, sharedObj} = msg;
Atomics.Mutex.lock(mutex, function() {
postMessage('Lock acquired');
while (!Atomics.load(sharedObj, 'done')) {
}
});
postMessage('Lock released');
};
postMessage('started');`;
let realmLockAsyncScript = `
Atomics.Mutex.lockAsync(Realm.shared.mutex, async function() {
Realm.shared.realmLocked = true;
});`;
let workerLock1 = new Worker(workerLockScript, {type: 'string'});
assertEquals('started', workerLock1.getMessage());
let workerLock2 = new Worker(workerLockScript, {type: 'string'});
assertEquals('started', workerLock2.getMessage());
let realmLockAsyc = Realm.create();
let mutex = new Atomics.Mutex;
let sharedObj = new (new SharedStructType(['done']))();
sharedObj.done = false;
let lock_msg = {mutex, sharedObj};
workerLock1.postMessage(lock_msg);
assertEquals('Lock acquired', workerLock1.getMessage());
Realm.shared = {mutex, realmLocked: false};
Realm.eval(realmLockAsyc, realmLockAsyncScript);
workerLock2.postMessage(lock_msg);
while (%AtomicsSynchronizationPrimitiveNumWaitersForTesting(mutex) !== 2) {
}
Realm.dispose(realmLockAsyc);
let collected = false;
// Cleanup the realm's native context.
gc({type: 'major', execution: 'async'})
.then(() => {collected = true}, (e) => {
throw e;
});
let executeAsserts = () => {
// The realm was disposed but the waiter node that it created is still in
// the isolate's unlocked waiters list.
assertEquals(
1, %AtomicsSychronizationNumAsyncWaitersInIsolateForTesting());
// There are still 2 waiters in the mutex queue.
assertEquals(
2, %AtomicsSynchronizationPrimitiveNumWaitersForTesting(mutex));
sharedObj.done = true;
assertEquals('Lock released', workerLock1.getMessage());
// If the async waiter was still alive, it would acquire the lock and
// set Realm.shared.realmLocked to true when we flush the microtask queue
// here.
setTimeout(() => {
// The lock was never acquired by the realm because it was destroyed.
assertFalse(Realm.shared.realmLocked)
// The async waiter notification was processed, removed itself from this
// isolate's async waiters list and notified the next worker.
assertEquals(
0, %AtomicsSychronizationNumAsyncWaitersInIsolateForTesting())
assertEquals('Lock acquired', workerLock2.getMessage());
assertEquals('Lock released', workerLock2.getMessage());
}, 0);
};
let asyncLoop = () => {
if (!collected) {
setTimeout(asyncLoop, 0);
return;
}
executeAsserts();
};
asyncLoop();
})();
}