Implement kqueue(2) support via CONFIG_ELOOP_KQUEUE
NOTE: kqueue has to be closed and re-build after forking. epoll *should* do the same, but it seems that wpa_supplicant doesn't need it at least. I have re-worked a little bit of the epoll code (moved into a similar kqueue function) so it's trivial to requeue epoll if needed in the future. Signed-off-by: Roy Marples <roy@marples.name>
This commit is contained in:
		
							parent
							
								
									2e69bdd16a
								
							
						
					
					
						commit
						f9982b3212
					
				
					 3 changed files with 246 additions and 42 deletions
				
			
		|  | @ -140,6 +140,10 @@ ifdef CONFIG_ELOOP_EPOLL | ||||||
| CFLAGS += -DCONFIG_ELOOP_EPOLL | CFLAGS += -DCONFIG_ELOOP_EPOLL | ||||||
| endif | endif | ||||||
| 
 | 
 | ||||||
|  | ifdef CONFIG_ELOOP_KQUEUE | ||||||
|  | CFLAGS += -DCONFIG_ELOOP_KQUEUE | ||||||
|  | endif | ||||||
|  | 
 | ||||||
| OBJS += ../src/utils/common.o | OBJS += ../src/utils/common.o | ||||||
| OBJS_c += ../src/utils/common.o | OBJS_c += ../src/utils/common.o | ||||||
| OBJS += ../src/utils/wpa_debug.o | OBJS += ../src/utils/wpa_debug.o | ||||||
|  |  | ||||||
|  | @ -18,7 +18,12 @@ | ||||||
| #error Do not define both of poll and epoll | #error Do not define both of poll and epoll | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #if !defined(CONFIG_ELOOP_POLL) && !defined(CONFIG_ELOOP_EPOLL) | #if defined(CONFIG_ELOOP_POLL) && defined(CONFIG_ELOOP_KQUEUE) | ||||||
|  | #error Do not define both of poll and kqueue | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #if !defined(CONFIG_ELOOP_POLL) && !defined(CONFIG_ELOOP_EPOLL) && \ | ||||||
|  |     !defined(CONFIG_ELOOP_KQUEUE) | ||||||
| #define CONFIG_ELOOP_SELECT | #define CONFIG_ELOOP_SELECT | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | @ -30,6 +35,10 @@ | ||||||
| #include <sys/epoll.h> | #include <sys/epoll.h> | ||||||
| #endif /* CONFIG_ELOOP_EPOLL */ | #endif /* CONFIG_ELOOP_EPOLL */ | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_ELOOP_KQUEUE | ||||||
|  | #include <sys/event.h> | ||||||
|  | #endif /* CONFIG_ELOOP_KQUEUE */ | ||||||
|  | 
 | ||||||
| struct eloop_sock { | struct eloop_sock { | ||||||
| 	int sock; | 	int sock; | ||||||
| 	void *eloop_data; | 	void *eloop_data; | ||||||
|  | @ -75,13 +84,20 @@ struct eloop_data { | ||||||
| 	struct pollfd *pollfds; | 	struct pollfd *pollfds; | ||||||
| 	struct pollfd **pollfds_map; | 	struct pollfd **pollfds_map; | ||||||
| #endif /* CONFIG_ELOOP_POLL */ | #endif /* CONFIG_ELOOP_POLL */ | ||||||
|  | #if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE) | ||||||
|  | 	int max_fd; | ||||||
|  | 	struct eloop_sock *fd_table; | ||||||
|  | #endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */ | ||||||
| #ifdef CONFIG_ELOOP_EPOLL | #ifdef CONFIG_ELOOP_EPOLL | ||||||
| 	int epollfd; | 	int epollfd; | ||||||
| 	int epoll_max_event_num; | 	int epoll_max_event_num; | ||||||
| 	int epoll_max_fd; |  | ||||||
| 	struct eloop_sock *epoll_table; |  | ||||||
| 	struct epoll_event *epoll_events; | 	struct epoll_event *epoll_events; | ||||||
| #endif /* CONFIG_ELOOP_EPOLL */ | #endif /* CONFIG_ELOOP_EPOLL */ | ||||||
|  | #ifdef CONFIG_ELOOP_KQUEUE | ||||||
|  | 	int kqueuefd; | ||||||
|  | 	int kqueue_nevents; | ||||||
|  | 	struct kevent *kqueue_events; | ||||||
|  | #endif /* CONFIG_ELOOP_KQUEUE */ | ||||||
| 	struct eloop_sock_table readers; | 	struct eloop_sock_table readers; | ||||||
| 	struct eloop_sock_table writers; | 	struct eloop_sock_table writers; | ||||||
| 	struct eloop_sock_table exceptions; | 	struct eloop_sock_table exceptions; | ||||||
|  | @ -153,10 +169,20 @@ int eloop_init(void) | ||||||
| 			   __func__, strerror(errno)); | 			   __func__, strerror(errno)); | ||||||
| 		return -1; | 		return -1; | ||||||
| 	} | 	} | ||||||
|  | #endif /* CONFIG_ELOOP_EPOLL */ | ||||||
|  | #ifdef CONFIG_ELOOP_KQUEUE | ||||||
|  | 	eloop.kqueuefd = kqueue(); | ||||||
|  | 	if (eloop.kqueuefd < 0) { | ||||||
|  | 		wpa_printf(MSG_ERROR, "%s: kqueue failed: %s", | ||||||
|  | 			   __func__, strerror(errno)); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | #endif /* CONFIG_ELOOP_KQUEUE */ | ||||||
|  | #if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE) | ||||||
| 	eloop.readers.type = EVENT_TYPE_READ; | 	eloop.readers.type = EVENT_TYPE_READ; | ||||||
| 	eloop.writers.type = EVENT_TYPE_WRITE; | 	eloop.writers.type = EVENT_TYPE_WRITE; | ||||||
| 	eloop.exceptions.type = EVENT_TYPE_EXCEPTION; | 	eloop.exceptions.type = EVENT_TYPE_EXCEPTION; | ||||||
| #endif /* CONFIG_ELOOP_EPOLL */ | #endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */ | ||||||
| #ifdef WPA_TRACE | #ifdef WPA_TRACE | ||||||
| 	signal(SIGSEGV, eloop_sigsegv_handler); | 	signal(SIGSEGV, eloop_sigsegv_handler); | ||||||
| #endif /* WPA_TRACE */ | #endif /* WPA_TRACE */ | ||||||
|  | @ -164,15 +190,80 @@ int eloop_init(void) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_ELOOP_EPOLL | ||||||
|  | static int eloop_sock_queue(int sock, eloop_event_type type) | ||||||
|  | { | ||||||
|  | 	struct epoll_event ev; | ||||||
|  | 
 | ||||||
|  | 	os_memset(&ev, 0, sizeof(ev)); | ||||||
|  | 	switch (type) { | ||||||
|  | 	case EVENT_TYPE_READ: | ||||||
|  | 		ev.events = EPOLLIN; | ||||||
|  | 		break; | ||||||
|  | 	case EVENT_TYPE_WRITE: | ||||||
|  | 		ev.events = EPOLLOUT; | ||||||
|  | 		break; | ||||||
|  | 	/*
 | ||||||
|  | 	 * Exceptions are always checked when using epoll, but I suppose it's | ||||||
|  | 	 * possible that someone registered a socket *only* for exception | ||||||
|  | 	 * handling. | ||||||
|  | 	 */ | ||||||
|  | 	case EVENT_TYPE_EXCEPTION: | ||||||
|  | 		ev.events = EPOLLERR | EPOLLHUP; | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 	ev.data.fd = sock; | ||||||
|  | 	if (epoll_ctl(eloop.epollfd, EPOLL_CTL_ADD, sock, &ev) < 0) { | ||||||
|  | 		wpa_printf(MSG_ERROR, "%s: epoll_ctl(ADD) for fd=%d failed: %s", | ||||||
|  | 			   __func__, sock, strerror(errno)); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | #endif /* CONFIG_ELOOP_EPOLL */ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | #ifdef CONFIG_ELOOP_KQUEUE | ||||||
|  | static int eloop_sock_queue(int sock, eloop_event_type type) | ||||||
|  | { | ||||||
|  | 	int filter; | ||||||
|  | 	struct kevent ke; | ||||||
|  | 
 | ||||||
|  | 	switch (type) { | ||||||
|  | 	case EVENT_TYPE_READ: | ||||||
|  | 		filter = EVFILT_READ; | ||||||
|  | 		break; | ||||||
|  | 	case EVENT_TYPE_WRITE: | ||||||
|  | 		filter = EVFILT_WRITE; | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		filter = 0; | ||||||
|  | 	} | ||||||
|  | 	EV_SET(&ke, sock, filter, EV_ADD, 0, 0, NULL); | ||||||
|  | 	if (kevent(eloop.kqueuefd, &ke, 1, NULL, 0, NULL) == -1) { | ||||||
|  | 		wpa_printf(MSG_ERROR, "%s: kevent(ADD) for fd=%d failed: %s", | ||||||
|  | 			   __func__, sock, strerror(errno)); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | #endif /* CONFIG_ELOOP_KQUEUE */ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| static int eloop_sock_table_add_sock(struct eloop_sock_table *table, | static int eloop_sock_table_add_sock(struct eloop_sock_table *table, | ||||||
|                                      int sock, eloop_sock_handler handler, |                                      int sock, eloop_sock_handler handler, | ||||||
|                                      void *eloop_data, void *user_data) |                                      void *eloop_data, void *user_data) | ||||||
| { | { | ||||||
| #ifdef CONFIG_ELOOP_EPOLL | #ifdef CONFIG_ELOOP_EPOLL | ||||||
| 	struct eloop_sock *temp_table; | 	struct epoll_event *temp_events; | ||||||
| 	struct epoll_event ev, *temp_events; |  | ||||||
| 	int next; |  | ||||||
| #endif /* CONFIG_ELOOP_EPOLL */ | #endif /* CONFIG_ELOOP_EPOLL */ | ||||||
|  | #ifdef CONFIG_ELOOP_KQUEUE | ||||||
|  | 	struct kevent *temp_events; | ||||||
|  | #endif /* CONFIG_ELOOP_EPOLL */ | ||||||
|  | #if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE) | ||||||
|  | 	struct eloop_sock *temp_table; | ||||||
|  | 	int next; | ||||||
|  | #endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */ | ||||||
| 	struct eloop_sock *tmp; | 	struct eloop_sock *tmp; | ||||||
| 	int new_max_sock; | 	int new_max_sock; | ||||||
| 
 | 
 | ||||||
|  | @ -208,18 +299,20 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table, | ||||||
| 		eloop.pollfds = n; | 		eloop.pollfds = n; | ||||||
| 	} | 	} | ||||||
| #endif /* CONFIG_ELOOP_POLL */ | #endif /* CONFIG_ELOOP_POLL */ | ||||||
| #ifdef CONFIG_ELOOP_EPOLL | #if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE) | ||||||
| 	if (new_max_sock >= eloop.epoll_max_fd) { | 	if (new_max_sock >= eloop.max_fd) { | ||||||
| 		next = eloop.epoll_max_fd == 0 ? 16 : eloop.epoll_max_fd * 2; | 		next = eloop.max_fd == 0 ? 16 : eloop.max_fd * 2; | ||||||
| 		temp_table = os_realloc_array(eloop.epoll_table, next, | 		temp_table = os_realloc_array(eloop.fd_table, next, | ||||||
| 					      sizeof(struct eloop_sock)); | 					      sizeof(struct eloop_sock)); | ||||||
| 		if (temp_table == NULL) | 		if (temp_table == NULL) | ||||||
| 			return -1; | 			return -1; | ||||||
| 
 | 
 | ||||||
| 		eloop.epoll_max_fd = next; | 		eloop.max_fd = next; | ||||||
| 		eloop.epoll_table = temp_table; | 		eloop.fd_table = temp_table; | ||||||
| 	} | 	} | ||||||
|  | #endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */ | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_ELOOP_EPOLL | ||||||
| 	if (eloop.count + 1 > eloop.epoll_max_event_num) { | 	if (eloop.count + 1 > eloop.epoll_max_event_num) { | ||||||
| 		next = eloop.epoll_max_event_num == 0 ? 8 : | 		next = eloop.epoll_max_event_num == 0 ? 8 : | ||||||
| 			eloop.epoll_max_event_num * 2; | 			eloop.epoll_max_event_num * 2; | ||||||
|  | @ -235,6 +328,22 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table, | ||||||
| 		eloop.epoll_events = temp_events; | 		eloop.epoll_events = temp_events; | ||||||
| 	} | 	} | ||||||
| #endif /* CONFIG_ELOOP_EPOLL */ | #endif /* CONFIG_ELOOP_EPOLL */ | ||||||
|  | #ifdef CONFIG_ELOOP_KQUEUE | ||||||
|  | 	if (eloop.count + 1 > eloop.kqueue_nevents) { | ||||||
|  | 		next = eloop.kqueue_nevents == 0 ? 8 : eloop.kqueue_nevents * 2; | ||||||
|  | 		temp_events = os_malloc(next * sizeof(*temp_events)); | ||||||
|  | 		if (!temp_events) { | ||||||
|  | 			wpa_printf(MSG_ERROR, | ||||||
|  | 				   "%s: malloc for kqueue failed: %s", | ||||||
|  | 				   __func__, strerror(errno)); | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		os_free(eloop.kqueue_events); | ||||||
|  | 		eloop.kqueue_events = temp_events; | ||||||
|  | 		eloop.kqueue_nevents = next; | ||||||
|  | 	} | ||||||
|  | #endif /* CONFIG_ELOOP_KQUEUE */ | ||||||
| 
 | 
 | ||||||
| 	eloop_trace_sock_remove_ref(table); | 	eloop_trace_sock_remove_ref(table); | ||||||
| 	tmp = os_realloc_array(table->table, table->count + 1, | 	tmp = os_realloc_array(table->table, table->count + 1, | ||||||
|  | @ -256,33 +365,12 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table, | ||||||
| 	table->changed = 1; | 	table->changed = 1; | ||||||
| 	eloop_trace_sock_add_ref(table); | 	eloop_trace_sock_add_ref(table); | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_ELOOP_EPOLL | #if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE) | ||||||
| 	os_memset(&ev, 0, sizeof(ev)); | 	if (eloop_sock_queue(sock, table->type) < 0) | ||||||
| 	switch (table->type) { |  | ||||||
| 	case EVENT_TYPE_READ: |  | ||||||
| 		ev.events = EPOLLIN; |  | ||||||
| 		break; |  | ||||||
| 	case EVENT_TYPE_WRITE: |  | ||||||
| 		ev.events = EPOLLOUT; |  | ||||||
| 		break; |  | ||||||
| 	/*
 |  | ||||||
| 	 * Exceptions are always checked when using epoll, but I suppose it's |  | ||||||
| 	 * possible that someone registered a socket *only* for exception |  | ||||||
| 	 * handling. |  | ||||||
| 	 */ |  | ||||||
| 	case EVENT_TYPE_EXCEPTION: |  | ||||||
| 		ev.events = EPOLLERR | EPOLLHUP; |  | ||||||
| 		break; |  | ||||||
| 	} |  | ||||||
| 	ev.data.fd = sock; |  | ||||||
| 	if (epoll_ctl(eloop.epollfd, EPOLL_CTL_ADD, sock, &ev) < 0) { |  | ||||||
| 		wpa_printf(MSG_ERROR, "%s: epoll_ctl(ADD) for fd=%d " |  | ||||||
| 			   "failed. %s\n", __func__, sock, strerror(errno)); |  | ||||||
| 		return -1; | 		return -1; | ||||||
| 	} | 	os_memcpy(&eloop.fd_table[sock], &table->table[table->count - 1], | ||||||
| 	os_memcpy(&eloop.epoll_table[sock], &table->table[table->count - 1], |  | ||||||
| 		  sizeof(struct eloop_sock)); | 		  sizeof(struct eloop_sock)); | ||||||
| #endif /* CONFIG_ELOOP_EPOLL */ | #endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */ | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -290,6 +378,9 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table, | ||||||
| static void eloop_sock_table_remove_sock(struct eloop_sock_table *table, | static void eloop_sock_table_remove_sock(struct eloop_sock_table *table, | ||||||
|                                          int sock) |                                          int sock) | ||||||
| { | { | ||||||
|  | #ifdef CONFIG_ELOOP_KQUEUE | ||||||
|  | 	struct kevent ke; | ||||||
|  | #endif /* CONFIG_ELOOP_KQUEUE */ | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	if (table == NULL || table->table == NULL || table->count == 0) | 	if (table == NULL || table->table == NULL || table->count == 0) | ||||||
|  | @ -317,8 +408,17 @@ static void eloop_sock_table_remove_sock(struct eloop_sock_table *table, | ||||||
| 			   "failed. %s\n", __func__, sock, strerror(errno)); | 			   "failed. %s\n", __func__, sock, strerror(errno)); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 	os_memset(&eloop.epoll_table[sock], 0, sizeof(struct eloop_sock)); | 	os_memset(&eloop.fd_table[sock], 0, sizeof(struct eloop_sock)); | ||||||
| #endif /* CONFIG_ELOOP_EPOLL */ | #endif /* CONFIG_ELOOP_EPOLL */ | ||||||
|  | #ifdef CONFIG_ELOOP_KQUEUE | ||||||
|  | 	EV_SET(&ke, sock, 0, EV_DELETE, 0, 0, NULL); | ||||||
|  | 	if (kevent(eloop.kqueuefd, &ke, 1, NULL, 0, NULL) < 0) { | ||||||
|  | 		wpa_printf(MSG_ERROR, "%s: kevent(DEL) for fd=%d failed: %s", | ||||||
|  | 			   __func__, sock, strerror(errno)); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	os_memset(&eloop.fd_table[sock], 0, sizeof(struct eloop_sock)); | ||||||
|  | #endif /* CONFIG_ELOOP_KQUEUE */ | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -511,7 +611,7 @@ static void eloop_sock_table_dispatch(struct epoll_event *events, int nfds) | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < nfds; i++) { | 	for (i = 0; i < nfds; i++) { | ||||||
| 		table = &eloop.epoll_table[events[i].data.fd]; | 		table = &eloop.fd_table[events[i].data.fd]; | ||||||
| 		if (table->handler == NULL) | 		if (table->handler == NULL) | ||||||
| 			continue; | 			continue; | ||||||
| 		table->handler(table->sock, table->eloop_data, | 		table->handler(table->sock, table->eloop_data, | ||||||
|  | @ -525,9 +625,64 @@ static void eloop_sock_table_dispatch(struct epoll_event *events, int nfds) | ||||||
| #endif /* CONFIG_ELOOP_EPOLL */ | #endif /* CONFIG_ELOOP_EPOLL */ | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_ELOOP_KQUEUE | ||||||
|  | 
 | ||||||
|  | static void eloop_sock_table_dispatch(struct kevent *events, int nfds) | ||||||
|  | { | ||||||
|  | 	struct eloop_sock *table; | ||||||
|  | 	int i; | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < nfds; i++) { | ||||||
|  | 		table = &eloop.fd_table[events[i].ident]; | ||||||
|  | 		if (table->handler == NULL) | ||||||
|  | 			continue; | ||||||
|  | 		table->handler(table->sock, table->eloop_data, | ||||||
|  | 			       table->user_data); | ||||||
|  | 		if (eloop.readers.changed || | ||||||
|  | 		    eloop.writers.changed || | ||||||
|  | 		    eloop.exceptions.changed) | ||||||
|  | 			break; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static int eloop_sock_table_requeue(struct eloop_sock_table *table) | ||||||
|  | { | ||||||
|  | 	int i, r; | ||||||
|  | 
 | ||||||
|  | 	r = 0; | ||||||
|  | 	for (i = 0; i < table->count && table->table; i++) { | ||||||
|  | 		if (eloop_sock_queue(table->table[i].sock, table->type) == -1) | ||||||
|  | 			r = -1; | ||||||
|  | 	} | ||||||
|  | 	return r; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #endif /* CONFIG_ELOOP_KQUEUE */ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| int eloop_sock_requeue(void) | int eloop_sock_requeue(void) | ||||||
| { | { | ||||||
| 	return 0; | 	int r = 0; | ||||||
|  | 
 | ||||||
|  | #ifdef CONFIG_ELOOP_KQUEUE | ||||||
|  | 	close(eloop.kqueuefd); | ||||||
|  | 	eloop.kqueuefd = kqueue(); | ||||||
|  | 	if (eloop.kqueuefd < 0) { | ||||||
|  | 		wpa_printf(MSG_ERROR, "%s: kqueue failed: %s", | ||||||
|  | 			   __func__, strerror(errno)); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (eloop_sock_table_requeue(&eloop.readers) < 0) | ||||||
|  | 		r = -1; | ||||||
|  | 	if (eloop_sock_table_requeue(&eloop.writers) < 0) | ||||||
|  | 		r = -1; | ||||||
|  | 	if (eloop_sock_table_requeue(&eloop.exceptions) < 0) | ||||||
|  | 		r = -1; | ||||||
|  | #endif /* CONFIG_ELOOP_KQUEUE */ | ||||||
|  | 
 | ||||||
|  | 	return r; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -911,6 +1066,9 @@ void eloop_run(void) | ||||||
| #ifdef CONFIG_ELOOP_EPOLL | #ifdef CONFIG_ELOOP_EPOLL | ||||||
| 	int timeout_ms = -1; | 	int timeout_ms = -1; | ||||||
| #endif /* CONFIG_ELOOP_EPOLL */ | #endif /* CONFIG_ELOOP_EPOLL */ | ||||||
|  | #ifdef CONFIG_ELOOP_KQUEUE | ||||||
|  | 	struct timespec ts; | ||||||
|  | #endif /* CONFIG_ELOOP_KQUEUE */ | ||||||
| 	int res; | 	int res; | ||||||
| 	struct os_reltime tv, now; | 	struct os_reltime tv, now; | ||||||
| 
 | 
 | ||||||
|  | @ -955,6 +1113,10 @@ void eloop_run(void) | ||||||
| 			_tv.tv_sec = tv.sec; | 			_tv.tv_sec = tv.sec; | ||||||
| 			_tv.tv_usec = tv.usec; | 			_tv.tv_usec = tv.usec; | ||||||
| #endif /* CONFIG_ELOOP_SELECT */ | #endif /* CONFIG_ELOOP_SELECT */ | ||||||
|  | #ifdef CONFIG_ELOOP_KQUEUE | ||||||
|  | 			ts.tv_sec = tv.sec; | ||||||
|  | 			ts.tv_nsec = tv.usec * 1000L; | ||||||
|  | #endif /* CONFIG_ELOOP_KQUEUE */ | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_ELOOP_POLL | #ifdef CONFIG_ELOOP_POLL | ||||||
|  | @ -980,6 +1142,15 @@ void eloop_run(void) | ||||||
| 					 eloop.count, timeout_ms); | 					 eloop.count, timeout_ms); | ||||||
| 		} | 		} | ||||||
| #endif /* CONFIG_ELOOP_EPOLL */ | #endif /* CONFIG_ELOOP_EPOLL */ | ||||||
|  | #ifdef CONFIG_ELOOP_KQUEUE | ||||||
|  | 		if (eloop.count == 0) { | ||||||
|  | 			res = 0; | ||||||
|  | 		} else { | ||||||
|  | 			res = kevent(eloop.kqueuefd, NULL, 0, | ||||||
|  | 				     eloop.kqueue_events, eloop.kqueue_nevents, | ||||||
|  | 				     timeout ? &ts : NULL); | ||||||
|  | 		} | ||||||
|  | #endif /* CONFIG_ELOOP_KQUEUE */ | ||||||
| 		if (res < 0 && errno != EINTR && errno != 0) { | 		if (res < 0 && errno != EINTR && errno != 0) { | ||||||
| 			wpa_printf(MSG_ERROR, "eloop: %s: %s", | 			wpa_printf(MSG_ERROR, "eloop: %s: %s", | ||||||
| #ifdef CONFIG_ELOOP_POLL | #ifdef CONFIG_ELOOP_POLL | ||||||
|  | @ -991,6 +1162,10 @@ void eloop_run(void) | ||||||
| #ifdef CONFIG_ELOOP_EPOLL | #ifdef CONFIG_ELOOP_EPOLL | ||||||
| 				   "epoll" | 				   "epoll" | ||||||
| #endif /* CONFIG_ELOOP_EPOLL */ | #endif /* CONFIG_ELOOP_EPOLL */ | ||||||
|  | #ifdef CONFIG_ELOOP_KQUEUE | ||||||
|  | 				   "kqueue" | ||||||
|  | #endif /* CONFIG_ELOOP_EKQUEUE */ | ||||||
|  | 
 | ||||||
| 				   , strerror(errno)); | 				   , strerror(errno)); | ||||||
| 			goto out; | 			goto out; | ||||||
| 		} | 		} | ||||||
|  | @ -1001,6 +1176,7 @@ void eloop_run(void) | ||||||
| 
 | 
 | ||||||
| 		eloop_process_pending_signals(); | 		eloop_process_pending_signals(); | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| 		/* check if some registered timeouts have occurred */ | 		/* check if some registered timeouts have occurred */ | ||||||
| 		timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, | 		timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, | ||||||
| 					list); | 					list); | ||||||
|  | @ -1046,6 +1222,9 @@ void eloop_run(void) | ||||||
| #ifdef CONFIG_ELOOP_EPOLL | #ifdef CONFIG_ELOOP_EPOLL | ||||||
| 		eloop_sock_table_dispatch(eloop.epoll_events, res); | 		eloop_sock_table_dispatch(eloop.epoll_events, res); | ||||||
| #endif /* CONFIG_ELOOP_EPOLL */ | #endif /* CONFIG_ELOOP_EPOLL */ | ||||||
|  | #ifdef CONFIG_ELOOP_KQUEUE | ||||||
|  | 		eloop_sock_table_dispatch(eloop.kqueue_events, res); | ||||||
|  | #endif /* CONFIG_ELOOP_KQUEUE */ | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	eloop.terminate = 0; | 	eloop.terminate = 0; | ||||||
|  | @ -1098,11 +1277,17 @@ void eloop_destroy(void) | ||||||
| 	os_free(eloop.pollfds); | 	os_free(eloop.pollfds); | ||||||
| 	os_free(eloop.pollfds_map); | 	os_free(eloop.pollfds_map); | ||||||
| #endif /* CONFIG_ELOOP_POLL */ | #endif /* CONFIG_ELOOP_POLL */ | ||||||
|  | #if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE) | ||||||
|  | 	os_free(eloop.fd_table); | ||||||
|  | #endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */ | ||||||
| #ifdef CONFIG_ELOOP_EPOLL | #ifdef CONFIG_ELOOP_EPOLL | ||||||
| 	os_free(eloop.epoll_table); |  | ||||||
| 	os_free(eloop.epoll_events); | 	os_free(eloop.epoll_events); | ||||||
| 	close(eloop.epollfd); | 	close(eloop.epollfd); | ||||||
| #endif /* CONFIG_ELOOP_EPOLL */ | #endif /* CONFIG_ELOOP_EPOLL */ | ||||||
|  | #ifdef CONFIG_ELOOP_KQUEUE | ||||||
|  | 	os_free(eloop.kqueue_events); | ||||||
|  | 	close(eloop.kqueuefd); | ||||||
|  | #endif /* CONFIG_ELOOP_KQUEUE */ | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -1141,6 +1326,17 @@ void eloop_wait_for_read_sock(int sock) | ||||||
| 	FD_SET(sock, &rfds); | 	FD_SET(sock, &rfds); | ||||||
| 	select(sock + 1, &rfds, NULL, NULL, NULL); | 	select(sock + 1, &rfds, NULL, NULL, NULL); | ||||||
| #endif /* defined(CONFIG_ELOOP_SELECT) || defined(CONFIG_ELOOP_EPOLL) */ | #endif /* defined(CONFIG_ELOOP_SELECT) || defined(CONFIG_ELOOP_EPOLL) */ | ||||||
|  | #ifdef CONFIG_ELOOP_KQUEUE | ||||||
|  | 	int kfd; | ||||||
|  | 	struct kevent ke1, ke2; | ||||||
|  | 
 | ||||||
|  | 	kfd = kqueue(); | ||||||
|  | 	if (kfd == -1) | ||||||
|  | 		return; | ||||||
|  | 	EV_SET(&ke1, sock, EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, NULL); | ||||||
|  | 	kevent(kfd, &ke1, 1, &ke2, 1, NULL); | ||||||
|  | 	close(kfd); | ||||||
|  | #endif /* CONFIG_ELOOP_KQUEUE */ | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_ELOOP_SELECT | #ifdef CONFIG_ELOOP_SELECT | ||||||
|  |  | ||||||
|  | @ -170,6 +170,10 @@ ifdef CONFIG_ELOOP_EPOLL | ||||||
| CFLAGS += -DCONFIG_ELOOP_EPOLL | CFLAGS += -DCONFIG_ELOOP_EPOLL | ||||||
| endif | endif | ||||||
| 
 | 
 | ||||||
|  | ifdef CONFIG_ELOOP_KQUEUE | ||||||
|  | CFLAGS += -DCONFIG_ELOOP_KQUEUE | ||||||
|  | endif | ||||||
|  | 
 | ||||||
| ifdef CONFIG_EAPOL_TEST | ifdef CONFIG_EAPOL_TEST | ||||||
| CFLAGS += -Werror -DEAPOL_TEST | CFLAGS += -Werror -DEAPOL_TEST | ||||||
| endif | endif | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Roy Marples
						Roy Marples