sunos: make fs.watch scale better

Instead of using one port per watch, use one port for all the watches.
This is a cherry-pick of commit 7326962 from v0.6 into master.

Conflicts:

	include/uv-private/uv-unix.h
	src/unix/core.c
	src/unix/sunos.c
This commit is contained in:
Ben Noordhuis 2012-05-05 00:51:32 +00:00
parent 1d24c76df7
commit b5f9bc861f
3 changed files with 52 additions and 23 deletions

View File

@ -37,6 +37,11 @@
#include <termios.h>
#include <pthread.h>
#if __sun
# include <sys/port.h>
# include <port.h>
#endif
/* Note: May be cast to struct iovec. See writev(2). */
typedef struct {
char* base;
@ -76,6 +81,10 @@ typedef struct {
} inotify_watchers; \
ev_io inotify_read_watcher; \
int inotify_fd;
#elif defined(PORT_SOURCE_FILE)
# define UV_LOOP_PRIVATE_PLATFORM_FIELDS \
ev_io fs_event_watcher; \
int fs_fd;
#else
# define UV_LOOP_PRIVATE_PLATFORM_FIELDS
#endif
@ -249,9 +258,6 @@ typedef struct {
#elif defined(__sun)
#include <sys/port.h>
#include <port.h>
#ifdef PORT_SOURCE_FILE
# define UV_FS_EVENT_PRIVATE_FIELDS \
ev_io event_watcher; \

View File

@ -43,6 +43,9 @@ int uv__loop_init(uv_loop_t* loop, int default_loop) {
#if __linux__
RB_INIT(&loop->inotify_watchers);
loop->inotify_fd = -1;
#endif
#if HAVE_PORTS_FS
loop->fs_fd = -1;
#endif
return 0;
}
@ -57,4 +60,8 @@ void uv__loop_delete(uv_loop_t* loop) {
close(loop->inotify_fd);
loop->inotify_fd = -1;
#endif
#if HAVE_PORTS_FS
if (loop->fs_fd != -1)
close(loop->fs_fd);
#endif
}

View File

@ -42,6 +42,11 @@
#if HAVE_PORTS_FS
# include <sys/port.h>
# include <port.h>
# define PORT_FIRED 0x69
# define PORT_UNUSED 0x0
# define PORT_LOADED 0x99
# define PORT_DELETED -1
#endif
#if (!defined(_LP64)) && (_FILE_OFFSET_BITS - 0 == 64)
@ -109,36 +114,41 @@ void uv_loadavg(double avg[3]) {
#if HAVE_PORTS_FS
static void uv__fs_event_rearm(uv_fs_event_t *handle) {
if (port_associate(handle->fd,
if (handle->fd == -1)
return;
if (port_associate(handle->loop->fs_fd,
PORT_SOURCE_FILE,
(uintptr_t) &handle->fo,
FILE_ATTRIB | FILE_MODIFIED,
NULL) == -1) {
handle) == -1) {
uv__set_sys_error(handle->loop, errno);
}
handle->fd = PORT_LOADED;
}
static void uv__fs_event_read(EV_P_ ev_io* w, int revents) {
uv_fs_event_t *handle;
uv_loop_t *loop_;
timespec_t timeout;
port_event_t pe;
int events;
int r;
handle = container_of(w, uv_fs_event_t, event_watcher);
loop_ = container_of(w, uv_loop_t, fs_event_watcher);
do {
/* TODO use port_getn() */
do {
memset(&timeout, 0, sizeof timeout);
r = port_get(handle->fd, &pe, &timeout);
r = port_get(loop_->fs_fd, &pe, &timeout);
}
while (r == -1 && errno == EINTR);
if (r == -1 && errno == ETIME)
break;
handle = (uv_fs_event_t *)pe.portev_user;
assert((r == 0) && "unexpected port_get() error");
events = 0;
@ -147,12 +157,12 @@ static void uv__fs_event_read(EV_P_ ev_io* w, int revents) {
if (pe.portev_events & ~(FILE_ATTRIB | FILE_MODIFIED))
events |= UV_RENAME;
assert(events != 0);
handle->fd = PORT_FIRED;
handle->cb(handle, NULL, events, 0);
}
while (handle->fd != -1);
while (handle->fd != PORT_DELETED);
if (handle->fd != -1)
if (handle->fd != PORT_DELETED)
uv__fs_event_rearm(handle);
}
@ -163,39 +173,45 @@ int uv_fs_event_init(uv_loop_t* loop,
uv_fs_event_cb cb,
int flags) {
int portfd;
int first_run = 0;
loop->counters.fs_event_init++;
/* We don't support any flags yet. */
assert(!flags);
if ((portfd = port_create()) == -1) {
uv__set_sys_error(loop, errno);
return -1;
if (loop->fs_fd == -1) {
if ((portfd = port_create()) == -1) {
uv__set_sys_error(loop, errno);
return -1;
}
loop->fs_fd = portfd;
first_run = 1;
}
uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT);
handle->filename = strdup(filename);
handle->fd = portfd;
handle->fd = PORT_UNUSED;
handle->cb = cb;
memset(&handle->fo, 0, sizeof handle->fo);
handle->fo.fo_name = handle->filename;
uv__fs_event_rearm(handle);
ev_io_init(&handle->event_watcher, uv__fs_event_read, portfd, EV_READ);
ev_io_start(loop->ev, &handle->event_watcher);
ev_unref(loop->ev);
if (first_run) {
ev_io_init(&loop->fs_event_watcher, uv__fs_event_read, portfd, EV_READ);
ev_io_start(loop->ev, &loop->fs_event_watcher);
ev_unref(loop->ev);
}
return 0;
}
void uv__fs_event_close(uv_fs_event_t* handle) {
ev_ref(handle->loop->ev);
ev_io_stop(handle->loop->ev, &handle->event_watcher);
close(handle->fd);
handle->fd = -1;
if (handle->fd == PORT_FIRED) {
port_dissociate(handle->loop->fs_fd, PORT_SOURCE_FILE, (uintptr_t)&handle->fo);
}
handle->fd = PORT_DELETED;
free(handle->filename);
handle->filename = NULL;
handle->fo.fo_name = NULL;