binaryen icon indicating copy to clipboard operation
binaryen copied to clipboard

undefined asyncify_get_state

Open andrewmd5 opened this issue 9 months ago • 3 comments

Is there currently a recommended way to go about calling asyncify_get_state from inside native code? To manage this with other methods currently I'm doing:

#ifndef ASYNCJMP_SUPPORT_ASYNCIFY_H
#define ASYNCJMP_SUPPORT_ASYNCIFY_H

__attribute__((import_module("asyncify"), import_name("start_unwind"))) void asyncify_start_unwind(void *buf);
#define asyncify_start_unwind(buf)         \
    do                                     \
    {                                      \
        extern void *pl_asyncify_unwind_buf; \
        pl_asyncify_unwind_buf = (buf);      \
        asyncify_start_unwind((buf));      \
    } while (0)

__attribute__((import_module("asyncify"), import_name("stop_unwind"))) void asyncify_stop_unwind(void);
#define asyncify_stop_unwind()             \
    do                                     \
    {                                      \
        extern void *pl_asyncify_unwind_buf; \
        pl_asyncify_unwind_buf = NULL;       \
        asyncify_stop_unwind();            \
    } while (0)

__attribute__((import_module("asyncify"), import_name("start_rewind"))) void asyncify_start_rewind(void *buf);

__attribute__((import_module("asyncify"), import_name("stop_rewind"))) void asyncify_stop_rewind(void);

__attribute__((import_module("asyncify"), import_name("get_state"))) int asyncify_get_state(void);

#endif

Which all get successfully turned into exports. But for asyncify_get_state the pass raises an error:

 "/opt/wasm-opt" zeroperl_unopt -O3 -o zeroperl_unopt
Fatal: call to unidenfied asyncify import: get_state

What I'm trying to achieve:

__attribute__((noinline))
ssize_t __wrap_read(int fd, void *buf, size_t count) {
    if (asyncify_get_state() == 2) {
        asyncify_stop_rewind();
        if (have_saved_result) {
            have_saved_result = false; 
            return saved_result;
        }
        return -1;
    }

    ssize_t r = sfs_read(fd, buf, count);
    if (r >= 0) {
        return r; // Fast path succeeded
    }
    
    
    ssize_t real_val = __real_read(fd, buf, count);

        if (asyncify_get_state() == 1) {
            saved_result     = real_val;
            have_saved_result = true;

            asyncify_stop_unwind();

            return real_val;
        }


        return real_val;

}

I'm using binaryen-version_121

edit:

looking at the pass more closely I can see get_state is missing from here & here, but the documentation says that it should be there

andrewmd5 avatar Feb 24 '25 05:02 andrewmd5

cc: @kripken

andrewmd5 avatar Feb 24 '25 06:02 andrewmd5

Here is a patch that unblocks me for the time being:

diff --git a/src/passes/Asyncify.cpp b/src/passes/Asyncify.cpp
index 994142e48..f6500ed2c 100644
--- a/src/passes/Asyncify.cpp
+++ b/src/passes/Asyncify.cpp
@@ -349,6 +349,7 @@ static const Name START_UNWIND = "start_unwind";
 static const Name STOP_UNWIND = "stop_unwind";
 static const Name START_REWIND = "start_rewind";
 static const Name STOP_REWIND = "stop_rewind";
+static const Name GET_STATE = "get_state";
 static const Name ASYNCIFY_GET_CALL_INDEX = "__asyncify_get_call_index";
 static const Name ASYNCIFY_CHECK_CALL_INDEX = "__asyncify_check_call_index";
 
@@ -569,6 +570,8 @@ public:
           renamings[func->name] = ASYNCIFY_START_REWIND;
         } else if (func->base == STOP_REWIND) {
           renamings[func->name] = ASYNCIFY_STOP_REWIND;
+	} else if (func->base == GET_STATE) {
+          renamings[func->name] = ASYNCIFY_GET_STATE;
         } else {
           Fatal() << "call to unidenfied asyncify import: " << func->base;
         }
@@ -624,6 +627,8 @@ public:
               } else if (target->base == STOP_REWIND) {
                 info.canChangeState = true;
                 info.isTopMostRuntime = true;
+	      } else if (target->base == GET_STATE) {
+		// NOTE: asyncify.get_state doesn't actually change the state; NOOP
               } else {
                 WASM_UNREACHABLE("call to unidenfied asyncify import");
               }

andrewmd5 avatar Feb 24 '25 07:02 andrewmd5

The patch makes sense to me (though we don't need the last part that is just a comment, I think). get_state doesn't modify the state, which is why this was missed I guess. But it is part of the API. A PR would be welcome.

kripken avatar Feb 24 '25 22:02 kripken