File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / lighttpd / src / fdevent_freebsd_kqueue.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Oct 14 10:32:47 2013 UTC (10 years, 8 months ago) by misho
Branches: lighttpd, MAIN
CVS tags: v1_4_35p0, v1_4_35, v1_4_33, HEAD
1.4.33

    1: #include "fdevent.h"
    2: #include "buffer.h"
    3: #include "log.h"
    4: 
    5: #include <sys/types.h>
    6: 
    7: #include <unistd.h>
    8: #include <stdlib.h>
    9: #include <stdio.h>
   10: #include <string.h>
   11: #include <errno.h>
   12: #include <signal.h>
   13: #include <fcntl.h>
   14: 
   15: #ifdef USE_FREEBSD_KQUEUE
   16: # include <sys/event.h>
   17: # include <sys/time.h>
   18: 
   19: static void fdevent_freebsd_kqueue_free(fdevents *ev) {
   20: 	close(ev->kq_fd);
   21: 	free(ev->kq_results);
   22: }
   23: 
   24: static int fdevent_freebsd_kqueue_event_del(fdevents *ev, int fde_ndx, int fd) {
   25: 	int ret, n = 0;
   26: 	struct kevent kev[2];
   27: 	struct timespec ts;
   28: 	int oevents;
   29: 
   30: 	if (fde_ndx < 0) return -1;
   31: 
   32: 	oevents = ev->fdarray[fd]->events;
   33: 
   34: 	if (oevents & FDEVENT_IN)  {
   35: 		EV_SET(&kev[n], fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
   36: 		n++;
   37: 	}
   38: 	if (oevents & FDEVENT_OUT)  {
   39: 		EV_SET(&kev[n], fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
   40: 		n++;
   41: 	}
   42: 
   43: 	if (0 == n) return -1;
   44: 
   45: 	ts.tv_sec  = 0;
   46: 	ts.tv_nsec = 0;
   47: 
   48: 	ret = kevent(ev->kq_fd,
   49: 		&kev, n,
   50: 		NULL, 0,
   51: 		&ts);
   52: 
   53: 	if (ret == -1) {
   54: 		log_error_write(ev->srv, __FILE__, __LINE__, "SS",
   55: 			"kqueue event delete failed: ", strerror(errno));
   56: 
   57: 		return -1;
   58: 	}
   59: 
   60: 	return -1;
   61: }
   62: 
   63: static int fdevent_freebsd_kqueue_event_set(fdevents *ev, int fde_ndx, int fd, int events) {
   64: 	int ret, n = 0;
   65: 	struct kevent kev[2];
   66: 	struct timespec ts;
   67: 	int oevents = ev->fdarray[fd]->events;
   68: 	int addevents = events & ~oevents;
   69: 	int delevents = ~events & oevents;
   70: 
   71: 	UNUSED(fde_ndx);
   72: 
   73: 	if (events == oevents) return fd;
   74: 
   75: 	if (addevents & FDEVENT_IN)  {
   76: 		EV_SET(&kev[n], fd, EVFILT_READ, EV_ADD|EV_CLEAR, 0, 0, NULL);
   77: 		n++;
   78: 	} else if (delevents & FDEVENT_IN) {
   79: 		EV_SET(&kev[n], fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
   80: 		n++;
   81: 	}
   82: 	if (addevents & FDEVENT_OUT)  {
   83: 		EV_SET(&kev[n], fd, EVFILT_WRITE, EV_ADD|EV_CLEAR, 0, 0, NULL);
   84: 		n++;
   85: 	} else if (delevents & FDEVENT_OUT) {
   86: 		EV_SET(&kev[n], fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
   87: 		n++;
   88: 	}
   89: 
   90: 	if (0 == n) return fd;
   91: 
   92: 	ts.tv_sec  = 0;
   93: 	ts.tv_nsec = 0;
   94: 
   95: 	ret = kevent(ev->kq_fd,
   96: 		kev, n,
   97: 		NULL, 0,
   98: 		&ts);
   99: 
  100: 	if (ret == -1) {
  101: 		log_error_write(ev->srv, __FILE__, __LINE__, "SS",
  102: 			"kqueue event set failed: ", strerror(errno));
  103: 
  104: 		return -1;
  105: 	}
  106: 
  107: 	return fd;
  108: }
  109: 
  110: static int fdevent_freebsd_kqueue_poll(fdevents *ev, int timeout_ms) {
  111: 	int ret;
  112: 	struct timespec ts;
  113: 
  114: 	ts.tv_sec  = timeout_ms / 1000;
  115: 	ts.tv_nsec = (timeout_ms % 1000) * 1000000;
  116: 
  117: 	ret = kevent(ev->kq_fd,
  118: 		NULL, 0,
  119: 		ev->kq_results, ev->maxfds,
  120: 		&ts);
  121: 
  122: 	if (ret == -1) {
  123: 		switch(errno) {
  124: 		case EINTR:
  125: 			/* we got interrupted, perhaps just a SIGCHLD of a CGI script */
  126: 			return 0;
  127: 		default:
  128: 			log_error_write(ev->srv, __FILE__, __LINE__, "SS",
  129: 				"kqueue failed polling: ", strerror(errno));
  130: 			break;
  131: 		}
  132: 	}
  133: 
  134: 	return ret;
  135: }
  136: 
  137: static int fdevent_freebsd_kqueue_event_get_revent(fdevents *ev, size_t ndx) {
  138: 	int events = 0, e;
  139: 
  140: 	e = ev->kq_results[ndx].filter;
  141: 
  142: 	if (e == EVFILT_READ) {
  143: 		events |= FDEVENT_IN;
  144: 	} else if (e == EVFILT_WRITE) {
  145: 		events |= FDEVENT_OUT;
  146: 	}
  147: 
  148: 	e = ev->kq_results[ndx].flags;
  149: 
  150: 	if (e & EV_EOF) {
  151: 		events |= FDEVENT_HUP;
  152: 	}
  153: 
  154: 	if (e & EV_ERROR) {
  155: 		events |= FDEVENT_ERR;
  156: 	}
  157: 
  158: 	return events;
  159: }
  160: 
  161: static int fdevent_freebsd_kqueue_event_get_fd(fdevents *ev, size_t ndx) {
  162: 	return ev->kq_results[ndx].ident;
  163: }
  164: 
  165: static int fdevent_freebsd_kqueue_event_next_fdndx(fdevents *ev, int ndx) {
  166: 	UNUSED(ev);
  167: 
  168: 	return (ndx < 0) ? 0 : ndx + 1;
  169: }
  170: 
  171: static int fdevent_freebsd_kqueue_reset(fdevents *ev) {
  172: 	if (-1 == (ev->kq_fd = kqueue())) {
  173: 		log_error_write(ev->srv, __FILE__, __LINE__, "SSS",
  174: 			"kqueue failed (", strerror(errno), "), try to set server.event-handler = \"poll\" or \"select\"");
  175: 
  176: 		return -1;
  177: 	}
  178: 
  179: 	return 0;
  180: }
  181: 
  182: 
  183: int fdevent_freebsd_kqueue_init(fdevents *ev) {
  184: 	ev->type = FDEVENT_HANDLER_FREEBSD_KQUEUE;
  185: #define SET(x) \
  186: 	ev->x = fdevent_freebsd_kqueue_##x;
  187: 
  188: 	SET(free);
  189: 	SET(poll);
  190: 	SET(reset);
  191: 
  192: 	SET(event_del);
  193: 	SET(event_set);
  194: 
  195: 	SET(event_next_fdndx);
  196: 	SET(event_get_fd);
  197: 	SET(event_get_revent);
  198: 
  199: 	ev->kq_fd = -1;
  200: 
  201: 	ev->kq_results = calloc(ev->maxfds, sizeof(*ev->kq_results));
  202: 
  203: 	/* check that kqueue works */
  204: 
  205: 	if (-1 == (ev->kq_fd = kqueue())) {
  206: 		log_error_write(ev->srv, __FILE__, __LINE__, "SSS",
  207: 			"kqueue failed (", strerror(errno), "), try to set server.event-handler = \"poll\" or \"select\"");
  208: 
  209: 		return -1;
  210: 	}
  211: 
  212: 	close(ev->kq_fd);
  213: 	ev->kq_fd = -1;
  214: 
  215: 	return 0;
  216: }
  217: #else
  218: int fdevent_freebsd_kqueue_init(fdevents *ev) {
  219: 	UNUSED(ev);
  220: 
  221: 	log_error_write(ev->srv, __FILE__, __LINE__, "S",
  222: 		"kqueue not available, try to set server.event-handler = \"poll\" or \"select\"");
  223: 
  224: 	return -1;
  225: }
  226: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>