diff --git a/Makefile b/Makefile index dd326550..cc17c12a 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,15 @@ .PHONY : all clean CFLAGS = -g -Wall -SHARED = -fPIC --shared -LUALIB = -llua +LDFLAGS = -lpthread -llua -ldl -lm + +uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') +ifeq ($(uname_S), Darwin) + SHARED = -fPIC -dynamiclib -Wl,-undefined,dynamic_lookup +else + LDFLAGS += -ldl -lrt -Wl,-E + SHARED = -fPIC --shared +endif all : \ skynet \ @@ -37,7 +44,7 @@ skynet : \ skynet-src/skynet_env.c \ skynet-src/skynet_monitor.c \ luacompat/compat52.c - gcc $(CFLAGS) -Iluacompat -Wl,-E -o $@ $^ -Iskynet-src -lpthread -ldl -lrt -Wl,-E $(LUALIB) -lm + gcc $(CFLAGS) -Iluacompat -o $@ $^ -Iskynet-src $(LDFLAGS) luaclib: mkdir luaclib @@ -89,4 +96,4 @@ client : client-src/client.c clean : rm skynet client service/*.so luaclib/*.so - \ No newline at end of file + diff --git a/connection/connection.c b/connection/connection.c index bd6f8dd1..a975820e 100644 --- a/connection/connection.c +++ b/connection/connection.c @@ -1,28 +1,67 @@ #include "connection.h" #include -#include #include #include #include +/* Test for polling API */ +#ifdef __linux__ +#define HAVE_EPOLL 1 +#endif + +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined (__NetBSD__) +#define HAVE_KQUEUE 1 +#endif + +#if !defined(HAVE_EPOLL) && !defined(HAVE_KQUEUE) +#error "system does not support epoll or kqueue API" +#endif +/* ! Test for polling API */ + +#ifdef HAVE_EPOLL +#include +#elif HAVE_KQUEUE +#include +#endif + #define EPOLLQUEUE 32 struct connection_pool { +#ifdef HAVE_EPOLL int epoll_fd; +#elif HAVE_KQUEUE + int kqueue_fd; +#endif int queue_len; int queue_head; +#ifdef HAVE_EPOLL struct epoll_event ev[EPOLLQUEUE]; +#elif HAVE_KQUEUE + struct kevent ev[EPOLLQUEUE]; +#endif }; struct connection_pool * connection_newpool(int max) { +#ifdef HAVE_EPOLL int epoll_fd = epoll_create(max); if (epoll_fd == -1) { return NULL; } +#elif HAVE_KQUEUE + int kqueue_fd = kqueue(); + if (kqueue_fd == -1) { + return NULL; + } +#endif + struct connection_pool * pool = malloc(sizeof(*pool)); +#ifdef HAVE_EPOLL pool->epoll_fd = epoll_fd; +#elif HAVE_KQUEUE + pool->kqueue_fd = kqueue_fd; +#endif pool->queue_len = 0; pool->queue_head = 0; @@ -31,12 +70,17 @@ connection_newpool(int max) { void connection_deletepool(struct connection_pool * pool) { +#if HAVE_EPOLL close(pool->epoll_fd); +#elif HAVE_KQUEUE + close(pool->kqueue_fd); +#endif free(pool); } int connection_add(struct connection_pool * pool, int fd, void *ud) { +#if HAVE_EPOLL struct epoll_event ev; ev.events = EPOLLIN; ev.data.ptr = ud; @@ -44,19 +88,39 @@ connection_add(struct connection_pool * pool, int fd, void *ud) { if (epoll_ctl(pool->epoll_fd, EPOLL_CTL_ADD, fd, &ev) == -1) { return 1; } +#elif HAVE_KQUEUE + struct kevent ke; + EV_SET(&ke, fd, EVFILT_READ, EV_ADD, 0, 0, ud); + if (kevent(pool->kqueue_fd, &ke, 1, NULL, 0, NULL) == -1) { + return 1; + } +#endif return 0; } void connection_del(struct connection_pool * pool, int fd) { +#if HAVE_EPOLL epoll_ctl(pool->epoll_fd, EPOLL_CTL_DEL, fd , NULL); +#elif HAVE_KQUEUE + struct kevent ke; + EV_SET(&ke, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL); + kevent(pool->kqueue_fd, &ke, 1, NULL, 0, NULL); +#endif close(fd); } static int _read_queue(struct connection_pool * pool, int timeout) { pool->queue_head = 0; +#if HAVE_EPOLL int n = epoll_wait(pool->epoll_fd , pool->ev, EPOLLQUEUE, timeout); +#elif HAVE_KQUEUE + struct timespec timeoutspec; + timeoutspec.tv_sec = timeout; + timeoutspec.tv_nsec = 0; + int n = kevent(pool->kqueue_fd, NULL, 0, pool->ev, EPOLLQUEUE, &timeoutspec); +#endif if (n == -1) { pool->queue_len = 0; return -1; @@ -72,6 +136,10 @@ connection_poll(struct connection_pool * pool, int timeout) { return NULL; } } +#if HAVE_EPOLL return pool->ev[pool->queue_head ++].data.ptr; +#elif HAVE_KQUEUE + return pool->ev[pool->queue_head ++].udata; +#endif } diff --git a/gate/mread.c b/gate/mread.c index bc95f80e..4e8ff13b 100644 --- a/gate/mread.c +++ b/gate/mread.c @@ -1,7 +1,26 @@ #include "mread.h" #include "ringbuffer.h" +/* Test for polling API */ +#ifdef __linux__ +#define HAVE_EPOLL 1 +#endif + +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined (__NetBSD__) +#define HAVE_KQUEUE 1 +#endif + +#if !defined(HAVE_EPOLL) && !defined(HAVE_KQUEUE) +#error "system does not support epoll or kqueue API" +#endif +/* ! Test for polling API */ + +#ifdef HAVE_EPOLL #include +#elif HAVE_KQUEUE +#include +#endif + #include #include #include @@ -38,7 +57,11 @@ struct socket { struct mread_pool { int listen_fd; +#ifdef HAVE_EPOLL int epoll_fd; +#elif HAVE_KQUEUE + int kqueue_fd; +#endif int max_connection; int closed; int active; @@ -47,7 +70,11 @@ struct mread_pool { struct socket * free_socket; int queue_len; int queue_head; +#ifdef HAVE_EPOLL struct epoll_event ev[READQUEUE]; +#elif HAVE_KQUEUE + struct kevent ev[READQUEUE]; +#endif struct ringbuffer * rb; }; @@ -84,12 +111,12 @@ _release_rb(struct ringbuffer * rb) { static int _set_nonblocking(int fd) { - int flag = fcntl(fd, F_GETFL, 0); - if ( -1 == flag ) { - return -1; - } + int flag = fcntl(fd, F_GETFL, 0); + if ( -1 == flag ) { + return -1; + } - return fcntl(fd, F_SETFL, flag | O_NONBLOCK); + return fcntl(fd, F_SETFL, flag | O_NONBLOCK); } struct mread_pool * @@ -120,6 +147,7 @@ mread_create(uint32_t addr, int port , int max , int buffer_size) { return NULL; } +#ifdef HAVE_EPOLL int epoll_fd = epoll_create(max + 1); if (epoll_fd == -1) { close(listen_fd); @@ -135,11 +163,30 @@ mread_create(uint32_t addr, int port , int max , int buffer_size) { close(epoll_fd); return NULL; } +#elif HAVE_KQUEUE + int kqueue_fd = kqueue(); + if (kqueue_fd == -1) { + close(listen_fd); + return NULL; + } + + struct kevent ke; + EV_SET(&ke, listen_fd, EVFILT_READ, EV_ADD, 0, 0, LISTENSOCKET); + if (kevent(kqueue_fd, &ke, 1, NULL, 0, NULL) == -1) { + close(listen_fd); + close(kqueue_fd); + return NULL; + } +#endif struct mread_pool * self = malloc(sizeof(*self)); self->listen_fd = listen_fd; +#ifdef HAVE_EPOLL self->epoll_fd = epoll_fd; +#elif HAVE_KQUEUE + self->kqueue_fd = kqueue_fd; +#endif self->max_connection = max; self->closed = 0; self->active = -1; @@ -172,7 +219,11 @@ mread_close(struct mread_pool *self) { if (self->listen_fd >= 0) { close(self->listen_fd); } - close(self->epoll_fd); +#ifdef HAVE_EPOLL + close(self->epoll_fd); +#elif HAVE_KQUEUE + close(self->kqueue_fd); +#endif _release_rb(self->rb); free(self); } @@ -180,7 +231,14 @@ mread_close(struct mread_pool *self) { static int _read_queue(struct mread_pool * self, int timeout) { self->queue_head = 0; +#ifdef HAVE_EPOLL int n = epoll_wait(self->epoll_fd , self->ev, READQUEUE, timeout); +#elif HAVE_KQUEUE + struct timespec timeoutspec; + timeoutspec.tv_sec = timeout; + timeoutspec.tv_nsec = 0; + int n = kevent(self->kqueue_fd, NULL, 0, self->ev, READQUEUE, &timeoutspec); +#endif if (n == -1) { self->queue_len = 0; return -1; @@ -194,7 +252,11 @@ _read_one(struct mread_pool * self) { if (self->queue_head >= self->queue_len) { return NULL; } +#ifdef HAVE_EPOLL return self->ev[self->queue_head ++].data.ptr; +#elif HAVE_KQUEUE + return self->ev[self->queue_head ++].udata; +#endif } static struct socket * @@ -219,6 +281,7 @@ _add_client(struct mread_pool * self, int fd) { close(fd); return NULL; } +#ifdef HAVE_EPOLL struct epoll_event ev; ev.events = EPOLLIN; ev.data.ptr = s; @@ -226,6 +289,14 @@ _add_client(struct mread_pool * self, int fd) { close(fd); return NULL; } +#elif HAVE_KQUEUE + struct kevent ke; + EV_SET(&ke, fd, EVFILT_READ, EV_ADD, 0, 0, s); + if (kevent(self->kqueue_fd, &ke, 1, NULL, 0, NULL) == -1) { + close(fd); + return NULL; + } +#endif s->fd = fd; s->node = NULL; @@ -276,7 +347,7 @@ mread_poll(struct mread_pool * self , int timeout) { socklen_t len = sizeof(struct sockaddr_in); int client_fd = accept(self->listen_fd , (struct sockaddr *)&remote_addr , &len); if (client_fd >= 0) { -// printf("MREAD(%p) connect %s:%u (fd=%d)\n",self, inet_ntoa(remote_addr.sin_addr),ntohs(remote_addr.sin_port), client_fd); +// printf("MREAD connect %s:%u (fd=%d)\n",inet_ntoa(remote_addr.sin_addr),ntohs(remote_addr.sin_port), client_fd); struct socket * s = _add_client(self, client_fd); if (s) { self->active = -1; @@ -301,7 +372,7 @@ mread_socket(struct mread_pool * self, int index) { static void _link_node(struct ringbuffer * rb, int id, struct socket * s , struct ringbuffer_block * blk) { if (s->node) { - ringbuffer_link(rb, s->node , blk); + ringbuffer_link(rb, s->node , blk); } else { blk->id = id; s->node = blk; @@ -316,7 +387,14 @@ mread_close_client(struct mread_pool * self, int id) { s->temp = NULL; close(s->fd); // printf("MREAD close %d (fd=%d)\n",id,s->fd); + +#ifdef HAVE_EPOLL epoll_ctl(self->epoll_fd, EPOLL_CTL_DEL, s->fd , NULL); +#elif HAVE_KQUEUE + struct kevent ke; + EV_SET(&ke, s->fd, EVFILT_READ, EV_DELETE, 0, 0, NULL); + kevent(self->kqueue_fd, &ke, 1, NULL, 0, NULL); +#endif ++self->closed; } @@ -343,7 +421,7 @@ _ringbuffer_read(struct mread_pool * self, int *size) { return ret; } -void * +void * mread_pull(struct mread_pool * self , int size) { if (self->active == -1) { return NULL; @@ -388,16 +466,8 @@ mread_pull(struct mread_pool * self , int size) { buffer = (char *)(blk + 1); for (;;) { - int bytes = recv(s->fd, buffer, rd, MSG_DONTWAIT); + int bytes = recv(s->fd, buffer, rd, MSG_DONTWAIT); if (bytes > 0) { -/* - printf("recv: [%d] ",s->fd); - int i; - for (i=0;iactive, s , blk); @@ -456,7 +526,7 @@ mread_pull(struct mread_pool * self , int size) { return ret; } -void +void mread_yield(struct mread_pool * self) { if (self->active == -1) { return; @@ -482,7 +552,7 @@ mread_yield(struct mread_pool * self) { } } -int +int mread_closed(struct mread_pool * self) { if (self->active == -1) { return 0; diff --git a/lualib-src/lua-skynet.c b/lualib-src/lua-skynet.c index d37aaade..b6378431 100644 --- a/lualib-src/lua-skynet.c +++ b/lualib-src/lua-skynet.c @@ -15,6 +15,11 @@ #include #include +#if defined(__APPLE__) +#include +#include +#endif + struct stat { lua_State *L; int count; @@ -27,7 +32,15 @@ struct stat { static void _stat_begin(struct stat *S, struct timespec *ti) { S->count++; +#if defined(_POSIX_TIMERS) && defined(_POSIX_THREAD_CPUTIME) clock_gettime(CLOCK_THREAD_CPUTIME_ID, ti); +#elif defined(__APPLE__) + struct task_thread_times_info aTaskInfo; + mach_msg_type_number_t aTaskInfoCount = TASK_THREAD_TIMES_INFO_COUNT; + assert(KERN_SUCCESS == task_info(mach_task_self(), TASK_THREAD_TIMES_INFO, (task_info_t )&aTaskInfo, &aTaskInfoCount)); + ti->tv_sec = aTaskInfo.user_time.seconds; + ti->tv_nsec = aTaskInfo.user_time.microseconds * 1000; +#endif } inline static void diff --git a/lualib-src/trace_service.c b/lualib-src/trace_service.c index 3bd905fe..227beee8 100644 --- a/lualib-src/trace_service.c +++ b/lualib-src/trace_service.c @@ -8,10 +8,23 @@ #define HASH_SIZE 32 +#if defined(__APPLE__) +#include +#include +#endif + void diff_time(struct timespec *ti, uint32_t *sec, uint32_t *nsec) { struct timespec end; +#if defined(_POSIX_TIMERS) && defined(_POSIX_THREAD_CPUTIME) clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end); +#elif defined(__APPLE__) + struct task_thread_times_info aTaskInfo; + mach_msg_type_number_t aTaskInfoCount = TASK_THREAD_TIMES_INFO_COUNT; + assert(KERN_SUCCESS == task_info(mach_task_self(), TASK_THREAD_TIMES_INFO, (task_info_t )&aTaskInfo, &aTaskInfoCount)); + end.tv_sec = aTaskInfo.user_time.seconds; + end.tv_nsec = aTaskInfo.user_time.microseconds * 1000; +#endif int diffsec = end.tv_sec - ti->tv_sec; assert(diffsec>=0); int diffnsec = end.tv_nsec - ti->tv_nsec; @@ -76,7 +89,15 @@ trace_new(struct trace_pool *p) { t->next = NULL; t->ti_sec = 0; t->ti_nsec = 0; +#if defined(_POSIX_TIMERS) && defined(_POSIX_THREAD_CPUTIME) clock_gettime(CLOCK_THREAD_CPUTIME_ID, &t->ti); +#elif defined(__APPLE__) + struct task_thread_times_info aTaskInfo; + mach_msg_type_number_t aTaskInfoCount = TASK_THREAD_TIMES_INFO_COUNT; + assert(KERN_SUCCESS == task_info(mach_task_self(), TASK_THREAD_TIMES_INFO, (task_info_t )&aTaskInfo, &aTaskInfoCount)); + t->ti.tv_sec = aTaskInfo.user_time.seconds; + t->ti.tv_nsec = aTaskInfo.user_time.microseconds * 1000; +#endif return t; } @@ -130,7 +151,15 @@ trace_switch(struct trace_pool *p, int session) { if (t->next) { t->next->prev = prev; } - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &t->ti); +#if defined(_POSIX_TIMERS) && defined(_POSIX_THREAD_CPUTIME) + clock_gettime(CLOCK_THREAD_CPUTIME_ID, &t->ti); +#elif defined(__APPLE__) + struct task_thread_times_info aTaskInfo; + mach_msg_type_number_t aTaskInfoCount = TASK_THREAD_TIMES_INFO_COUNT; + assert(KERN_SUCCESS == task_info(mach_task_self(), TASK_THREAD_TIMES_INFO, (task_info_t )&aTaskInfo, &aTaskInfoCount)); + t->ti.tv_sec = aTaskInfo.user_time.seconds; + t->ti.tv_nsec = aTaskInfo.user_time.microseconds * 1000; +#endif return; } prev = t; diff --git a/skynet-src/skynet_timer.c b/skynet-src/skynet_timer.c index 2ed08e5f..bebd79c3 100644 --- a/skynet-src/skynet_timer.c +++ b/skynet-src/skynet_timer.c @@ -9,6 +9,10 @@ #include #include +#if !defined(_POSIX_TIMERS) +#include +#endif + typedef void (*timer_execute_func)(void *ud,void *arg); #define TIME_NEAR_SHIFT 8 @@ -198,11 +202,18 @@ skynet_timeout(uint32_t handle, int time, int session) { static uint32_t _gettime(void) { + uint32_t t; +#if defined(_POSIX_TIMERS) struct timespec ti; clock_gettime(CLOCK_MONOTONIC, &ti); - uint32_t t = (uint32_t)(ti.tv_sec & 0xffffff) * 100; + t = (uint32_t)(ti.tv_sec & 0xffffff) * 100; t += ti.tv_nsec / 10000000; - +#else + struct timeval tv; + gettimeofday(&tv, NULL); + t = (uint32_t)(tv.tv_sec & 0xffffff) * 100; + t += tv.tv_usec / 10000; +#endif return t; } @@ -234,9 +245,15 @@ skynet_timer_init(void) { TI = timer_create_timer(); TI->current = _gettime(); +#if defined(_POSIX_TIMERS) struct timespec ti; clock_gettime(CLOCK_REALTIME, &ti); uint32_t sec = (uint32_t)ti.tv_sec; +#else + struct timeval tv; + gettimeofday(&tv, NULL); + uint32_t sec = (uint32_t)tv.tv_sec; +#endif uint32_t mono = _gettime() / 100; TI->starttime = sec - mono;