Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

sunos: make fs.watch scale better

Instead of using one port per watch, use one port for all the watches.
  • Loading branch information...
commit 7326962ec3f27737ff9f072e979be09d2b42abf3 1 parent 936795a
Ira Cooper authored bnoordhuis committed
Showing with 64 additions and 25 deletions.
  1. +15 −4 include/uv-private/uv-unix.h
  2. +13 −1 src/unix/core.c
  3. +36 −20 src/unix/sunos.c
View
19 include/uv-private/uv-unix.h
@@ -36,6 +36,11 @@
#include <pwd.h>
#include <termios.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;
@@ -52,6 +57,14 @@ typedef uid_t uv_uid_t;
typedef void* uv_lib_t;
#define UV_DYNAMIC /* empty */
+#if 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
+
#define UV_LOOP_PRIVATE_FIELDS \
ares_channel channel; \
/* \
@@ -60,7 +73,8 @@ typedef void* uv_lib_t;
* definition of ares_timeout(). \
*/ \
ev_timer timer; \
- struct ev_loop* ev;
+ struct ev_loop* ev; \
+ UV_LOOP_PRIVATE_PLATFORM_FIELDS
#define UV_REQ_BUFSML_SIZE (4)
@@ -206,9 +220,6 @@ typedef void* uv_lib_t;
#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
14 src/unix/core.c
@@ -19,7 +19,7 @@
*/
#include "uv.h"
-#include "unix/internal.h"
+#include "internal.h"
#include <stddef.h> /* NULL */
#include <stdio.h> /* printf */
@@ -151,6 +151,9 @@ uv_loop_t* uv_loop_new(void) {
uv_loop_t* loop = calloc(1, sizeof(uv_loop_t));
loop->ev = ev_loop_new(0);
ev_set_userdata(loop->ev, loop);
+#if HAVE_PORTS_FS
+ loop->fs_fd = -1;
+#endif
return loop;
}
@@ -163,6 +166,12 @@ void uv_loop_delete(uv_loop_t* loop) {
memset(loop, 0, sizeof *loop);
#endif
+#if HAVE_PORTS_FS
+ if (loop->fs_fd != -1) {
+ uv__close(loop->fs_fd);
+ }
+#endif
+
if (loop == default_loop_ptr)
default_loop_ptr = NULL;
else
@@ -183,6 +192,9 @@ uv_loop_t* uv_default_loop(void) {
#else
default_loop_struct.ev = ev_default_loop(EVFLAG_AUTO);
#endif
+#if HAVE_PORTS_FS
+ default_loop_struct.fs_fd = -1;
+#endif
ev_set_userdata(default_loop_struct.ev, default_loop_ptr);
}
assert(default_loop_ptr->ev == EV_DEFAULT_UC);
View
56 src/unix/sunos.c
@@ -36,6 +36,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
@@ -90,36 +95,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;
@@ -128,12 +138,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);
}
@@ -144,39 +154,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_destroy(uv_fs_event_t* handle) {
- ev_ref(handle->loop->ev);
- ev_io_stop(handle->loop->ev, &handle->event_watcher);
- uv__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;
Please sign in to comment.
Something went wrong with that request. Please try again.