From 2deef79a527218dd362d29682a54ddccbc026f7a Mon Sep 17 00:00:00 2001 From: Nidin Vinayakan <01@01alchemist.com> Date: Sat, 17 Nov 2018 09:29:06 +0100 Subject: [PATCH 1/4] Wait wake feature added --- examples/atomic-wait-wake/assembly/index.js | 23 ++++ examples/atomic-wait-wake/assembly/index.ts | 13 ++ .../atomic-wait-wake/assembly/tsconfig.json | 6 + examples/atomic-wait-wake/build/index.js | 8 ++ examples/atomic-wait-wake/index.html | 108 ++++++++++++++++ examples/atomic-wait-wake/js/worker1.js | 17 +++ examples/atomic-wait-wake/js/worker2.js | 19 +++ examples/atomic-wait-wake/package.json | 16 +++ src/builtins.ts | 117 +++++++++++++++++- std/assembly/builtins.ts | 6 + std/assembly/index.d.ts | 6 + tests/compiler.shared-memory/builtins.ts | 1 - 12 files changed, 334 insertions(+), 6 deletions(-) create mode 100644 examples/atomic-wait-wake/assembly/index.js create mode 100644 examples/atomic-wait-wake/assembly/index.ts create mode 100644 examples/atomic-wait-wake/assembly/tsconfig.json create mode 100644 examples/atomic-wait-wake/build/index.js create mode 100644 examples/atomic-wait-wake/index.html create mode 100644 examples/atomic-wait-wake/js/worker1.js create mode 100644 examples/atomic-wait-wake/js/worker2.js create mode 100644 examples/atomic-wait-wake/package.json diff --git a/examples/atomic-wait-wake/assembly/index.js b/examples/atomic-wait-wake/assembly/index.js new file mode 100644 index 0000000000..5621c90d80 --- /dev/null +++ b/examples/atomic-wait-wake/assembly/index.js @@ -0,0 +1,23 @@ +const fs = require("fs"); +const path = require("path"); + +const compiled = new WebAssembly.Module( + fs.readFileSync(path.resolve(__dirname, "..", "build", "atomic.builtins.wasm")) +); +const memory = new WebAssembly.Memory({ + initial: 256, + maximum: 256, + shared: true +}) +const imports = { + env: { + memory, + abort: (filename, line, column) => { + throw Error("abort called at " + line + ":" + colum); + } + } +}; + +Object.defineProperty(module, "exports", { + get: () => new WebAssembly.Instance(compiled, imports).exports +}); diff --git a/examples/atomic-wait-wake/assembly/index.ts b/examples/atomic-wait-wake/assembly/index.ts new file mode 100644 index 0000000000..6343d6501a --- /dev/null +++ b/examples/atomic-wait-wake/assembly/index.ts @@ -0,0 +1,13 @@ +declare function log(v: i32): void; + +export function wait(): void { + // Atomic.wait(0, 1, 1000); + Atomic.wait(8, 1, -1); + log(1); +} + +// export function wake(): void { +// // Atomic.wake(0, 1); +// Atomic.wake(8, 1); +// log(2); +// } diff --git a/examples/atomic-wait-wake/assembly/tsconfig.json b/examples/atomic-wait-wake/assembly/tsconfig.json new file mode 100644 index 0000000000..449ca07c76 --- /dev/null +++ b/examples/atomic-wait-wake/assembly/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "../../../std/assembly.json", + "include": [ + "./**/*.ts" + ] +} \ No newline at end of file diff --git a/examples/atomic-wait-wake/build/index.js b/examples/atomic-wait-wake/build/index.js new file mode 100644 index 0000000000..0870226f6f --- /dev/null +++ b/examples/atomic-wait-wake/build/index.js @@ -0,0 +1,8 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("allocator/arena"); +let str = "A"; +function read() { + return str; +} +exports.read = read; diff --git a/examples/atomic-wait-wake/index.html b/examples/atomic-wait-wake/index.html new file mode 100644 index 0000000000..ea6563e2a7 --- /dev/null +++ b/examples/atomic-wait-wake/index.html @@ -0,0 +1,108 @@ + + + + Shared Memory - AssemblyScript + + + + + + +

+ Shared Memory in + AssemblyScript ( + source + ) +

+ + + diff --git a/examples/atomic-wait-wake/js/worker1.js b/examples/atomic-wait-wake/js/worker1.js new file mode 100644 index 0000000000..581a1b952a --- /dev/null +++ b/examples/atomic-wait-wake/js/worker1.js @@ -0,0 +1,17 @@ +addEventListener("message", onMessageReceived, false); +let memory = null; +let i32 = null; +function onMessageReceived(e) { + try { + const data = e.data; + switch (data.command) { + case "init": { + memory = data.memory; + i32 = new Int32Array(memory.buffer); + console.log("Waiting", i32[0]); + Atomics.wait(i32, 0, 0); + console.log("Waken", i32[0]); + } + } + } catch (e) {} +} diff --git a/examples/atomic-wait-wake/js/worker2.js b/examples/atomic-wait-wake/js/worker2.js new file mode 100644 index 0000000000..d5bafc2b2c --- /dev/null +++ b/examples/atomic-wait-wake/js/worker2.js @@ -0,0 +1,19 @@ +addEventListener("message", onMessageReceived, false); +let memory = null; +let i32 = null; +function onMessageReceived(e) { + try { + const data = e.data; + switch (data.command) { + case "init": { + memory = data.memory; + i32 = new Int32Array(memory.buffer); + Atomics.store(i32, 0, 123); + console.log("Stored", 123); + setTimeout(() => { + Atomics.wake(i32, 0, 1); + }, 2000); + } + } + } catch (e) {} +} diff --git a/examples/atomic-wait-wake/package.json b/examples/atomic-wait-wake/package.json new file mode 100644 index 0000000000..6bb4f6c435 --- /dev/null +++ b/examples/atomic-wait-wake/package.json @@ -0,0 +1,16 @@ +{ + "name": "@assemblyscript/shared-memory-example", + "version": "1.0.0", + "private": true, + "scripts": { + "asbuild:untouched": "asc assembly/index.ts -b build/untouched.wasm -t build/untouched.wat --sourceMap --importMemory --sharedMemory=256 --validate", + "asbuild:optimized": "asc assembly/index.ts -b build/optimized.wasm -t build/optimized.wat -O3 --importMemory --sharedMemory=256 --validate --noDebug --noAssert", + "asbuild": "npm run asbuild:untouched && npm run asbuild:optimized", + "build": "npm run asbuild", + "server": "http-server . -o -c-1", + "test": "node tests" + }, + "devDependencies": { + "http-server": "^0.11.1" + } +} diff --git a/src/builtins.ts b/src/builtins.ts index 4cd1742dd3..4f91c65265 100644 --- a/src/builtins.ts +++ b/src/builtins.ts @@ -1942,6 +1942,114 @@ export function compileCall( typeArguments[0].byteSize, offset, arg0, arg1, arg2, type.toNativeType() ); } + case "Atomic.wait": { // wait(ptr: usize, expected:T, timeout: i64): i32; + let hasError = typeArguments == null; + if (operands.length != 3) { + compiler.error( + DiagnosticCode.Expected_0_arguments_but_got_1, + reportNode.range, "3", operands.length.toString(10) + ); + hasError = true; + } + if (!(typeArguments && typeArguments.length == 1)) { + compiler.error( + DiagnosticCode.Expected_0_type_arguments_but_got_1, + reportNode.range, "1", typeArguments ? typeArguments.length.toString(10) : "0" + ); + hasError = true; + } + + if (!typeArguments || hasError) { + return module.createUnreachable(); + } + + arg0 = compiler.compileExpression( + operands[0], + compiler.options.usizeType, + ConversionKind.IMPLICIT, + WrapMode.NONE + ); + arg1 = compiler.compileExpression( + operands[1], + typeArguments[0], + typeArguments[0].is(TypeFlags.INTEGER) + ? ConversionKind.NONE // no need to convert to small int (but now might result in a float) + : ConversionKind.IMPLICIT, + WrapMode.NONE + ); + arg2 = compiler.compileExpression( + operands[2], + Type.i64, + ConversionKind.IMPLICIT, + WrapMode.NONE + ); + + let type: Type = typeArguments[0]; + if ( + typeArguments[0].is(TypeFlags.INTEGER) && + ( + !compiler.currentType.is(TypeFlags.INTEGER) || // float to int + compiler.currentType.size < typeArguments[0].size // int to larger int (clear garbage bits) + ) + ) { + arg1 = compiler.convertExpression( + arg1, + compiler.currentType, typeArguments[0], + ConversionKind.IMPLICIT, + WrapMode.NONE, // still clears garbage bits + operands[1] + ); + arg2 = compiler.convertExpression( + arg2, + compiler.currentType, typeArguments[0], + ConversionKind.IMPLICIT, + WrapMode.NONE, // still clears garbage bits + operands[2] + ); + } + + return module.createAtomicWait( + arg0, arg1, arg2, type.toNativeType() + ); + } + case "Atomic.wake": { // wake(ptr: usize, count: u32): u32; + let hasError = typeArguments == null; + if (operands.length != 2) { + compiler.error( + DiagnosticCode.Expected_0_arguments_but_got_1, + reportNode.range, "2", operands.length.toString(10) + ); + hasError = true; + } + if (!(typeArguments && typeArguments.length == 1)) { + compiler.error( + DiagnosticCode.Expected_0_type_arguments_but_got_1, + reportNode.range, "1", typeArguments ? typeArguments.length.toString(10) : "0" + ); + hasError = true; + } + + if (!typeArguments || hasError) { + return module.createUnreachable(); + } + + arg0 = compiler.compileExpression( + operands[0], + compiler.options.usizeType, + ConversionKind.IMPLICIT, + WrapMode.NONE + ); + arg1 = compiler.compileExpression( + operands[1], + Type.i32, + ConversionKind.IMPLICIT, + WrapMode.NONE + ); + + return module.createAtomicWake( + arg0, arg1 + ); + } case "sizeof": { // sizeof() -> usize compiler.currentType = compiler.options.usizeType; if (operands.length != 0) { @@ -3159,11 +3267,10 @@ function deferASMCall( case "i64.atomic.rmw32_u.cmpxchg": return deferASM("Atomic.cmpxchg", compiler, Type.u32, operands, Type.u64, reportNode); case "i64.atomic.rmw.cmpxchg": return deferASM("Atomic.cmpxchg", compiler, Type.u64, operands, Type.u64, reportNode); - // TODO: wait - wake postponed to next version - // case "i32.atomic.wait": return deferASM("Atomic.wait", compiler, Type.u32, operands, Type.u32, reportNode); - // case "i64.atomic.wait": return deferASM("Atomic.wait", compiler, Type.u64, operands, Type.u64, reportNode); - // case "i32.atomic.wake": return deferASM("Atomic.wake", compiler, Type.u32, operands, Type.u32, reportNode); - // case "i64.atomic.wake": return deferASM("Atomic.wake", compiler, Type.u32, operands, Type.u32, reportNode); + case "i32.atomic.wait": return deferASM("Atomic.wait", compiler, Type.u32, operands, Type.u32, reportNode); + case "i64.atomic.wait": return deferASM("Atomic.wait", compiler, Type.u64, operands, Type.u64, reportNode); + case "i32.atomic.wake": return deferASM("Atomic.wake", compiler, Type.u32, operands, Type.u32, reportNode); + case "i64.atomic.wake": return deferASM("Atomic.wake", compiler, Type.u32, operands, Type.u32, reportNode); } return 0; } diff --git a/std/assembly/builtins.ts b/std/assembly/builtins.ts index ad926fcdad..4f70d9ef17 100644 --- a/std/assembly/builtins.ts +++ b/std/assembly/builtins.ts @@ -52,6 +52,8 @@ export namespace Atomic { @builtin export declare function xor(ptr: usize, value: T, constantOffset?: usize): T; @builtin export declare function xchg(ptr: usize, value: T, constantOffset?: usize): T; @builtin export declare function cmpxchg(ptr: usize, expected:T, replacement: T, constantOffset?: usize): T; + @builtin export declare function wait(ptr: usize, expected:T, timeout:i64): i32; + @builtin export declare function wake(ptr: usize, count: u32): u32; } @builtin export declare function i8(value: void): i8; @@ -100,6 +102,8 @@ export namespace i32 { @builtin export declare function store8(offset: usize, value: i32, constantOffset?: usize): void; @builtin export declare function store16(offset: usize, value: i32, constantOffset?: usize): void; @builtin export declare function store(offset: usize, value: i32, constantOffset?: usize): void; + @builtin export declare function wait(ptr: usize, expected:i32, timeout:i64): i32; + @builtin export declare function wake(ptr: usize, count:u32): u32; namespace rmw8_u { @builtin export declare function add(offset: usize, value: i32, constantOffset?: usize): i32 @@ -166,6 +170,8 @@ export namespace i64 { @builtin export declare function store8(offset: usize, value: i64, constantOffset?: usize): void; @builtin export declare function store16(offset: usize, value: i64, constantOffset?: usize): void; @builtin export declare function store(offset: usize, value: i64, constantOffset?: usize): void; + @builtin export declare function wait(ptr: usize, expected:i64, timeout:i64): i32; + @builtin export declare function wake(ptr: usize, count:u32): u32; namespace rmw8_u { @builtin export declare function add(offset: usize, value: i64, constantOffset?: usize): i64 diff --git a/std/assembly/index.d.ts b/std/assembly/index.d.ts index 96cde24567..672e9cccca 100644 --- a/std/assembly/index.d.ts +++ b/std/assembly/index.d.ts @@ -239,6 +239,9 @@ declare namespace i32 { export function store16(offset: usize, value: i32, constantOffset?: usize): void; /** Atomically stores a 32-bit integer to memory. */ export function store(offset: usize, value: i32, constantOffset?: usize): void; + + export function wait(offset: usize, value: i32, timeout: i64): i32; + export function wake(offset: usize, count: u32): u32; namespace rmw8_u { export function add(offset: usize, value: i32, constantOffset?: usize): i32 @@ -328,6 +331,9 @@ declare namespace i64 { export function store32(offset: usize, value: i64, constantOffset?: usize): void; /** Atomically stores a 64-bit integer to memory. */ export function store(offset: usize, value: i64, constantOffset?: usize): void; + + export function wait(offset: usize, value: i64, timeout: i64): i32; + export function wake(offset: usize, count: u32): u32; namespace rmw8_u { export function add(offset: usize, value: i64, constantOffset?: usize): i64 diff --git a/tests/compiler.shared-memory/builtins.ts b/tests/compiler.shared-memory/builtins.ts index f3e35a1688..36e6804611 100644 --- a/tests/compiler.shared-memory/builtins.ts +++ b/tests/compiler.shared-memory/builtins.ts @@ -12,7 +12,6 @@ Atomic.store(2, 16); Atomic.store(4, 32); Atomic.store(8, 64); - // Atomic load i = Atomic.load(0); i = Atomic.load(2); From ff102b5d8a4366e1433d82e532b681629d39f9fa Mon Sep 17 00:00:00 2001 From: Nidin Vinayakan <01@01alchemist.com> Date: Thu, 29 Nov 2018 14:39:36 +0100 Subject: [PATCH 2/4] Atomic wait wake example updated --- examples/atomic-wait-wake/assembly/index.ts | 11 +-- .../atomic-wait-wake/assembly/index_32.ts | 27 ++++++ .../atomic-wait-wake/assembly/index_64.ts | 27 ++++++ examples/atomic-wait-wake/index.html | 88 +++++++++++-------- examples/atomic-wait-wake/js/worker1.js | 81 +++++++++++++++-- examples/atomic-wait-wake/js/worker2.js | 4 +- examples/atomic-wait-wake/package.json | 2 +- src/builtins.ts | 8 +- std/assembly/index.d.ts | 8 +- 9 files changed, 196 insertions(+), 60 deletions(-) create mode 100644 examples/atomic-wait-wake/assembly/index_32.ts create mode 100644 examples/atomic-wait-wake/assembly/index_64.ts diff --git a/examples/atomic-wait-wake/assembly/index.ts b/examples/atomic-wait-wake/assembly/index.ts index 6343d6501a..f6a8c78009 100644 --- a/examples/atomic-wait-wake/assembly/index.ts +++ b/examples/atomic-wait-wake/assembly/index.ts @@ -1,13 +1,4 @@ -declare function log(v: i32): void; export function wait(): void { - // Atomic.wait(0, 1, 1000); - Atomic.wait(8, 1, -1); - log(1); + Atomic.wait(0, 0, -1); } - -// export function wake(): void { -// // Atomic.wake(0, 1); -// Atomic.wake(8, 1); -// log(2); -// } diff --git a/examples/atomic-wait-wake/assembly/index_32.ts b/examples/atomic-wait-wake/assembly/index_32.ts new file mode 100644 index 0000000000..97fecab030 --- /dev/null +++ b/examples/atomic-wait-wake/assembly/index_32.ts @@ -0,0 +1,27 @@ +import "allocator/atomic"; +import { itoa } from "internal/number"; + +declare function log(v: i32): void; +declare function logi64(v: i64): void; +declare function log_str(v: string): void; + +var id = 1; + +export function setId(_id: i32): void { + id = _id; +} + +export function wait(mutexAddr: i32 = 0, value: i32 = 1): void { + log_str('[WASM][' + itoa(id) + '] waiting...'); + Atomic.store(mutexAddr, value); + Atomic.wait(mutexAddr, value, -1); + // logi64(result); + log_str('[WASM][' + itoa(id) + '] waken'); +} + +export function wake(mutexAddr: i32 = 0, value: i32 = 0, numAgents: i32 = 1): void { + log_str('[WASM][' + itoa(id) + '] waking '+ itoa(numAgents) + ' agent(s)...'); + Atomic.store(mutexAddr, value); + var count = Atomic.wake(mutexAddr, numAgents); + log_str('[WASM][' + itoa(id) + '] waken ' + itoa(count) + ' agent(s)'); +} diff --git a/examples/atomic-wait-wake/assembly/index_64.ts b/examples/atomic-wait-wake/assembly/index_64.ts new file mode 100644 index 0000000000..5b0fe081c3 --- /dev/null +++ b/examples/atomic-wait-wake/assembly/index_64.ts @@ -0,0 +1,27 @@ +// import "allocator/atomic"; +// import { itoa } from "internal/number"; + +declare function log(v: i32): void; +declare function logi64(v: i64): void; +declare function log_str(v: string): void; + +var id = 1; + +export function setId(_id: i32): void { + id = _id; +} + +export function wait_i64(mutexAddr: i32 = 0, value: i64 = 1): void { + // log_str('[WASM][' + itoa(id) + '] waiting...'); + Atomic.store(mutexAddr, value); + Atomic.wait(mutexAddr, value, -1); + // logi64(result); + // log_str('[WASM][' + itoa(id) + '] waken'); +} + +export function wake_i64(mutexAddr: i32 = 0, value: i64 = 0, numAgents: i32 = 1): void { + // log_str('[WASM][' + itoa(id) + '] waking '+ itoa(numAgents) + ' agent(s)...'); + // Atomic.store(mutexAddr, value); + // var count = Atomic.wake(mutexAddr, numAgents); + // log_str('[WASM][' + itoa(id) + '] waken ' + itoa(count) + ' agent(s)'); +} diff --git a/examples/atomic-wait-wake/index.html b/examples/atomic-wait-wake/index.html index ea6563e2a7..6a18973971 100644 --- a/examples/atomic-wait-wake/index.html +++ b/examples/atomic-wait-wake/index.html @@ -1,7 +1,7 @@ - Shared Memory - AssemblyScript + Atomic wait wake - AssemblyScript

- Shared Memory in + Atomic wait wake in AssemblyScript ( source ) +

+
Open console to results
diff --git a/examples/atomic-wait-wake/js/worker1.js b/examples/atomic-wait-wake/js/worker1.js index 581a1b952a..80297ba494 100644 --- a/examples/atomic-wait-wake/js/worker1.js +++ b/examples/atomic-wait-wake/js/worker1.js @@ -1,17 +1,88 @@ addEventListener("message", onMessageReceived, false); let memory = null; +let dataView = null; +let u8 = null; let i32 = null; -function onMessageReceived(e) { +let id = 0; +let _exports = null; +const mutexAddr = 0; +const numAgents = 1; +async function onMessageReceived(e) { try { const data = e.data; switch (data.command) { case "init": { + id = data.id; memory = data.memory; + dataView = new DataView(memory.buffer); + u8 = new Uint8Array(memory.buffer); i32 = new Int32Array(memory.buffer); - console.log("Waiting", i32[0]); - Atomics.wait(i32, 0, 0); - console.log("Waken", i32[0]); + const instance = await WebAssembly.instantiate(data.wasm, { + env: { + memory, + abort: function() {}, + }, + index: { + log: console.log, + log_str, + }, + }); + const exp = instance.exports; + + _exports = exp; + _exports.setId(id); + self.postMessage({ command: "inited" }); + break; + } + case "wait": { + _exports.wait(mutexAddr, data.value); + break; + } + case "wait_i64": { + _exports.wait_i64(mutexAddr, data.value); + break; + } + case "wait_js": { + console.log(`[JS][${id}] waiting...`) + Atomics.store(i32, mutexAddr, data.value); + Atomics.wait(i32, mutexAddr, data.value); + console.log(`[JS][${id}] waken`); + break; + } + case "wake": { + _exports.wake(mutexAddr, data.value, numAgents); + console.log('-----') + break; + } + case "wake_i64": { + _exports.wake_i64(mutexAddr, data.value, numAgents); + console.log('-----') + break; + } + case "wake_js": { + console.log(`[JS][${id}] waking ${numAgents} agent(s)...`) + Atomics.store(i32, mutexAddr, data.value); + const count = Atomics.wake(i32, mutexAddr, numAgents); + console.log(`[JS][${id}] waken ${count} agent(s)`) + console.log('-----') + break; } } - } catch (e) {} + } catch (e) { + console.log(e); + } +} + +function log_str(ptr) { + console.log(readUTF16(ptr, dataView)); } + +function readUTF16(ptr, _memoryView) { + _memoryView = _memoryView || memoryView; + const u8a = new Uint8Array(_memoryView.buffer); + const str_len = _memoryView.getUint32(ptr, true); + const utf16 = u8a.subarray(ptr + 4, ptr + (str_len * 2) + 4); + const decoder = new TextDecoder("utf-16"); + const _utf16 = utf16.map(a => a); + return decoder.decode(_utf16); + } diff --git a/examples/atomic-wait-wake/js/worker2.js b/examples/atomic-wait-wake/js/worker2.js index d5bafc2b2c..c2723ed9a8 100644 --- a/examples/atomic-wait-wake/js/worker2.js +++ b/examples/atomic-wait-wake/js/worker2.js @@ -8,9 +8,9 @@ function onMessageReceived(e) { case "init": { memory = data.memory; i32 = new Int32Array(memory.buffer); - Atomics.store(i32, 0, 123); - console.log("Stored", 123); setTimeout(() => { + Atomics.store(i32, 0, 123); + console.log("Stored", 123); Atomics.wake(i32, 0, 1); }, 2000); } diff --git a/examples/atomic-wait-wake/package.json b/examples/atomic-wait-wake/package.json index 6bb4f6c435..2054a75c84 100644 --- a/examples/atomic-wait-wake/package.json +++ b/examples/atomic-wait-wake/package.json @@ -4,7 +4,7 @@ "private": true, "scripts": { "asbuild:untouched": "asc assembly/index.ts -b build/untouched.wasm -t build/untouched.wat --sourceMap --importMemory --sharedMemory=256 --validate", - "asbuild:optimized": "asc assembly/index.ts -b build/optimized.wasm -t build/optimized.wat -O3 --importMemory --sharedMemory=256 --validate --noDebug --noAssert", + "asbuild:optimized": "asc assembly/index.ts -b build/optimized.wasm -t build/optimized.wat -O3 --importMemory --sharedMemory=256 --validate --noAssert", "asbuild": "npm run asbuild:untouched && npm run asbuild:optimized", "build": "npm run asbuild", "server": "http-server . -o -c-1", diff --git a/src/builtins.ts b/src/builtins.ts index 4f91c65265..bf34109874 100644 --- a/src/builtins.ts +++ b/src/builtins.ts @@ -3267,10 +3267,10 @@ function deferASMCall( case "i64.atomic.rmw32_u.cmpxchg": return deferASM("Atomic.cmpxchg", compiler, Type.u32, operands, Type.u64, reportNode); case "i64.atomic.rmw.cmpxchg": return deferASM("Atomic.cmpxchg", compiler, Type.u64, operands, Type.u64, reportNode); - case "i32.atomic.wait": return deferASM("Atomic.wait", compiler, Type.u32, operands, Type.u32, reportNode); - case "i64.atomic.wait": return deferASM("Atomic.wait", compiler, Type.u64, operands, Type.u64, reportNode); - case "i32.atomic.wake": return deferASM("Atomic.wake", compiler, Type.u32, operands, Type.u32, reportNode); - case "i64.atomic.wake": return deferASM("Atomic.wake", compiler, Type.u32, operands, Type.u32, reportNode); + case "i32.wait": return deferASM("Atomic.wait", compiler, Type.i32, operands, Type.u32, reportNode); + case "i64.wait": return deferASM("Atomic.wait", compiler, Type.i64, operands, Type.i64, reportNode); + case "i32.wake": return deferASM("Atomic.wake", compiler, Type.i32, operands, Type.u32, reportNode); + case "i64.wake": return deferASM("Atomic.wake", compiler, Type.i64, operands, Type.i64, reportNode); } return 0; } diff --git a/std/assembly/index.d.ts b/std/assembly/index.d.ts index 672e9cccca..896a303fe2 100644 --- a/std/assembly/index.d.ts +++ b/std/assembly/index.d.ts @@ -168,6 +168,10 @@ declare namespace Atomic { export function xchg(ptr: usize, value: T, constantOffset?: usize): T; /** Atomically compare exchange a value of the specified type to memory.*/ export function cmpxchg(ptr: usize, expected:T, replacement: T, constantOffset?: usize): T; + + export function wait(offset: usize, expected: T, timeout: i64): i32; + + export function wake(offset: usize, count: u32): u32; } /** Converts any other numeric value to an 8-bit signed integer. */ @@ -240,7 +244,7 @@ declare namespace i32 { /** Atomically stores a 32-bit integer to memory. */ export function store(offset: usize, value: i32, constantOffset?: usize): void; - export function wait(offset: usize, value: i32, timeout: i64): i32; + export function wait(offset: usize, expected: i32, timeout: i64): i32; export function wake(offset: usize, count: u32): u32; namespace rmw8_u { @@ -332,7 +336,7 @@ declare namespace i64 { /** Atomically stores a 64-bit integer to memory. */ export function store(offset: usize, value: i64, constantOffset?: usize): void; - export function wait(offset: usize, value: i64, timeout: i64): i32; + export function wait(offset: usize, expected: i64, timeout: i64): i32; export function wake(offset: usize, count: u32): u32; namespace rmw8_u { From ba56ef1c2ddce631aa94c3ddb2281f06c9240631 Mon Sep 17 00:00:00 2001 From: Nidin Vinayakan <01@01alchemist.com> Date: Thu, 29 Nov 2018 14:59:49 +0100 Subject: [PATCH 3/4] Wait wake example clean up --- examples/atomic-wait-wake/assembly/index.ts | 26 ++++++++++++++++-- .../atomic-wait-wake/assembly/index_32.ts | 27 ------------------- .../atomic-wait-wake/assembly/index_64.ts | 27 ------------------- 3 files changed, 24 insertions(+), 56 deletions(-) delete mode 100644 examples/atomic-wait-wake/assembly/index_32.ts delete mode 100644 examples/atomic-wait-wake/assembly/index_64.ts diff --git a/examples/atomic-wait-wake/assembly/index.ts b/examples/atomic-wait-wake/assembly/index.ts index f6a8c78009..ab185e5a6c 100644 --- a/examples/atomic-wait-wake/assembly/index.ts +++ b/examples/atomic-wait-wake/assembly/index.ts @@ -1,4 +1,26 @@ +import "allocator/atomic"; +import { itoa } from "internal/number"; -export function wait(): void { - Atomic.wait(0, 0, -1); +declare function log_str(v: string): void; + +var id = 1; +type int = i32; +// type int = i64; + +export function setId(_id: i32): void { + id = _id; +} + +export function wait(mutexAddr: i32 = 0, value: int = 1): void { + log_str('[WASM][' + itoa(id) + '] waiting...'); + Atomic.store(mutexAddr, value); + Atomic.wait(mutexAddr, value, -1); + log_str('[WASM][' + itoa(id) + '] waken'); +} + +export function wake(mutexAddr: i32 = 0, value: int = 0, numAgents: i32 = 1): void { + log_str('[WASM][' + itoa(id) + '] waking '+ itoa(numAgents) + ' agent(s)...'); + Atomic.store(mutexAddr, value); + var count = Atomic.wake(mutexAddr, numAgents); + log_str('[WASM][' + itoa(id) + '] waken ' + itoa(count) + ' agent(s)'); } diff --git a/examples/atomic-wait-wake/assembly/index_32.ts b/examples/atomic-wait-wake/assembly/index_32.ts deleted file mode 100644 index 97fecab030..0000000000 --- a/examples/atomic-wait-wake/assembly/index_32.ts +++ /dev/null @@ -1,27 +0,0 @@ -import "allocator/atomic"; -import { itoa } from "internal/number"; - -declare function log(v: i32): void; -declare function logi64(v: i64): void; -declare function log_str(v: string): void; - -var id = 1; - -export function setId(_id: i32): void { - id = _id; -} - -export function wait(mutexAddr: i32 = 0, value: i32 = 1): void { - log_str('[WASM][' + itoa(id) + '] waiting...'); - Atomic.store(mutexAddr, value); - Atomic.wait(mutexAddr, value, -1); - // logi64(result); - log_str('[WASM][' + itoa(id) + '] waken'); -} - -export function wake(mutexAddr: i32 = 0, value: i32 = 0, numAgents: i32 = 1): void { - log_str('[WASM][' + itoa(id) + '] waking '+ itoa(numAgents) + ' agent(s)...'); - Atomic.store(mutexAddr, value); - var count = Atomic.wake(mutexAddr, numAgents); - log_str('[WASM][' + itoa(id) + '] waken ' + itoa(count) + ' agent(s)'); -} diff --git a/examples/atomic-wait-wake/assembly/index_64.ts b/examples/atomic-wait-wake/assembly/index_64.ts deleted file mode 100644 index 5b0fe081c3..0000000000 --- a/examples/atomic-wait-wake/assembly/index_64.ts +++ /dev/null @@ -1,27 +0,0 @@ -// import "allocator/atomic"; -// import { itoa } from "internal/number"; - -declare function log(v: i32): void; -declare function logi64(v: i64): void; -declare function log_str(v: string): void; - -var id = 1; - -export function setId(_id: i32): void { - id = _id; -} - -export function wait_i64(mutexAddr: i32 = 0, value: i64 = 1): void { - // log_str('[WASM][' + itoa(id) + '] waiting...'); - Atomic.store(mutexAddr, value); - Atomic.wait(mutexAddr, value, -1); - // logi64(result); - // log_str('[WASM][' + itoa(id) + '] waken'); -} - -export function wake_i64(mutexAddr: i32 = 0, value: i64 = 0, numAgents: i32 = 1): void { - // log_str('[WASM][' + itoa(id) + '] waking '+ itoa(numAgents) + ' agent(s)...'); - // Atomic.store(mutexAddr, value); - // var count = Atomic.wake(mutexAddr, numAgents); - // log_str('[WASM][' + itoa(id) + '] waken ' + itoa(count) + ' agent(s)'); -} From cbaa786b9623c38ea5be329baa112645f2407760 Mon Sep 17 00:00:00 2001 From: Nidin Vinayakan <01@01alchemist.com> Date: Thu, 29 Nov 2018 15:00:23 +0100 Subject: [PATCH 4/4] Wait wake example html updated --- examples/atomic-wait-wake/index.html | 29 ++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/examples/atomic-wait-wake/index.html b/examples/atomic-wait-wake/index.html index 6a18973971..5ac0014dae 100644 --- a/examples/atomic-wait-wake/index.html +++ b/examples/atomic-wait-wake/index.html @@ -91,16 +91,17 @@

case "inited":{ readyCount++; if(readyCount === 2) { - // workers[0].postMessage({ command: "wait", value: 1 }); - // setTimeout(() => { - // workers[1].postMessage({ command: "wake", value: 1 }); - // }, 1000) - // setTimeout(() => { - // workers[0].postMessage({ command: "wait_js", value: 1 }); - // }, 2000) - // setTimeout(() => { - // workers[1].postMessage({ command: "wake", value: 2 }); - // }, 3000) + workers[0].postMessage({ command: "wait", value: 1 }); + setTimeout(() => { + workers[1].postMessage({ command: "wake", value: 1 }); + }, 1000) + + setTimeout(() => { + workers[0].postMessage({ command: "wait_js", value: 1 }); + }, 1500) + setTimeout(() => { + workers[1].postMessage({ command: "wake", value: 2 }); + }, 3000) // setTimeout(() => { // workers[0].postMessage({ command: "wait_i64", value: 1 }); // }, 0) @@ -109,10 +110,10 @@

// }, 1000) setTimeout(() => { workers[0].postMessage({ command: "wait", value: 1 }); - }, 0) - // setTimeout(() => { - // workers[1].postMessage({ command: "wake", value: 2 }); - // }, 1000) + }, 3500) + setTimeout(() => { + workers[1].postMessage({ command: "wake_js", value: 2 }); + }, 5000) } break; }