Skip to content

Commit

Permalink
sunos: make fs.watch scale better
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bnoordhuis committed May 5, 2012
1 parent 1d24c76 commit b5f9bc8
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 23 deletions.
12 changes: 9 additions & 3 deletions include/uv-private/uv-unix.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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; \
Expand Down
7 changes: 7 additions & 0 deletions src/unix/loop.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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
}
56 changes: 36 additions & 20 deletions src/unix/sunos.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand All @@ -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);
}

Expand All @@ -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;
Expand Down

0 comments on commit b5f9bc8

Please sign in to comment.