Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
From b10341fae399f8c25887c348af9577640b1e233e Mon Sep 17 00:00:00 2001
From: Jan Kiszka <[email protected]>
Date: Mon, 5 Dec 2022 11:45:15 +0100
Subject: [PATCH] gpio: Fix JS binding regarding interrupt injections

According to [1] and based on stress tests, it is not correct to call
uv_queue_work outside of the loop thread. We rather need to use the
async API of libuv. That even simplifies things.

Resolves "uv__queue_done: Assertion `uv__has_active_reqs(req->loop)' failed"
errors that were easy to trigger by multiple DIs being used in parallel.
See also [2].

[1] https://github.com/libuv/libuv/discussions/3847
[2] https://github.com/siemens/meta-iot2050/issues/386

Signed-off-by: Jan Kiszka <[email protected]>
---
api/mraa/gpio.hpp | 37 +++++++++++++++++++++----------------
1 file changed, 21 insertions(+), 16 deletions(-)

diff --git a/api/mraa/gpio.hpp b/api/mraa/gpio.hpp
index 8fc0881..c41d527 100644
--- a/api/mraa/gpio.hpp
+++ b/api/mraa/gpio.hpp
@@ -31,10 +31,10 @@
#include <stdexcept>

#if defined(SWIGJAVASCRIPT)
-#if NODE_MODULE_VERSION >= 0x000D
#include <uv.h>
#endif
-#endif
+
+#define container_of(ptr, type, member) ((type*) ((char*) (ptr) - offsetof(type, member)))

namespace mraa
{
@@ -124,6 +124,10 @@ class Gpio
if (!owner) {
mraa_gpio_owner(m_gpio, 0);
}
+
+#if defined(SWIGJAVASCRIPT)
+ uv_async_init(uv_default_loop(), &m_async, v8isr);
+#endif
}
/**
* Gpio Constructor, takes a pointer to the GPIO context and initialises
@@ -137,6 +141,9 @@ class Gpio
if (m_gpio == NULL) {
throw std::invalid_argument("Invalid GPIO context");
}
+#if defined(SWIGJAVASCRIPT)
+ uv_async_init(uv_default_loop(), &m_async, v8isr);
+#endif
}
/**
* Gpio object destructor, this will only unexport the gpio if we where
@@ -146,6 +153,9 @@ class Gpio
{
if (m_gpio != NULL) {
mraa_gpio_close(m_gpio);
+#if defined(SWIGJAVASCRIPT)
+ uv_close((uv_handle_t*) &m_async, NULL);
+#endif
}
}
/**
@@ -156,6 +166,9 @@ class Gpio
{
mraa_gpio_close(m_gpio);
m_gpio = NULL;
+#if defined(SWIGJAVASCRIPT)
+ uv_close((uv_handle_t*) &m_async, NULL);
+#endif
}
/**
* Set the edge mode for ISR
@@ -176,12 +189,12 @@ class Gpio
}
#elif defined(SWIGJAVASCRIPT)
static void
- v8isr(uv_work_t* req, int status)
+ v8isr(uv_async_t* async)
{
#if NODE_MODULE_VERSION >= 0x000D
v8::HandleScope scope(v8::Isolate::GetCurrent());
#endif
- mraa::Gpio* This = (mraa::Gpio*) req->data;
+ mraa::Gpio* This = container_of(async, mraa::Gpio, m_async);
int argc = 1;
v8::Local<v8::Value> argv[] = { SWIGV8_INTEGER_NEW(-1) };
#if NODE_MODULE_VERSION >= 0x000D
@@ -194,21 +207,12 @@ class Gpio
#else
This->m_v8isr->Call(SWIGV8_CURRENT_CONTEXT()->Global(), argc, argv);
#endif
- delete req;
- }
-
- static void
- nop(uv_work_t* req)
- {
- // Do nothing.
}

static void
- uvwork(void* ctx)
+ trigger_async(void* async)
{
- uv_work_t* req = new uv_work_t;
- req->data = ctx;
- uv_queue_work(uv_default_loop(), req, nop, v8isr);
+ uv_async_send((uv_async_t*) async);
}

Result
@@ -219,7 +223,7 @@ class Gpio
#else
m_v8isr = v8::Persistent<v8::Function>::New(func);
#endif
- return (Result) mraa_gpio_isr(m_gpio, (mraa_gpio_edge_t) mode, &uvwork, this);
+ return (Result) mraa_gpio_isr(m_gpio, (mraa_gpio_edge_t) mode, trigger_async, &m_async);
}
#elif defined(SWIGJAVA) || defined(JAVACALLBACK)
Result
@@ -376,6 +380,7 @@ class Gpio
private:
mraa_gpio_context m_gpio;
#if defined(SWIGJAVASCRIPT)
+ uv_async_t m_async;
v8::Persistent<v8::Function> m_v8isr;
#endif
};
--
2.35.3

1 change: 1 addition & 0 deletions recipes-app/mraa/mraa_2.2.0+git.bb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ inherit dpkg
DESCRIPTION = "Low Level Skeleton Library for Communication on GNU/Linux platforms"
MAINTAINER = "[email protected]"
SRC_URI += "git://github.com/eclipse/mraa.git;protocol=https \
file://0001-gpio-Fix-JS-binding-regarding-interrupt-injections.patch \
file://rules"
SRCREV = "8b1c54934e80edc2d36abac9d9c96fe1e01cb669"

Expand Down