Skip to content

Commit

Permalink
Solution to deadlock problem when lock_double_fd is the same fd. rewr…
Browse files Browse the repository at this point in the history
…itten fd_renumber. add .vscode on .gitignore. rm unused change. Pass fd_map as is to child threads. Change .gitmodules to tabs. reset run-testsuite.sh Minor modifications to the code.

patch about null equal undefined on parse JSON.
  • Loading branch information
oligamiq committed Oct 6, 2024
1 parent c198838 commit 08ffd65
Show file tree
Hide file tree
Showing 10 changed files with 123 additions and 98 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
node_modules/
dist/
typings/
.vscode/
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@
[submodule "examples/wasi_multi_threads_rustc/rust_wasm"]
path = examples/wasi_multi_threads_rustc/rust_wasm
url = https://github.com/oligamiq/rust_wasm
sharrow = true
sharrow = true
2 changes: 1 addition & 1 deletion src/fs_mem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ export class OpenDirectory extends Fd {
super();
this.dir = dir;
}
OpenDirectory;

// eslint-disable-next-line @typescript-eslint/no-unused-vars
fd_seek(offset: bigint, whence: number): { ret: number; offset: bigint } {
return { ret: wasi.ERRNO_BADF, offset: 0n };
Expand Down
8 changes: 4 additions & 4 deletions src/wasi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ export class WASIProcExit extends Error {
}

export default class WASI {
private args: Array<string> = [];
private env: Array<string> = [];
private fds: Array<Fd> = [];
private inst: { exports: { memory: WebAssembly.Memory } };
args: Array<string> = [];
env: Array<string> = [];
fds: Array<Fd> = [];
inst: { exports: { memory: WebAssembly.Memory } };
// eslint-disable-next-line @typescript-eslint/no-explicit-any
wasiImport: { [key: string]: (...args: Array<any>) => unknown };

Expand Down
43 changes: 26 additions & 17 deletions src/wasi_farm/animals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,11 @@ export class WASIFarmAnimal {
const view = new Uint8Array(this.get_share_memory().buffer);
view.fill(0);

await this.thread_spawner.async_start_on_thread(this.args, this.env);
await this.thread_spawner.async_start_on_thread(
this.args,
this.env,
this.fd_map,
);

const code = await this.thread_spawner.async_wait_done_or_error();

Expand All @@ -148,7 +152,7 @@ export class WASIFarmAnimal {

console.log("block_start_on_thread: start");

this.thread_spawner.block_start_on_thread(this.args, this.env);
this.thread_spawner.block_start_on_thread(this.args, this.env, this.fd_map);

console.log("block_start_on_thread: wait");

Expand Down Expand Up @@ -303,7 +307,7 @@ export class WASIFarmAnimal {
if (rm_fds.length > 0) {
for (let i = 0; i < this.fd_map.length; i++) {
const fd_and_wasi_ref_n = this.fd_map[i];
if (fd_and_wasi_ref_n === undefined) {
if (!fd_and_wasi_ref_n) {
continue;
}
const [fd, wasi_ref_n] = fd_and_wasi_ref_n;
Expand Down Expand Up @@ -333,6 +337,7 @@ export class WASIFarmAnimal {
can_thread_spawn?: boolean;
thread_spawn_worker_url?: string;
thread_spawn_wasm?: WebAssembly.Module;
hand_override_fd_map?: Array<[number, number]>;
} = {},
override_fd_maps?: Array<number[]>,
thread_spawner?: ThreadSpawner,
Expand Down Expand Up @@ -401,6 +406,10 @@ export class WASIFarmAnimal {

this.mapping_fds(this.wasi_farm_refs, override_fd_maps);

if (options.hand_override_fd_map) {
this.fd_map = options.hand_override_fd_map;
}

// console.log("this.fd_map", this.fd_map);

this.args = args;
Expand Down Expand Up @@ -848,26 +857,23 @@ export class WASIFarmAnimal {
fd_renumber(fd: number, to: number) {
self.check_fds();

const [mapped_fd, wasi_farm_ref_n] = self.get_fd_and_wasi_ref_n(fd);
const [mapped_to, wasi_farm_ref_to] = self.get_fd_and_wasi_ref(to);

if (
mapped_fd === undefined ||
wasi_farm_ref_n === undefined ||
mapped_to === undefined ||
wasi_farm_ref_to === undefined
) {
return wasi.ERRNO_BADF;
if (mapped_to !== undefined && wasi_farm_ref_to !== undefined) {
const ret = wasi_farm_ref_to.fd_close(mapped_to);
self.check_fds();
if (ret !== wasi.ERRNO_SUCCESS) {
return ret;
}
}

const ret = wasi_farm_ref_to.fd_close(mapped_to);
self.check_fds();

if (ret !== wasi.ERRNO_SUCCESS) {
return ret;
if (self.fd_map[to]) {
throw new Error("fd is already mapped");
}

self.map_set_fd_and_notify(mapped_fd, wasi_farm_ref_n, to);
self.fd_map[to] = self.fd_map[fd];

self.fd_map[fd] = undefined;

return wasi.ERRNO_SUCCESS;
},
Expand Down Expand Up @@ -1147,6 +1153,9 @@ export class WASIFarmAnimal {
new_path_ptr: number,
new_path_len: number,
) {
if (old_fd === new_fd) {
return wasi.ERRNO_SUCCESS;
}
self.check_fds();
const [mapped_old_fd, wasi_farm_ref] = self.get_fd_and_wasi_ref(old_fd);
const [mapped_new_fd, wasi_farm_ref_new] =
Expand Down
8 changes: 8 additions & 0 deletions src/wasi_farm/shared_array_buffer/ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,10 @@ export class WASIFarmRefUseArrayBuffer extends WASIFarmRef {

private lock_double_fd(fd1: number, fd2: number) {
// console.log("lock_double_fd", fd1, fd2);
if (fd1 === fd2) {
this.lock_fd(fd1);
return;
}
const view = new Int32Array(this.lock_fds);
// eslint-disable-next-line no-constant-condition
while (true) {
Expand Down Expand Up @@ -213,6 +217,10 @@ export class WASIFarmRefUseArrayBuffer extends WASIFarmRef {

private release_double_fd(fd1: number, fd2: number) {
// console.log("release_double_fd", fd1, fd2);
if (fd1 === fd2) {
this.release_fd(fd1);
return;
}
const view = new Int32Array(this.lock_fds);
Atomics.store(view, fd1 * 3, 0);
Atomics.notify(view, fd1 * 3, 1);
Expand Down
95 changes: 51 additions & 44 deletions src/wasi_farm/shared_array_buffer/thread_spawn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,9 @@ export class ThreadSpawner {
worker_background_ref_object: this.worker_background_ref_object,
});
} else {
this.worker_background_ref_object = worker_background_ref_object;
this.worker_background_ref = WorkerBackgroundRef.init_self(
worker_background_ref_object,
this.worker_background_ref_object,
);
}
}
Expand Down Expand Up @@ -161,6 +162,7 @@ export class ThreadSpawner {
async async_start_on_thread(
args: Array<string>,
env: Array<string>,
fd_map: Array<[number, number]>,
): Promise<void> {
if (!self.Worker.toString().includes("[native code]")) {
if (self.Worker.toString().includes("function")) {
Expand All @@ -178,11 +180,16 @@ export class ThreadSpawner {
this_is_start: true,
args,
env,
fd_map,
},
);
}

block_start_on_thread(args: Array<string>, env: Array<string>): void {
block_start_on_thread(
args: Array<string>,
env: Array<string>,
fd_map: Array<[number, number]>,
): void {
if (!self.Worker.toString().includes("[native code]")) {
if (self.Worker.toString().includes("function")) {
console.warn("SubWorker(new Worker on Worker) is polyfilled maybe.");
Expand All @@ -199,6 +206,7 @@ export class ThreadSpawner {
this_is_start: true,
args,
env,
fd_map,
},
);
}
Expand Down Expand Up @@ -278,29 +286,56 @@ export const thread_spawn_on_worker = async (msg: {
thread_spawn_wasm: WebAssembly.Module;
args: Array<string>;
env: Array<string>;
fd_map: Array<number[]>;
fd_map: [number, number][];
this_is_start?: boolean;
}): Promise<WASIFarmAnimal> => {
if (msg.this_is_thread_spawn) {
if (msg.this_is_start) {
const thread_spawner = ThreadSpawner.init_self_with_worker_background_ref(
msg.sl_object,
msg.worker_background_ref,
);
const {
sl_object,
fd_map,
worker_background_ref,
thread_spawn_wasm,
args,
env,
} = msg;

const override_fd_map: Array<number[]> = new Array(
sl_object.wasi_farm_refs_object.length,
);

// Possibly null (undefined)
for (const fd_and_wasi_ref_n of fd_map) {
// biome-ignore lint/suspicious/noDoubleEquals: <explanation>
if (fd_and_wasi_ref_n == undefined) {
continue;
}
const [fd, wasi_ref_n] = fd_and_wasi_ref_n;
if (override_fd_map[wasi_ref_n] === undefined) {
override_fd_map[wasi_ref_n] = [];
}
override_fd_map[wasi_ref_n].push(fd);
}

const thread_spawner = ThreadSpawner.init_self_with_worker_background_ref(
sl_object,
worker_background_ref,
);

if (msg.this_is_start) {
const wasi = new WASIFarmAnimal(
msg.sl_object.wasi_farm_refs_object,
msg.args,
msg.env,
sl_object.wasi_farm_refs_object,
args,
env,
{
can_thread_spawn: true,
thread_spawn_worker_url: msg.sl_object.worker_url,
thread_spawn_worker_url: sl_object.worker_url,
hand_override_fd_map: fd_map,
},
undefined,
override_fd_map,
thread_spawner,
);

const inst = await WebAssembly.instantiate(msg.thread_spawn_wasm, {
const inst = await WebAssembly.instantiate(thread_spawn_wasm, {
env: {
memory: wasi.get_share_memory(),
},
Expand All @@ -324,46 +359,18 @@ export const thread_spawn_on_worker = async (msg: {
return wasi;
}

const {
worker_id: thread_id,
start_arg,
args,
env,
sl_object,
thread_spawn_wasm,
} = msg;
const { worker_id: thread_id, start_arg } = msg;

console.log(`thread_spawn worker ${thread_id} start`);

const thread_spawner = ThreadSpawner.init_self_with_worker_background_ref(
sl_object,
msg.worker_background_ref,
);

const override_fd_map: Array<number[]> = new Array(
sl_object.wasi_farm_refs_object.length,
);

// Possibly null (undefined)
for (const fd_and_wasi_ref_n of msg.fd_map) {
// biome-ignore lint/suspicious/noDoubleEquals: <explanation>
if (fd_and_wasi_ref_n == undefined) {
continue;
}
const [fd, wasi_ref_n] = fd_and_wasi_ref_n;
if (override_fd_map[wasi_ref_n] === undefined) {
override_fd_map[wasi_ref_n] = [];
}
override_fd_map[wasi_ref_n].push(fd);
}

const wasi = new WASIFarmAnimal(
sl_object.wasi_farm_refs_object,
args,
env,
{
can_thread_spawn: true,
thread_spawn_worker_url: sl_object.worker_url,
hand_override_fd_map: fd_map,
},
override_fd_map,
thread_spawner,
Expand Down
Loading

0 comments on commit 08ffd65

Please sign in to comment.