mirror of
				https://github.com/bytecodealliance/wasm-micro-runtime.git
				synced 2025-10-31 05:11:19 +00:00 
			
		
		
		
	 444b159963
			
		
	
	
		444b159963
		
			
		
	
	
	
	
		
			
			Send a signal whose handler is no-op to a blocking thread to wake up the blocking syscall with either EINTR equivalent or partial success. Unlike the approach taken in the `dev/interrupt_block_insn` branch (that is, signal + longjmp similarly to `OS_ENABLE_HW_BOUND_CHECK`), this PR does not use longjmp because: * longjmp from signal handler doesn't work on nuttx refer to https://github.com/apache/nuttx/issues/10326 * the singal+longjmp approach may be too difficult for average programmers who might implement host functions to deal with See also https://github.com/bytecodealliance/wasm-micro-runtime/issues/1910
		
			
				
	
	
		
			93 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			93 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Copyright (C) 2023 Midokura Japan KK.  All rights reserved.
 | |
|  * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | |
|  */
 | |
| 
 | |
| #include "wasm_runtime_common.h"
 | |
| 
 | |
| #include "bh_platform.h"
 | |
| #include "bh_common.h"
 | |
| #include "bh_assert.h"
 | |
| 
 | |
| #if WASM_ENABLE_THREAD_MGR != 0 && defined(OS_ENABLE_WAKEUP_BLOCKING_OP)
 | |
| 
 | |
| #define LOCK(env) WASM_SUSPEND_FLAGS_LOCK((env)->wait_lock)
 | |
| #define UNLOCK(env) WASM_SUSPEND_FLAGS_UNLOCK((env)->wait_lock)
 | |
| 
 | |
| #define ISSET(env, bit)                                                       \
 | |
|     ((WASM_SUSPEND_FLAGS_GET((env)->suspend_flags) & WASM_SUSPEND_FLAG_##bit) \
 | |
|      != 0)
 | |
| #define SET(env, bit) \
 | |
|     WASM_SUSPEND_FLAGS_FETCH_OR((env)->suspend_flags, WASM_SUSPEND_FLAG_##bit)
 | |
| #define CLR(env, bit) \
 | |
|     WASM_SUSPEND_FLAGS_FETCH_AND((env)->suspend_flags, ~WASM_SUSPEND_FLAG_##bit)
 | |
| 
 | |
| bool
 | |
| wasm_runtime_begin_blocking_op(wasm_exec_env_t env)
 | |
| {
 | |
|     LOCK(env);
 | |
|     bh_assert(!ISSET(env, BLOCKING));
 | |
|     SET(env, BLOCKING);
 | |
|     if (ISSET(env, TERMINATE)) {
 | |
|         CLR(env, BLOCKING);
 | |
|         UNLOCK(env);
 | |
|         return false;
 | |
|     }
 | |
|     UNLOCK(env);
 | |
|     os_begin_blocking_op();
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| void
 | |
| wasm_runtime_end_blocking_op(wasm_exec_env_t env)
 | |
| {
 | |
|     int saved_errno = errno;
 | |
|     LOCK(env);
 | |
|     bh_assert(ISSET(env, BLOCKING));
 | |
|     CLR(env, BLOCKING);
 | |
|     UNLOCK(env);
 | |
|     os_end_blocking_op();
 | |
|     errno = saved_errno;
 | |
| }
 | |
| 
 | |
| void
 | |
| wasm_runtime_interrupt_blocking_op(wasm_exec_env_t env)
 | |
| {
 | |
|     /*
 | |
|      * ISSET(BLOCKING) here means that the target thread
 | |
|      * is in somewhere between wasm_begin_blocking_op and
 | |
|      * wasm_end_blocking_op.
 | |
|      * keep waking it up until it reaches wasm_end_blocking_op,
 | |
|      * which clears the BLOCKING bit.
 | |
|      *
 | |
|      * this dumb loop is necessary because posix doesn't provide
 | |
|      * a way to unmask signal and block atomically.
 | |
|      */
 | |
| 
 | |
|     LOCK(env);
 | |
|     SET(env, TERMINATE);
 | |
|     while (ISSET(env, BLOCKING)) {
 | |
|         UNLOCK(env);
 | |
|         os_wakeup_blocking_op(env->handle);
 | |
| 
 | |
|         /* relax a bit */
 | |
|         os_usleep(50 * 1000);
 | |
|         LOCK(env);
 | |
|     }
 | |
|     UNLOCK(env);
 | |
| }
 | |
| 
 | |
| #else /* WASM_ENABLE_THREAD_MGR && OS_ENABLE_WAKEUP_BLOCKING_OP */
 | |
| 
 | |
| bool
 | |
| wasm_runtime_begin_blocking_op(wasm_exec_env_t env)
 | |
| {
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| void
 | |
| wasm_runtime_end_blocking_op(wasm_exec_env_t env)
 | |
| {}
 | |
| 
 | |
| #endif /* WASM_ENABLE_THREAD_MGR && OS_ENABLE_WAKEUP_BLOCKING_OP */
 |