wasm_blocking_op.c 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. /*
  2. * Copyright (C) 2023 Midokura Japan KK. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "wasm_runtime_common.h"
  6. #include "bh_platform.h"
  7. #include "bh_common.h"
  8. #include "bh_assert.h"
  9. #if WASM_ENABLE_THREAD_MGR != 0 && defined(OS_ENABLE_WAKEUP_BLOCKING_OP)
  10. #define LOCK(env) WASM_SUSPEND_FLAGS_LOCK((env)->wait_lock)
  11. #define UNLOCK(env) WASM_SUSPEND_FLAGS_UNLOCK((env)->wait_lock)
  12. #define ISSET(env, bit) \
  13. ((WASM_SUSPEND_FLAGS_GET((env)->suspend_flags) & WASM_SUSPEND_FLAG_##bit) \
  14. != 0)
  15. #define SET(env, bit) \
  16. WASM_SUSPEND_FLAGS_FETCH_OR((env)->suspend_flags, WASM_SUSPEND_FLAG_##bit)
  17. #define CLR(env, bit) \
  18. WASM_SUSPEND_FLAGS_FETCH_AND((env)->suspend_flags, ~WASM_SUSPEND_FLAG_##bit)
  19. bool
  20. wasm_runtime_begin_blocking_op(wasm_exec_env_t env)
  21. {
  22. LOCK(env);
  23. bh_assert(!ISSET(env, BLOCKING));
  24. SET(env, BLOCKING);
  25. if (ISSET(env, TERMINATE)) {
  26. CLR(env, BLOCKING);
  27. UNLOCK(env);
  28. return false;
  29. }
  30. UNLOCK(env);
  31. os_begin_blocking_op();
  32. return true;
  33. }
  34. void
  35. wasm_runtime_end_blocking_op(wasm_exec_env_t env)
  36. {
  37. int saved_errno = errno;
  38. LOCK(env);
  39. bh_assert(ISSET(env, BLOCKING));
  40. CLR(env, BLOCKING);
  41. UNLOCK(env);
  42. os_end_blocking_op();
  43. errno = saved_errno;
  44. }
  45. void
  46. wasm_runtime_interrupt_blocking_op(wasm_exec_env_t env)
  47. {
  48. /*
  49. * ISSET(BLOCKING) here means that the target thread
  50. * is in somewhere between wasm_begin_blocking_op and
  51. * wasm_end_blocking_op.
  52. * keep waking it up until it reaches wasm_end_blocking_op,
  53. * which clears the BLOCKING bit.
  54. *
  55. * this dumb loop is necessary because posix doesn't provide
  56. * a way to unmask signal and block atomically.
  57. */
  58. LOCK(env);
  59. SET(env, TERMINATE);
  60. while (ISSET(env, BLOCKING)) {
  61. UNLOCK(env);
  62. os_wakeup_blocking_op(env->handle);
  63. /* relax a bit */
  64. os_usleep(50 * 1000);
  65. LOCK(env);
  66. }
  67. UNLOCK(env);
  68. }
  69. #else /* WASM_ENABLE_THREAD_MGR && OS_ENABLE_WAKEUP_BLOCKING_OP */
  70. bool
  71. wasm_runtime_begin_blocking_op(wasm_exec_env_t env)
  72. {
  73. return true;
  74. }
  75. void
  76. wasm_runtime_end_blocking_op(wasm_exec_env_t env)
  77. {}
  78. #endif /* WASM_ENABLE_THREAD_MGR && OS_ENABLE_WAKEUP_BLOCKING_OP */