qnx: add qnx 8 support (#4801)

Fixes: https://github.com/libuv/libuv/issues/4710
This commit is contained in:
Deep C 2025-06-30 11:56:11 +05:30 committed by GitHub
parent 2545ffe74c
commit 04fc1580d4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 117 additions and 42 deletions

View File

@ -747,6 +747,14 @@ if(LIBUV_BUILD_TESTS)
"$<TARGET_FILE:uv_run_tests_a>"
"$<TARGET_FILE_DIR:uv_run_tests_a>/uv_run_tests_a_no_ext")
endif()
if(QNX)
install(TARGETS uv_run_tests uv_run_tests_a uv_run_benchmarks_a
DESTINATION ${CMAKE_INSTALL_BINDIR}/libuv_tests)
install(DIRECTORY test/fixtures
DESTINATION ${CMAKE_INSTALL_BINDIR}/libuv_tests)
endif()
endif()
# Now for some gibbering horrors from beyond the stars...

View File

@ -275,7 +275,7 @@ void uv__make_close_pending(uv_handle_t* handle) {
int uv__getiovmax(void) {
#if defined(IOV_MAX)
return IOV_MAX;
#elif defined(_SC_IOV_MAX)
#elif defined(_SC_IOV_MAX) && !defined(__QNX__)
static _Atomic int iovmax_cached = -1;
int iovmax;
@ -1611,6 +1611,10 @@ int uv_cpumask_size(void) {
}
int uv_os_getpriority(uv_pid_t pid, int* priority) {
#if defined(__QNX__)
/* QNX priority is not process-based */
return UV_ENOSYS;
#else
int r;
if (priority == NULL)
@ -1624,10 +1628,15 @@ int uv_os_getpriority(uv_pid_t pid, int* priority) {
*priority = r;
return 0;
#endif
}
int uv_os_setpriority(uv_pid_t pid, int priority) {
#if defined(__QNX__)
/* QNX priority is not process-based */
return UV_ENOSYS;
#else
if (priority < UV_PRIORITY_HIGHEST || priority > UV_PRIORITY_LOW)
return UV_EINVAL;
@ -1635,6 +1644,7 @@ int uv_os_setpriority(uv_pid_t pid, int priority) {
return UV__ERR(errno);
return 0;
#endif
}
/**

View File

@ -211,7 +211,8 @@ static ssize_t uv__fs_fdatasync(uv_fs_t* req) {
|| defined(__NetBSD__) \
|| defined(__OpenBSD__) \
|| defined(__linux__) \
|| defined(__sun)
|| defined(__sun) \
|| defined(__QNX__)
static struct timespec uv__fs_to_timespec(double time) {
struct timespec ts;
@ -248,7 +249,8 @@ static ssize_t uv__fs_futime(uv_fs_t* req) {
|| defined(__NetBSD__) \
|| defined(__OpenBSD__) \
|| defined(__linux__) \
|| defined(__sun)
|| defined(__sun) \
|| defined(__QNX__)
struct timespec ts[2];
ts[0] = uv__fs_to_timespec(req->atime);
ts[1] = uv__fs_to_timespec(req->mtime);
@ -1147,7 +1149,8 @@ static ssize_t uv__fs_utime(uv_fs_t* req) {
|| defined(__NetBSD__) \
|| defined(__OpenBSD__) \
|| defined(__linux__) \
|| defined(__sun)
|| defined(__sun) \
|| defined(__QNX__)
struct timespec ts[2];
ts[0] = uv__fs_to_timespec(req->atime);
ts[1] = uv__fs_to_timespec(req->mtime);
@ -1181,7 +1184,8 @@ static ssize_t uv__fs_lutime(uv_fs_t* req) {
|| defined(__NetBSD__) \
|| defined(__OpenBSD__) \
|| defined(__linux__) \
|| defined(__sun)
|| defined(__sun) \
|| defined(__QNX__)
struct timespec ts[2];
ts[0] = uv__fs_to_timespec(req->atime);
ts[1] = uv__fs_to_timespec(req->mtime);

View File

@ -141,6 +141,11 @@ union uv__sockaddr {
/* Leans on the fact that, on Linux, POLLRDHUP == EPOLLRDHUP. */
#ifdef POLLRDHUP
# define UV__POLLRDHUP POLLRDHUP
#elif defined(__QNX__)
/* On QNX, POLLRDHUP is not available and the 0x2000 workaround
* leads to undefined bahavior.
*/
# define UV__POLLRDHUP 0
#else
# define UV__POLLRDHUP 0x2000
#endif

View File

@ -28,6 +28,14 @@
#include <sys/memmsg.h>
#include <sys/syspage.h>
#include <sys/procfs.h>
#include <time.h>
#include <stdlib.h>
#include <inttypes.h>
#if __QNX__ >= 800
#define cpuinfo_val cpuinfo
#else
#define cpuinfo_val new_cpuinfo
#endif
static void
get_mem_info(uint64_t* totalmem, uint64_t* freemem) {
@ -67,18 +75,44 @@ int uv_exepath(char* buffer, size_t* size) {
}
static uint64_t uv__read_pidin_info(const char* what) {
uint64_t rc;
char* p;
char buf[2048];
FILE* fp = popen("pidin info", "r");
if (fp == NULL)
return 0;
size_t sz = fread(buf, 1, sizeof(buf) - 1, fp);
buf[sz] = '\0';
pclose(fp);
p = strstr(buf, what);
if (p == NULL)
return 0;
p += strlen(what);
rc = 0;
sscanf(p, "%" PRIu64 " MB", &rc);
return rc * 1024 * 1024;
}
uint64_t uv_get_free_memory(void) {
uint64_t totalmem;
uint64_t freemem;
get_mem_info(&totalmem, &freemem);
freemem = uv__read_pidin_info("FreeMem:");
return freemem;
}
uint64_t uv_get_total_memory(void) {
uint64_t totalmem;
uint64_t freemem;
get_mem_info(&totalmem, &freemem);
totalmem = uv__read_pidin_info("MB/");
return totalmem;
}
@ -113,15 +147,17 @@ int uv_resident_set_memory(size_t* rss) {
int uv_uptime(double* uptime) {
struct qtime_entry* qtime = _SYSPAGE_ENTRY(_syspage_ptr, qtime);
*uptime = (qtime->nsec / 1000000000.0);
struct timespec ts;
if(clock_gettime(CLOCK_MONOTONIC, &ts))
return UV__ERR(errno);
*uptime = (double)ts.tv_sec;
return 0;
}
int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
struct cpuinfo_entry* cpuinfo =
(struct cpuinfo_entry*)_SYSPAGE_ENTRY(_syspage_ptr, new_cpuinfo);
(struct cpuinfo_entry*)_SYSPAGE_ENTRY(_syspage_ptr, cpuinfo_val);
size_t cpuinfo_size = _SYSPAGE_ELEMENT_SIZE(_syspage_ptr, cpuinfo);
struct strings_entry* strings = _SYSPAGE_ENTRY(_syspage_ptr, strings);
int num_cpus = _syspage_ptr->num_cpu;

View File

@ -560,7 +560,7 @@ int uv__udp_disconnect(uv_udp_t* handle) {
} while (r == -1 && errno == EINTR);
if (r == -1) {
#if defined(BSD) /* The macro BSD is from sys/param.h */
#if defined(BSD) || defined(__QNX__) /* The macro BSD is from sys/param.h */
if (errno != EAFNOSUPPORT && errno != EINVAL)
return UV__ERR(errno);
#else
@ -766,8 +766,8 @@ static int uv__udp_set_membership6(uv_udp_t* handle,
!defined(__NetBSD__) && \
!defined(__ANDROID__) && \
!defined(__DragonFly__) && \
!defined(__QNX__) && \
!defined(__GNU__)
!defined(__GNU__) && \
!defined(QNX_IOPKT)
static int uv__udp_set_source_membership4(uv_udp_t* handle,
const struct sockaddr_in* multicast_addr,
const char* interface_addr,
@ -957,8 +957,8 @@ int uv_udp_set_source_membership(uv_udp_t* handle,
!defined(__NetBSD__) && \
!defined(__ANDROID__) && \
!defined(__DragonFly__) && \
!defined(__QNX__) && \
!defined(__GNU__)
!defined(__GNU__) && \
!defined(QNX_IOPKT)
int err;
union uv__sockaddr mcast_addr;
union uv__sockaddr src_addr;
@ -1312,7 +1312,7 @@ static int uv__udp_sendmsgv(int fd,
nsent = 0;
#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || \
(defined(__sun__) && defined(MSG_WAITFORONE))
(defined(__sun__) && defined(MSG_WAITFORONE)) || defined(__QNX__)
if (count > 1) {
for (i = 0; i < count; /*empty*/) {
struct mmsghdr m[20];
@ -1340,7 +1340,7 @@ static int uv__udp_sendmsgv(int fd,
goto exit;
}
#endif /* defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) ||
* (defined(__sun__) && defined(MSG_WAITFORONE))
* (defined(__sun__) && defined(MSG_WAITFORONE)) || defined(__QNX__)
*/
for (i = 0; i < count; i++, nsent++)

View File

@ -358,7 +358,7 @@ UNUSED static int can_ipv6(void) {
return supported;
}
#if defined(__CYGWIN__) || defined(__MSYS__) || defined(__PASE__)
#if defined(__CYGWIN__) || defined(__MSYS__) || defined(__PASE__) || defined(__QNX__)
# define NO_FS_EVENTS "Filesystem watching not supported on this platform."
#endif

View File

@ -25,7 +25,7 @@
#include <stdlib.h>
#include <errno.h>
#if !defined(_WIN32) && !defined(_AIX)
#if !defined(_WIN32) && !defined(_AIX) && !defined(__QNX__)
#include <poll.h>
#endif
@ -56,7 +56,7 @@ TEST_IMPL(embed) {
ASSERT_LE(0, uv_barrier_wait(&barrier));
while (uv_loop_alive(loop)) {
#if defined(_WIN32) || defined(_AIX)
#if defined(_WIN32) || defined(_AIX) || defined(__QNX__)
ASSERT_LE(0, uv_run(loop, UV_RUN_ONCE));
#else
int rc;

View File

@ -152,7 +152,7 @@ int uv_test_getiovmax(void) {
int uv_test_getiovmax(void) {
#if defined(IOV_MAX)
return IOV_MAX;
#elif defined(_SC_IOV_MAX)
#elif defined(_SC_IOV_MAX) && !defined(__QNX__)
static int iovmax = -1;
if (iovmax == -1) {
iovmax = sysconf(_SC_IOV_MAX);
@ -356,7 +356,7 @@ static void statfs_cb(uv_fs_t* req) {
stats = req->ptr;
#if defined(_WIN32) || defined(__sun) || defined(_AIX) || defined(__MVS__) || \
defined(__OpenBSD__) || defined(__NetBSD__)
defined(__OpenBSD__) || defined(__NetBSD__) || defined(__QNX__)
ASSERT_OK(stats->f_type);
#else
ASSERT_UINT64_GT(stats->f_type, 0);
@ -2833,7 +2833,9 @@ TEST_IMPL(fs_utime_round) {
double mtime;
uv_fs_t req;
int r;
#if defined(__QNX__)
RETURN_SKIP("Setting time to a negative value is unsupported on QNX");
#endif
loop = uv_default_loop();
unlink(path);
r = uv_fs_open(NULL, &req, path, UV_FS_O_RDWR | UV_FS_O_CREAT,
@ -3889,6 +3891,12 @@ TEST_IMPL(fs_read_dir) {
* created on. That is why this assertion is a bit lenient.
*/
ASSERT((r >= 0) || (r == UV_EISDIR));
#elif defined(__QNX__)
/*
* If UV_FS_O_DIRECTORY is supplied, QNX returns ENOSYS. Otherwise
* UV_EISDIR is returned. Here we are lenient and accept both.
*/
ASSERT((r == UV_ENOSYS) || (r == UV_EISDIR));
#else
ASSERT_EQ(r, UV_EISDIR);
#endif

View File

@ -83,9 +83,9 @@ static int closed_connections = 0;
static int valid_writable_wakeups = 0;
static int spurious_writable_wakeups = 0;
#if !defined(__sun) && !defined(_AIX) && !defined(__MVS__)
#if !defined(__sun) && !defined(_AIX) && !defined(__MVS__) && !defined(__QNX__)
static int disconnects = 0;
#endif /* !__sun && !_AIX && !__MVS__ */
#endif /* !__sun && !_AIX && !__MVS__ && !__QNX__*/
static int got_eagain(void) {
#ifdef _WIN32
@ -409,7 +409,7 @@ static void connection_poll_cb(uv_poll_t* handle, int status, int events) {
new_events &= ~UV_WRITABLE;
}
}
#if !defined(__sun) && !defined(_AIX) && !defined(__MVS__)
#if !defined(__sun) && !defined(_AIX) && !defined(__MVS__) && !defined(__QNX__)
if (events & UV_DISCONNECT) {
context->got_disconnect = 1;
++disconnects;
@ -417,9 +417,9 @@ static void connection_poll_cb(uv_poll_t* handle, int status, int events) {
}
if (context->got_fin && context->sent_fin && context->got_disconnect) {
#else /* __sun && _AIX && __MVS__ */
#else /* __sun && _AIX && __MVS__ && __QNX__*/
if (context->got_fin && context->sent_fin) {
#endif /* !__sun && !_AIX && !__MVS__ */
#endif /* !__sun && !_AIX && !__MVS__ && !__QNX__ */
/* Sent and received FIN. Close and destroy context. */
close_socket(context->sock);
destroy_connection_context(context);
@ -587,7 +587,7 @@ static void start_poll_test(void) {
spurious_writable_wakeups > 20, 0);
ASSERT_EQ(closed_connections, NUM_CLIENTS * 2);
#if !defined(__sun) && !defined(_AIX) && !defined(__MVS__)
#if !defined(__sun) && !defined(_AIX) && !defined(__MVS__) && !defined(__QNX__)
ASSERT_EQ(disconnects, NUM_CLIENTS * 2);
#endif
MAKE_VALGRIND_HAPPY(uv_default_loop());
@ -638,7 +638,7 @@ TEST_IMPL(poll_unidirectional) {
TEST_IMPL(poll_bad_fdtype) {
#if !defined(__sun) && \
!defined(_AIX) && !defined(__MVS__) && \
!defined(__CYGWIN__) && !defined(__MSYS__)
!defined(__CYGWIN__) && !defined(__MSYS__) && !defined(__QNX__)
uv_poll_t poll_handle;
int fd[2];

View File

@ -28,9 +28,9 @@ TEST_IMPL(process_priority) {
int r;
int i;
#if defined(__MVS__)
#if defined(__MVS__) || defined(__QNX__)
if (uv_os_setpriority(0, 0) == UV_ENOSYS)
RETURN_SKIP("functionality not supported on zOS");
RETURN_SKIP("functionality not supported on zOS and QNX");
#endif
/* Verify that passing a NULL pointer returns UV_EINVAL. */

View File

@ -85,7 +85,7 @@ TEST_IMPL(process_title_threadsafe) {
int i;
#if defined(__sun) || defined(__CYGWIN__) || defined(__MSYS__) || \
defined(__MVS__) || defined(__PASE__)
defined(__MVS__) || defined(__PASE__) || defined(__QNX__)
RETURN_SKIP("uv_(get|set)_process_title is not implemented.");
#endif

View File

@ -61,7 +61,7 @@ static void uv_get_process_title_edge_cases(void) {
TEST_IMPL(process_title) {
#if defined(__sun) || defined(__CYGWIN__) || defined(__MSYS__) || \
defined(__PASE__)
defined(__PASE__) || defined(__QNX__)
RETURN_SKIP("uv_(get|set)_process_title is not implemented.");
#endif

View File

@ -26,7 +26,7 @@
#include <stdlib.h>
#include <string.h>
#if defined(__FreeBSD__) || defined(__NetBSD__)
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__QNX__)
#include <sys/sysctl.h>
#endif
@ -49,7 +49,7 @@ static int recv_cb_called;
static int close_cb_called;
static uint16_t client_port;
#if defined(__FreeBSD__) || defined(__NetBSD__)
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__QNX__)
static int can_ipv6_ipv4_dual(void) {
int v6only;
size_t size = sizeof(int);
@ -228,7 +228,7 @@ TEST_IMPL(udp_dual_stack) {
if (!can_ipv6())
RETURN_SKIP("IPv6 not supported");
#if defined(__FreeBSD__) || defined(__NetBSD__)
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__QNX__)
if (!can_ipv6_ipv4_dual())
RETURN_SKIP("IPv6-IPv4 dual stack not supported");
#elif defined(__OpenBSD__)

View File

@ -144,8 +144,8 @@ static void cl_recv_cb(uv_udp_t* handle,
TEST_IMPL(udp_multicast_join) {
#if defined(__OpenBSD__)
RETURN_SKIP("Test does not currently work in OpenBSD");
#if defined(__OpenBSD__) || defined(QNX_IOPKT)
RETURN_SKIP("Test does not currently work in OpenBSD or QNX");
#endif
int r;
struct sockaddr_in addr;

View File

@ -35,7 +35,8 @@
defined(__MVS__) || \
defined(__FreeBSD__) || \
defined(__NetBSD__) || \
defined(__OpenBSD__)
defined(__OpenBSD__) || \
defined(__QNX__)
#define MULTICAST_ADDR "ff02::1%lo0"
#define INTERFACE_ADDR "::1%lo0"
#else
@ -167,6 +168,9 @@ static int can_ipv6_external(void) {
TEST_IMPL(udp_multicast_join6) {
#if defined(QNX_IOPKT)
RETURN_SKIP("Test does not currently work in QNX");
#endif
int r;
struct sockaddr_in6 addr;