mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-05 21:31:08 -06:00
Merge branch 'upstream-libuv' into update-libuv
* upstream-libuv: libuv 2017-02-21 (52ae8264)
This commit is contained in:
@@ -18,7 +18,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#define _UV_PTHREAD_BARRIER_
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#if !defined(__MVS__)
|
||||
#include <semaphore.h> /* sem_t */
|
||||
#endif
|
||||
|
||||
#define PTHREAD_BARRIER_SERIAL_THREAD 0x12345
|
||||
|
||||
|
||||
@@ -24,4 +24,7 @@
|
||||
|
||||
#define UV_PLATFORM_SEM_T int
|
||||
|
||||
#define UV_PLATFORM_LOOP_FIELDS \
|
||||
void* ep; \
|
||||
|
||||
#endif /* UV_MVS_H */
|
||||
|
||||
@@ -36,7 +36,9 @@
|
||||
#include <termios.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#if !defined(__MVS__)
|
||||
#include <semaphore.h>
|
||||
#endif
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
|
||||
@@ -44,6 +46,8 @@
|
||||
|
||||
#if defined(__linux__)
|
||||
# include "uv-linux.h"
|
||||
#elif defined (__MVS__)
|
||||
# include "uv-os390.h"
|
||||
#elif defined(_AIX)
|
||||
# include "uv-aix.h"
|
||||
#elif defined(__sun)
|
||||
|
||||
@@ -31,8 +31,8 @@
|
||||
*/
|
||||
|
||||
#define UV_VERSION_MAJOR 1
|
||||
#define UV_VERSION_MINOR 9
|
||||
#define UV_VERSION_PATCH 2
|
||||
#define UV_VERSION_MINOR 11
|
||||
#define UV_VERSION_PATCH 1
|
||||
#define UV_VERSION_IS_RELEASE 0
|
||||
#define UV_VERSION_SUFFIX "dev"
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ typedef struct pollfd {
|
||||
|
||||
#include <process.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1600
|
||||
|
||||
@@ -367,6 +367,8 @@ typedef enum {
|
||||
} uv_membership;
|
||||
|
||||
|
||||
UV_EXTERN int uv_translate_sys_error(int sys_errno);
|
||||
|
||||
UV_EXTERN const char* uv_strerror(int err);
|
||||
UV_EXTERN const char* uv_err_name(int err);
|
||||
|
||||
|
||||
@@ -64,6 +64,11 @@
|
||||
#define RDWR_BUF_SIZE 4096
|
||||
#define EQ(a,b) (strcmp(a,b) == 0)
|
||||
|
||||
static void* args_mem = NULL;
|
||||
static char** process_argv = NULL;
|
||||
static int process_argc = 0;
|
||||
static char* process_title_ptr = NULL;
|
||||
|
||||
int uv__platform_loop_init(uv_loop_t* loop) {
|
||||
loop->fs_fd = -1;
|
||||
|
||||
@@ -753,6 +758,13 @@ static void uv__ahafs_event(uv_loop_t* loop, uv__io_t* event_watch, unsigned int
|
||||
|
||||
assert((bytes >= 0) && "uv__ahafs_event - Error reading monitor file");
|
||||
|
||||
/* In file / directory move cases, AIX Event infrastructure
|
||||
* produces a second event with no data.
|
||||
* Ignore it and return gracefully.
|
||||
*/
|
||||
if(bytes == 0)
|
||||
return;
|
||||
|
||||
/* Parse the data */
|
||||
if(bytes > 0)
|
||||
rc = uv__parse_data(result_data, &events, handle);
|
||||
@@ -881,24 +893,94 @@ void uv__fs_event_close(uv_fs_event_t* handle) {
|
||||
|
||||
|
||||
char** uv_setup_args(int argc, char** argv) {
|
||||
return argv;
|
||||
char** new_argv;
|
||||
size_t size;
|
||||
char* s;
|
||||
int i;
|
||||
|
||||
if (argc <= 0)
|
||||
return argv;
|
||||
|
||||
/* Save the original pointer to argv.
|
||||
* AIX uses argv to read the process name.
|
||||
* (Not the memory pointed to by argv[0..n] as on Linux.)
|
||||
*/
|
||||
process_argv = argv;
|
||||
process_argc = argc;
|
||||
|
||||
/* Calculate how much memory we need for the argv strings. */
|
||||
size = 0;
|
||||
for (i = 0; i < argc; i++)
|
||||
size += strlen(argv[i]) + 1;
|
||||
|
||||
/* Add space for the argv pointers. */
|
||||
size += (argc + 1) * sizeof(char*);
|
||||
|
||||
new_argv = uv__malloc(size);
|
||||
if (new_argv == NULL)
|
||||
return argv;
|
||||
args_mem = new_argv;
|
||||
|
||||
/* Copy over the strings and set up the pointer table. */
|
||||
s = (char*) &new_argv[argc + 1];
|
||||
for (i = 0; i < argc; i++) {
|
||||
size = strlen(argv[i]) + 1;
|
||||
memcpy(s, argv[i], size);
|
||||
new_argv[i] = s;
|
||||
s += size;
|
||||
}
|
||||
new_argv[i] = NULL;
|
||||
|
||||
return new_argv;
|
||||
}
|
||||
|
||||
|
||||
int uv_set_process_title(const char* title) {
|
||||
char* new_title;
|
||||
|
||||
/* We cannot free this pointer when libuv shuts down,
|
||||
* the process may still be using it.
|
||||
*/
|
||||
new_title = uv__strdup(title);
|
||||
if (new_title == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
/* If this is the first time this is set,
|
||||
* don't free and set argv[1] to NULL.
|
||||
*/
|
||||
if (process_title_ptr != NULL)
|
||||
uv__free(process_title_ptr);
|
||||
|
||||
process_title_ptr = new_title;
|
||||
|
||||
process_argv[0] = process_title_ptr;
|
||||
if (process_argc > 1)
|
||||
process_argv[1] = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv_get_process_title(char* buffer, size_t size) {
|
||||
size_t len;
|
||||
len = strlen(process_argv[0]);
|
||||
if (buffer == NULL || size == 0)
|
||||
return -EINVAL;
|
||||
else if (size <= len)
|
||||
return -ENOBUFS;
|
||||
|
||||
memcpy(buffer, process_argv[0], len + 1);
|
||||
|
||||
buffer[0] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
UV_DESTRUCTOR(static void free_args_mem(void)) {
|
||||
uv__free(args_mem); /* Keep valgrind happy. */
|
||||
args_mem = NULL;
|
||||
}
|
||||
|
||||
|
||||
int uv_resident_set_memory(size_t* rss) {
|
||||
char pp[64];
|
||||
psinfo_t psinfo;
|
||||
|
||||
@@ -43,8 +43,12 @@ UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) {
|
||||
__compare_and_swap(ptr, &oldval, newval);
|
||||
return out;
|
||||
#elif defined(__MVS__)
|
||||
return __plo_CS(ptr, (unsigned int*) ptr,
|
||||
oldval, (unsigned int*) &newval);
|
||||
unsigned int op4;
|
||||
if (__plo_CSST(ptr, (unsigned int*) &oldval, newval,
|
||||
(unsigned int*) ptr, *ptr, &op4))
|
||||
return oldval;
|
||||
else
|
||||
return op4;
|
||||
#else
|
||||
return __sync_val_compare_and_swap(ptr, oldval, newval);
|
||||
#endif
|
||||
@@ -67,13 +71,18 @@ UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)) {
|
||||
# endif /* if defined(__64BIT__) */
|
||||
return out;
|
||||
#elif defined (__MVS__)
|
||||
# ifdef _LP64
|
||||
return __plo_CSGR(ptr, (unsigned long long*) ptr,
|
||||
oldval, (unsigned long long*) &newval);
|
||||
# else
|
||||
return __plo_CS(ptr, (unsigned int*) ptr,
|
||||
oldval, (unsigned int*) &newval);
|
||||
# endif
|
||||
#ifdef _LP64
|
||||
unsigned long long op4;
|
||||
if (__plo_CSSTGR(ptr, (unsigned long long*) &oldval, newval,
|
||||
(unsigned long long*) ptr, *ptr, &op4))
|
||||
#else
|
||||
unsigned long op4;
|
||||
if (__plo_CSST(ptr, (unsigned int*) &oldval, newval,
|
||||
(unsigned int*) ptr, *ptr, &op4))
|
||||
#endif
|
||||
return oldval;
|
||||
else
|
||||
return op4;
|
||||
#else
|
||||
return __sync_val_compare_and_swap(ptr, oldval, newval);
|
||||
#endif
|
||||
|
||||
@@ -98,7 +98,7 @@ uint64_t uv_hrtime(void) {
|
||||
|
||||
|
||||
void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
|
||||
assert(!(handle->flags & (UV_CLOSING | UV_CLOSED)));
|
||||
assert(!uv__is_closing(handle));
|
||||
|
||||
handle->flags |= UV_CLOSING;
|
||||
handle->close_cb = close_cb;
|
||||
@@ -517,6 +517,9 @@ int uv__close_nocheckstdio(int fd) {
|
||||
|
||||
int uv__close(int fd) {
|
||||
assert(fd > STDERR_FILENO); /* Catch stdio close bugs. */
|
||||
#if defined(__MVS__)
|
||||
epoll_file_close(fd);
|
||||
#endif
|
||||
return uv__close_nocheckstdio(fd);
|
||||
}
|
||||
|
||||
@@ -836,13 +839,8 @@ void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
|
||||
* every tick of the event loop but the other backends allow us to
|
||||
* short-circuit here if the event mask is unchanged.
|
||||
*/
|
||||
if (w->events == w->pevents) {
|
||||
if (w->events == 0 && !QUEUE_EMPTY(&w->watcher_queue)) {
|
||||
QUEUE_REMOVE(&w->watcher_queue);
|
||||
QUEUE_INIT(&w->watcher_queue);
|
||||
}
|
||||
if (w->events == w->pevents)
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (QUEUE_EMPTY(&w->watcher_queue))
|
||||
@@ -1236,3 +1234,9 @@ void uv_os_free_passwd(uv_passwd_t* pwd) {
|
||||
int uv_os_get_passwd(uv_passwd_t* pwd) {
|
||||
return uv__getpwuid_r(pwd);
|
||||
}
|
||||
|
||||
|
||||
int uv_translate_sys_error(int sys_errno) {
|
||||
/* If < 0 then it's already a libuv error. */
|
||||
return sys_errno <= 0 ? sys_errno : -sys_errno;
|
||||
}
|
||||
|
||||
@@ -129,8 +129,23 @@
|
||||
static ssize_t uv__fs_fdatasync(uv_fs_t* req) {
|
||||
#if defined(__linux__) || defined(__sun) || defined(__NetBSD__)
|
||||
return fdatasync(req->file);
|
||||
#elif defined(__APPLE__) && defined(SYS_fdatasync)
|
||||
return syscall(SYS_fdatasync, req->file);
|
||||
#elif defined(__APPLE__)
|
||||
/* Apple's fdatasync and fsync explicitly do NOT flush the drive write cache
|
||||
* to the drive platters. This is in contrast to Linux's fdatasync and fsync
|
||||
* which do, according to recent man pages. F_FULLFSYNC is Apple's equivalent
|
||||
* for flushing buffered data to permanent storage.
|
||||
*/
|
||||
return fcntl(req->file, F_FULLFSYNC);
|
||||
#else
|
||||
return fsync(req->file);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static ssize_t uv__fs_fsync(uv_fs_t* req) {
|
||||
#if defined(__APPLE__)
|
||||
/* See the comment in uv__fs_fdatasync. */
|
||||
return fcntl(req->file, F_FULLFSYNC);
|
||||
#else
|
||||
return fsync(req->file);
|
||||
#endif
|
||||
@@ -365,7 +380,6 @@ static int uv__fs_scandir_sort(UV_CONST_DIRENT** a, UV_CONST_DIRENT** b) {
|
||||
|
||||
static ssize_t uv__fs_scandir(uv_fs_t* req) {
|
||||
uv__dirent_t **dents;
|
||||
int saved_errno;
|
||||
int n;
|
||||
|
||||
dents = NULL;
|
||||
@@ -374,29 +388,18 @@ static ssize_t uv__fs_scandir(uv_fs_t* req) {
|
||||
/* NOTE: We will use nbufs as an index field */
|
||||
req->nbufs = 0;
|
||||
|
||||
if (n == 0)
|
||||
goto out; /* osx still needs to deallocate some memory */
|
||||
else if (n == -1)
|
||||
if (n == 0) {
|
||||
/* OS X still needs to deallocate some memory.
|
||||
* Memory was allocated using the system allocator, so use free() here.
|
||||
*/
|
||||
free(dents);
|
||||
dents = NULL;
|
||||
} else if (n == -1) {
|
||||
return n;
|
||||
}
|
||||
|
||||
req->ptr = dents;
|
||||
|
||||
return n;
|
||||
|
||||
out:
|
||||
saved_errno = errno;
|
||||
if (dents != NULL) {
|
||||
int i;
|
||||
|
||||
/* Memory was allocated using the system allocator, so use free() here. */
|
||||
for (i = 0; i < n; i++)
|
||||
free(dents[i]);
|
||||
free(dents);
|
||||
}
|
||||
errno = saved_errno;
|
||||
|
||||
req->ptr = NULL;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -798,6 +801,10 @@ static void uv__to_stat(struct stat* src, uv_stat_t* dst) {
|
||||
dst->st_flags = 0;
|
||||
dst->st_gen = 0;
|
||||
#elif !defined(_AIX) && ( \
|
||||
defined(__DragonFly__) || \
|
||||
defined(__FreeBSD__) || \
|
||||
defined(__OpenBSD__) || \
|
||||
defined(__NetBSD__) || \
|
||||
defined(_GNU_SOURCE) || \
|
||||
defined(_BSD_SOURCE) || \
|
||||
defined(_SVID_SOURCE) || \
|
||||
@@ -809,9 +816,7 @@ static void uv__to_stat(struct stat* src, uv_stat_t* dst) {
|
||||
dst->st_mtim.tv_nsec = src->st_mtim.tv_nsec;
|
||||
dst->st_ctim.tv_sec = src->st_ctim.tv_sec;
|
||||
dst->st_ctim.tv_nsec = src->st_ctim.tv_nsec;
|
||||
# if defined(__DragonFly__) || \
|
||||
defined(__FreeBSD__) || \
|
||||
defined(__OpenBSD__) || \
|
||||
# if defined(__FreeBSD__) || \
|
||||
defined(__NetBSD__)
|
||||
dst->st_birthtim.tv_sec = src->st_birthtim.tv_sec;
|
||||
dst->st_birthtim.tv_nsec = src->st_birthtim.tv_nsec;
|
||||
@@ -945,7 +950,7 @@ static void uv__fs_work(struct uv__work* w) {
|
||||
X(FCHOWN, fchown(req->file, req->uid, req->gid));
|
||||
X(FDATASYNC, uv__fs_fdatasync(req));
|
||||
X(FSTAT, uv__fs_fstat(req->file, &req->statbuf));
|
||||
X(FSYNC, fsync(req->file));
|
||||
X(FSYNC, uv__fs_fsync(req));
|
||||
X(FTRUNCATE, ftruncate(req->file, req->off));
|
||||
X(FUTIME, uv__fs_futime(req));
|
||||
X(LSTAT, uv__fs_lstat(req->path, &req->statbuf));
|
||||
|
||||
@@ -38,6 +38,10 @@
|
||||
# include "linux-syscalls.h"
|
||||
#endif /* __linux__ */
|
||||
|
||||
#if defined(__MVS__)
|
||||
# include "os390-syscalls.h"
|
||||
#endif /* __MVS__ */
|
||||
|
||||
#if defined(__sun)
|
||||
# include <sys/port.h>
|
||||
# include <port.h>
|
||||
@@ -51,6 +55,10 @@
|
||||
# include <poll.h>
|
||||
#endif /* _AIX */
|
||||
|
||||
#if defined(__APPLE__) && !TARGET_OS_IPHONE
|
||||
# include <AvailabilityMacros.h>
|
||||
#endif
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset);
|
||||
# ifdef pthread_sigmask
|
||||
@@ -154,7 +162,8 @@ struct uv__stream_queued_fds_s {
|
||||
defined(__DragonFly__) || \
|
||||
defined(__FreeBSD__) || \
|
||||
defined(__FreeBSD_kernel__) || \
|
||||
defined(__linux__)
|
||||
defined(__linux__) || \
|
||||
defined(__OpenBSD__)
|
||||
#define uv__cloexec uv__cloexec_ioctl
|
||||
#define uv__nonblock uv__nonblock_ioctl
|
||||
#else
|
||||
@@ -268,7 +277,6 @@ int uv__make_socketpair(int fds[2], int flags);
|
||||
int uv__make_pipe(int fds[2], int flags);
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <AvailabilityMacros.h>
|
||||
|
||||
int uv__fsevents_init(uv_fs_event_t* handle);
|
||||
int uv__fsevents_close(uv_fs_event_t* handle);
|
||||
|
||||
@@ -163,7 +163,7 @@ char** uv_setup_args(int argc, char** argv) {
|
||||
int uv_set_process_title(const char* title) {
|
||||
uv__free(process_title);
|
||||
process_title = uv__strdup(title);
|
||||
setproctitle(title);
|
||||
setproctitle("%s", title);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
334
Utilities/cmlibuv/src/unix/os390-syscalls.c
Normal file
334
Utilities/cmlibuv/src/unix/os390-syscalls.c
Normal file
@@ -0,0 +1,334 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include "os390-syscalls.h"
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <search.h>
|
||||
|
||||
#define CW_CONDVAR 32
|
||||
|
||||
#pragma linkage(BPX4CTW, OS)
|
||||
#pragma linkage(BPX1CTW, OS)
|
||||
|
||||
static int number_of_epolls;
|
||||
static QUEUE global_epoll_queue;
|
||||
static uv_mutex_t global_epoll_lock;
|
||||
static uv_once_t once = UV_ONCE_INIT;
|
||||
|
||||
int scandir(const char* maindir, struct dirent*** namelist,
|
||||
int (*filter)(const struct dirent*),
|
||||
int (*compar)(const struct dirent**,
|
||||
const struct dirent **)) {
|
||||
struct dirent** nl;
|
||||
struct dirent* dirent;
|
||||
unsigned count;
|
||||
size_t allocated;
|
||||
DIR* mdir;
|
||||
|
||||
nl = NULL;
|
||||
count = 0;
|
||||
allocated = 0;
|
||||
mdir = opendir(maindir);
|
||||
if (!mdir)
|
||||
return -1;
|
||||
|
||||
while (1) {
|
||||
dirent = readdir(mdir);
|
||||
if (!dirent)
|
||||
break;
|
||||
if (!filter || filter(dirent)) {
|
||||
struct dirent* copy;
|
||||
copy = uv__malloc(sizeof(*copy));
|
||||
if (!copy) {
|
||||
while (count) {
|
||||
dirent = nl[--count];
|
||||
uv__free(dirent);
|
||||
}
|
||||
uv__free(nl);
|
||||
closedir(mdir);
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
memcpy(copy, dirent, sizeof(*copy));
|
||||
|
||||
nl = uv__realloc(nl, sizeof(*copy) * (count + 1));
|
||||
nl[count++] = copy;
|
||||
}
|
||||
}
|
||||
|
||||
qsort(nl, count, sizeof(struct dirent *),
|
||||
(int (*)(const void *, const void *)) compar);
|
||||
|
||||
closedir(mdir);
|
||||
|
||||
*namelist = nl;
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static unsigned int next_power_of_two(unsigned int val) {
|
||||
val -= 1;
|
||||
val |= val >> 1;
|
||||
val |= val >> 2;
|
||||
val |= val >> 4;
|
||||
val |= val >> 8;
|
||||
val |= val >> 16;
|
||||
val += 1;
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
static void maybe_resize(uv__os390_epoll* lst, unsigned int len) {
|
||||
unsigned int newsize;
|
||||
unsigned int i;
|
||||
struct pollfd* newlst;
|
||||
|
||||
if (len <= lst->size)
|
||||
return;
|
||||
|
||||
newsize = next_power_of_two(len);
|
||||
newlst = uv__realloc(lst->items, newsize * sizeof(lst->items[0]));
|
||||
|
||||
if (newlst == NULL)
|
||||
abort();
|
||||
for (i = lst->size; i < newsize; ++i)
|
||||
newlst[i].fd = -1;
|
||||
|
||||
lst->items = newlst;
|
||||
lst->size = newsize;
|
||||
}
|
||||
|
||||
|
||||
static void epoll_init() {
|
||||
QUEUE_INIT(&global_epoll_queue);
|
||||
if (uv_mutex_init(&global_epoll_lock))
|
||||
abort();
|
||||
}
|
||||
|
||||
|
||||
uv__os390_epoll* epoll_create1(int flags) {
|
||||
uv__os390_epoll* lst;
|
||||
|
||||
uv_once(&once, epoll_init);
|
||||
uv_mutex_lock(&global_epoll_lock);
|
||||
lst = uv__malloc(sizeof(*lst));
|
||||
if (lst == -1)
|
||||
return NULL;
|
||||
QUEUE_INSERT_TAIL(&global_epoll_queue, &lst->member);
|
||||
uv_mutex_unlock(&global_epoll_lock);
|
||||
|
||||
/* initialize list */
|
||||
lst->size = 0;
|
||||
lst->items = NULL;
|
||||
return lst;
|
||||
}
|
||||
|
||||
|
||||
int epoll_ctl(uv__os390_epoll* lst,
|
||||
int op,
|
||||
int fd,
|
||||
struct epoll_event *event) {
|
||||
if(op == EPOLL_CTL_DEL) {
|
||||
if (fd >= lst->size || lst->items[fd].fd == -1) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
lst->items[fd].fd = -1;
|
||||
} else if(op == EPOLL_CTL_ADD) {
|
||||
maybe_resize(lst, fd + 1);
|
||||
if (lst->items[fd].fd != -1) {
|
||||
errno = EEXIST;
|
||||
return -1;
|
||||
}
|
||||
lst->items[fd].fd = fd;
|
||||
lst->items[fd].events = event->events;
|
||||
} else if(op == EPOLL_CTL_MOD) {
|
||||
if (fd >= lst->size || lst->items[fd].fd == -1) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
lst->items[fd].events = event->events;
|
||||
} else
|
||||
abort();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events,
|
||||
int maxevents, int timeout) {
|
||||
size_t size;
|
||||
struct pollfd* pfds;
|
||||
int pollret;
|
||||
int reventcount;
|
||||
|
||||
uv_mutex_lock(&global_epoll_lock);
|
||||
uv_mutex_unlock(&global_epoll_lock);
|
||||
size = lst->size;
|
||||
pfds = lst->items;
|
||||
pollret = poll(pfds, size, timeout);
|
||||
if(pollret == -1)
|
||||
return pollret;
|
||||
|
||||
reventcount = 0;
|
||||
for (int i = 0; i < lst->size && i < maxevents; ++i) {
|
||||
struct epoll_event ev;
|
||||
|
||||
ev.events = 0;
|
||||
ev.fd = pfds[i].fd;
|
||||
if(!pfds[i].revents)
|
||||
continue;
|
||||
|
||||
if(pfds[i].revents & POLLRDNORM)
|
||||
ev.events = ev.events | POLLIN;
|
||||
|
||||
if(pfds[i].revents & POLLWRNORM)
|
||||
ev.events = ev.events | POLLOUT;
|
||||
|
||||
if(pfds[i].revents & POLLHUP)
|
||||
ev.events = ev.events | POLLHUP;
|
||||
|
||||
pfds[i].revents = 0;
|
||||
events[reventcount++] = ev;
|
||||
}
|
||||
|
||||
return reventcount;
|
||||
}
|
||||
|
||||
|
||||
int epoll_file_close(int fd) {
|
||||
QUEUE* q;
|
||||
|
||||
uv_once(&once, epoll_init);
|
||||
uv_mutex_lock(&global_epoll_lock);
|
||||
QUEUE_FOREACH(q, &global_epoll_queue) {
|
||||
uv__os390_epoll* lst;
|
||||
|
||||
lst = QUEUE_DATA(q, uv__os390_epoll, member);
|
||||
if (fd < lst->size && lst->items != NULL && lst->items[fd].fd != -1)
|
||||
lst->items[fd].fd = -1;
|
||||
}
|
||||
|
||||
uv_mutex_unlock(&global_epoll_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void epoll_queue_close(uv__os390_epoll* lst) {
|
||||
uv_mutex_lock(&global_epoll_lock);
|
||||
QUEUE_REMOVE(&lst->member);
|
||||
uv_mutex_unlock(&global_epoll_lock);
|
||||
uv__free(lst->items);
|
||||
lst->items = NULL;
|
||||
}
|
||||
|
||||
|
||||
int nanosleep(const struct timespec* req, struct timespec* rem) {
|
||||
unsigned nano;
|
||||
unsigned seconds;
|
||||
unsigned events;
|
||||
unsigned secrem;
|
||||
unsigned nanorem;
|
||||
int rv;
|
||||
int rc;
|
||||
int rsn;
|
||||
|
||||
nano = (int)req->tv_nsec;
|
||||
seconds = req->tv_sec;
|
||||
events = CW_CONDVAR;
|
||||
|
||||
#if defined(_LP64)
|
||||
BPX4CTW(&seconds, &nano, &events, &secrem, &nanorem, &rv, &rc, &rsn);
|
||||
#else
|
||||
BPX1CTW(&seconds, &nano, &events, &secrem, &nanorem, &rv, &rc, &rsn);
|
||||
#endif
|
||||
|
||||
assert(rv == -1 && errno == EAGAIN);
|
||||
|
||||
if(rem != NULL) {
|
||||
rem->tv_nsec = nanorem;
|
||||
rem->tv_sec = secrem;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
char* mkdtemp(char* path) {
|
||||
static const char* tempchars =
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||
static const size_t num_chars = 62;
|
||||
static const size_t num_x = 6;
|
||||
char *ep, *cp;
|
||||
unsigned int tries, i;
|
||||
size_t len;
|
||||
uint64_t v;
|
||||
int fd;
|
||||
int retval;
|
||||
int saved_errno;
|
||||
|
||||
len = strlen(path);
|
||||
ep = path + len;
|
||||
if (len < num_x || strncmp(ep - num_x, "XXXXXX", num_x)) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fd = open("/dev/urandom", O_RDONLY);
|
||||
if (fd == -1)
|
||||
return NULL;
|
||||
|
||||
tries = TMP_MAX;
|
||||
retval = -1;
|
||||
do {
|
||||
if (read(fd, &v, sizeof(v)) != sizeof(v))
|
||||
break;
|
||||
|
||||
cp = ep - num_x;
|
||||
for (i = 0; i < num_x; i++) {
|
||||
*cp++ = tempchars[v % num_chars];
|
||||
v /= num_chars;
|
||||
}
|
||||
|
||||
if (mkdir(path, S_IRWXU) == 0) {
|
||||
retval = 0;
|
||||
break;
|
||||
}
|
||||
else if (errno != EEXIST)
|
||||
break;
|
||||
} while (--tries);
|
||||
|
||||
saved_errno = errno;
|
||||
uv__close(fd);
|
||||
if (tries == 0) {
|
||||
errno = EEXIST;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (retval == -1) {
|
||||
errno = saved_errno;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
69
Utilities/cmlibuv/src/unix/os390-syscalls.h
Normal file
69
Utilities/cmlibuv/src/unix/os390-syscalls.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/* 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_OS390_SYSCALL_H_
|
||||
#define UV_OS390_SYSCALL_H_
|
||||
|
||||
#include "uv.h"
|
||||
#include "internal.h"
|
||||
#include <dirent.h>
|
||||
#include <poll.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define EPOLL_CTL_ADD 1
|
||||
#define EPOLL_CTL_DEL 2
|
||||
#define EPOLL_CTL_MOD 3
|
||||
#define MAX_EPOLL_INSTANCES 256
|
||||
#define MAX_ITEMS_PER_EPOLL 1024
|
||||
|
||||
#define UV__O_CLOEXEC 0x80000
|
||||
#define UV__EPOLL_CLOEXEC UV__O_CLOEXEC
|
||||
#define UV__EPOLL_CTL_ADD EPOLL_CTL_ADD
|
||||
#define UV__EPOLL_CTL_DEL EPOLL_CTL_DEL
|
||||
#define UV__EPOLL_CTL_MOD EPOLL_CTL_MOD
|
||||
|
||||
struct epoll_event {
|
||||
int events;
|
||||
int fd;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
QUEUE member;
|
||||
struct pollfd* items;
|
||||
unsigned long size;
|
||||
} uv__os390_epoll;
|
||||
|
||||
/* epoll api */
|
||||
uv__os390_epoll* epoll_create1(int flags);
|
||||
int epoll_ctl(uv__os390_epoll* ep, int op, int fd, struct epoll_event *event);
|
||||
int epoll_wait(uv__os390_epoll* ep, struct epoll_event *events, int maxevents, int timeout);
|
||||
int epoll_file_close(int fd);
|
||||
|
||||
/* utility functions */
|
||||
int nanosleep(const struct timespec* req, struct timespec* rem);
|
||||
int scandir(const char* maindir, struct dirent*** namelist,
|
||||
int (*filter)(const struct dirent *),
|
||||
int (*compar)(const struct dirent **,
|
||||
const struct dirent **));
|
||||
char *mkdtemp(char* path);
|
||||
|
||||
#endif /* UV_OS390_SYSCALL_H_ */
|
||||
@@ -20,6 +20,628 @@
|
||||
*/
|
||||
|
||||
#include "internal.h"
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/if.h>
|
||||
#include <utmpx.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ps.h>
|
||||
#if defined(__clang__)
|
||||
#include "csrsic.h"
|
||||
#else
|
||||
#include "//'SYS1.SAMPLIB(CSRSIC)'"
|
||||
#endif
|
||||
|
||||
#define CVT_PTR 0x10
|
||||
#define CSD_OFFSET 0x294
|
||||
|
||||
/*
|
||||
Long-term average CPU service used by this logical partition,
|
||||
in millions of service units per hour. If this value is above
|
||||
the partition's defined capacity, the partition will be capped.
|
||||
It is calculated using the physical CPU adjustment factor
|
||||
(RCTPCPUA) so it may not match other measures of service which
|
||||
are based on the logical CPU adjustment factor. It is available
|
||||
if the hardware supports LPAR cluster.
|
||||
*/
|
||||
#define RCTLACS_OFFSET 0xC4
|
||||
|
||||
/* 32-bit count of alive CPUs. This includes both CPs and IFAs */
|
||||
#define CSD_NUMBER_ONLINE_CPUS 0xD4
|
||||
|
||||
/* Address of system resources manager (SRM) control table */
|
||||
#define CVTOPCTP_OFFSET 0x25C
|
||||
|
||||
/* Address of the RCT table */
|
||||
#define RMCTRCT_OFFSET 0xE4
|
||||
|
||||
/* Address of the rsm control and enumeration area. */
|
||||
#define CVTRCEP_OFFSET 0x490
|
||||
|
||||
/*
|
||||
Number of frames currently available to system.
|
||||
Excluded are frames backing perm storage, frames offline, and bad frames.
|
||||
*/
|
||||
#define RCEPOOL_OFFSET 0x004
|
||||
|
||||
/* Total number of frames currently on all available frame queues. */
|
||||
#define RCEAFC_OFFSET 0x088
|
||||
|
||||
/* CPC model length from the CSRSI Service. */
|
||||
#define CPCMODEL_LENGTH 16
|
||||
|
||||
/* Thread Entry constants */
|
||||
#define PGTH_CURRENT 1
|
||||
#define PGTH_LEN 26
|
||||
#define PGTHAPATH 0x20
|
||||
#pragma linkage(BPX4GTH, OS)
|
||||
#pragma linkage(BPX1GTH, OS)
|
||||
|
||||
typedef unsigned data_area_ptr_assign_type;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
#if defined(_LP64)
|
||||
data_area_ptr_assign_type lower;
|
||||
#endif
|
||||
data_area_ptr_assign_type assign;
|
||||
};
|
||||
char* deref;
|
||||
} data_area_ptr;
|
||||
|
||||
|
||||
void uv_loadavg(double avg[3]) {
|
||||
/* TODO: implement the following */
|
||||
avg[0] = 0;
|
||||
avg[1] = 0;
|
||||
avg[2] = 0;
|
||||
}
|
||||
|
||||
|
||||
int uv__platform_loop_init(uv_loop_t* loop) {
|
||||
uv__os390_epoll* ep;
|
||||
|
||||
ep = epoll_create1(UV__EPOLL_CLOEXEC);
|
||||
loop->ep = ep;
|
||||
if (ep == NULL)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void uv__platform_loop_delete(uv_loop_t* loop) {
|
||||
if (loop->ep != NULL) {
|
||||
epoll_queue_close(loop->ep);
|
||||
loop->ep = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint64_t uv__hrtime(uv_clocktype_t type) {
|
||||
struct timeval time;
|
||||
gettimeofday(&time, NULL);
|
||||
return (uint64_t) time.tv_sec * 1e9 + time.tv_usec * 1e3;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Get the exe path using the thread entry information
|
||||
in the address space.
|
||||
*/
|
||||
static int getexe(const int pid, char* buf, size_t len) {
|
||||
struct {
|
||||
int pid;
|
||||
int thid[2];
|
||||
char accesspid;
|
||||
char accessthid;
|
||||
char asid[2];
|
||||
char loginname[8];
|
||||
char flag;
|
||||
char len;
|
||||
} Input_data;
|
||||
|
||||
union {
|
||||
struct {
|
||||
char gthb[4];
|
||||
int pid;
|
||||
int thid[2];
|
||||
char accesspid;
|
||||
char accessthid[3];
|
||||
int lenused;
|
||||
int offsetProcess;
|
||||
int offsetConTTY;
|
||||
int offsetPath;
|
||||
int offsetCommand;
|
||||
int offsetFileData;
|
||||
int offsetThread;
|
||||
} Output_data;
|
||||
char buf[2048];
|
||||
} Output_buf;
|
||||
|
||||
struct Output_path_type {
|
||||
char gthe[4];
|
||||
short int len;
|
||||
char path[1024];
|
||||
};
|
||||
|
||||
int Input_length;
|
||||
int Output_length;
|
||||
void* Input_address;
|
||||
void* Output_address;
|
||||
struct Output_path_type* Output_path;
|
||||
int rv;
|
||||
int rc;
|
||||
int rsn;
|
||||
|
||||
Input_length = PGTH_LEN;
|
||||
Output_length = sizeof(Output_buf);
|
||||
Output_address = &Output_buf;
|
||||
Input_address = &Input_data;
|
||||
memset(&Input_data, 0, sizeof Input_data);
|
||||
Input_data.flag |= PGTHAPATH;
|
||||
Input_data.pid = pid;
|
||||
Input_data.accesspid = PGTH_CURRENT;
|
||||
|
||||
#ifdef _LP64
|
||||
BPX4GTH(&Input_length,
|
||||
&Input_address,
|
||||
&Output_length,
|
||||
&Output_address,
|
||||
&rv,
|
||||
&rc,
|
||||
&rsn);
|
||||
#else
|
||||
BPX1GTH(&Input_length,
|
||||
&Input_address,
|
||||
&Output_length,
|
||||
&Output_address,
|
||||
&rv,
|
||||
&rc,
|
||||
&rsn);
|
||||
#endif
|
||||
|
||||
if (rv == -1) {
|
||||
errno = rc;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check highest byte to ensure data availability */
|
||||
assert(((Output_buf.Output_data.offsetPath >>24) & 0xFF) == 'A');
|
||||
|
||||
/* Get the offset from the lowest 3 bytes */
|
||||
Output_path = (char*)(&Output_buf) +
|
||||
(Output_buf.Output_data.offsetPath & 0x00FFFFFF);
|
||||
|
||||
if (Output_path->len >= len) {
|
||||
errno = ENOBUFS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncpy(buf, Output_path->path, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* We could use a static buffer for the path manipulations that we need outside
|
||||
* of the function, but this function could be called by multiple consumers and
|
||||
* we don't want to potentially create a race condition in the use of snprintf.
|
||||
* There is no direct way of getting the exe path in zOS - either through /procfs
|
||||
* or through some libc APIs. The below approach is to parse the argv[0]'s pattern
|
||||
* and use it in conjunction with PATH environment variable to craft one.
|
||||
*/
|
||||
int uv_exepath(char* buffer, size_t* size) {
|
||||
int res;
|
||||
char args[PATH_MAX];
|
||||
char abspath[PATH_MAX];
|
||||
size_t abspath_size;
|
||||
int pid;
|
||||
|
||||
if (buffer == NULL || size == NULL || *size == 0)
|
||||
return -EINVAL;
|
||||
|
||||
pid = getpid();
|
||||
res = getexe(pid, args, sizeof(args));
|
||||
if (res < 0)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Possibilities for args:
|
||||
* i) an absolute path such as: /home/user/myprojects/nodejs/node
|
||||
* ii) a relative path such as: ./node or ../myprojects/nodejs/node
|
||||
* iii) a bare filename such as "node", after exporting PATH variable
|
||||
* to its location.
|
||||
*/
|
||||
|
||||
/* Case i) and ii) absolute or relative paths */
|
||||
if (strchr(args, '/') != NULL) {
|
||||
if (realpath(args, abspath) != abspath)
|
||||
return -errno;
|
||||
|
||||
abspath_size = strlen(abspath);
|
||||
|
||||
*size -= 1;
|
||||
if (*size > abspath_size)
|
||||
*size = abspath_size;
|
||||
|
||||
memcpy(buffer, abspath, *size);
|
||||
buffer[*size] = '\0';
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
/* Case iii). Search PATH environment variable */
|
||||
char trypath[PATH_MAX];
|
||||
char* clonedpath = NULL;
|
||||
char* token = NULL;
|
||||
char* path = getenv("PATH");
|
||||
|
||||
if (path == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
clonedpath = uv__strdup(path);
|
||||
if (clonedpath == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
token = strtok(clonedpath, ":");
|
||||
while (token != NULL) {
|
||||
snprintf(trypath, sizeof(trypath) - 1, "%s/%s", token, args);
|
||||
if (realpath(trypath, abspath) == abspath) {
|
||||
/* Check the match is executable */
|
||||
if (access(abspath, X_OK) == 0) {
|
||||
abspath_size = strlen(abspath);
|
||||
|
||||
*size -= 1;
|
||||
if (*size > abspath_size)
|
||||
*size = abspath_size;
|
||||
|
||||
memcpy(buffer, abspath, *size);
|
||||
buffer[*size] = '\0';
|
||||
|
||||
uv__free(clonedpath);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
token = strtok(NULL, ":");
|
||||
}
|
||||
uv__free(clonedpath);
|
||||
|
||||
/* Out of tokens (path entries), and no match found */
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint64_t uv_get_free_memory(void) {
|
||||
uint64_t freeram;
|
||||
|
||||
data_area_ptr cvt = {0};
|
||||
data_area_ptr rcep = {0};
|
||||
cvt.assign = *(data_area_ptr_assign_type*)(CVT_PTR);
|
||||
rcep.assign = *(data_area_ptr_assign_type*)(cvt.deref + CVTRCEP_OFFSET);
|
||||
freeram = *((uint64_t*)(rcep.deref + RCEAFC_OFFSET)) * 4;
|
||||
return freeram;
|
||||
}
|
||||
|
||||
|
||||
uint64_t uv_get_total_memory(void) {
|
||||
uint64_t totalram;
|
||||
|
||||
data_area_ptr cvt = {0};
|
||||
data_area_ptr rcep = {0};
|
||||
cvt.assign = *(data_area_ptr_assign_type*)(CVT_PTR);
|
||||
rcep.assign = *(data_area_ptr_assign_type*)(cvt.deref + CVTRCEP_OFFSET);
|
||||
totalram = *((uint64_t*)(rcep.deref + RCEPOOL_OFFSET)) * 4;
|
||||
return totalram;
|
||||
}
|
||||
|
||||
|
||||
int uv_resident_set_memory(size_t* rss) {
|
||||
W_PSPROC buf;
|
||||
|
||||
memset(&buf, 0, sizeof(buf));
|
||||
if (w_getpsent(0, &buf, sizeof(W_PSPROC)) == -1)
|
||||
return -EINVAL;
|
||||
|
||||
*rss = buf.ps_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv_uptime(double* uptime) {
|
||||
struct utmpx u ;
|
||||
struct utmpx *v;
|
||||
time64_t t;
|
||||
|
||||
u.ut_type = BOOT_TIME;
|
||||
v = getutxid(&u);
|
||||
if (v == NULL)
|
||||
return -1;
|
||||
*uptime = difftime64(time64(&t), v->ut_tv.tv_sec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
|
||||
uv_cpu_info_t* cpu_info;
|
||||
int result;
|
||||
int idx;
|
||||
siv1v2 info;
|
||||
data_area_ptr cvt = {0};
|
||||
data_area_ptr csd = {0};
|
||||
data_area_ptr rmctrct = {0};
|
||||
data_area_ptr cvtopctp = {0};
|
||||
int cpu_usage_avg;
|
||||
|
||||
cvt.assign = *(data_area_ptr_assign_type*)(CVT_PTR);
|
||||
|
||||
csd.assign = *((data_area_ptr_assign_type *) (cvt.deref + CSD_OFFSET));
|
||||
cvtopctp.assign = *((data_area_ptr_assign_type *) (cvt.deref + CVTOPCTP_OFFSET));
|
||||
rmctrct.assign = *((data_area_ptr_assign_type *) (cvtopctp.deref + RMCTRCT_OFFSET));
|
||||
|
||||
*count = *((int*) (csd.deref + CSD_NUMBER_ONLINE_CPUS));
|
||||
cpu_usage_avg = *((unsigned short int*) (rmctrct.deref + RCTLACS_OFFSET));
|
||||
|
||||
*cpu_infos = uv__malloc(*count * sizeof(uv_cpu_info_t));
|
||||
if (!*cpu_infos)
|
||||
return -ENOMEM;
|
||||
|
||||
cpu_info = *cpu_infos;
|
||||
idx = 0;
|
||||
while (idx < *count) {
|
||||
cpu_info->speed = *(int*)(info.siv1v2si22v1.si22v1cpucapability);
|
||||
cpu_info->model = uv__malloc(CPCMODEL_LENGTH + 1);
|
||||
memset(cpu_info->model, '\0', CPCMODEL_LENGTH + 1);
|
||||
memcpy(cpu_info->model, info.siv1v2si11v1.si11v1cpcmodel, CPCMODEL_LENGTH);
|
||||
cpu_info->cpu_times.user = cpu_usage_avg;
|
||||
/* TODO: implement the following */
|
||||
cpu_info->cpu_times.sys = 0;
|
||||
cpu_info->cpu_times.idle = 0;
|
||||
cpu_info->cpu_times.irq = 0;
|
||||
cpu_info->cpu_times.nice = 0;
|
||||
++cpu_info;
|
||||
++idx;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
|
||||
for (int i = 0; i < count; ++i)
|
||||
uv__free(cpu_infos[i].model);
|
||||
uv__free(cpu_infos);
|
||||
}
|
||||
|
||||
|
||||
static int uv__interface_addresses_v6(uv_interface_address_t** addresses,
|
||||
int* count) {
|
||||
uv_interface_address_t* address;
|
||||
int sockfd;
|
||||
int maxsize;
|
||||
__net_ifconf6header_t ifc;
|
||||
__net_ifconf6entry_t* ifr;
|
||||
__net_ifconf6entry_t* p;
|
||||
__net_ifconf6entry_t flg;
|
||||
|
||||
*count = 0;
|
||||
/* Assume maximum buffer size allowable */
|
||||
maxsize = 16384;
|
||||
|
||||
if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)))
|
||||
return -errno;
|
||||
|
||||
ifc.__nif6h_version = 1;
|
||||
ifc.__nif6h_buflen = maxsize;
|
||||
ifc.__nif6h_buffer = uv__calloc(1, maxsize);;
|
||||
|
||||
if (ioctl(sockfd, SIOCGIFCONF6, &ifc) == -1) {
|
||||
uv__close(sockfd);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
|
||||
*count = 0;
|
||||
ifr = (__net_ifconf6entry_t*)(ifc.__nif6h_buffer);
|
||||
while ((char*)ifr < (char*)ifc.__nif6h_buffer + ifc.__nif6h_buflen) {
|
||||
p = ifr;
|
||||
ifr = (__net_ifconf6entry_t*)((char*)ifr + ifc.__nif6h_entrylen);
|
||||
|
||||
if (!(p->__nif6e_addr.sin6_family == AF_INET6 ||
|
||||
p->__nif6e_addr.sin6_family == AF_INET))
|
||||
continue;
|
||||
|
||||
if (!(p->__nif6e_flags & _NIF6E_FLAGS_ON_LINK_ACTIVE))
|
||||
continue;
|
||||
|
||||
++(*count);
|
||||
}
|
||||
|
||||
/* Alloc the return interface structs */
|
||||
*addresses = uv__malloc(*count * sizeof(uv_interface_address_t));
|
||||
if (!(*addresses)) {
|
||||
uv__close(sockfd);
|
||||
return -ENOMEM;
|
||||
}
|
||||
address = *addresses;
|
||||
|
||||
ifr = (__net_ifconf6entry_t*)(ifc.__nif6h_buffer);
|
||||
while ((char*)ifr < (char*)ifc.__nif6h_buffer + ifc.__nif6h_buflen) {
|
||||
p = ifr;
|
||||
ifr = (__net_ifconf6entry_t*)((char*)ifr + ifc.__nif6h_entrylen);
|
||||
|
||||
if (!(p->__nif6e_addr.sin6_family == AF_INET6 ||
|
||||
p->__nif6e_addr.sin6_family == AF_INET))
|
||||
continue;
|
||||
|
||||
if (!(p->__nif6e_flags & _NIF6E_FLAGS_ON_LINK_ACTIVE))
|
||||
continue;
|
||||
|
||||
/* All conditions above must match count loop */
|
||||
|
||||
address->name = uv__strdup(p->__nif6e_name);
|
||||
|
||||
if (p->__nif6e_addr.sin6_family == AF_INET6)
|
||||
address->address.address6 = *((struct sockaddr_in6*) &p->__nif6e_addr);
|
||||
else
|
||||
address->address.address4 = *((struct sockaddr_in*) &p->__nif6e_addr);
|
||||
|
||||
/* TODO: Retrieve netmask using SIOCGIFNETMASK ioctl */
|
||||
|
||||
address->is_internal = flg.__nif6e_flags & _NIF6E_FLAGS_LOOPBACK ? 1 : 0;
|
||||
|
||||
address++;
|
||||
}
|
||||
|
||||
uv__close(sockfd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||
uv_interface_address_t* address;
|
||||
int sockfd;
|
||||
int maxsize;
|
||||
struct ifconf ifc;
|
||||
struct ifreq flg;
|
||||
struct ifreq* ifr;
|
||||
struct ifreq* p;
|
||||
int count_v6;
|
||||
|
||||
/* get the ipv6 addresses first */
|
||||
uv_interface_address_t* addresses_v6;
|
||||
uv__interface_addresses_v6(&addresses_v6, &count_v6);
|
||||
|
||||
/* now get the ipv4 addresses */
|
||||
*count = 0;
|
||||
|
||||
/* Assume maximum buffer size allowable */
|
||||
maxsize = 16384;
|
||||
|
||||
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
|
||||
if (0 > sockfd)
|
||||
return -errno;
|
||||
|
||||
ifc.ifc_req = uv__calloc(1, maxsize);
|
||||
ifc.ifc_len = maxsize;
|
||||
if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) {
|
||||
uv__close(sockfd);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
#define MAX(a,b) (((a)>(b))?(a):(b))
|
||||
#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p))
|
||||
|
||||
/* Count all up and running ipv4/ipv6 addresses */
|
||||
ifr = ifc.ifc_req;
|
||||
while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
|
||||
p = ifr;
|
||||
ifr = (struct ifreq*)
|
||||
((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr));
|
||||
|
||||
if (!(p->ifr_addr.sa_family == AF_INET6 ||
|
||||
p->ifr_addr.sa_family == AF_INET))
|
||||
continue;
|
||||
|
||||
memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
|
||||
if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
|
||||
uv__close(sockfd);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
|
||||
continue;
|
||||
|
||||
(*count)++;
|
||||
}
|
||||
|
||||
/* Alloc the return interface structs */
|
||||
*addresses = uv__malloc((*count + count_v6) *
|
||||
sizeof(uv_interface_address_t));
|
||||
|
||||
if (!(*addresses)) {
|
||||
uv__close(sockfd);
|
||||
return -ENOMEM;
|
||||
}
|
||||
address = *addresses;
|
||||
|
||||
/* copy over the ipv6 addresses */
|
||||
memcpy(address, addresses_v6, count_v6 * sizeof(uv_interface_address_t));
|
||||
address += count_v6;
|
||||
*count += count_v6;
|
||||
uv__free(addresses_v6);
|
||||
|
||||
ifr = ifc.ifc_req;
|
||||
while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
|
||||
p = ifr;
|
||||
ifr = (struct ifreq*)
|
||||
((char*)ifr + sizeof(ifr->ifr_name) + ADDR_SIZE(ifr->ifr_addr));
|
||||
|
||||
if (!(p->ifr_addr.sa_family == AF_INET6 ||
|
||||
p->ifr_addr.sa_family == AF_INET))
|
||||
continue;
|
||||
|
||||
memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name));
|
||||
if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) {
|
||||
uv__close(sockfd);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
|
||||
continue;
|
||||
|
||||
/* All conditions above must match count loop */
|
||||
|
||||
address->name = uv__strdup(p->ifr_name);
|
||||
|
||||
if (p->ifr_addr.sa_family == AF_INET6) {
|
||||
address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr);
|
||||
} else {
|
||||
address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr);
|
||||
}
|
||||
|
||||
address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0;
|
||||
address++;
|
||||
}
|
||||
|
||||
#undef ADDR_SIZE
|
||||
#undef MAX
|
||||
|
||||
uv__close(sockfd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void uv_free_interface_addresses(uv_interface_address_t* addresses,
|
||||
int count) {
|
||||
int i;
|
||||
for (i = 0; i < count; ++i)
|
||||
uv__free(addresses[i].name);
|
||||
uv__free(addresses);
|
||||
}
|
||||
|
||||
|
||||
void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
|
||||
struct epoll_event* events;
|
||||
struct epoll_event dummy;
|
||||
uintptr_t i;
|
||||
uintptr_t nfds;
|
||||
|
||||
assert(loop->watchers != NULL);
|
||||
|
||||
events = (struct epoll_event*) loop->watchers[loop->nwatchers];
|
||||
nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
|
||||
if (events != NULL)
|
||||
/* Invalidate events with same file descriptor */
|
||||
for (i = 0; i < nfds; i++)
|
||||
if ((int) events[i].fd == fd)
|
||||
events[i].fd = -1;
|
||||
|
||||
/* Remove the file descriptor from the epoll. */
|
||||
if (loop->ep != NULL)
|
||||
epoll_ctl(loop->ep, UV__EPOLL_CTL_DEL, fd, &dummy);
|
||||
}
|
||||
|
||||
|
||||
int uv__io_check_fd(uv_loop_t* loop, int fd) {
|
||||
struct pollfd p[1];
|
||||
@@ -40,3 +662,204 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void uv__fs_event_close(uv_fs_event_t* handle) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
|
||||
int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb,
|
||||
const char* filename, unsigned int flags) {
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
|
||||
int uv_fs_event_stop(uv_fs_event_t* handle) {
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
|
||||
void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
static const int max_safe_timeout = 1789569;
|
||||
struct epoll_event events[1024];
|
||||
struct epoll_event* pe;
|
||||
struct epoll_event e;
|
||||
int real_timeout;
|
||||
QUEUE* q;
|
||||
uv__io_t* w;
|
||||
uint64_t base;
|
||||
int count;
|
||||
int nfds;
|
||||
int fd;
|
||||
int op;
|
||||
int i;
|
||||
|
||||
if (loop->nfds == 0) {
|
||||
assert(QUEUE_EMPTY(&loop->watcher_queue));
|
||||
return;
|
||||
}
|
||||
|
||||
while (!QUEUE_EMPTY(&loop->watcher_queue)) {
|
||||
uv_stream_t* stream;
|
||||
|
||||
q = QUEUE_HEAD(&loop->watcher_queue);
|
||||
QUEUE_REMOVE(q);
|
||||
QUEUE_INIT(q);
|
||||
w = QUEUE_DATA(q, uv__io_t, watcher_queue);
|
||||
|
||||
assert(w->pevents != 0);
|
||||
assert(w->fd >= 0);
|
||||
|
||||
stream= container_of(w, uv_stream_t, io_watcher);
|
||||
|
||||
assert(w->fd < (int) loop->nwatchers);
|
||||
|
||||
e.events = w->pevents;
|
||||
e.fd = w->fd;
|
||||
|
||||
if (w->events == 0)
|
||||
op = UV__EPOLL_CTL_ADD;
|
||||
else
|
||||
op = UV__EPOLL_CTL_MOD;
|
||||
|
||||
/* XXX Future optimization: do EPOLL_CTL_MOD lazily if we stop watching
|
||||
* events, skip the syscall and squelch the events after epoll_wait().
|
||||
*/
|
||||
if (epoll_ctl(loop->ep, op, w->fd, &e)) {
|
||||
if (errno != EEXIST)
|
||||
abort();
|
||||
|
||||
assert(op == UV__EPOLL_CTL_ADD);
|
||||
|
||||
/* We've reactivated a file descriptor that's been watched before. */
|
||||
if (epoll_ctl(loop->ep, UV__EPOLL_CTL_MOD, w->fd, &e))
|
||||
abort();
|
||||
}
|
||||
|
||||
w->events = w->pevents;
|
||||
}
|
||||
|
||||
assert(timeout >= -1);
|
||||
base = loop->time;
|
||||
count = 48; /* Benchmarks suggest this gives the best throughput. */
|
||||
real_timeout = timeout;
|
||||
int nevents = 0;
|
||||
|
||||
nfds = 0;
|
||||
for (;;) {
|
||||
if (sizeof(int32_t) == sizeof(long) && timeout >= max_safe_timeout)
|
||||
timeout = max_safe_timeout;
|
||||
|
||||
nfds = epoll_wait(loop->ep, events,
|
||||
ARRAY_SIZE(events), timeout);
|
||||
|
||||
/* Update loop->time unconditionally. It's tempting to skip the update when
|
||||
* timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the
|
||||
* operating system didn't reschedule our process while in the syscall.
|
||||
*/
|
||||
base = loop->time;
|
||||
SAVE_ERRNO(uv__update_time(loop));
|
||||
if (nfds == 0) {
|
||||
assert(timeout != -1);
|
||||
timeout = real_timeout - timeout;
|
||||
if (timeout > 0)
|
||||
continue;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (nfds == -1) {
|
||||
|
||||
if (errno != EINTR)
|
||||
abort();
|
||||
|
||||
if (timeout == -1)
|
||||
continue;
|
||||
|
||||
if (timeout == 0)
|
||||
return;
|
||||
|
||||
/* Interrupted by a signal. Update timeout and poll again. */
|
||||
goto update_timeout;
|
||||
}
|
||||
|
||||
|
||||
assert(loop->watchers != NULL);
|
||||
loop->watchers[loop->nwatchers] = (void*) events;
|
||||
loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds;
|
||||
for (i = 0; i < nfds; i++) {
|
||||
pe = events + i;
|
||||
fd = pe->fd;
|
||||
|
||||
/* Skip invalidated events, see uv__platform_invalidate_fd */
|
||||
if (fd == -1)
|
||||
continue;
|
||||
|
||||
assert(fd >= 0);
|
||||
assert((unsigned) fd < loop->nwatchers);
|
||||
|
||||
w = loop->watchers[fd];
|
||||
|
||||
if (w == NULL) {
|
||||
/* File descriptor that we've stopped watching, disarm it.
|
||||
*
|
||||
* Ignore all errors because we may be racing with another thread
|
||||
* when the file descriptor is closed.
|
||||
*/
|
||||
epoll_ctl(loop->ep, UV__EPOLL_CTL_DEL, fd, pe);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Give users only events they're interested in. Prevents spurious
|
||||
* callbacks when previous callback invocation in this loop has stopped
|
||||
* the current watcher. Also, filters out events that users has not
|
||||
* requested us to watch.
|
||||
*/
|
||||
pe->events &= w->pevents | POLLERR | POLLHUP;
|
||||
|
||||
if (pe->events == POLLERR || pe->events == POLLHUP)
|
||||
pe->events |= w->pevents & (POLLIN | POLLOUT);
|
||||
|
||||
if (pe->events != 0) {
|
||||
w->cb(loop, w, pe->events);
|
||||
nevents++;
|
||||
}
|
||||
}
|
||||
loop->watchers[loop->nwatchers] = NULL;
|
||||
loop->watchers[loop->nwatchers + 1] = NULL;
|
||||
|
||||
if (nevents != 0) {
|
||||
if (nfds == ARRAY_SIZE(events) && --count != 0) {
|
||||
/* Poll for more events but don't block this time. */
|
||||
timeout = 0;
|
||||
continue;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (timeout == 0)
|
||||
return;
|
||||
|
||||
if (timeout == -1)
|
||||
continue;
|
||||
|
||||
update_timeout:
|
||||
assert(timeout > 0);
|
||||
|
||||
real_timeout -= (loop->time - base);
|
||||
if (real_timeout <= 0)
|
||||
return;
|
||||
|
||||
timeout = real_timeout;
|
||||
}
|
||||
}
|
||||
|
||||
void uv__set_process_title(const char* title) {
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ static void uv__poll_stop(uv_poll_t* handle) {
|
||||
|
||||
|
||||
int uv_poll_stop(uv_poll_t* handle) {
|
||||
assert(!(handle->flags & (UV_CLOSING | UV_CLOSED)));
|
||||
assert(!uv__is_closing(handle));
|
||||
uv__poll_stop(handle);
|
||||
return 0;
|
||||
}
|
||||
@@ -102,7 +102,7 @@ int uv_poll_start(uv_poll_t* handle, int pevents, uv_poll_cb poll_cb) {
|
||||
int events;
|
||||
|
||||
assert((pevents & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT)) == 0);
|
||||
assert(!(handle->flags & (UV_CLOSING | UV_CLOSED)));
|
||||
assert(!uv__is_closing(handle));
|
||||
|
||||
uv__poll_stop(handle);
|
||||
|
||||
|
||||
@@ -323,7 +323,7 @@ static void uv__process_child_init(const uv_process_options_t* options,
|
||||
}
|
||||
|
||||
if (fd == use_fd)
|
||||
uv__cloexec(use_fd, 0);
|
||||
uv__cloexec_fcntl(use_fd, 0);
|
||||
else
|
||||
fd = dup2(use_fd, fd);
|
||||
|
||||
@@ -333,7 +333,7 @@ static void uv__process_child_init(const uv_process_options_t* options,
|
||||
}
|
||||
|
||||
if (fd <= 2)
|
||||
uv__nonblock(fd, 0);
|
||||
uv__nonblock_fcntl(fd, 0);
|
||||
|
||||
if (close_fd >= stdio_count)
|
||||
uv__close(close_fd);
|
||||
|
||||
@@ -48,9 +48,15 @@ char** uv_setup_args(int argc, char** argv) {
|
||||
for (i = 0; i < argc; i++)
|
||||
size += strlen(argv[i]) + 1;
|
||||
|
||||
#if defined(__MVS__)
|
||||
/* argv is not adjacent. So just use argv[0] */
|
||||
process_title.str = argv[0];
|
||||
process_title.len = strlen(argv[0]);
|
||||
#else
|
||||
process_title.str = argv[0];
|
||||
process_title.len = argv[argc - 1] + strlen(argv[argc - 1]) - argv[0];
|
||||
assert(process_title.len + 1 == size); /* argv memory should be adjacent. */
|
||||
#endif
|
||||
|
||||
/* Add space for the argv pointers. */
|
||||
size += (argc + 1) * sizeof(char*);
|
||||
|
||||
@@ -73,7 +73,8 @@ int pthread_barrier_wait(pthread_barrier_t* barrier) {
|
||||
if (++b->in == b->threshold) {
|
||||
b->in = 0;
|
||||
b->out = b->threshold - 1;
|
||||
assert(pthread_cond_signal(&b->cond) == 0);
|
||||
rc = pthread_cond_signal(&b->cond);
|
||||
assert(rc == 0);
|
||||
|
||||
pthread_mutex_unlock(&b->mutex);
|
||||
return PTHREAD_BARRIER_SERIAL_THREAD;
|
||||
|
||||
@@ -43,7 +43,7 @@ static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2);
|
||||
static void uv__signal_stop(uv_signal_t* handle);
|
||||
|
||||
|
||||
static pthread_once_t uv__signal_global_init_guard = PTHREAD_ONCE_INIT;
|
||||
static uv_once_t uv__signal_global_init_guard = UV_ONCE_INIT;
|
||||
static struct uv__signal_tree_s uv__signal_tree =
|
||||
RB_INITIALIZER(uv__signal_tree);
|
||||
static int uv__signal_lock_pipefd[2];
|
||||
@@ -64,7 +64,7 @@ static void uv__signal_global_init(void) {
|
||||
|
||||
|
||||
void uv__signal_global_once_init(void) {
|
||||
pthread_once(&uv__signal_global_init_guard, uv__signal_global_init);
|
||||
uv_once(&uv__signal_global_init_guard, uv__signal_global_init);
|
||||
}
|
||||
|
||||
|
||||
@@ -290,7 +290,7 @@ int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) {
|
||||
sigset_t saved_sigmask;
|
||||
int err;
|
||||
|
||||
assert(!(handle->flags & (UV_CLOSING | UV_CLOSED)));
|
||||
assert(!uv__is_closing(handle));
|
||||
|
||||
/* If the user supplies signum == 0, then return an error already. If the
|
||||
* signum is otherwise invalid then uv__signal_register will find out
|
||||
@@ -434,7 +434,7 @@ static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) {
|
||||
|
||||
|
||||
int uv_signal_stop(uv_signal_t* handle) {
|
||||
assert(!(handle->flags & (UV_CLOSING | UV_CLOSED)));
|
||||
assert(!uv__is_closing(handle));
|
||||
uv__signal_stop(handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -390,7 +390,7 @@ failed_malloc:
|
||||
|
||||
|
||||
int uv__stream_open(uv_stream_t* stream, int fd, int flags) {
|
||||
#if defined(__APPLE__)
|
||||
#if defined(__APPLE__) || defined(__MVS__)
|
||||
int enable;
|
||||
#endif
|
||||
|
||||
@@ -409,7 +409,7 @@ int uv__stream_open(uv_stream_t* stream, int fd, int flags) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#if defined(__APPLE__) || defined(__MVS__)
|
||||
enable = 1;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, &enable, sizeof(enable)) &&
|
||||
errno != ENOTSOCK &&
|
||||
@@ -1194,6 +1194,30 @@ static void uv__read(uv_stream_t* stream) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__MVS__)
|
||||
if (is_ipc && msg.msg_controllen > 0) {
|
||||
uv_buf_t blankbuf;
|
||||
int nread;
|
||||
struct iovec *old;
|
||||
|
||||
blankbuf.base = 0;
|
||||
blankbuf.len = 0;
|
||||
old = msg.msg_iov;
|
||||
msg.msg_iov = (struct iovec*) &blankbuf;
|
||||
nread = 0;
|
||||
do {
|
||||
nread = uv__recvmsg(uv__stream_fd(stream), &msg, 0);
|
||||
err = uv__stream_recv_cmsg(stream, &msg);
|
||||
if (err != 0) {
|
||||
stream->read_cb(stream, err, &buf);
|
||||
msg.msg_iov = old;
|
||||
return;
|
||||
}
|
||||
} while (nread == 0 && msg.msg_controllen > 0);
|
||||
msg.msg_iov = old;
|
||||
}
|
||||
#endif
|
||||
stream->read_cb(stream, nread, &buf);
|
||||
|
||||
/* Return if we didn't fill the buffer, there is no more data to read. */
|
||||
@@ -1221,8 +1245,7 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) {
|
||||
if (!(stream->flags & UV_STREAM_WRITABLE) ||
|
||||
stream->flags & UV_STREAM_SHUT ||
|
||||
stream->flags & UV_STREAM_SHUTTING ||
|
||||
stream->flags & UV_CLOSED ||
|
||||
stream->flags & UV_CLOSING) {
|
||||
uv__is_closing(stream)) {
|
||||
return -ENOTCONN;
|
||||
}
|
||||
|
||||
|
||||
@@ -695,6 +695,11 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) {
|
||||
uv__free(cpu_infos);
|
||||
}
|
||||
|
||||
#ifdef SUNOS_NO_IFADDRS
|
||||
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||
return -ENOSYS;
|
||||
}
|
||||
#else /* SUNOS_NO_IFADDRS */
|
||||
/*
|
||||
* Inspired By:
|
||||
* https://blogs.oracle.com/paulie/entry/retrieving_mac_address_in_solaris
|
||||
@@ -742,9 +747,6 @@ static int uv__set_phys_addr(uv_interface_address_t* address,
|
||||
}
|
||||
|
||||
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||
#ifdef SUNOS_NO_IFADDRS
|
||||
return -ENOSYS;
|
||||
#else
|
||||
uv_interface_address_t* address;
|
||||
struct ifaddrs* addrs;
|
||||
struct ifaddrs* ent;
|
||||
@@ -805,9 +807,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||
freeifaddrs(addrs);
|
||||
|
||||
return 0;
|
||||
#endif /* SUNOS_NO_IFADDRS */
|
||||
}
|
||||
|
||||
#endif /* SUNOS_NO_IFADDRS */
|
||||
|
||||
void uv_free_interface_addresses(uv_interface_address_t* addresses,
|
||||
int count) {
|
||||
|
||||
@@ -40,28 +40,8 @@
|
||||
#undef NANOSEC
|
||||
#define NANOSEC ((uint64_t) 1e9)
|
||||
|
||||
struct thread_ctx {
|
||||
void (*entry)(void* arg);
|
||||
void* arg;
|
||||
};
|
||||
|
||||
|
||||
static void* uv__thread_start(void *arg)
|
||||
{
|
||||
struct thread_ctx *ctx_p;
|
||||
struct thread_ctx ctx;
|
||||
|
||||
ctx_p = arg;
|
||||
ctx = *ctx_p;
|
||||
uv__free(ctx_p);
|
||||
ctx.entry(ctx.arg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
|
||||
struct thread_ctx* ctx;
|
||||
int err;
|
||||
pthread_attr_t* attr;
|
||||
#if defined(__APPLE__)
|
||||
@@ -69,13 +49,6 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
|
||||
struct rlimit lim;
|
||||
#endif
|
||||
|
||||
ctx = uv__malloc(sizeof(*ctx));
|
||||
if (ctx == NULL)
|
||||
return UV_ENOMEM;
|
||||
|
||||
ctx->entry = entry;
|
||||
ctx->arg = arg;
|
||||
|
||||
/* On OSX threads other than the main thread are created with a reduced stack
|
||||
* size by default, adjust it to RLIMIT_STACK.
|
||||
*/
|
||||
@@ -99,14 +72,11 @@ int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
|
||||
attr = NULL;
|
||||
#endif
|
||||
|
||||
err = pthread_create(tid, attr, uv__thread_start, ctx);
|
||||
err = pthread_create(tid, attr, (void*(*)(void*)) entry, arg);
|
||||
|
||||
if (attr != NULL)
|
||||
pthread_attr_destroy(attr);
|
||||
|
||||
if (err)
|
||||
uv__free(ctx);
|
||||
|
||||
return -err;
|
||||
}
|
||||
|
||||
|
||||
@@ -512,8 +512,18 @@ void uv__fs_scandir_cleanup(uv_fs_t* req) {
|
||||
int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent) {
|
||||
uv__dirent_t** dents;
|
||||
uv__dirent_t* dent;
|
||||
unsigned int* nbufs;
|
||||
|
||||
unsigned int* nbufs = uv__get_nbufs(req);
|
||||
/* Check to see if req passed */
|
||||
if (req->result < 0)
|
||||
return req->result;
|
||||
|
||||
/* Ptr will be null if req was canceled or no files found */
|
||||
if (!req->ptr)
|
||||
return UV_EOF;
|
||||
|
||||
nbufs = uv__get_nbufs(req);
|
||||
assert(nbufs);
|
||||
|
||||
dents = req->ptr;
|
||||
|
||||
|
||||
@@ -35,10 +35,6 @@
|
||||
#include "handle-inl.h"
|
||||
#include "req-inl.h"
|
||||
|
||||
|
||||
static uv_loop_t default_loop_struct;
|
||||
static uv_loop_t* default_loop_ptr;
|
||||
|
||||
/* uv_once initialization guards */
|
||||
static uv_once_t uv_init_guard_ = UV_ONCE_INIT;
|
||||
|
||||
|
||||
@@ -71,6 +71,7 @@ int uv_translate_sys_error(int sys_errno) {
|
||||
switch (sys_errno) {
|
||||
case ERROR_NOACCESS: return UV_EACCES;
|
||||
case WSAEACCES: return UV_EACCES;
|
||||
case ERROR_ELEVATION_REQUIRED: return UV_EACCES;
|
||||
case ERROR_ADDRESS_ALREADY_ASSOCIATED: return UV_EADDRINUSE;
|
||||
case WSAEADDRINUSE: return UV_EADDRINUSE;
|
||||
case WSAEADDRNOTAVAIL: return UV_EADDRNOTAVAIL;
|
||||
|
||||
@@ -188,7 +188,6 @@ int uv_fs_event_start(uv_fs_event_t* handle,
|
||||
|
||||
if (is_path_dir) {
|
||||
/* path is a directory, so that's the directory that we will watch. */
|
||||
handle->dirw = pathw;
|
||||
dir_to_watch = pathw;
|
||||
} else {
|
||||
/*
|
||||
@@ -274,6 +273,8 @@ int uv_fs_event_start(uv_fs_event_t* handle,
|
||||
goto error;
|
||||
}
|
||||
|
||||
assert(is_path_dir ? pathw != NULL : pathw == NULL);
|
||||
handle->dirw = pathw;
|
||||
handle->req_pending = 1;
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ INLINE static int fs__capture_path(uv_fs_t* req, const char* path,
|
||||
const char* new_path, const int copy_path) {
|
||||
char* buf;
|
||||
char* pos;
|
||||
ssize_t buf_sz = 0, path_len, pathw_len = 0, new_pathw_len = 0;
|
||||
ssize_t buf_sz = 0, path_len = 0, pathw_len = 0, new_pathw_len = 0;
|
||||
|
||||
/* new_path can only be set if path is also set. */
|
||||
assert(new_path == NULL || path != NULL);
|
||||
@@ -403,7 +403,6 @@ void fs__open(uv_fs_t* req) {
|
||||
switch (flags & (_O_RDONLY | _O_WRONLY | _O_RDWR)) {
|
||||
case _O_RDONLY:
|
||||
access = FILE_GENERIC_READ;
|
||||
attributes |= FILE_FLAG_BACKUP_SEMANTICS;
|
||||
break;
|
||||
case _O_WRONLY:
|
||||
access = FILE_GENERIC_WRITE;
|
||||
@@ -418,7 +417,6 @@ void fs__open(uv_fs_t* req) {
|
||||
if (flags & _O_APPEND) {
|
||||
access &= ~FILE_WRITE_DATA;
|
||||
access |= FILE_APPEND_DATA;
|
||||
attributes &= ~FILE_FLAG_BACKUP_SEMANTICS;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -262,8 +262,7 @@ int uv_getaddrinfo(uv_loop_t* loop,
|
||||
int err;
|
||||
|
||||
if (req == NULL || (node == NULL && service == NULL)) {
|
||||
err = WSAEINVAL;
|
||||
goto error;
|
||||
return UV_EINVAL;
|
||||
}
|
||||
|
||||
uv_req_init(loop, (uv_req_t*)req);
|
||||
|
||||
@@ -372,6 +372,7 @@ int uv__stdio_create(uv_loop_t* loop,
|
||||
|
||||
case FILE_TYPE_PIPE:
|
||||
CHILD_STDIO_CRT_FLAGS(buffer, i) = FOPEN | FPIPE;
|
||||
break;
|
||||
|
||||
case FILE_TYPE_CHAR:
|
||||
case FILE_TYPE_REMOTE:
|
||||
|
||||
@@ -492,7 +492,7 @@ WCHAR* quote_cmd_arg(const WCHAR *source, WCHAR *target) {
|
||||
* input : hello\\"world
|
||||
* output: "hello\\\\\"world"
|
||||
* input : hello world\
|
||||
* output: "hello world\"
|
||||
* output: "hello world\\"
|
||||
*/
|
||||
|
||||
*(target++) = L'"';
|
||||
|
||||
@@ -30,12 +30,14 @@
|
||||
RB_HEAD(uv_signal_tree_s, uv_signal_s);
|
||||
|
||||
static struct uv_signal_tree_s uv__signal_tree = RB_INITIALIZER(uv__signal_tree);
|
||||
static ssize_t volatile uv__signal_control_handler_refs = 0;
|
||||
static CRITICAL_SECTION uv__signal_lock;
|
||||
|
||||
static BOOL WINAPI uv__signal_control_handler(DWORD type);
|
||||
|
||||
void uv_signals_init() {
|
||||
InitializeCriticalSection(&uv__signal_lock);
|
||||
if (!SetConsoleCtrlHandler(uv__signal_control_handler, TRUE))
|
||||
abort();
|
||||
}
|
||||
|
||||
|
||||
@@ -125,102 +127,6 @@ static BOOL WINAPI uv__signal_control_handler(DWORD type) {
|
||||
}
|
||||
|
||||
|
||||
static int uv__signal_register_control_handler() {
|
||||
/* When this function is called, the uv__signal_lock must be held. */
|
||||
|
||||
/* If the console control handler has already been hooked, just add a */
|
||||
/* reference. */
|
||||
if (uv__signal_control_handler_refs > 0) {
|
||||
uv__signal_control_handler_refs++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!SetConsoleCtrlHandler(uv__signal_control_handler, TRUE))
|
||||
return GetLastError();
|
||||
|
||||
uv__signal_control_handler_refs++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void uv__signal_unregister_control_handler() {
|
||||
/* When this function is called, the uv__signal_lock must be held. */
|
||||
BOOL r;
|
||||
|
||||
/* Don't unregister if the number of console control handlers exceeds one. */
|
||||
/* Just remove a reference in that case. */
|
||||
if (uv__signal_control_handler_refs > 1) {
|
||||
uv__signal_control_handler_refs--;
|
||||
return;
|
||||
}
|
||||
|
||||
assert(uv__signal_control_handler_refs == 1);
|
||||
|
||||
r = SetConsoleCtrlHandler(uv__signal_control_handler, FALSE);
|
||||
/* This should never fail; if it does it is probably a bug in libuv. */
|
||||
assert(r);
|
||||
|
||||
uv__signal_control_handler_refs--;
|
||||
}
|
||||
|
||||
|
||||
static int uv__signal_register(int signum) {
|
||||
switch (signum) {
|
||||
case SIGINT:
|
||||
case SIGBREAK:
|
||||
case SIGHUP:
|
||||
return uv__signal_register_control_handler();
|
||||
|
||||
case SIGWINCH:
|
||||
/* SIGWINCH is generated in tty.c. No need to register anything. */
|
||||
return 0;
|
||||
|
||||
case SIGILL:
|
||||
case SIGABRT_COMPAT:
|
||||
case SIGFPE:
|
||||
case SIGSEGV:
|
||||
case SIGTERM:
|
||||
case SIGABRT:
|
||||
/* Signal is never raised. */
|
||||
return 0;
|
||||
|
||||
default:
|
||||
/* Invalid signal. */
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void uv__signal_unregister(int signum) {
|
||||
switch (signum) {
|
||||
case SIGINT:
|
||||
case SIGBREAK:
|
||||
case SIGHUP:
|
||||
uv__signal_unregister_control_handler();
|
||||
return;
|
||||
|
||||
case SIGWINCH:
|
||||
/* SIGWINCH is generated in tty.c. No need to unregister anything. */
|
||||
return;
|
||||
|
||||
case SIGILL:
|
||||
case SIGABRT_COMPAT:
|
||||
case SIGFPE:
|
||||
case SIGSEGV:
|
||||
case SIGTERM:
|
||||
case SIGABRT:
|
||||
/* Nothing is registered for this signal. */
|
||||
return;
|
||||
|
||||
default:
|
||||
/* Libuv bug. */
|
||||
assert(0 && "Invalid signum");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle) {
|
||||
uv_req_t* req;
|
||||
|
||||
@@ -247,8 +153,6 @@ int uv_signal_stop(uv_signal_t* handle) {
|
||||
|
||||
EnterCriticalSection(&uv__signal_lock);
|
||||
|
||||
uv__signal_unregister(handle->signum);
|
||||
|
||||
removed_handle = RB_REMOVE(uv_signal_tree_s, &uv__signal_tree, handle);
|
||||
assert(removed_handle == handle);
|
||||
|
||||
@@ -262,14 +166,9 @@ int uv_signal_stop(uv_signal_t* handle) {
|
||||
|
||||
|
||||
int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) {
|
||||
int err;
|
||||
|
||||
/* If the user supplies signum == 0, then return an error already. If the */
|
||||
/* signum is otherwise invalid then uv__signal_register will find out */
|
||||
/* eventually. */
|
||||
if (signum == 0) {
|
||||
/* Test for invalid signal values. */
|
||||
if (signum != SIGWINCH && (signum <= 0 || signum >= NSIG))
|
||||
return UV_EINVAL;
|
||||
}
|
||||
|
||||
/* Short circuit: if the signal watcher is already watching {signum} don't */
|
||||
/* go through the process of deregistering and registering the handler. */
|
||||
@@ -289,13 +188,6 @@ int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) {
|
||||
|
||||
EnterCriticalSection(&uv__signal_lock);
|
||||
|
||||
err = uv__signal_register(signum);
|
||||
if (err) {
|
||||
/* Uh-oh, didn't work. */
|
||||
LeaveCriticalSection(&uv__signal_lock);
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
|
||||
handle->signum = signum;
|
||||
RB_INSERT(uv_signal_tree_s, &uv__signal_tree, handle);
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
#define ANSI_BACKSLASH_SEEN 0x80
|
||||
|
||||
#define MAX_INPUT_BUFFER_LENGTH 8192
|
||||
#define MAX_CONSOLE_CHAR 8192
|
||||
|
||||
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
||||
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
|
||||
@@ -1003,6 +1004,9 @@ int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb,
|
||||
if (handle->tty.rd.last_key_len > 0) {
|
||||
SET_REQ_SUCCESS(&handle->read_req);
|
||||
uv_insert_pending_req(handle->loop, (uv_req_t*) &handle->read_req);
|
||||
/* Make sure no attempt is made to insert it again until it's handled. */
|
||||
handle->flags |= UV_HANDLE_READ_PENDING;
|
||||
handle->reqs_pending++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1616,17 +1620,29 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
|
||||
DWORD* error) {
|
||||
/* We can only write 8k characters at a time. Windows can't handle */
|
||||
/* much more characters in a single console write anyway. */
|
||||
WCHAR utf16_buf[8192];
|
||||
WCHAR utf16_buf[MAX_CONSOLE_CHAR];
|
||||
WCHAR* utf16_buffer;
|
||||
DWORD utf16_buf_used = 0;
|
||||
unsigned int i;
|
||||
unsigned int i, len, max_len, pos;
|
||||
int allocate = 0;
|
||||
|
||||
#define FLUSH_TEXT() \
|
||||
do { \
|
||||
if (utf16_buf_used > 0) { \
|
||||
uv_tty_emit_text(handle, utf16_buf, utf16_buf_used, error); \
|
||||
utf16_buf_used = 0; \
|
||||
} \
|
||||
} while (0)
|
||||
#define FLUSH_TEXT() \
|
||||
do { \
|
||||
pos = 0; \
|
||||
do { \
|
||||
len = utf16_buf_used - pos; \
|
||||
if (len > MAX_CONSOLE_CHAR) \
|
||||
len = MAX_CONSOLE_CHAR; \
|
||||
uv_tty_emit_text(handle, &utf16_buffer[pos], len, error); \
|
||||
pos += len; \
|
||||
} while (pos < utf16_buf_used); \
|
||||
if (allocate) { \
|
||||
uv__free(utf16_buffer); \
|
||||
allocate = 0; \
|
||||
utf16_buffer = utf16_buf; \
|
||||
} \
|
||||
utf16_buf_used = 0; \
|
||||
} while (0)
|
||||
|
||||
#define ENSURE_BUFFER_SPACE(wchars_needed) \
|
||||
if (wchars_needed > ARRAY_SIZE(utf16_buf) - utf16_buf_used) { \
|
||||
@@ -1644,39 +1660,48 @@ static int uv_tty_write_bufs(uv_tty_t* handle,
|
||||
/* state. */
|
||||
*error = ERROR_SUCCESS;
|
||||
|
||||
utf16_buffer = utf16_buf;
|
||||
|
||||
uv_sem_wait(&uv_tty_output_lock);
|
||||
|
||||
for (i = 0; i < nbufs; i++) {
|
||||
uv_buf_t buf = bufs[i];
|
||||
unsigned int j;
|
||||
|
||||
if (uv__vterm_state == UV_SUPPORTED) {
|
||||
utf16_buf_used = MultiByteToWideChar(CP_UTF8,
|
||||
0,
|
||||
buf.base,
|
||||
buf.len,
|
||||
NULL,
|
||||
0);
|
||||
if (uv__vterm_state == UV_SUPPORTED && buf.len > 0) {
|
||||
utf16_buf_used = MultiByteToWideChar(CP_UTF8,
|
||||
0,
|
||||
buf.base,
|
||||
buf.len,
|
||||
NULL,
|
||||
0);
|
||||
|
||||
if (utf16_buf_used == 0) {
|
||||
*error = GetLastError();
|
||||
break;
|
||||
if (utf16_buf_used == 0) {
|
||||
*error = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
max_len = (utf16_buf_used + 1) * sizeof(WCHAR);
|
||||
allocate = max_len > MAX_CONSOLE_CHAR;
|
||||
if (allocate)
|
||||
utf16_buffer = uv__malloc(max_len);
|
||||
if (!MultiByteToWideChar(CP_UTF8,
|
||||
0,
|
||||
buf.base,
|
||||
buf.len,
|
||||
utf16_buffer,
|
||||
utf16_buf_used)) {
|
||||
if (allocate)
|
||||
uv__free(utf16_buffer);
|
||||
*error = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
FLUSH_TEXT();
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!MultiByteToWideChar(CP_UTF8,
|
||||
0,
|
||||
buf.base,
|
||||
buf.len,
|
||||
utf16_buf,
|
||||
utf16_buf_used)) {
|
||||
*error = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
FLUSH_TEXT();
|
||||
continue;
|
||||
}
|
||||
|
||||
for (j = 0; j < buf.len; j++) {
|
||||
unsigned char c = buf.base[j];
|
||||
|
||||
|
||||
@@ -4615,6 +4615,10 @@ typedef NTSTATUS (NTAPI *sNtQueryDirectoryFile)
|
||||
#endif
|
||||
|
||||
/* from winerror.h */
|
||||
#ifndef ERROR_ELEVATION_REQUIRED
|
||||
# define ERROR_ELEVATION_REQUIRED 740
|
||||
#endif
|
||||
|
||||
#ifndef ERROR_SYMLINK_NOT_SUPPORTED
|
||||
# define ERROR_SYMLINK_NOT_SUPPORTED 1464
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user