Index: Makefile =================================================================== --- Makefile (revision 451265) +++ Makefile (working copy) @@ -85,6 +85,7 @@ OPTIONS_DEFINE+= UNIQUE VALSORT SMBPWD SHA2 DYNAMI OPTIONS_DEFINE+= LMPASSWD OPTIONS_DEFINE+= OUTLOOK OPTIONS_DEFINE+= LASTBIND +OPTIONS_DEFINE+= KQUEUE OPTIONS_DEFAULT= MDB SYNCPROV DYNAMIC_BACKENDS @@ -130,6 +131,7 @@ LMPASSWD_DESC= With LM hash password support (DEP DYNAMIC_BACKENDS_DESC= Build dynamic backends OUTLOOK_DESC= Force caseIgnoreOrderingMatch on name attribute (experimental) LASTBIND_DESC= With lastbind overlay +KQUEUE_DESC= With kqueue support (experimental) .endif .if defined(CLIENT_ONLY) @@ -196,8 +198,9 @@ CONFIGURE_ARGS= --with-threads=posix \ --disable-dependency-tracking \ --enable-dynamic -# XXX FreeBSD does not implement O_DSYNC and fdatasync at this time. +.if ${OSVERSION} < 1101000 CFLAGS+= -DMDB_DSYNC=O_SYNC -Dfdatasync=fsync +.endif .if ${PORT_OPTIONS:MSASL} LIB_DEPENDS+= libsasl2.so:security/cyrus-sasl2 @@ -502,6 +505,11 @@ CONFIGURE_ARGS+= --enable-wrappers EXTRA_PATCHES+= ${FILESDIR}/extrapatch-outlook-servers__slapd__schema_prep.c .endif +.if ${PORT_OPTIONS:MKQUEUE} +EXTRA_PATCHES+= ${FILESDIR}/extrapatch-ITS6300 +USE_AUTOTOOLS= autoconf +.endif + # end of client/server specific configuration .endif Index: files/extrapatch-ITS6300 =================================================================== --- files/extrapatch-ITS6300 (nonexistent) +++ files/extrapatch-ITS6300 (working copy) @@ -0,0 +1,406 @@ +--- configure.in.orig 2017-06-01 20:01:07 UTC ++++ configure.in +@@ -978,6 +978,18 @@ if test "${ac_cv_header_sys_epoll_h}" = yes; then + fi + + dnl ---------------------------------------------------------------- ++AC_CHECK_HEADERS( sys/event.h ) ++if test "${ac_cv_header_sys_event_h}" = yes; then ++AC_MSG_CHECKING(for kqueue system call) ++AC_RUN_IFELSE([AC_LANG_SOURCE([[int main(int argc, char **argv) ++{ ++ int kqfd = kqueue(); ++ exit (kqfd == -1 ? 1 : 0); ++}]])],[AC_MSG_RESULT(yes) ++AC_DEFINE(HAVE_KQUEUE,1, [define if your system supports kqueue])],[AC_MSG_RESULT(no)],[AC_MSG_RESULT(no)]) ++fi ++ ++dnl ---------------------------------------------------------------- + AC_CHECK_HEADERS( sys/devpoll.h ) + dnl "/dev/poll" needs as well... + if test "${ac_cv_header_sys_devpoll_h}" = yes \ +--- include/portable.hin.orig 2017-06-01 20:01:07 UTC ++++ include/portable.hin +@@ -280,6 +280,9 @@ + /* Define to 1 if you have the header file. */ + #undef HAVE_IO_H + ++/* define if your system supports kqueue */ ++#undef HAVE_KQUEUE ++ + /* Define to 1 if you have the `gen' library (-lgen). */ + #undef HAVE_LIBGEN + +@@ -664,6 +667,9 @@ + + /* Define to 1 if you have the header file. */ + #undef HAVE_SYS_ERRNO_H ++ ++/* Define to 1 if you have the header file. */ ++#undef HAVE_SYS_EVENT_H + + /* Define to 1 if you have the header file. */ + #undef HAVE_SYS_FILE_H +--- servers/slapd/daemon.c.orig 2017-06-01 20:01:07 UTC ++++ servers/slapd/daemon.c +@@ -41,14 +41,18 @@ + + #include "ldap_rq.h" + +-#if defined(HAVE_SYS_EPOLL_H) && defined(HAVE_EPOLL) ++#ifdef HAVE_KQUEUE ++# include ++# include ++# include ++#elif defined(HAVE_SYS_EPOLL_H) && defined(HAVE_EPOLL) + # include + #elif defined(SLAP_X_DEVPOLL) && defined(HAVE_SYS_DEVPOLL_H) && defined(HAVE_DEVPOLL) + # include + # include + # include + # include +-#endif /* ! epoll && ! /dev/poll */ ++#endif /* ! kqueue && ! epoll && ! /dev/poll */ + + #ifdef HAVE_TCPD + int allow_severity = LOG_INFO; +@@ -89,7 +93,7 @@ static volatile sig_atomic_t listening = 1; /* 0 when + static ldap_pvt_thread_t *listener_tid; + + #ifndef SLAPD_LISTEN_BACKLOG +-#define SLAPD_LISTEN_BACKLOG 1024 ++#define SLAPD_LISTEN_BACKLOG 2048 + #endif /* ! SLAPD_LISTEN_BACKLOG */ + + #define DAEMON_ID(fd) (fd & slapd_daemon_mask) +@@ -138,7 +142,21 @@ typedef struct slap_daemon_st { + int sd_nwriters; + int sd_nfds; + +-#if defined(HAVE_EPOLL) ++#if defined(HAVE_KQUEUE) ++ uint8_t* sd_fdmodes; /* indexed by fd */ ++ Listener** sd_l; /* indexed by fd */ ++ /* Double buffer the kqueue changes to avoid holding the sd_mutex \ ++ * during a kevent() call. \ ++ */ ++ struct kq_change { ++ struct kevent* sd_changes; ++ int sd_nchanges; ++ int sd_maxchanges; ++ } sd_kqc[2]; ++ int sd_changeidx; /* index to current change buffer */ ++ int sd_kq; ++#elif defined(HAVE_EPOLL) ++ + struct epoll_event *sd_epolls; + int *sd_index; + int sd_epfd; +@@ -148,7 +166,7 @@ typedef struct slap_daemon_st { + int *sd_index; + Listener **sd_l; + int sd_dpfd; +-#else /* ! epoll && ! /dev/poll */ ++#else /* ! kqueue && ! epoll && ! /dev/poll */ + #ifdef HAVE_WINSOCK + char *sd_flags; + char *sd_rflags; +@@ -157,7 +175,7 @@ typedef struct slap_daemon_st { + fd_set sd_readers; + fd_set sd_writers; + #endif /* ! HAVE_WINSOCK */ +-#endif /* ! epoll && ! /dev/poll */ ++#endif /* ! kqueue && ! epoll && ! /dev/poll */ + } slap_daemon_st; + + static slap_daemon_st slap_daemon[SLAPD_MAX_DAEMON_THREADS]; +@@ -169,11 +187,220 @@ static slap_daemon_st slap_daemon[SLAPD_MAX_DAEMON_THR + * with file descriptors and events respectively + * + * - SLAP__* for private interface; type by now is one of +- * EPOLL, DEVPOLL, SELECT ++ * EPOLL, DEVPOLL, SELECT, KQUEUE + * + * private interface should not be used in the code. + */ +-#if defined(HAVE_EPOLL) ++#ifdef HAVE_KQUEUE ++# define SLAP_EVENT_FNAME "kqueue" ++# define SLAP_EVENTS_ARE_INDEXED 0 ++# define SLAP_EVENT_MAX(t) (2 * dtblsize) /* each fd can have a read & a write event */ ++ ++# define SLAP_EVENT_DECL \ ++ static struct kevent* events = NULL ++ ++# define SLAP_EVENT_INIT(t) do {\ ++ if (!events) { \ ++ events = ch_malloc(sizeof(*events) * SLAP_EVENT_MAX(t)); \ ++ if (!events) { \ ++ Debug(LDAP_DEBUG_ANY, \ ++ "daemon: SLAP_EVENT_INIT: ch_malloc of events failed, wanted %d bytes\n", \ ++ sizeof(*events) * SLAP_EVENT_MAX(t), 0, 0); \ ++ slapd_shutdown = 2; \ ++ } \ ++ } \ ++} while (0) ++ ++# define SLAP_SOCK_INIT(t) do { \ ++ int kq_i; \ ++ size_t kq_nbytes; \ ++ Debug(LDAP_DEBUG_ANY, "daemon: SLAP_SOCK_INIT: dtblsize=%d\n", dtblsize, 0, 0); \ ++ slap_daemon[t].sd_nfds = 0; \ ++ slap_daemon[t].sd_changeidx = 0; \ ++ for (kq_i = 0; kq_i < 2; kq_i++) { \ ++ struct kq_change* kqc = &slap_daemon[t].sd_kqc[kq_i]; \ ++ kqc->sd_nchanges = 0; \ ++ kqc->sd_maxchanges = 256; /* will grow as needed */ \ ++ kq_nbytes = sizeof(*kqc->sd_changes) * kqc->sd_maxchanges; \ ++ kqc->sd_changes = ch_calloc(1, kq_nbytes); \ ++ if (!kqc->sd_changes) { \ ++ Debug(LDAP_DEBUG_ANY, \ ++ "daemon: SLAP_SOCK_INIT: ch_calloc of slap_daemon.sd_changes[%d] failed, wanted %d bytes, shutting down\n", \ ++ kq_i, kq_nbytes, 0); \ ++ slapd_shutdown = 2; \ ++ } \ ++ } \ ++ kq_nbytes = sizeof(*slap_daemon[t].sd_fdmodes) * dtblsize; \ ++ slap_daemon[t].sd_fdmodes = ch_calloc(1, kq_nbytes); \ ++ if (!slap_daemon[t].sd_fdmodes) { \ ++ Debug(LDAP_DEBUG_ANY, \ ++ "daemon: SLAP_SOCK_INIT: ch_calloc of slap_daemon.sd_fdmodes failed, wanted %d bytes, shutting down\n", \ ++ kq_nbytes, 0, 0); \ ++ slapd_shutdown = 2; \ ++ } \ ++ kq_nbytes = sizeof(*slap_daemon[t].sd_l) * dtblsize; \ ++ slap_daemon[t].sd_l = ch_calloc(1, kq_nbytes); \ ++ if (!slap_daemon[t].sd_l) { \ ++ Debug(LDAP_DEBUG_ANY, \ ++ "daemon: SLAP_SOCK_INIT: ch_calloc of slap_daemon.sd_l failed, wanted %d bytes, shutting down\n", \ ++ kq_nbytes, 0, 0); \ ++ slapd_shutdown = 2; \ ++ } \ ++ slap_daemon[t].sd_kq = kqueue(); \ ++ if (slap_daemon[t].sd_kq < 0) { \ ++ Debug(LDAP_DEBUG_ANY, "daemon: SLAP_SOCK_INIT: kqueue() failed, errno=%d, shutting down\n", errno, 0, 0); \ ++ slapd_shutdown = 2; \ ++ } \ ++} while (0) ++ ++# define SLAP_SOCK_DESTROY(t) do { \ ++ int kq_i; \ ++ if (slap_daemon[t].sd_kq > 0) { \ ++ close(slap_daemon[t].sd_kq); \ ++ slap_daemon[t].sd_kq = -1; \ ++ } \ ++ for (kq_i = 0; kq_i < 2; kq_i++) { \ ++ if (slap_daemon[t].sd_kqc[kq_i].sd_changes != NULL) { \ ++ ch_free(slap_daemon[t].sd_kqc[kq_i].sd_changes); \ ++ slap_daemon[t].sd_kqc[kq_i].sd_changes = NULL; \ ++ } \ ++ slap_daemon[t].sd_kqc[kq_i].sd_nchanges = 0; \ ++ slap_daemon[t].sd_kqc[kq_i].sd_maxchanges = 0; \ ++ } \ ++ if (slap_daemon[t].sd_l != NULL) { \ ++ ch_free(slap_daemon[t].sd_l); \ ++ slap_daemon[t].sd_l = NULL; \ ++ } \ ++ if (slap_daemon[t].sd_fdmodes != NULL) { \ ++ ch_free(slap_daemon[t].sd_fdmodes); \ ++ slap_daemon[t].sd_fdmodes = NULL; \ ++ } \ ++ slap_daemon[t].sd_nfds = 0; \ ++} while (0) ++ ++# define SLAP_KQUEUE_SOCK_ACTIVE 0x01 ++# define SLAP_KQUEUE_SOCK_READ_ENABLED 0x02 ++# define SLAP_KQUEUE_SOCK_WRITE_ENABLED 0x04 ++ ++# define SLAP_SOCK_IS_ACTIVE(t,s) (slap_daemon[t].sd_fdmodes[(s)] != 0) ++# define SLAP_SOCK_NOT_ACTIVE(t,s) (slap_daemon[t].sd_fdmodes[(s)] == 0) ++# define SLAP_SOCK_IS_READ(t,s) (slap_daemon[t].sd_fdmodes[(s)] & SLAP_KQUEUE_SOCK_READ_ENABLED) ++# define SLAP_SOCK_IS_WRITE(t,s) (slap_daemon[t].sd_fdmodes[(s)] & SLAP_KQUEUE_SOCK_WRITE_ENABLED) ++ ++/* ++ * SLAP_SOCK_SET_* & SLAP_SOCK_CLR_* get called a _lot_. Since kevent() ++ * processes changes before it looks for events, batch up the changes which ++ * will get submitted the next time kevent() is called for events. ++ */ ++ ++# define SLAP_KQUEUE_CHANGE(t, s, filter, flag) do { \ ++ /* If maxchanges is reached, have to realloc to make room for more. \ ++ * Ideally we'd call kevent(), but the daemon thread could be sitting \ ++ * in kevent() waiting for events. \ ++ */ \ ++ struct kq_change* kqc = &slap_daemon[t].sd_kqc[slap_daemon[t].sd_changeidx]; \ ++ if (kqc->sd_nchanges == kqc->sd_maxchanges) { \ ++ /* Don't want to do this very often. Double the size. */ \ ++ size_t kq_nbytes; \ ++ Debug(LDAP_DEBUG_CONNS, \ ++ "daemon: SLAP_KQUEUE_CHANGE: increasing slap_daemon.sd_kqc[%d].maxchanges from %d to %d\n", \ ++ slap_daemon[t].sd_changeidx, kqc->sd_maxchanges, 2*kqc->sd_maxchanges); \ ++ kqc->sd_maxchanges += kqc->sd_maxchanges; \ ++ kq_nbytes = sizeof(*kqc->sd_changes) * kqc->sd_maxchanges; \ ++ kqc->sd_changes = ch_realloc(kqc->sd_changes, kq_nbytes); \ ++ if (!kqc->sd_changes) { \ ++ Debug(LDAP_DEBUG_ANY, \ ++ "daemon: SLAP_KQUEUE_CHANGE: ch_realloc of slap_daemon.sd_kqc[%d].sd_changes failed, wanted %d bytes, shutting down\n", \ ++ slap_daemon[t].sd_changeidx, kq_nbytes, 0); \ ++ slapd_shutdown = 2; \ ++ break; /* Don't want to do the EV_SET if sd_changes is NULL */ \ ++ } \ ++ } \ ++ EV_SET(&kqc->sd_changes[kqc->sd_nchanges++], \ ++ (s), (filter), (flag), 0, 0, slap_daemon[t].sd_l[(s)]); \ ++} while (0) ++ ++# define SLAP_KQUEUE_SOCK_SET(t, s, filter, mode) do { \ ++ if ((slap_daemon[t].sd_fdmodes[(s)] & (mode)) != (mode)) { \ ++ slap_daemon[t].sd_fdmodes[(s)] |= (mode); \ ++ SLAP_KQUEUE_CHANGE(t, (s), (filter), EV_ENABLE); \ ++ } \ ++} while (0) ++ ++# define SLAP_KQUEUE_SOCK_CLR(t, s, filter, mode) do { \ ++ if (slap_daemon[t].sd_fdmodes[(s)] & (mode)) { \ ++ slap_daemon[t].sd_fdmodes[(s)] &= ~(mode); \ ++ SLAP_KQUEUE_CHANGE(t, (s), (filter), EV_DISABLE); \ ++ } \ ++} while (0) ++ ++# define SLAP_SOCK_SET_READ(t, s) SLAP_KQUEUE_SOCK_SET(t, (s), EVFILT_READ, SLAP_KQUEUE_SOCK_READ_ENABLED) ++# define SLAP_SOCK_SET_WRITE(t, s) SLAP_KQUEUE_SOCK_SET(t, (s), EVFILT_WRITE, SLAP_KQUEUE_SOCK_WRITE_ENABLED) ++# define SLAP_SOCK_CLR_READ(t, s) SLAP_KQUEUE_SOCK_CLR(t, (s), EVFILT_READ, SLAP_KQUEUE_SOCK_READ_ENABLED) ++# define SLAP_SOCK_CLR_WRITE(t, s) SLAP_KQUEUE_SOCK_CLR(t, (s), EVFILT_WRITE, SLAP_KQUEUE_SOCK_WRITE_ENABLED) ++ ++/* kqueue doesn't need to do anything to clear the event. */ ++# define SLAP_EVENT_CLR_READ(i) do {} while (0) ++# define SLAP_EVENT_CLR_WRITE(i) do {} while (0) ++ ++# define SLAP_SOCK_ADD(t, s, l) do { \ ++ assert( s < dtblsize ); \ ++ slap_daemon[t].sd_l[(s)] = (l); \ ++ slap_daemon[t].sd_fdmodes[(s)] = SLAP_KQUEUE_SOCK_ACTIVE | SLAP_KQUEUE_SOCK_READ_ENABLED; \ ++ ++slap_daemon[t].sd_nfds; \ ++ SLAP_KQUEUE_CHANGE(t, (s), EVFILT_READ, EV_ADD); \ ++ SLAP_KQUEUE_CHANGE(t, (s), EVFILT_WRITE, EV_ADD | EV_DISABLE); \ ++} while (0) ++ ++# define SLAP_SOCK_DEL(t, s) do { \ ++ SLAP_KQUEUE_CHANGE(t, (s), EVFILT_READ, EV_DELETE); \ ++ SLAP_KQUEUE_CHANGE(t, (s), EVFILT_WRITE, EV_DELETE); \ ++ slap_daemon[t].sd_l[(s)] = NULL; \ ++ slap_daemon[t].sd_fdmodes[(s)] = 0; \ ++ --slap_daemon[t].sd_nfds; \ ++} while (0) ++ ++# define SLAP_EVENT_FD(t, i) (events[(i)].ident) ++ ++# define SLAP_EVENT_IS_READ(t, i) \ ++ (events[(i)].filter == EVFILT_READ && SLAP_SOCK_IS_READ(t, SLAP_EVENT_FD(0, i))) ++ ++# define SLAP_EVENT_IS_WRITE(t, i) \ ++ (events[(i)].filter == EVFILT_WRITE && SLAP_SOCK_IS_WRITE(t, SLAP_EVENT_FD(0, i))) ++ ++# define SLAP_EVENT_IS_LISTENER(t, i) \ ++ (events[(i)].udata && SLAP_SOCK_IS_READ(t, SLAP_EVENT_FD(t, i))) ++ ++# define SLAP_EVENT_LISTENER(t, i) ((Listener*)(events[(i)].udata)) ++ ++# define SLAP_EVENT_WAIT(t, tvp, nsp) do { \ ++ struct timespec kq_ts; \ ++ struct timespec* kq_tsp; \ ++ int kq_idx; \ ++ if (tvp) { \ ++ TIMEVAL_TO_TIMESPEC((tvp), &kq_ts); \ ++ kq_tsp = &kq_ts; \ ++ } else { \ ++ kq_tsp = NULL; \ ++ } \ ++ /* Save the change buffer index for use when the mutex is unlocked, \ ++ * then switch the index so new changes go to the other buffer. \ ++ */ \ ++ ldap_pvt_thread_mutex_lock( &slap_daemon[t].sd_mutex ); \ ++ kq_idx = slap_daemon[t].sd_changeidx; \ ++ slap_daemon[t].sd_changeidx ^= 1; \ ++ ldap_pvt_thread_mutex_unlock( &slap_daemon[t].sd_mutex ); \ ++ *(nsp) = kevent(slap_daemon[t].sd_kq, \ ++ slap_daemon[t].sd_kqc[kq_idx].sd_nchanges \ ++ ? slap_daemon[t].sd_kqc[kq_idx].sd_changes : NULL, \ ++ slap_daemon[t].sd_kqc[kq_idx].sd_nchanges, \ ++ events, SLAP_EVENT_MAX(t), kq_tsp); \ ++ slap_daemon[t].sd_kqc[kq_idx].sd_nchanges = 0; \ ++} while(0) ++ ++/*-------------------------------------------------------------------------------*/ ++ ++#elif defined(HAVE_EPOLL) + /*************************************** + * Use epoll infrastructure - epoll(4) * + ***************************************/ +@@ -486,7 +713,7 @@ static slap_daemon_st slap_daemon[SLAPD_MAX_DAEMON_THR + *(nsp) = ioctl( slap_daemon[t].sd_dpfd, DP_POLL, &sd_dvpoll ); \ + } while (0) + +-#else /* ! epoll && ! /dev/poll */ ++#else /* ! kqueue && ! epoll && ! /dev/poll */ + # ifdef HAVE_WINSOCK + # define SLAP_EVENT_FNAME "WSselect" + /* Winsock provides a "select" function but its fd_sets are +@@ -674,7 +901,7 @@ static slap_daemon_st slap_daemon[SLAPD_MAX_DAEMON_THR + nwriters > 0 ? &writefds : NULL, NULL, (tvp) ); \ + } while (0) + # endif /* !HAVE_WINSOCK */ +-#endif /* ! epoll && ! /dev/poll */ ++#endif /* ! kqueue && ! epoll && ! /dev/poll */ + + #ifdef HAVE_SLP + /* +@@ -2733,8 +2960,13 @@ loop: + /* Don't log internal wake events */ + if ( fd == wake_sds[tid][0] ) continue; + ++#ifdef HAVE_KQUEUE ++ r = SLAP_EVENT_IS_READ( tid, i ); ++ w = SLAP_EVENT_IS_WRITE( tid, i ); ++#else + r = SLAP_EVENT_IS_READ( i ); + w = SLAP_EVENT_IS_WRITE( i ); ++#endif /* HAVE_KQUEUE */ + if ( r || w ) { + Debug( LDAP_DEBUG_CONNS, " %d%s%s", fd, + r ? "r" : "", w ? "w" : "" ); +@@ -2765,7 +2997,11 @@ loop: + continue; + } + ++#ifdef HAVE_KQUEUE ++ if ( SLAP_EVENT_IS_WRITE( tid, i ) ) { ++#else + if ( SLAP_EVENT_IS_WRITE( i ) ) { ++#endif /* HAVE_KQUEUE */ + Debug( LDAP_DEBUG_CONNS, + "daemon: write active on %d\n", + fd, 0, 0 ); +@@ -2784,7 +3020,11 @@ loop: + } + } + /* If event is a read */ ++#ifdef HAVE_KQUEUE ++ if ( SLAP_EVENT_IS_READ( tid, i )) { ++#else + if ( SLAP_EVENT_IS_READ( i )) { ++#endif /* HAVE_KQUEUE */ + r = 1; + Debug( LDAP_DEBUG_CONNS, + "daemon: read active on %d\n", +@@ -2841,6 +3081,10 @@ loop: + slapd_abrupt_shutdown = 1; + connections_shutdown(); + } ++ ++#ifdef HAVE_KQUEUE ++ close( slap_daemon[tid].sd_kq ); ++#endif + + if ( LogTest( LDAP_DEBUG_ANY )) { + int t = ldap_pvt_thread_pool_backload( &connection_pool ); Property changes on: files/extrapatch-ITS6300 ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property