Skip to content

Commit aa0163d

Browse files
committed
Remove restriction on write-before-lift, remove invalid assert, add test
1 parent 4c6f1be commit aa0163d

File tree

3 files changed

+16
-11
lines changed

3 files changed

+16
-11
lines changed

design/mvp/CanonicalABI.md

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1655,7 +1655,6 @@ def lift_async_value(ReadableHandleT, WritableHandleT, cx, i, t):
16551655
cx.inst.waitables.remove(i)
16561656
case WritableHandleT():
16571657
trap_if(h.paired)
1658-
assert(not h.copying_buffer)
16591658
h.paired = True
16601659
if contains_borrow(t):
16611660
h.borrow_scope = cx.borrow_scope
@@ -3118,14 +3117,14 @@ async def async_copy(HandleT, BufferT, t, opts, event_code, task, i, ptr, n):
31183117
h = task.inst.waitables.get(i)
31193118
trap_if(not isinstance(h, HandleT))
31203119
trap_if(h.t != t)
3121-
trap_if(not h.paired)
31223120
trap_if(h.copying_buffer)
31233121
cx = LiftLowerContext(opts, task.inst, h.borrow_scope)
31243122
buffer = BufferT(cx, t, ptr, n)
31253123
if h.stream.closed():
31263124
flat_results = [pack_async_copy_result(task, buffer, h)]
31273125
else:
31283126
if opts.sync:
3127+
trap_if(not h.paired)
31293128
await task.call_sync(h.copy, buffer)
31303129
flat_results = [pack_async_copy_result(task, buffer, h)]
31313130
else:
@@ -3147,12 +3146,11 @@ async def async_copy(HandleT, BufferT, t, opts, event_code, task, i, ptr, n):
31473146
flat_results = [pack_async_copy_result(task, buffer, h)]
31483147
return flat_results
31493148
```
3150-
The trap if `not h.paired` prevents `write`s on the writable end of streams or
3151-
futures that have not yet been lifted. The `copying_buffer` field serves as a
3152-
boolean indication of whether an async `read` or `write` is already in
3153-
progress, preventing multiple overlapping calls to `read` or `write`. (This
3154-
restriction could be relaxed [in the future](Async.md#TODO) to allow greater
3155-
pipeline parallelism.)
3149+
The `trap_if(h.copying_buffer)` trap prevents multiple overlapping calls to
3150+
`read` or `write`. (This restriction could be relaxed [in the
3151+
future](Async.md#TODO) to allow greater pipeline parallelism.) The
3152+
`trap_if(not h.paired)` in the synchronous case prevents what would otherwise
3153+
be a deadlock, performing a blocking write when there is no reader.
31563154

31573155
One subtle corner case handled by this code that is worth pointing out is that,
31583156
between calling `h.copy()` and `h.copy()` returning, wasm guest code can call

design/mvp/canonical-abi/definitions.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1144,7 +1144,6 @@ def lift_async_value(ReadableHandleT, WritableHandleT, cx, i, t):
11441144
cx.inst.waitables.remove(i)
11451145
case WritableHandleT():
11461146
trap_if(h.paired)
1147-
assert(not h.copying_buffer)
11481147
h.paired = True
11491148
if contains_borrow(t):
11501149
h.borrow_scope = cx.borrow_scope
@@ -1978,14 +1977,14 @@ async def async_copy(HandleT, BufferT, t, opts, event_code, task, i, ptr, n):
19781977
h = task.inst.waitables.get(i)
19791978
trap_if(not isinstance(h, HandleT))
19801979
trap_if(h.t != t)
1981-
trap_if(not h.paired)
19821980
trap_if(h.copying_buffer)
19831981
cx = LiftLowerContext(opts, task.inst, h.borrow_scope)
19841982
buffer = BufferT(cx, t, ptr, n)
19851983
if h.stream.closed():
19861984
flat_results = [pack_async_copy_result(task, buffer, h)]
19871985
else:
19881986
if opts.sync:
1987+
trap_if(not h.paired)
19891988
await task.call_sync(h.copy, buffer)
19901989
flat_results = [pack_async_copy_result(task, buffer, h)]
19911990
else:

design/mvp/canonical-abi/run_tests.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1234,11 +1234,19 @@ async def core_func(task, args):
12341234
assert(len(args) == 0)
12351235
[wsi] = await canon_stream_new(U8Type(), task)
12361236
assert(wsi == 1)
1237-
retp = 4
1237+
[ret] = await canon_stream_write(U8Type(), opts, task, wsi, 0, 4)
1238+
assert(ret == definitions.BLOCKED)
1239+
retp = 8
1240+
[ret] = await canon_lower(opts, host_ft, host_import, task, [wsi, retp])
1241+
assert(ret == 0)
1242+
result = int.from_bytes(mem[retp : retp+4], 'little', signed=False)
1243+
assert(result == (wsi | 2**31))
12381244
[ret] = await canon_lower(opts, host_ft, host_import, task, [wsi, retp])
12391245
assert(ret == 0)
12401246
result = int.from_bytes(mem[retp : retp+4], 'little', signed=False)
12411247
assert(result == (wsi | 2**31))
1248+
[ret] = await canon_stream_cancel_write(True, task, wsi)
1249+
assert(ret == 0)
12421250
[] = await canon_stream_close_writable(U8Type(), task, wsi, 0)
12431251
return []
12441252

0 commit comments

Comments
 (0)