From 1cff5b7557483164d980aa60e6e0225ecbbe7df1 Mon Sep 17 00:00:00 2001 From: John Barboza Date: Tue, 5 Jul 2016 18:37:45 -0400 Subject: [PATCH] zos: add support for new platform MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - zos: disable test cases not applicable - zos: build options - zos: semaphore implementation - zos: use compare and swap builtins - zos: struct rusage not the same as other platforms - zos: backlog<=0 produces undefined behaviour Will redefine backlog in the following way * if backlog == 0, set it to 1 * if backlog < 0, set it to SOMAXCONN - zos: define IMAXBEL as empty flag and implement uv__tty_make_raw - zos: use udp multicast operations from aix - zos: ESC in ebcdic - zos: use LIBPATH for dynamic linker path - zos: uv_udp_set_ttl only works for ipv6 - zos: increase pthread stack size by factor of 4 - zos: return ENODEV instead of ENXIO errors for setsockopt - zos: use uv_cond_init the same way as aix - test: enable oob test for zos - zos: return EINVAL for zos error code EOPNOTSUPP PR-URL: https://github.com/libuv/libuv/pull/937 Reviewed-By: Ben Noordhuis Reviewed-By: Saúl Ibarra Corretgé --- Makefile.am | 38 +++++++++++++++ common.gypi | 7 ++- configure.ac | 5 +- include/pthread-barrier.h | 2 + include/uv-os390.h | 27 +++++++++++ src/unix/atomic-ops.h | 12 +++++ src/unix/core.c | 6 +++ src/unix/pipe.c | 8 +++ src/unix/tcp.c | 4 ++ src/unix/thread.c | 86 ++++++++++++++++++++++++++++++++- src/unix/tty.c | 6 ++- src/unix/udp.c | 33 ++++++++++--- test/runner-unix.c | 8 +++ test/test-emfile.c | 4 +- test/test-fs-event.c | 42 ++++++++++++++++ test/test-fs.c | 2 +- test/test-poll.c | 14 +++--- test/test-process-title.c | 2 +- test/test-ref.c | 3 ++ test/test-spawn.c | 5 ++ test/test-udp-multicast-join6.c | 2 +- test/test-udp-options.c | 11 +++++ test/test-watcher-cross-stop.c | 3 ++ uv.gyp | 79 ++++++++++++++++++++++-------- 24 files changed, 366 insertions(+), 43 deletions(-) create mode 100644 include/uv-os390.h diff --git a/Makefile.am b/Makefile.am index a0437359..aab6b0c8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -129,7 +129,11 @@ EXTRA_DIST = test/fixtures/empty_file \ TESTS = test/run-tests check_PROGRAMS = test/run-tests +if OS390 +test_run_tests_CFLAGS = +else test_run_tests_CFLAGS = -Wno-long-long +endif test_run_tests_LDFLAGS = test_run_tests_SOURCES = test/blackhole-server.c \ test/dns-server.c \ @@ -284,6 +288,21 @@ if SUNOS test_run_tests_CFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=500 endif +if OS390 +test_run_tests_CFLAGS += -D_UNIX03_THREADS \ + -D_UNIX03_SOURCE \ + -D_OPEN_SYS_IF_EXT=1 \ + -D_OPEN_SYS_SOCK_IPV6 \ + -D_OPEN_MSGQ_EXT \ + -D_XOPEN_SOURCE_EXTENDED \ + -D_ALL_SOURCE \ + -D_LARGE_TIME_API \ + -D_OPEN_SYS_FILE_EXT \ + -DPATH_MAX=255 \ + -qCHARS=signed \ + -qXPLINK \ + -qFLOAT=IEEE +endif if AIX libuv_la_CFLAGS += -D_ALL_SOURCE -D_XOPEN_SOURCE=500 -D_LINUX_SOURCE_COMPAT -D_THREAD_SAFE @@ -354,6 +373,25 @@ libuv_la_CFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=500 libuv_la_SOURCES += src/unix/sunos.c endif +if OS390 +include_HEADERS += include/pthread-fixes.h include/pthread-barrier.h +libuv_la_CFLAGS += -D_UNIX03_THREADS \ + -D_UNIX03_SOURCE \ + -D_OPEN_SYS_IF_EXT=1 \ + -D_OPEN_MSGQ_EXT \ + -D_XOPEN_SOURCE_EXTENDED \ + -D_ALL_SOURCE \ + -D_LARGE_TIME_API \ + -D_OPEN_SYS_SOCK_IPV6 \ + -D_OPEN_SYS_FILE_EXT \ + -DUV_PLATFORM_SEM_T=int \ + -DPATH_MAX=255 \ + -qCHARS=signed \ + -qXPLINK \ + -qFLOAT=IEEE +libuv_la_LDFLAGS += -qXPLINK +endif + if HAVE_PKG_CONFIG pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = @PACKAGE_NAME@.pc diff --git a/common.gypi b/common.gypi index 56bca294..44db701d 100644 --- a/common.gypi +++ b/common.gypi @@ -11,7 +11,7 @@ 'configurations': { 'Debug': { 'defines': [ 'DEBUG', '_DEBUG' ], - 'cflags': [ '-g', '-O0', '-fwrapv' ], + 'cflags': [ '-g' ], 'msvs_settings': { 'VCCLCompilerTool': { 'target_conditions': [ @@ -35,6 +35,9 @@ 'OTHER_CFLAGS': [ '-Wno-strict-aliasing' ], }, 'conditions': [ + ['OS != "zos"', { + 'cflags': [ '-O0', '-fwrapv' ] + }], ['OS == "android"', { 'cflags': [ '-fPIE' ], 'ldflags': [ '-fPIE', '-pie' ] @@ -151,7 +154,7 @@ 'cflags': [ '-pthreads' ], 'ldflags': [ '-pthreads' ], }], - [ 'OS not in "solaris android"', { + [ 'OS not in "solaris android zos"', { 'cflags': [ '-pthread' ], 'ldflags': [ '-pthread' ], }], diff --git a/configure.ac b/configure.ac index 4a106bec..239e919c 100644 --- a/configure.ac +++ b/configure.ac @@ -24,10 +24,12 @@ AC_ENABLE_SHARED AC_ENABLE_STATIC AC_PROG_CC AM_PROG_CC_C_O +AS_IF([AS_CASE([$host_os],[openedition*], [false], [true])], [ + CC_CHECK_CFLAGS_APPEND([-pedantic]) +]) CC_FLAG_VISIBILITY #[-fvisibility=hidden] CC_CHECK_CFLAGS_APPEND([-g]) CC_CHECK_CFLAGS_APPEND([-std=gnu89]) -CC_CHECK_CFLAGS_APPEND([-pedantic]) CC_CHECK_CFLAGS_APPEND([-Wall]) CC_CHECK_CFLAGS_APPEND([-Wextra]) CC_CHECK_CFLAGS_APPEND([-Wno-unused-parameter]) @@ -56,6 +58,7 @@ AM_CONDITIONAL([FREEBSD], [AS_CASE([$host_os],[freebsd*], [true], [false]) AM_CONDITIONAL([LINUX], [AS_CASE([$host_os],[linux*], [true], [false])]) AM_CONDITIONAL([NETBSD], [AS_CASE([$host_os],[netbsd*], [true], [false])]) AM_CONDITIONAL([OPENBSD], [AS_CASE([$host_os],[openbsd*], [true], [false])]) +AM_CONDITIONAL([OS390], [AS_CASE([$host_os],[openedition*], [true], [false])]) AM_CONDITIONAL([SUNOS], [AS_CASE([$host_os],[solaris*], [true], [false])]) AM_CONDITIONAL([WINNT], [AS_CASE([$host_os],[mingw*], [true], [false])]) AS_CASE([$host_os],[mingw*], [ diff --git a/include/pthread-barrier.h b/include/pthread-barrier.h index 084e1c2d..68468ad2 100644 --- a/include/pthread-barrier.h +++ b/include/pthread-barrier.h @@ -39,6 +39,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 2 * sizeof(sem_t) + \ 2 * sizeof(unsigned int) - \ sizeof(void *) +#elif defined(__MVS__) +# define UV_BARRIER_STRUCT_PADDING 0 #endif typedef struct { diff --git a/include/uv-os390.h b/include/uv-os390.h new file mode 100644 index 00000000..b0b068f4 --- /dev/null +++ b/include/uv-os390.h @@ -0,0 +1,27 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef UV_MVS_H +#define UV_MVS_H + +#define UV_PLATFORM_SEM_T int + +#endif /* UV_MVS_H */ diff --git a/src/unix/atomic-ops.h b/src/unix/atomic-ops.h index 84e47183..334c343e 100644 --- a/src/unix/atomic-ops.h +++ b/src/unix/atomic-ops.h @@ -42,6 +42,10 @@ UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) { const int out = (*(volatile int*) ptr); __compare_and_swap(ptr, &oldval, newval); return out; +#elif defined(__MVS__) + const int out = (*(volatile int*) ptr); + cs((cs_t*)&oldval, (cs_t*)ptr, *(cs_t*)(&newval)); + return out; #else return __sync_val_compare_and_swap(ptr, oldval, newval); #endif @@ -63,6 +67,14 @@ UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)) { __compare_and_swap(ptr, &oldval, newval); # endif /* if defined(__64BIT__) */ return out; +#elif defined (__MVS__) + const long out = (*(volatile int*) ptr); +# ifdef _LP64 + cds((cds_t*)(&oldval), (cds_t*)ptr, *(cds_t*)(&newval)); +# else + cs((cs_t*)&oldval, (cs_t*)ptr, *(cs_t*)(&newval)); +# endif + return out; #else return __sync_val_compare_and_swap(ptr, oldval, newval); #endif diff --git a/src/unix/core.c b/src/unix/core.c index 64522383..3df966e2 100644 --- a/src/unix/core.c +++ b/src/unix/core.c @@ -74,6 +74,10 @@ # include /* for dlsym */ #endif +#if defined(__MVS__) +#include +#endif + static int uv__run_pending(uv_loop_t* loop); /* Verify that uv_buf_t is ABI-compatible with struct iovec. */ @@ -915,6 +919,7 @@ int uv_getrusage(uv_rusage_t* rusage) { rusage->ru_stime.tv_sec = usage.ru_stime.tv_sec; rusage->ru_stime.tv_usec = usage.ru_stime.tv_usec; +#if !defined(__MVS__) rusage->ru_maxrss = usage.ru_maxrss; rusage->ru_ixrss = usage.ru_ixrss; rusage->ru_idrss = usage.ru_idrss; @@ -929,6 +934,7 @@ int uv_getrusage(uv_rusage_t* rusage) { rusage->ru_nsignals = usage.ru_nsignals; rusage->ru_nvcsw = usage.ru_nvcsw; rusage->ru_nivcsw = usage.ru_nivcsw; +#endif return 0; } diff --git a/src/unix/pipe.c b/src/unix/pipe.c index c8d163dc..a3797dda 100644 --- a/src/unix/pipe.c +++ b/src/unix/pipe.c @@ -97,6 +97,14 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) { if (uv__stream_fd(handle) == -1) return -EINVAL; +#if defined(__MVS__) + /* On zOS, backlog=0 has undefined behaviour */ + if (backlog == 0) + backlog = 1; + else if (backlog < 0) + backlog = SOMAXCONN; +#endif + if (listen(uv__stream_fd(handle), backlog)) return -errno; diff --git a/src/unix/tcp.c b/src/unix/tcp.c index 46d8cd25..fa52a137 100644 --- a/src/unix/tcp.c +++ b/src/unix/tcp.c @@ -115,6 +115,10 @@ int uv__tcp_bind(uv_tcp_t* tcp, IPV6_V6ONLY, &on, sizeof on) == -1) { +#if defined(__MVS__) + if (errno == EOPNOTSUPP) + return -EINVAL; +#endif return -errno; } } diff --git a/src/unix/thread.c b/src/unix/thread.c index 236f5913..52989f7f 100644 --- a/src/unix/thread.c +++ b/src/unix/thread.c @@ -32,6 +32,11 @@ #include +#ifdef __MVS__ +#include +#include +#endif + #undef NANOSEC #define NANOSEC ((uint64_t) 1e9) @@ -302,6 +307,85 @@ int uv_sem_trywait(uv_sem_t* sem) { return -EINVAL; /* Satisfy the compiler. */ } +#elif defined(__MVS__) + +int uv_sem_init(uv_sem_t* sem, unsigned int value) { + uv_sem_t semid; + struct sembuf buf; + int err; + + buf.sem_num = 0; + buf.sem_op = value; + buf.sem_flg = 0; + + semid = semget(IPC_PRIVATE, 1, S_IRUSR | S_IWUSR); + if (semid == -1) + return -errno; + + if (-1 == semop(semid, &buf, 1)) { + err = errno; + if (-1 == semctl(*sem, 0, IPC_RMID)) + abort(); + return -err; + } + + *sem = semid; + return 0; +} + +void uv_sem_destroy(uv_sem_t* sem) { + if (-1 == semctl(*sem, 0, IPC_RMID)) + abort(); +} + +void uv_sem_post(uv_sem_t* sem) { + struct sembuf buf; + + buf.sem_num = 0; + buf.sem_op = 1; + buf.sem_flg = 0; + + if (-1 == semop(*sem, &buf, 1)) + abort(); +} + +void uv_sem_wait(uv_sem_t* sem) { + struct sembuf buf; + int op_status; + + buf.sem_num = 0; + buf.sem_op = -1; + buf.sem_flg = 0; + + do + op_status = semop(*sem, &buf, 1); + while (op_status == -1 && errno == EINTR); + + if (op_status) + abort(); +} + +int uv_sem_trywait(uv_sem_t* sem) { + struct sembuf buf; + int op_status; + + buf.sem_num = 0; + buf.sem_op = -1; + buf.sem_flg = IPC_NOWAIT; + + do + op_status = semop(*sem, &buf, 1); + while (op_status == -1 && errno == EINTR); + + if (op_status) { + if (errno == EAGAIN) + return -EAGAIN; + abort(); + } + + return 0; +} + #else /* !(defined(__APPLE__) && defined(__MACH__)) */ int uv_sem_init(uv_sem_t* sem, unsigned int value) { @@ -354,7 +438,7 @@ int uv_sem_trywait(uv_sem_t* sem) { #endif /* defined(__APPLE__) && defined(__MACH__) */ -#if defined(__APPLE__) && defined(__MACH__) +#if defined(__APPLE__) && defined(__MACH__) || defined(__MVS__) int uv_cond_init(uv_cond_t* cond) { return -pthread_cond_init(cond, NULL); diff --git a/src/unix/tty.c b/src/unix/tty.c index a56afe18..fd4bcbcf 100644 --- a/src/unix/tty.c +++ b/src/unix/tty.c @@ -30,6 +30,10 @@ #include #include +#if defined(__MVS__) && !defined(IMAXBEL) +#define IMAXBEL 0 +#endif + static int orig_termios_fd = -1; static struct termios orig_termios; static uv_spinlock_t termios_spinlock = UV_SPINLOCK_INITIALIZER; @@ -168,7 +172,7 @@ skip: static void uv__tty_make_raw(struct termios* tio) { assert(tio != NULL); -#ifdef __sun +#if defined __sun || defined __MVS__ /* * This implementation of cfmakeraw for Solaris and derivatives is taken from * http://www.perkin.org.uk/posts/solaris-portability-cfmakeraw.html. diff --git a/src/unix/udp.c b/src/unix/udp.c index f5d7ed14..7c9dae99 100644 --- a/src/unix/udp.c +++ b/src/unix/udp.c @@ -27,6 +27,9 @@ #include #include #include +#if defined(__MVS__) +#include +#endif #if defined(IPV6_JOIN_GROUP) && !defined(IPV6_ADD_MEMBERSHIP) # define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP @@ -508,6 +511,10 @@ static int uv__udp_set_membership4(uv_udp_t* handle, optname, &mreq, sizeof(mreq))) { +#if defined(__MVS__) + if (errno == ENXIO) + return -ENODEV; +#endif return -errno; } @@ -551,6 +558,10 @@ static int uv__udp_set_membership6(uv_udp_t* handle, optname, &mreq, sizeof(mreq))) { +#if defined(__MVS__) + if (errno == ENXIO) + return -ENODEV; +#endif return -errno; } @@ -669,7 +680,7 @@ static int uv__setsockopt_maybe_char(uv_udp_t* handle, int option4, int option6, int val) { -#if defined(__sun) || defined(_AIX) +#if defined(__sun) || defined(_AIX) || defined(__MVS__) char arg = val; #elif defined(__OpenBSD__) unsigned char arg = val; @@ -701,19 +712,27 @@ int uv_udp_set_ttl(uv_udp_t* handle, int ttl) { if (ttl < 1 || ttl > 255) return -EINVAL; +#if defined(__MVS__) + if (!(handle->flags & UV_HANDLE_IPV6)) + return -ENOTSUP; /* zOS does not support setting ttl for IPv4 */ +#endif + /* * On Solaris and derivatives such as SmartOS, the length of socket options * is sizeof(int) for IP_TTL and IPV6_UNICAST_HOPS, * so hardcode the size of these options on this platform, * and use the general uv__setsockopt_maybe_char call on other platforms. */ -#if defined(__sun) || defined(_AIX) || defined(__OpenBSD__) +#if defined(__sun) || defined(_AIX) || defined(__OpenBSD__) || \ + defined(__MVS__) + return uv__setsockopt(handle, IP_TTL, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl)); -#endif /* defined(__sun) || defined(_AIX) || defined (__OpenBSD__) */ +#endif /* defined(__sun) || defined(_AIX) || defined (__OpenBSD__) || + defined(__MVS__) */ return uv__setsockopt_maybe_char(handle, IP_TTL, @@ -729,14 +748,14 @@ int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl) { * IP_MULTICAST_TTL, so hardcode the size of the option in the IPv6 case, * and use the general uv__setsockopt_maybe_char call otherwise. */ -#if defined(__sun) || defined(_AIX) +#if defined(__sun) || defined(_AIX) || defined(__MVS__) if (handle->flags & UV_HANDLE_IPV6) return uv__setsockopt(handle, IP_MULTICAST_TTL, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)); -#endif /* defined(__sun) || defined(_AIX) */ +#endif /* defined(__sun) || defined(_AIX) || defined(__MVS__) */ return uv__setsockopt_maybe_char(handle, IP_MULTICAST_TTL, @@ -752,14 +771,14 @@ int uv_udp_set_multicast_loop(uv_udp_t* handle, int on) { * IP_MULTICAST_LOOP, so hardcode the size of the option in the IPv6 case, * and use the general uv__setsockopt_maybe_char call otherwise. */ -#if defined(__sun) || defined(_AIX) +#if defined(__sun) || defined(_AIX) || defined(__MVS__) if (handle->flags & UV_HANDLE_IPV6) return uv__setsockopt(handle, IP_MULTICAST_LOOP, IPV6_MULTICAST_LOOP, &on, sizeof(on)); -#endif /* defined(__sun) || defined(_AIX) */ +#endif /* defined(__sun) || defined(_AIX) || defined(__MVS__) */ return uv__setsockopt_maybe_char(handle, IP_MULTICAST_LOOP, diff --git a/test/runner-unix.c b/test/runner-unix.c index 0edd671b..63f801b5 100644 --- a/test/runner-unix.c +++ b/test/runner-unix.c @@ -201,7 +201,11 @@ int process_wait(process_info_t* vec, int n, int timeout) { if (pthread_attr_init(&attr)) abort(); +#if defined(__MVS__) + if (pthread_attr_setstacksize(&attr, 1024 * 1024)) +#else if (pthread_attr_setstacksize(&attr, 256 * 1024)) +#endif abort(); r = pthread_create(&tid, &attr, dowait, &args); @@ -372,7 +376,11 @@ void process_cleanup(process_info_t *p) { /* Move the console cursor one line up and back to the first column. */ void rewind_cursor(void) { +#if defined(__MVS__) + fprintf(stderr, "\047[2K\r"); +#else fprintf(stderr, "\033[2K\r"); +#endif } diff --git a/test/test-emfile.c b/test/test-emfile.c index 5f4dd9ef..8e44ac5c 100644 --- a/test/test-emfile.c +++ b/test/test-emfile.c @@ -38,12 +38,12 @@ static uv_tcp_t client_handle; TEST_IMPL(emfile) { -#ifdef _AIX +#if defined(_AIX) || defined(__MVS__) /* On AIX, if a 'accept' call fails ECONNRESET is set on the socket * which causes uv__emfile_trick to not work as intended and this test * to fail. */ - RETURN_SKIP("uv__emfile_trick does not work on AIX"); + RETURN_SKIP("uv__emfile_trick does not work on this OS"); #endif struct sockaddr_in addr; struct rlimit limits; diff --git a/test/test-fs-event.c b/test/test-fs-event.c index 25eef07b..7dd2cb39 100644 --- a/test/test-fs-event.c +++ b/test/test-fs-event.c @@ -376,6 +376,10 @@ static void timer_cb_watch_twice(uv_timer_t* handle) { } TEST_IMPL(fs_event_watch_dir) { +#if defined(__MVS__) + RETURN_SKIP("Filesystem watching not supported on this platform."); +#endif + uv_loop_t* loop = uv_default_loop(); int r; @@ -455,6 +459,10 @@ TEST_IMPL(fs_event_watch_dir_recursive) { TEST_IMPL(fs_event_watch_file) { +#if defined(__MVS__) + RETURN_SKIP("Filesystem watching not supported on this platform."); +#endif + uv_loop_t* loop = uv_default_loop(); int r; @@ -495,6 +503,11 @@ TEST_IMPL(fs_event_watch_file_exact_path) { This test watches a file named "file.jsx" and modifies a file named "file.js". The test verifies that no events occur for file.jsx. */ + +#if defined(__MVS__) + RETURN_SKIP("Filesystem watching not supported on this platform."); +#endif + uv_loop_t* loop; int r; @@ -530,6 +543,9 @@ TEST_IMPL(fs_event_watch_file_exact_path) { } TEST_IMPL(fs_event_watch_file_twice) { +#if defined(__MVS__) + RETURN_SKIP("Filesystem watching not supported on this platform."); +#endif const char path[] = "test/fixtures/empty_file"; uv_fs_event_t watchers[2]; uv_timer_t timer; @@ -551,6 +567,9 @@ TEST_IMPL(fs_event_watch_file_twice) { } TEST_IMPL(fs_event_watch_file_current_dir) { +#if defined(__MVS__) + RETURN_SKIP("Filesystem watching not supported on this platform."); +#endif uv_timer_t timer; uv_loop_t* loop; int r; @@ -621,6 +640,10 @@ TEST_IMPL(fs_event_watch_file_root_dir) { #endif TEST_IMPL(fs_event_no_callback_after_close) { +#if defined(__MVS__) + RETURN_SKIP("Filesystem watching not supported on this platform."); +#endif + uv_loop_t* loop = uv_default_loop(); int r; @@ -655,6 +678,10 @@ TEST_IMPL(fs_event_no_callback_after_close) { } TEST_IMPL(fs_event_no_callback_on_close) { +#if defined(__MVS__) + RETURN_SKIP("Filesystem watching not supported on this platform."); +#endif + uv_loop_t* loop = uv_default_loop(); int r; @@ -702,6 +729,9 @@ static void timer_cb(uv_timer_t* handle) { TEST_IMPL(fs_event_immediate_close) { +#if defined(__MVS__) + RETURN_SKIP("Filesystem watching not supported on this platform."); +#endif uv_timer_t timer; uv_loop_t* loop; int r; @@ -724,6 +754,9 @@ TEST_IMPL(fs_event_immediate_close) { TEST_IMPL(fs_event_close_with_pending_event) { +#if defined(__MVS__) + RETURN_SKIP("Filesystem watching not supported on this platform."); +#endif uv_loop_t* loop; int r; @@ -782,6 +815,9 @@ static void fs_event_cb_close(uv_fs_event_t* handle, const char* filename, TEST_IMPL(fs_event_close_in_callback) { +#if defined(__MVS__) + RETURN_SKIP("Filesystem watching not supported on this platform."); +#endif uv_loop_t* loop; int r; @@ -826,6 +862,9 @@ TEST_IMPL(fs_event_close_in_callback) { #endif /* HAVE_KQUEUE || _AIX */ TEST_IMPL(fs_event_start_and_close) { +#if defined(__MVS__) + RETURN_SKIP("Filesystem watching not supported on this platform."); +#endif uv_loop_t* loop; uv_fs_event_t fs_event1; uv_fs_event_t fs_event2; @@ -858,6 +897,9 @@ TEST_IMPL(fs_event_start_and_close) { } TEST_IMPL(fs_event_getpath) { +#if defined(__MVS__) + RETURN_SKIP("Filesystem watching not supported on this platform."); +#endif uv_loop_t* loop = uv_default_loop(); int r; char buf[1024]; diff --git a/test/test-fs.c b/test/test-fs.c index 250d1350..7c3c6f20 100644 --- a/test/test-fs.c +++ b/test/test-fs.c @@ -29,7 +29,7 @@ /* FIXME we shouldn't need to branch in this file */ #if defined(__unix__) || defined(__POSIX__) || \ - defined(__APPLE__) || defined(_AIX) + defined(__APPLE__) || defined(_AIX) || defined(__MVS__) #include /* unlink, rmdir, etc. */ #else # include diff --git a/test/test-poll.c b/test/test-poll.c index 33d0761a..848ce88a 100644 --- a/test/test-poll.c +++ b/test/test-poll.c @@ -82,9 +82,9 @@ static int closed_connections = 0; static int valid_writable_wakeups = 0; static int spurious_writable_wakeups = 0; -#ifndef _AIX +#if !defined(_AIX) && !defined(__MVS__) static int disconnects = 0; -#endif /* !_AIX */ +#endif /* !_AIX && !__MVS__ */ static int got_eagain(void) { #ifdef _WIN32 @@ -388,7 +388,7 @@ static void connection_poll_cb(uv_poll_t* handle, int status, int events) { new_events &= ~UV_WRITABLE; } } -#ifndef _AIX +#if !defined(_AIX) && !defined(__MVS__) if (events & UV_DISCONNECT) { context->got_disconnect = 1; ++disconnects; @@ -396,9 +396,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 /* _AIX */ +#else /* _AIX && __MVS__ */ if (context->got_fin && context->sent_fin) { -#endif /* !_AIx */ +#endif /* !_AIX && !__MVS__ */ /* Sent and received FIN. Close and destroy context. */ close_socket(context->sock); destroy_connection_context(context); @@ -566,7 +566,7 @@ static void start_poll_test(void) { spurious_writable_wakeups > 20); ASSERT(closed_connections == NUM_CLIENTS * 2); -#ifndef _AIX +#if !defined(_AIX) && !defined(__MVS__) ASSERT(disconnects == NUM_CLIENTS * 2); #endif MAKE_VALGRIND_HAPPY(); @@ -594,7 +594,7 @@ TEST_IMPL(poll_unidirectional) { */ TEST_IMPL(poll_bad_fdtype) { #if !defined(__DragonFly__) && !defined(__FreeBSD__) && !defined(__sun) && \ - !defined(_AIX) + !defined(_AIX) && !defined(__MVS__) uv_poll_t poll_handle; int fd; diff --git a/test/test-process-title.c b/test/test-process-title.c index 00f164a4..21ab0ed4 100644 --- a/test/test-process-title.c +++ b/test/test-process-title.c @@ -60,7 +60,7 @@ static void uv_get_process_title_edge_cases() { TEST_IMPL(process_title) { -#if defined(__sun) || defined(_AIX) +#if defined(__sun) || defined(_AIX) || defined(__MVS__) RETURN_SKIP("uv_(get|set)_process_title is not implemented."); #else /* Check for format string vulnerabilities. */ diff --git a/test/test-ref.c b/test/test-ref.c index ddaa1738..39f4b0fc 100644 --- a/test/test-ref.c +++ b/test/test-ref.c @@ -194,6 +194,9 @@ TEST_IMPL(timer_ref2) { TEST_IMPL(fs_event_ref) { +#if defined(__MVS__) + RETURN_SKIP("Filesystem watching not supported on this platform."); +#endif uv_fs_event_t h; uv_fs_event_init(uv_default_loop(), &h); uv_fs_event_start(&h, (uv_fs_event_cb)fail_cb, ".", 0); diff --git a/test/test-spawn.c b/test/test-spawn.c index eba54ae7..0e84ad6d 100644 --- a/test/test-spawn.c +++ b/test/test-spawn.c @@ -1431,6 +1431,9 @@ TEST_IMPL(spawn_fs_open) { #ifndef _WIN32 TEST_IMPL(closed_fd_events) { +#if defined(__MVS__) + RETURN_SKIP("Filesystem watching not supported on this platform."); +#endif uv_stdio_container_t stdio[3]; uv_pipe_t pipe_handle; int fd[2]; @@ -1500,6 +1503,8 @@ TEST_IMPL(spawn_reads_child_path) { */ #if defined(__APPLE__) static const char dyld_path_var[] = "DYLD_LIBRARY_PATH"; +#elif defined __MVS__ + static const char dyld_path_var[] = "LIBPATH"; #else static const char dyld_path_var[] = "LD_LIBRARY_PATH"; #endif diff --git a/test/test-udp-multicast-join6.c b/test/test-udp-multicast-join6.c index f635bdb9..26a27d60 100644 --- a/test/test-udp-multicast-join6.c +++ b/test/test-udp-multicast-join6.c @@ -119,7 +119,7 @@ TEST_IMPL(udp_multicast_join6) { ASSERT(r == 0); /* join the multicast channel */ -#if defined(__APPLE__) || defined(_AIX) +#if defined(__APPLE__) || defined(_AIX) || defined(__MVS__) r = uv_udp_set_membership(&client, "ff02::1", "::1%lo0", UV_JOIN_GROUP); #else r = uv_udp_set_membership(&client, "ff02::1", NULL, UV_JOIN_GROUP); diff --git a/test/test-udp-options.c b/test/test-udp-options.c index 0da1786f..8f913675 100644 --- a/test/test-udp-options.c +++ b/test/test-udp-options.c @@ -52,7 +52,14 @@ static int udp_options_test(const struct sockaddr* addr) { /* values 1-255 should work */ for (i = 1; i <= 255; i++) { r = uv_udp_set_ttl(&h, i); +#if defined(__MVS__) + if (addr->sa_family == AF_INET6) + ASSERT(r == 0); + else + ASSERT(r == UV_ENOTSUP); +#else ASSERT(r == 0); +#endif } for (i = 0; i < (int) ARRAY_SIZE(invalid_ttls); i++) { @@ -113,7 +120,11 @@ TEST_IMPL(udp_no_autobind) { ASSERT(0 == uv_udp_init(loop, &h)); ASSERT(UV_EBADF == uv_udp_set_multicast_ttl(&h, 32)); ASSERT(UV_EBADF == uv_udp_set_broadcast(&h, 1)); +#if defined(__MVS__) + ASSERT(UV_ENOTSUP == uv_udp_set_ttl(&h, 1)); +#else ASSERT(UV_EBADF == uv_udp_set_ttl(&h, 1)); +#endif ASSERT(UV_EBADF == uv_udp_set_multicast_loop(&h, 1)); ASSERT(UV_EBADF == uv_udp_set_multicast_interface(&h, "0.0.0.0")); diff --git a/test/test-watcher-cross-stop.c b/test/test-watcher-cross-stop.c index 910ed0fb..6ff48d44 100644 --- a/test/test-watcher-cross-stop.c +++ b/test/test-watcher-cross-stop.c @@ -59,6 +59,9 @@ static void close_cb(uv_handle_t* handle) { TEST_IMPL(watcher_cross_stop) { +#if defined(__MVS__) + RETURN_SKIP("zOS does not allow address or port reuse when using UDP sockets"); +#endif uv_loop_t* loop = uv_default_loop(); unsigned int i; struct sockaddr_in addr; diff --git a/uv.gyp b/uv.gyp index 953a6fdc..3a480dea 100644 --- a/uv.gyp +++ b/uv.gyp @@ -10,9 +10,25 @@ ['OS=="solaris"', { 'cflags': [ '-pthreads' ], }], - ['OS not in "solaris android"', { + ['OS not in "solaris android zos"', { 'cflags': [ '-pthread' ], }], + ['OS in "zos"', { + 'defines': [ + '_UNIX03_THREADS', + '_UNIX03_SOURCE', + '_OPEN_SYS_IF_EXT', + '_OPEN_SYS_SOCK_IPV6', + '_OPEN_MSGQ_EXT', + '_XOPEN_SOURCE_EXTENDED', + '_ALL_SOURCE', + '_LARGE_TIME_API', + '_OPEN_SYS_FILE_EXT', + '_AE_BIMODAL', + 'PATH_MAX=255' + ], + 'cflags': [ '-qxplink' ], + }] ], }], ], @@ -119,15 +135,6 @@ ], }, }, { # Not Windows i.e. POSIX - 'cflags': [ - '-fvisibility=hidden', - '-g', - '--std=gnu89', - '-pedantic', - '-Wall', - '-Wextra', - '-Wno-unused-parameter', - ], 'sources': [ 'include/uv-unix.h', 'include/uv-linux.h', @@ -163,16 +170,25 @@ ['OS=="solaris"', { 'ldflags': [ '-pthreads' ], }], - ['OS != "solaris" and OS != "android"', { + [ 'OS=="zos" and uv_library=="shared_library"', { + 'ldflags': [ '-Wl,DLL' ], + }], + ['OS != "solaris" and OS != "android" and OS != "zos"', { 'ldflags': [ '-pthread' ], }], ], }, 'conditions': [ ['uv_library=="shared_library"', { - 'cflags': [ '-fPIC' ], + 'conditions': [ + ['OS=="zos"', { + 'cflags': [ '-qexportall' ], + }, { + 'cflags': [ '-fPIC' ], + }], + ], }], - ['uv_library=="shared_library" and OS!="mac"', { + ['uv_library=="shared_library" and OS!="mac" and OS!="zos"', { # This will cause gyp to set soname # Must correspond with UV_VERSION_MAJOR # in include/uv-version.h @@ -183,6 +199,17 @@ [ 'OS in "linux mac ios android"', { 'sources': [ 'src/unix/proctitle.c' ], }], + [ 'OS != "zos"', { + 'cflags': [ + '-fvisibility=hidden', + '-g', + '--std=gnu89', + '-pedantic', + '-Wall', + '-Wextra', + '-Wno-unused-parameter', + ], + }], [ 'OS in "mac ios"', { 'sources': [ 'src/unix/darwin.c', @@ -195,7 +222,7 @@ '_DARWIN_UNLIMITED_SELECT=1', ] }], - [ 'OS!="mac"', { + [ 'OS!="mac" and OS!="zos"', { # Enable on all platforms except OS X. The antique gcc/clang that # ships with Xcode emits waaaay too many false positives. 'cflags': [ '-Wstrict-aliasing' ], @@ -428,13 +455,17 @@ ], 'libraries': [ '-lws2_32' ] }, { # POSIX - 'defines': [ '_GNU_SOURCE' ], - 'cflags': [ '-Wno-long-long' ], 'sources': [ 'test/runner-unix.c', 'test/runner-unix.h', ], - }], + 'conditions': [ + [ 'OS != "zos"', { + 'defines': [ '_GNU_SOURCE' ], + 'cflags': [ '-Wno-long-long' ], + }], + ]}, + ], [ 'OS in "mac dragonflybsd freebsd linux netbsd openbsd".split()', { 'link_settings': { 'libraries': [ '-lutil' ], @@ -453,7 +484,12 @@ ], }], ['uv_library=="shared_library"', { - 'defines': [ 'USING_UV_SHARED=1' ] + 'defines': [ 'USING_UV_SHARED=1' ], + 'conditions': [ + [ 'OS == "zos"', { + 'cflags': [ '-Wc,DLL' ], + }], + ], }], ], 'msvs-settings': { @@ -509,7 +545,12 @@ ] }], ['uv_library=="shared_library"', { - 'defines': [ 'USING_UV_SHARED=1' ] + 'defines': [ 'USING_UV_SHARED=1' ], + 'conditions': [ + [ 'OS == "zos"', { + 'cflags': [ '-Wc,DLL' ], + }], + ], }], ], 'msvs-settings': {