diff --git a/lib_acl/changes.txt b/lib_acl/changes.txt index 55e94f8bc..d50d563c7 100644 --- a/lib_acl/changes.txt +++ b/lib_acl/changes.txt @@ -1,6 +1,10 @@ 修改历史列表: ------------------------------------------------------------------------ +557) 2016.8.11 +557.1) bugfix: events_epoll_thr.c 中的 event_enable_read 函数里,解锁调用过程 +THREAD_UNLOCK 需要 epoll_ctl 调用之后,以免主线程和子线程同时操作同一对象 + 556) 2016.7.29 556.1) feature: json 解析器支持 double 数据元素 diff --git a/lib_acl/src/event/events_epoll_thr.c b/lib_acl/src/event/events_epoll_thr.c index 7fb81bef2..bac87330f 100644 --- a/lib_acl/src/event/events_epoll_thr.c +++ b/lib_acl/src/event/events_epoll_thr.c @@ -64,6 +64,8 @@ static void event_enable_read(ACL_EVENT *eventp, ACL_VSTREAM *fp, fdp = event_fdtable_alloc(); fdp->listener = 0; fdp->stream = fp; + + /* fdp will be freed in acl_vstream_close */ fp->fdp = (void *) fdp; } else if (fdp->flag & EVENT_FDTABLE_FLAG_WRITE) acl_msg_panic("%s(%d), %s: fd %d: multiple I/O request", @@ -135,8 +137,6 @@ static void event_enable_read(ACL_EVENT *eventp, ACL_VSTREAM *fp, return; } - THREAD_UNLOCK(&evthr->event.tb_mutex); - if (epoll_ctl(evthr->handle, EPOLL_CTL_ADD, fd, &ev) < 0) { if (errno == EEXIST) acl_msg_warn("%s: epoll_ctl: %s, fd: %d", @@ -150,6 +150,8 @@ static void event_enable_read(ACL_EVENT *eventp, ACL_VSTREAM *fp, acl_msg_fatal("%s: epoll_ctl: %s, fd: %d, epfd: %d", myname, acl_last_serror(), fd, evthr->handle); } + + THREAD_UNLOCK(&evthr->event.tb_mutex); } static void event_enable_listen(ACL_EVENT *eventp, ACL_VSTREAM *fp, @@ -167,6 +169,8 @@ static void event_enable_listen(ACL_EVENT *eventp, ACL_VSTREAM *fp, fdp = event_fdtable_alloc(); fdp->stream = fp; fdp->listener = 1; + + /* fdp will be freed in acl_vstream_close */ fp->fdp = (void *) fdp; } else if (fdp->flag & EVENT_FDTABLE_FLAG_WRITE) acl_msg_panic("%s(%d)->%s: fd %d: multiple I/O request", @@ -237,6 +241,8 @@ static void event_enable_write(ACL_EVENT *eventp, ACL_VSTREAM *fp, fdp = event_fdtable_alloc(); fdp->listener = 0; fdp->stream = fp; + + /* fdp will be freed in acl_vstream_close */ fp->fdp = (void *) fdp; } else if (fdp->flag & EVENT_FDTABLE_FLAG_READ) acl_msg_panic("%s(%d)->%s: fd %d: multiple I/O request", @@ -293,8 +299,6 @@ static void event_enable_write(ACL_EVENT *eventp, ACL_VSTREAM *fp, THREAD_UNLOCK(&evthr->event.tb_mutex); return; } - - THREAD_UNLOCK(&evthr->event.tb_mutex); if (epoll_ctl(evthr->handle, EPOLL_CTL_ADD, fd, &ev) < 0) { if (errno == EEXIST) @@ -309,6 +313,8 @@ static void event_enable_write(ACL_EVENT *eventp, ACL_VSTREAM *fp, acl_msg_fatal("%s: epoll_ctl: %s, fd: %d, epfd: %d", myname, acl_last_serror(), fd, evthr->handle); } + + THREAD_UNLOCK(&evthr->event.tb_mutex); } /* event_disable_readwrite - disable request for read or write events */ @@ -376,6 +382,7 @@ static void event_disable_readwrite(ACL_EVENT *eventp, ACL_VSTREAM *stream) myname, acl_last_serror(), sockfd); } + /* fdp will be freed in acl_vstream_close */ event_fdtable_reset(fdp); } diff --git a/lib_fiber/README.md b/lib_fiber/README.md new file mode 100644 index 000000000..b83d379b6 --- /dev/null +++ b/lib_fiber/README.md @@ -0,0 +1,213 @@ +鏈ā鍧(lib_fiber)涓哄熀浜庡崗绋嬫柟寮忚繘琛岄珮骞跺彂銆侀珮鎬ц兘寮鍙戠殑缃戠粶鍗忕▼搴撱備娇鐢ㄨ呭彲浠ヨ薄鍒涘缓绾跨▼涓鏍峰垱寤哄崗绋嬶紝鐩稿浜庣嚎绋嬭岃█锛屽崗绋嬫洿涓衡滆交閲忊濓紝鍥犳浣跨敤鑰呭彲浠ュ垱寤哄ぇ閲(鎴愬崈涓婁竾)鐨勫崗绋嬨傛瘡涓崗绋嬪彲浠ヤ笌涓涓綉缁滆繛鎺ョ粦瀹氾紱鍚屾椂浣跨敤鑰呭彲浠ラ噰鐢ㄢ滃悓姝モ濇濈淮鏂瑰紡缂栧啓缃戠粶绋嬪簭锛岃屼笉蹇呰薄闈為樆濉炵▼搴忎竴鏍烽噰鐢ㄥ紓姝ュ洖璋冩柟寮忥紝鍥犳浣跨敤鑰呬娇鐢ㄨ捣鏉ュ苟娌℃湁澶氬ぇ缂栫▼澶嶆潅搴︺ +鏈綉缁滃崗绋嬪簱鐨勫崗绋嬮儴鍒嗘槸鍩轰簬 Russ Cox (golang 鐨勫崗绋嬩綔鑰) 鍦 2005 骞村疄鐜扮殑 libtask锛宭ibtask 瀹炵幇浜嗗崗绋嬬紪绋嬬殑鍩烘湰鍘熷瀷锛宭ib_fiber 涓鏂归潰浣垮崗绋嬬紪绋嬫帴鍙f洿鍔犵畝鍗曟槗鐢(鐢ㄦ埛鍙互鐩存帴璋冪敤 acl_fiber_create 鍒涘缓鍗忕▼)锛屽彟涓鏂归潰 lib_fiber 瀹炵幇浜嗙嚎绋嬪畨鍏ㄧ殑鍗忕▼搴擄紝閫氳繃缁欐瘡涓嚎绋嬩竴涓嫭绔嬬殑鍗忕▼璋冨害鍣紝浠庤屾柟渚跨敤鎴蜂娇鐢ㄥ鏍革紝姝ゅ锛宭ib_fiber 杩樺鍔犱簡鍩轰簬鍗忕▼鐨勪俊鍙烽噺銆佸崗绋嬪眬閮ㄥ彉閲忕瓑鍔熻兘銆 +鏈綉缁滃崗绋嬪簱鐨勫紓姝 IO 浜嬩欢閮ㄥ垎鍩轰簬 redis 涓殑 event 妯″潡鏀归犺屾潵锛屽鍔犱簡寤惰繜鍒犻櫎銆佸彞鏌勭紦瀛樼瓑鍔熻兘銆 + +涓嬮潰鏄竴涓畝鍗曚娇鐢ㄧ綉缁滃崗绋嬪簱缂栧啓鐨勪竴涓畝鍗曠殑楂樺苟鍙戞湇鍔″櫒锛 + +```c++ +#include +#include +#include +#include +#include +#include +#include +#include "lib_acl.h" +#include "fiber/lib_fiber.h" + +static int __nconnect = 0; +static int __count = 0; +static char __listen_ip[64]; +static int __listen_port = 9001; +static int __listen_qlen = 64; +static int __rw_timeout = 0; +static int __echo_data = 1; +static int __stack_size = 32000; + +static int check_read(int fd, int timeout) +{ + struct pollfd pfd; + int n; + + memset(&pfd, 0, sizeof(struct pollfd)); + pfd.fd = fd; + pfd.events = POLLIN; + + n = poll(&pfd, 1, timeout); + if (n < 0) { + printf("poll error: %s\r\n", strerror(errno)); + return -1; + } + + if (n == 0) + return 0; + if (pfd.revents & POLLIN) + return 1; + else + return 0; +} + +static void echo_client(ACL_FIBER *fiber acl_unused, void *ctx) +{ + int *cfd = (int *) ctx; + char buf[8192]; + int ret; + + printf("client fiber-%d: fd: %d\r\n", acl_fiber_self(), *cfd); + + while (1) { + if (__rw_timeout > 0) { + ret = check_read(*cfd, 10000); + if (ret < 0) + break; + if (ret == 0) + continue; + } + + ret = read(*cfd, buf, sizeof(buf)); + if (ret == 0) { + printf("read close by peer fd: %d\r\n", *cfd); + break; + } else if (ret < 0) { + if (errno == EINTR) { + printf("catch a EINTR signal\r\n"); + continue; + } + + printf("read error %s, fd: %d\n", strerror(errno), *cfd); + break; + } + + __count++; + + if (!__echo_data) + continue; + + if (write(*cfd, buf, ret) < 0) { + if (errno == EINTR) + continue; + printf("write error, fd: %d\r\n", *cfd); + break; + } + } + + printf("close %d\r\n", *cfd); + close(*cfd); + free(cfd); + + if (--__nconnect == 0) { + printf("\r\n----total read/write: %d----\r\n", __count); + __count = 0; + } +} + +static void fiber_accept(ACL_FIBER *fiber acl_unused, void *ctx acl_unused) +{ + int lfd, on = 1; + struct sockaddr_in sa; + + memset(&sa, 0, sizeof(sa)); + sa.sin_family = AF_INET; + sa.sin_port = htons(__listen_port); + sa.sin_addr.s_addr = inet_addr(__listen_ip); + + lfd = socket(AF_INET, SOCK_STREAM, 0); + if (lfd < 0) + abort(); + + if (setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) { + printf("setsockopt error %s\r\n", strerror(errno)); + exit (1); + } + + if (bind(lfd, (struct sockaddr *) &sa, sizeof(struct sockaddr)) < 0) { + printf("bind error %s\r\n", strerror(errno)); + exit (1); + } + + if (listen(lfd, 128) < 0) { + printf("listen error %s\r\n", strerror(errno)); + exit (1); + } + + printf("fiber-%d listen %s:%d ok\r\n", + acl_fiber_self(), __listen_ip, __listen_port); + + for (;;) { + int len = sizeof(sa), *fd; + int cfd = accept(lfd, (struct sockaddr *)& sa, (socklen_t *) &len); + if (cfd < 0) { + printf("accept error %s\r\n", strerror(errno)); + break; + } + + fd = malloc(sizeof(int)); + assert(fd != NULL); + *fd = cfd; + + __nconnect++; + printf("accept one, fd: %d\r\n", cfd); + acl_fiber_create(echo_client, fd, __stack_size); + } + + close(lfd); + exit(0); +} + +static void usage(const char *procname) +{ + printf("usage: %s -h [help]\r\n" + " -s listen_ip\r\n" + " -p listen_port\r\n" + " -r rw_timeout\r\n" + " -q listen_queue\r\n" + " -z stack_size\r\n" + " -S [if using single IO, default: no]\r\n", procname); +} + +int main(int argc, char *argv[]) +{ + int ch; + + snprintf(__listen_ip, sizeof(__listen_ip), "%s", "127.0.0.1"); + + while ((ch = getopt(argc, argv, "hs:p:r:q:Sz:")) > 0) { + switch (ch) { + case 'h': + usage(argv[0]); + return 0; + case 's': + snprintf(__listen_ip, sizeof(__listen_ip), "%s", optarg); + break; + case 'p': + __listen_port = atoi(optarg); + break; + case 'r': + __rw_timeout = atoi(optarg); + break; + case 'q': + __listen_qlen = atoi(optarg); + break; + case 'S': + __echo_data = 0; + break; + case 'z': + __stack_size = atoi(optarg); + break; + default: + break; + } + } + + signal(SIGPIPE, SIG_IGN); + acl_msg_stdout_enable(1); + + printf("%s: call fiber_creater\r\n", __FUNCTION__); + acl_fiber_create(fiber_accept, NULL, 32768); + + printf("call fiber_schedule\r\n"); + acl_fiber_schedule(); + + return 0; +} +``` diff --git a/lib_fiber/author.txt b/lib_fiber/author.txt new file mode 100644 index 000000000..3e72c755a --- /dev/null +++ b/lib_fiber/author.txt @@ -0,0 +1,3 @@ +Author: +niukey@qq.com +shuxin.zheng@qq.com diff --git a/lib_fiber/c/Makefile b/lib_fiber/c/Makefile index 3450ccd7c..4a7cb2c2e 100644 --- a/lib_fiber/c/Makefile +++ b/lib_fiber/c/Makefile @@ -17,7 +17,8 @@ CFLAGS = -c -g -W \ -D_REENTRANT \ -D_POSIX_PTHREAD_SEMANTICS \ -D_USE_FAST_MACRO \ --Wno-long-long +-Wno-long-long \ +-DUSE_JMP #-DUSE_VALGRIND #-Wno-clobbered #-O3 diff --git a/lib_fiber/c/src/dev/fiber.c b/lib_fiber/c/src/dev/fiber.c new file mode 100644 index 000000000..74bc81387 --- /dev/null +++ b/lib_fiber/c/src/dev/fiber.c @@ -0,0 +1,555 @@ +#include "stdafx.h" +#define __USE_GNU +#include + +#ifdef USE_VALGRIND +#include +#endif + +#include "fiber/lib_fiber.h" +#include "event_epoll.h" /* just for hook_epoll */ +#include "fiber.h" + +typedef int *(*errno_fn)(void); +typedef int (*fcntl_fn)(int, int, ...); + +static errno_fn __sys_errno = NULL; +static fcntl_fn __sys_fcntl = NULL; + +typedef struct { + ACL_RING ready; /* ready fiber queue */ + ACL_RING dead; /* dead fiber queue */ + ACL_FIBER **fibers; + size_t size; + int exitcode; + ACL_FIBER *running; + ACL_FIBER *schedule; + ACL_FIBER *fiber; + int errnum; + size_t idgen; + int count; + int switched; +} FIBER_TLS; + +static FIBER_TLS *__main_fiber = NULL; +static __thread FIBER_TLS *__thread_fiber = NULL; +__thread int acl_var_hook_sys_api = 0; + +static acl_pthread_key_t __fiber_key; +static void fiber_free(ACL_FIBER *fiber); +static ACL_FIBER *fiber_alloc(void (*fn)(ACL_FIBER *, void *), + void *arg, size_t size); + +void acl_fiber_hook_api(int onoff) +{ + acl_var_hook_sys_api = onoff; +} + +static void thread_free(void *ctx) +{ + FIBER_TLS *tf = (FIBER_TLS *) ctx; + + if (__thread_fiber == NULL) + return; + + if (tf->fibers) + acl_myfree(tf->fibers); + fiber_free(tf->schedule); + fiber_free(tf->fiber); + acl_myfree(tf); + if (__main_fiber == __thread_fiber) + __main_fiber = NULL; + __thread_fiber = NULL; +} + +static void fiber_schedule_main_free(void) +{ + if (__main_fiber) { + thread_free(__main_fiber); + if (__thread_fiber == __main_fiber) + __thread_fiber = NULL; + __main_fiber = NULL; + } +} + +static void thread_init(void) +{ + acl_assert(acl_pthread_key_create(&__fiber_key, thread_free) == 0); +} + +static acl_pthread_once_t __once_control = ACL_PTHREAD_ONCE_INIT; + +static void fiber_check(void) +{ + if (__thread_fiber != NULL) + return; + + acl_assert(acl_pthread_once(&__once_control, thread_init) == 0); + + __thread_fiber = (FIBER_TLS *) acl_mycalloc(1, sizeof(FIBER_TLS)); + __thread_fiber->fibers = NULL; + __thread_fiber->size = 0; + __thread_fiber->idgen = 0; + __thread_fiber->count = 0; + __thread_fiber->schedule = fiber_alloc(NULL, NULL, 6400000); + __thread_fiber->fiber = fiber_alloc(NULL, NULL, 6400000); + + acl_ring_init(&__thread_fiber->ready); + acl_ring_init(&__thread_fiber->dead); + + if ((unsigned long) acl_pthread_self() == acl_main_thread_self()) { + __main_fiber = __thread_fiber; + atexit(fiber_schedule_main_free); + } else if (acl_pthread_setspecific(__fiber_key, __thread_fiber) != 0) + acl_msg_fatal("acl_pthread_setspecific error!"); +} + +/* see /usr/include/bits/errno.h for __errno_location */ +int *__errno_location(void) +{ + if (!acl_var_hook_sys_api) + return __sys_errno(); + + if (__thread_fiber == NULL) + fiber_check(); + + if (__thread_fiber->running) + return &__thread_fiber->running->errnum; + else + return &__thread_fiber->schedule->errnum; +} + +int fcntl(int fd, int cmd, ...) +{ + long arg; + struct flock *lock; + va_list ap; + int ret; + + va_start(ap, cmd); + + switch (cmd) { + case F_GETFD: + case F_GETFL: + ret = __sys_fcntl(fd, cmd); + break; + case F_SETFD: + case F_SETFL: + arg = va_arg(ap, long); + ret = __sys_fcntl(fd, cmd, arg); + break; + case F_GETLK: + case F_SETLK: + case F_SETLKW: + lock = va_arg(ap, struct flock*); + ret = __sys_fcntl(fd, cmd, lock); + break; + default: + ret = -1; + acl_msg_error("%s(%d), %s: unknown cmd: %d, fd: %d", + __FILE__, __LINE__, __FUNCTION__, cmd, fd); + break; + } + + va_end(ap); + + if (ret < 0) + fiber_save_errno(); + + return ret; +} + +void acl_fiber_set_errno(ACL_FIBER *fiber, int errnum) +{ + fiber->errnum = errnum; +} + +int acl_fiber_errno(ACL_FIBER *fiber) +{ + fiber->flag |= FIBER_F_SAVE_ERRNO; + return fiber->errnum; +} + +void fiber_save_errno(void) +{ + ACL_FIBER *curr; + + if (__thread_fiber == NULL) + fiber_check(); + + if ((curr = __thread_fiber->running) == NULL) + curr = __thread_fiber->schedule; + + if (curr->flag & FIBER_F_SAVE_ERRNO) { + curr->flag &= ~FIBER_F_SAVE_ERRNO; + return; + } + + if (__sys_errno != NULL) + curr->errnum = *__sys_errno(); + else + curr->errnum = errno; +} + +static void fiber_swap(ACL_FIBER *from, ACL_FIBER *to) +{ + ACL_FIBER *fiber = __thread_fiber->fiber; + int i; + + if (&from->uctx != &__thread_fiber->schedule->uctx) { + ssize_t off = (char *) from->stack_top - (char *) &i + 1024; + printf("----->fiber-%d: off: %ld, size: %ld, off: %p, %p\r\n", + acl_fiber_id(from), off, from->size, &i, + from->stack_top); + assert(off > 0); + assert(from->size); + if (off > (ssize_t) from->size) { + acl_myfree(from->buff); + from->buff = (char *) acl_mycalloc(1, off); + from->size = off; + from->uctx.uc_stack.ss_sp = from->buff + 8; + from->uctx.uc_stack.ss_size = from->size - 64; + } + } + else + printf("from fiber-%d: size: %ld; to fiber-%d, size: %ld\n", + acl_fiber_id(from), from->size, + acl_fiber_id(to), to->size); + + fiber->errnum = 0; + fiber->fn = to->fn; + fiber->arg = to->arg; + fiber->id = to->id; + + memcpy(&fiber->uctx, &to->uctx, sizeof(to->uctx)); + assert(fiber->size >= to->size); + memcpy(fiber->buff, to->buff, to->size); + fiber->uctx.uc_stack.ss_sp = fiber->buff + 8; + fiber->uctx.uc_stack.ss_size = fiber->size - 64; + printf("----ss_size: %ld\r\n", fiber->uctx.uc_stack.ss_size); + + if (swapcontext(&from->uctx, &fiber->uctx) < 0) + acl_msg_fatal("%s(%d), %s: swapcontext error %s", + __FILE__, __LINE__, __FUNCTION__, acl_last_serror()); +} + +ACL_FIBER *fiber_running(void) +{ + fiber_check(); + return __thread_fiber->running; +} + +void fiber_exit(int exit_code) +{ + fiber_check(); + + __thread_fiber->exitcode = exit_code; + __thread_fiber->running->status = FIBER_STATUS_EXITING; + + acl_fiber_switch(); +} + +void acl_fiber_ready(ACL_FIBER *fiber) +{ + fiber->status = FIBER_STATUS_READY; + acl_ring_prepend(&__thread_fiber->ready, &fiber->me); +} + +int acl_fiber_yield(void) +{ + int n; + + if (acl_ring_size(&__thread_fiber->ready) == 0) + return 0; + + n = __thread_fiber->switched; + acl_fiber_ready(__thread_fiber->running); + acl_fiber_switch(); + + return __thread_fiber->switched - n - 1; +} + +union cc_arg +{ + void *p; + int i[2]; +}; + +static void fiber_start(unsigned int x, unsigned int y) +{ + union cc_arg arg; + ACL_FIBER *fiber; + int i; + + arg.i[0] = x; + arg.i[1] = y; + + fiber = (ACL_FIBER *) arg.p; + fiber->stack_top = &i; + + fiber->fn(fiber, fiber->arg); + + for (i = 0; i < fiber->nlocal; i++) { + if (fiber->locals[i]->free_fn) + fiber->locals[i]->free_fn(fiber->locals[i]->ctx); + } + + if (fiber->locals) { + acl_myfree(fiber->locals); + fiber->locals = NULL; + fiber->nlocal = 0; + } + + fiber_exit(0); +} + +#define MAX_CACHE 100 + +static void fiber_free(ACL_FIBER *fiber) +{ + acl_myfree(fiber->buff); + acl_myfree(fiber); +} + +static ACL_FIBER *fiber_alloc(void (*fn)(ACL_FIBER *, void *), + void *arg, size_t size) +{ + ACL_FIBER *fiber; + sigset_t zero; + union cc_arg carg; + ACL_RING *head; + size_t n; + + fiber_check(); + + n = acl_ring_size(&__thread_fiber->dead); + if (n > MAX_CACHE) { + n -= MAX_CACHE; + while (n > 0) { + head = acl_ring_pop_head(&__thread_fiber->dead); + acl_assert(head != NULL); + fiber = ACL_RING_TO_APPL(head, ACL_FIBER,me); + fiber_free(fiber); + n--; + } + } + +#define APPL ACL_RING_TO_APPL + + head = acl_ring_pop_head(&__thread_fiber->dead); + if (head == NULL) { + fiber = (ACL_FIBER *) acl_mycalloc(1, sizeof(ACL_FIBER)); + fiber->buff = (char *) acl_mycalloc(1, size); + } else if ((fiber = APPL(head, ACL_FIBER, me))->size < size) { + acl_myfree(fiber->buff); + fiber->buff = (char *) acl_mycalloc(1, size); + } else + size = fiber->size; + + fiber->errnum = 0; + fiber->fn = fn; + fiber->arg = arg; + fiber->size = size; + fiber->id = ++__thread_fiber->idgen; + + sigemptyset(&zero); + sigprocmask(SIG_BLOCK, &zero, &fiber->uctx.uc_sigmask); + + if (getcontext(&fiber->uctx) < 0) + acl_msg_fatal("%s(%d), %s: getcontext error: %s", + __FILE__, __LINE__, __FUNCTION__, acl_last_serror()); + + fiber->uctx.uc_stack.ss_sp = fiber->buff + 8; + fiber->uctx.uc_stack.ss_size = fiber->size - 64; + //fiber->uctx.uc_stack.ss_sp = fiber->buff; + //fiber->uctx.uc_stack.ss_size = fiber->size; + if (__thread_fiber->schedule != NULL) + fiber->uctx.uc_link = &__thread_fiber->schedule->uctx; + +#ifdef USE_VALGRIND + fiber->vid = VALGRIND_STACK_REGISTER(fiber->uctx.uc_stack.ss_sp, + fiber->uctx.uc_stack.ss_sp + + fiber->uctx.uc_stack.ss_size); +#endif + + carg.p = fiber; + makecontext(&fiber->uctx, (void(*)(void)) fiber_start, + 2, carg.i[0], carg.i[1]); + + return fiber; +} + +ACL_FIBER *acl_fiber_create(void (*fn)(ACL_FIBER *, void *), void *arg, size_t size) +{ + ACL_FIBER *fiber = fiber_alloc(fn, arg, size); + + __thread_fiber->count++; + if (__thread_fiber->size % 64 == 0) + __thread_fiber->fibers = (ACL_FIBER **) acl_myrealloc( + __thread_fiber->fibers, + (__thread_fiber->size + 64) * sizeof(ACL_FIBER *)); + + fiber->slot = __thread_fiber->size; + __thread_fiber->fibers[__thread_fiber->size++] = fiber; + acl_fiber_ready(fiber); + + return fiber; +} + +int acl_fiber_id(const ACL_FIBER *fiber) +{ + return fiber->id; +} + +int acl_fiber_self(void) +{ + ACL_FIBER *curr = fiber_running(); + return acl_fiber_id(curr); +} + +int acl_fiber_status(const ACL_FIBER *fiber) +{ + return fiber->status; +} + +static void fiber_init(void) __attribute__ ((constructor)); + +static void fiber_init(void) +{ + static int __called = 0; + + if (__called != 0) + return; + + __called++; + + __sys_errno = (errno_fn) dlsym(RTLD_NEXT, "__errno_location"); + __sys_fcntl = (fcntl_fn) dlsym(RTLD_NEXT, "fcntl"); + + hook_io(); + hook_net(); + hook_epoll(); +} + +void acl_fiber_schedule(void) +{ + ACL_FIBER *fiber; + ACL_RING *head; + + acl_fiber_hook_api(1); + + for (;;) { + head = acl_ring_pop_head(&__thread_fiber->ready); + if (head == NULL) { + acl_msg_info("------- NO ACL_FIBER NOW --------"); + break; + } + + fiber = ACL_RING_TO_APPL(head, ACL_FIBER, me); + fiber->status = FIBER_STATUS_READY; + + __thread_fiber->running = fiber; + __thread_fiber->switched++; + + fiber_swap(__thread_fiber->schedule, fiber); + __thread_fiber->running = NULL; + } + + /* release dead fiber */ + while ((head = acl_ring_pop_head(&__thread_fiber->dead)) != NULL) { + fiber = ACL_RING_TO_APPL(head, ACL_FIBER, me); + fiber_free(fiber); + } +} + +void fiber_system(void) +{ + if (!__thread_fiber->running->sys) { + __thread_fiber->running->sys = 1; + __thread_fiber->count--; + } +} + +void fiber_count_inc(void) +{ + __thread_fiber->count++; +} + +void fiber_count_dec(void) +{ + __thread_fiber->count--; +} + +void acl_fiber_switch(void) +{ + ACL_FIBER *fiber, *current = __thread_fiber->running; + ACL_RING *head; + +#ifdef _DEBUG + acl_assert(current); +#endif + + if (current->status == FIBER_STATUS_EXITING) { + size_t slot = current->slot; + + if (!current->sys) + __thread_fiber->count--; + + __thread_fiber->fibers[slot] = + __thread_fiber->fibers[--__thread_fiber->size]; + __thread_fiber->fibers[slot]->slot = slot; + acl_ring_append(&__thread_fiber->dead, ¤t->me); + } + + head = acl_ring_pop_head(&__thread_fiber->ready); + + if (head == NULL) { + fiber_swap(current, __thread_fiber->schedule); + return; + } + + fiber = ACL_RING_TO_APPL(head, ACL_FIBER, me); + fiber->status = FIBER_STATUS_READY; + + __thread_fiber->running = fiber; + __thread_fiber->switched++; + fiber_swap(current, __thread_fiber->running); +} + +int acl_fiber_set_specific(void *ctx, void (*free_fn)(void *)) +{ + FIBER_LOCAL *local; + ACL_FIBER *curr; + int key; + + if (__thread_fiber == NULL || __thread_fiber->running == NULL) + return -1; + + curr = __thread_fiber->running; + + key = curr->nlocal; + local = (FIBER_LOCAL *) acl_mymalloc(sizeof(FIBER_LOCAL)); + local->ctx = ctx; + local->free_fn = free_fn; + + if (curr->nlocal % 64 == 0) + curr->locals = (FIBER_LOCAL **) acl_myrealloc(curr->locals, + (curr->nlocal + 64) * sizeof(FIBER_LOCAL*)); + curr->locals[curr->nlocal++] = local; + + return key; +} + +void *acl_fiber_get_specific(int key) +{ + ACL_FIBER *curr; + + if (__thread_fiber == NULL || __thread_fiber->running == NULL) + return NULL; + + curr = __thread_fiber->running; + if (key >= curr->nlocal || key < 0) + return NULL; + + return curr->locals[key]; +} diff --git a/lib_fiber/c/src/dev/fiber.h b/lib_fiber/c/src/dev/fiber.h new file mode 100644 index 000000000..54d894665 --- /dev/null +++ b/lib_fiber/c/src/dev/fiber.h @@ -0,0 +1,128 @@ +#ifndef FIBER_INCLUDE_H +#define FIBER_INCLUDE_H + +#include +#include "event.h" + +typedef enum { + FIBER_STATUS_READY, + FIBER_STATUS_RUNNING, + FIBER_STATUS_EXITING, +} fiber_status_t; + +typedef struct { + void *ctx; + void (*free_fn)(void *); +} FIBER_LOCAL; + +struct ACL_FIBER { +#ifdef USE_VALGRIND + unsigned int vid; +#endif + fiber_status_t status; + ACL_RING me; + size_t id; + size_t slot; + acl_int64 when; + int errnum; + int sys; + unsigned int flag; +#define FIBER_F_SAVE_ERRNO (unsigned) 1 << 0 + + FIBER_LOCAL **locals; + int nlocal; + + ucontext_t uctx; + void (*fn)(ACL_FIBER *, void *); + void *arg; + void (*timer_fn)(ACL_FIBER *, void *); + size_t size; + void *stack_top; + char *buff; +}; + +/* + * channel communication + */ +enum +{ + CHANEND, + CHANSND, + CHANRCV, + CHANNOP, + CHANNOBLK, +}; + +typedef struct FIBER_ALT FIBER_ALT; +typedef struct FIBER_ALT_ARRAY FIBER_ALT_ARRAY; + +struct FIBER_ALT { + ACL_CHANNEL *c; + void *v; + unsigned int op; + ACL_FIBER *fiber; + FIBER_ALT *xalt; +}; + +struct FIBER_ALT_ARRAY { + FIBER_ALT **a; + unsigned int n; + unsigned int m; +}; + +struct ACL_CHANNEL { + unsigned int bufsize; + unsigned int elemsize; + unsigned char *buf; + unsigned int nbuf; + unsigned int off; + FIBER_ALT_ARRAY asend; + FIBER_ALT_ARRAY arecv; + char *name; +}; + +struct ACL_FIBER_MUTEX { + ACL_FIBER *owner; + ACL_RING waiting; +}; + +struct ACL_FIBER_RWLOCK { + int readers; + ACL_FIBER *writer; + ACL_RING rwaiting; + ACL_RING wwaiting; +}; + +struct ACL_FIBER_SEM { + int num; + ACL_RING waiting; +}; + +/* in fiber.c */ +extern __thread int acl_var_hook_sys_api; + +/* in fiber_schedule.c */ +ACL_FIBER *fiber_running(void); +void fiber_save_errno(void); +void fiber_exit(int exit_code); +void fiber_system(void); +void fiber_count_inc(void); +void fiber_count_dec(void); + +/* in fiber_io.c */ +void fiber_io_check(void); +void fiber_io_close(int fd); +void fiber_wait_read(int fd); +void fiber_wait_write(int fd); +void fiber_io_dec(void); +void fiber_io_inc(void); +EVENT *fiber_io_event(void); + +/* in hook_io.c */ +void hook_io(void); + +/* in fiber_net.c */ +void hook_net(void); +int epoll_event_close(int epfd); + +#endif diff --git a/lib_fiber/c/src/fiber.c b/lib_fiber/c/src/fiber.c index 9fbfa585c..cc17cda61 100644 --- a/lib_fiber/c/src/fiber.c +++ b/lib_fiber/c/src/fiber.c @@ -23,7 +23,7 @@ typedef struct { size_t size; int exitcode; ACL_FIBER *running; - ACL_FIBER schedule; + ACL_FIBER original; int errnum; size_t idgen; int count; @@ -50,7 +50,10 @@ static void thread_free(void *ctx) if (tf->fibers) acl_myfree(tf->fibers); + if (tf->original.context) + acl_myfree(tf->original.context); acl_myfree(tf); + if (__main_fiber == __thread_fiber) __main_fiber = NULL; __thread_fiber = NULL; @@ -81,6 +84,15 @@ static void fiber_check(void) acl_assert(acl_pthread_once(&__once_control, thread_init) == 0); __thread_fiber = (FIBER_TLS *) acl_mycalloc(1, sizeof(FIBER_TLS)); +#ifdef USE_JMP + /* set context NULL when using setjmp that setcontext will not be + * called in fiber_swap. + */ + __thread_fiber->original.context = NULL; +#else + __thread_fiber->original.context = (ucontext_t *) + acl_mycalloc(1, sizeof(ucontext_t)); +#endif __thread_fiber->fibers = NULL; __thread_fiber->size = 0; __thread_fiber->idgen = 0; @@ -108,7 +120,7 @@ int *__errno_location(void) if (__thread_fiber->running) return &__thread_fiber->running->errnum; else - return &__thread_fiber->schedule.errnum; + return &__thread_fiber->original.errnum; } int fcntl(int fd, int cmd, ...) @@ -170,7 +182,7 @@ void fiber_save_errno(void) fiber_check(); if ((curr = __thread_fiber->running) == NULL) - curr = &__thread_fiber->schedule; + curr = &__thread_fiber->original; if (curr->flag & FIBER_F_SAVE_ERRNO) { curr->flag &= ~FIBER_F_SAVE_ERRNO; @@ -183,11 +195,69 @@ void fiber_save_errno(void) curr->errnum = errno; } +#if defined(__x86_64__) +#define SETJMP(ctx) ({\ + int ret;\ + asm ("lea LJMPRET%=(%%rip), %%rcx\n\t"\ + "xor %%rax, %%rax\n\t"\ + "mov %%rbx, (%%rdx)\n\t"\ + "mov %%rbp, 8(%%rdx)\n\t"\ + "mov %%r12, 16(%%rdx)\n\t"\ + "mov %%rsp, 24(%%rdx)\n\t"\ + "mov %%r13, 32(%%rdx)\n\t"\ + "mov %%r14, 40(%%rdx)\n\t"\ + "mov %%r15, 48(%%rdx)\n\t"\ + "mov %%rcx, 56(%%rdx)\n\t"\ + "mov %%rdi, 64(%%rdx)\n\t"\ + "mov %%rsi, 72(%%rdx)\n\t"\ + "LJMPRET%=:\n\t"\ + : "=a" (ret)\ + : "d" (ctx) : "memory");\ + ret;\ +}) +#define LONGJMP(ctx) \ + asm("movq (%%rax), %%rbx\n\t"\ + "movq 8(%%rax), %%rbp\n\t"\ + "movq 16(%%rax), %%r12\n\t"\ + "movq 24(%%rax), %%rdx\n\t"\ + "movq 32(%%rax), %%r13\n\t"\ + "movq 40(%%rax), %%r14\n\t"\ + "mov %%rdx, %%rsp\n\t"\ + "movq 48(%%rax), %%r15\n\t"\ + "movq 56(%%rax), %%rdx\n\t"\ + "movq 64(%%rax), %%rdi\n\t"\ + "movq 72(%%rax), %%rsi\n\t"\ + "jmp *%%rdx\n\t"\ + : : "a" (ctx) : "rdx" \ + ) +#else +#define SETJMP(ctx) \ + sigsetjmp(ctx, 0) +#define LONGJMP(ctx) \ + siglongjmp(ctx, 1) +#endif + static void fiber_swap(ACL_FIBER *from, ACL_FIBER *to) { - if (swapcontext(&from->uctx, &to->uctx) < 0) +#ifdef USE_JMP + /* use setcontext() for the initial jump, as it allows us to set up + * a stack, but continue with longjmp() as it's much faster. + */ + if (SETJMP(from->jbuf) == 0) { + /* context just be used once for set up a stack, which will + * be freed in fiber_start. The context in __thread_fiber + * was set NULL. + */ + if (to->context != NULL) + setcontext(to->context); + else + LONGJMP(to->jbuf); + } +#else + if (swapcontext(from->context, to->context) < 0) acl_msg_fatal("%s(%d), %s: swapcontext error %s", __FILE__, __LINE__, __FUNCTION__, acl_last_serror()); +#endif } ACL_FIBER *fiber_running(void) @@ -243,6 +313,14 @@ static void fiber_start(unsigned int x, unsigned int y) fiber = (ACL_FIBER *) arg.p; +#ifdef USE_JMP + /* when using setjmp/longjmp, the context just be used only once */ + if (fiber->context != NULL) { + acl_myfree(fiber->context); + fiber->context = NULL; + } +#endif + fiber->fn(fiber, fiber->arg); for (i = 0; i < fiber->nlocal; i++) { @@ -261,9 +339,11 @@ static void fiber_start(unsigned int x, unsigned int y) #define MAX_CACHE 100 -static void fiber_free(FIBER_TLS *tls, ACL_FIBER *fiber) +static void fiber_free(ACL_FIBER *fiber) { - (void) tls; + if (fiber->context) + acl_myfree(fiber->context); + acl_myfree(fiber->buff); acl_myfree(fiber); } @@ -279,58 +359,70 @@ static ACL_FIBER *fiber_alloc(void (*fn)(ACL_FIBER *, void *), fiber_check(); n = acl_ring_size(&__thread_fiber->dead); + + /* if the cached dead fibers reached the limit, some will be freed */ if (n > MAX_CACHE) { n -= MAX_CACHE; while (n > 0) { head = acl_ring_pop_head(&__thread_fiber->dead); acl_assert(head != NULL); fiber = ACL_RING_TO_APPL(head, ACL_FIBER,me); - fiber_free(__thread_fiber, fiber); + fiber_free(fiber); n--; } } +#define APPL ACL_RING_TO_APPL + + /* try to reuse the fiber memory in dead queue */ head = acl_ring_pop_head(&__thread_fiber->dead); - if (head == NULL) - fiber = (ACL_FIBER *) acl_mycalloc(1, sizeof(ACL_FIBER) + size); - else if ((fiber = ACL_RING_TO_APPL(head, ACL_FIBER, me))->size < size) { - fiber_free(__thread_fiber, fiber); - fiber = (ACL_FIBER *) acl_mycalloc(1, sizeof(ACL_FIBER) + size); - } else + if (head == NULL) { + fiber = (ACL_FIBER *) acl_mycalloc(1, sizeof(ACL_FIBER)); + fiber->buff = (char *) acl_mycalloc(1, size); + } else if ((fiber = APPL(head, ACL_FIBER, me))->size < size) + fiber->buff = (char *) acl_myrealloc(fiber->buff, size); + else size = fiber->size; fiber->errnum = 0; fiber->fn = fn; fiber->arg = arg; - fiber->stack = fiber->buf; fiber->size = size; fiber->id = ++__thread_fiber->idgen; - sigemptyset(&zero); - sigprocmask(SIG_BLOCK, &zero, &fiber->uctx.uc_sigmask); + carg.p = fiber; - if (getcontext(&fiber->uctx) < 0) + fiber->context = (ucontext_t *) acl_mymalloc(sizeof(ucontext_t)); + sigemptyset(&zero); + sigprocmask(SIG_BLOCK, &zero, &fiber->context->uc_sigmask); + + if (getcontext(fiber->context) < 0) acl_msg_fatal("%s(%d), %s: getcontext error: %s", __FILE__, __LINE__, __FUNCTION__, acl_last_serror()); - fiber->uctx.uc_stack.ss_sp = fiber->stack + 8; - fiber->uctx.uc_stack.ss_size = fiber->size - 64; - fiber->uctx.uc_link = &__thread_fiber->schedule.uctx; + fiber->context->uc_stack.ss_sp = fiber->buff + 8; + fiber->context->uc_stack.ss_size = fiber->size - 64; -#ifdef USE_VALGRIND - fiber->vid = VALGRIND_STACK_REGISTER(fiber->uctx.uc_stack.ss_sp, - fiber->uctx.uc_stack.ss_sp - + fiber->uctx.uc_stack.ss_size); +#ifdef USE_JMP + fiber->context->uc_link = NULL; +#else + fiber->context->uc_link = __thread_fiber->original.context; #endif - carg.p = fiber; - makecontext(&fiber->uctx, (void(*)(void)) fiber_start, +#ifdef USE_VALGRIND + /* avoding the valgrind's warning */ + fiber->vid = VALGRIND_STACK_REGISTER(fiber->context->uc_stack.ss_sp, + fiber->context.uc_stack.ss_sp + + fiber->init_context.uc_stack.ss_size); +#endif + makecontext(fiber->context, (void(*)(void)) fiber_start, 2, carg.i[0], carg.i[1]); return fiber; } -ACL_FIBER *acl_fiber_create(void (*fn)(ACL_FIBER *, void *), void *arg, size_t size) +ACL_FIBER *acl_fiber_create(void (*fn)(ACL_FIBER *, void *), + void *arg, size_t size) { ACL_FIBER *fiber = fiber_alloc(fn, arg, size); @@ -402,15 +494,17 @@ void acl_fiber_schedule(void) __thread_fiber->running = fiber; __thread_fiber->switched++; - fiber_swap(&__thread_fiber->schedule, fiber); + fiber_swap(&__thread_fiber->original, fiber); __thread_fiber->running = NULL; } /* release dead fiber */ while ((head = acl_ring_pop_head(&__thread_fiber->dead)) != NULL) { fiber = ACL_RING_TO_APPL(head, ACL_FIBER, me); - fiber_free(__thread_fiber, fiber); + fiber_free(fiber); } + + acl_fiber_hook_api(0); } void fiber_system(void) @@ -455,7 +549,7 @@ void acl_fiber_switch(void) head = acl_ring_pop_head(&__thread_fiber->ready); if (head == NULL) { - fiber_swap(current, &__thread_fiber->schedule); + fiber_swap(current, &__thread_fiber->original); return; } diff --git a/lib_fiber/c/src/fiber.h b/lib_fiber/c/src/fiber.h index ef864d949..1965d661b 100644 --- a/lib_fiber/c/src/fiber.h +++ b/lib_fiber/c/src/fiber.h @@ -2,6 +2,7 @@ #define FIBER_INCLUDE_H #include +#include #include "event.h" typedef enum { @@ -32,13 +33,15 @@ struct ACL_FIBER { FIBER_LOCAL **locals; int nlocal; - ucontext_t uctx; +#ifdef USE_JMP + jmp_buf jbuf; +#endif + ucontext_t *context; void (*fn)(ACL_FIBER *, void *); void *arg; - char *stack; - size_t size; void (*timer_fn)(ACL_FIBER *, void *); - char buf[1]; + size_t size; + char *buff; }; /* diff --git a/lib_fiber/c/src/hook_io.c b/lib_fiber/c/src/hook_io.c index bb443b6ee..f2d4fa5c3 100644 --- a/lib_fiber/c/src/hook_io.c +++ b/lib_fiber/c/src/hook_io.c @@ -233,7 +233,6 @@ ssize_t read(int fd, void *buf, size_t count) event_clear_readable(ev, fd); ret = __sys_read(fd, buf, count); - //printf("---read ret: %ld----\r\n", ret); if (ret > 0) return ret; diff --git a/lib_fiber/changes.txt b/lib_fiber/changes.txt index be791f8bc..9a31467f5 100644 --- a/lib_fiber/changes.txt +++ b/lib_fiber/changes.txt @@ -1,3 +1,9 @@ +19) 2016.8.10 +19.1) performance&feature: 鍏佽浣跨敤 setjmp/longjmp 杩涜鏍堢殑璺宠浆锛屾ц兘鏇村ソ + +18) 2016.8.7 +18.1) feature: fiber.c 涓湪 acl_fiber_schedule 缁撴潫鍓嶈嚜鍔ㄥ皢 acl_var_hook_sys_api +缃 0锛屼粠鑰屾仮澶嶇郴缁 API 璋冪敤杩囩▼ 17) 2016.8.5 17.1) feature: hook_io.c 涓鍔犵郴缁 API sleep 鐨 hook 鍑芥暟 diff --git a/lib_fiber/cxx/Makefile b/lib_fiber/cxx/Makefile new file mode 100644 index 000000000..76eed87fc --- /dev/null +++ b/lib_fiber/cxx/Makefile @@ -0,0 +1,202 @@ +SHELL = /bin/sh +#CC = g++ +CC = ${ENV_CPP} +AR = ${ENV_AR} +ARFL = rv +#ARFL = cru +RANLIB = ${ENV_RANLIB} + +FLAGS = ${ENV_FLAGS} + +CFLAGS = -c -g -W \ +-O3 \ +-Wall \ +-Wpointer-arith \ +-Wshadow \ +-D_REENTRANT \ +-D_POSIX_PTHREAD_SEMANTICS \ +-Wno-long-long \ +-Wformat \ +-Winvalid-pch \ +-DACL_PREPARE_COMPILE +#-DUSE_DYNAMIC +# -Wcast-align +#-Wcast-qual +#just for freebsd's iconv.h +CFLAGS += -I/usr/local/include + +shared_ldflags = -l_acl_cpp -l_protocol -l_acl -lz -lpthread + +########################################################### +#Check system: +# Linux, SunOS, Solaris, BSD variants, AIX, HP-UX +SYSLIB = +CHECKSYSRES = @echo "Unknow system type!";exit 1 +UNIXNAME = $(shell uname -sm) +UNIXTYPE = LINUX + +ifeq ($(CC),) + CC = g++ +endif + +ifeq ($(AR),) + AR = ar +endif + +ifeq ($(RANLIB),) + RANLIB = ranlib +endif + +ifeq ($(findstring clang++, $(CC)), clang++) + CFLAGS += -Wno-invalid-source-encoding \ + -Wno-extended-offsetof +endif + +# For FreeBSD +ifeq ($(findstring FreeBSD, $(UNIXNAME)), FreeBSD) + CFLAGS += -DFREEBSD -fPIC -Werror + UNIXTYPE = FREEBSD + shared_ldflags = -l_acl_cpp -l_protocol -l_acl -L/usr/local/lib -liconv -lz -lpthread +endif + +# For Darwin +ifeq ($(findstring Darwin, $(UNIXNAME)), Darwin) + CFLAGS += -DMACOSX -Wno-invalid-source-encoding \ + -Wno-extended-offsetof -fPIC -Werror \ + -Wno-unused-private-field + UNIXTYPE = MACOSX + shared_ldflags = -l_acl_cpp -l_protocol -l_acl -L/usr/lib -liconv -lz -lpthread +endif + +# For Linux +ifeq ($(findstring Linux, $(UNIXNAME)), Linux) + CFLAGS += -DLINUX2 -fPIC -Werror + UNIXTYPE = LINUX + shared_ldflags = -l_acl_cpp -l_protocol -l_acl -lrt -lpthread -lz -ldl +endif + +# For MINGW +ifeq ($(findstring MINGW, $(UNIXNAME)), MINGW) + CFLAGS += -DLINUX2 -DMINGW + UNIXTYPE = LINUX +endif + +# For SunOS +ifeq ($(findstring SunOS, $(UNIXNAME)), SunOS) + ifeq ($(findstring 86, $(UNIXNAME)), 86) + SYSLIB = -lsocket -lnsl -lrt + endif + ifeq ($(findstring sun4u, $(UNIXNAME)), sun4u) + SYSLIB = -lsocket -lnsl -lrt + endif + CFLAGS += -DSUNOS5 -fPIC -Werror + UNIXTYPE = SUNOS5 +endif + +# For HP-UX +ifeq ($(findstring HP-UX, $(UNIXNAME)), HP-UX) + CFLAGS += -DHP_UX -DHPUX11 -fPIC -Werror + UNIXTYPE = HPUX +endif + +#Find system type. +ifneq ($(SYSPATH),) + CHECKSYSRES = @echo "System is $(shell uname -sm)" +endif +########################################################### + +OBJ_PATH_DST = ./debug +LIB_PATH_DST = ../lib +DEF_PATH_DST = ./debug + +CFLAGS += -I./src -I../c/include -I./include -I../../lib_acl/include -I../../lib_acl_cpp/include + +#Project's objs + +OBJS_DST = $(patsubst %.cpp, $(OBJ_PATH_DST)/%.o, $(notdir $(wildcard src/*.cpp))) +OBJS_DEF = $(patsubst %.cpp, $(DEF_PATH_DST)/%.inc, $(notdir $(wildcard src/*.cpp))) + +########################################################### +.PHONY = static shared clean +VERSION = 0.9 +DATE_NOW = 20`date +%y`.`date +%m`.`date +%d` + +STATIC_LIBNAME = lib_fiber_cpp.a +SHARED_LIBNAME = lib_fiber_cpp.so +PCH = ./acl_stdafx.hpp.gch + +lib: static +all: static shared sample + +$(shell mkdir -p $(DEF_PATH_DST)) +ifneq ($(MAKECMDGOALS),clean) +-include $(OBJS_DEF) +endif + +COMPILE = $(CC) $(CFLAGS) +COMPILE_OBJ = @(echo 'building $<'; $(COMPILE) $< -o $@) +CREATE_DEF = @(echo 'creating $@'; rm -f $@; \ + $(COMPILE) -MM $< > $@.$$$$; \ + sed 's,.*.o\( \)*:,$(patsubst %.inc,%.o,$@) $@ :,g' < $@.$$$$ > $@; \ + rm -f $@.$$$$) + +########################################################### + +sample: static + @(cd samples; make) + +static: depends $(OBJS_DST) + @echo 'creating $(LIB_PATH_DST)/$(STATIC_LIBNAME)' + @$(AR) $(ARFL) $(LIB_PATH_DST)/$(STATIC_LIBNAME) $(OBJS_DST) + @$(RANLIB) $(LIB_PATH_DST)/$(STATIC_LIBNAME) + @echo 'create $(LIB_PATH_DST)/$(STATIC_LIBNAME) ok!' + +shared: depends pch $(OBJS_DST) + @echo 'creating $(SHARED_LIBNAME)' + @if test -n "$(rpath)" && test "$(UNIXTYPE)" = "LINUX"; then \ + echo "building for linux"; \ + $(CC) -shared -o $(rpath)/$(SHARED_LIBNAME) $(OBJS_DST) \ + -L$(rpath) $(shared_ldflags) -Wl,-rpath,$(rpath); \ + echo 'build $(rpath)/$(SHARED_LIBNAME) ok!'; \ + elif test -n "$(rpath)" && test "$(UNIXTYPE)" = "SUNOS5"; then \ + echo "building for sunos5"; \ + $(CC) -shared -o $(rpath)/$(SHARED_LIBNAME) $(OBJS_DST) \ + -R$(rpath) -L$(rpath) $(shared_ldflags); \ + echo 'build $(rpath)/$(SHARED_LIBNAME) ok!'; \ + elif test -n "$(rpath)" && test "$(UNIXTYPE)" = "MACOSX"; then \ + echo "building for Darwin"; \ + $(CC) -shared -o $(rpath)/$(SHARED_LIBNAME) $(OBJS_DST) \ + -R$(rpath) -L$(rpath) $(shared_ldflags); \ + echo 'build $(rpath)/$(SHARED_LIBNAME) ok!'; \ + elif test -n "$(rpath)" && test "$(UNIXTYPE)" = "FREEBSD"; then \ + echo "building for Darwin"; \ + $(CC) -shared -o $(rpath)/$(SHARED_LIBNAME) $(OBJS_DST) \ + -R$(rpath) -L$(rpath) $(shared_ldflags); \ + echo 'build $(rpath)/$(SHARED_LIBNAME) ok!'; \ + else \ + echo 'skip build $(SHARED_LIBNAME); usage: make shared rpath=xxx'; \ + fi + +depends: $(OBJS_DEF) +pch: ./acl_stdafx.hpp + rm -f $(PCH) + @if test "$(UNIXTYPE)" = "LINUX" || test "$(UNIXTYPE)" = "FREEBSD" \ + || test "$(UNIXTYPE)" = "MACOSX"; then \ + $(CC) -o $(PCH) -x c++-header $(CFLAGS) src/acl_stdafx.hpp; \ + fi + +# src +$(OBJ_PATH_DST)/%.o: ./src/%.cpp + $(COMPILE_OBJ) + +$(DEF_PATH_DST)/%.inc: ./src/%.cpp + $(CREATE_DEF) + +clean: + rm -f $(LIB_PATH_DST)/lib_fiber_cpp.a + rm -f $(LIB_PATH_DST)/lib_fiber_cpp.so + rm -f $(OBJS_DST) + rm -f $(OBJS_DEF) + rm -f $(PCH) + +rebuild rb: clean static diff --git a/lib_fiber/cxx/README.md b/lib_fiber/cxx/README.md new file mode 100644 index 000000000..472a636c6 --- /dev/null +++ b/lib_fiber/cxx/README.md @@ -0,0 +1 @@ +using c++1x diff --git a/lib_fiber/cxx/debug/keep b/lib_fiber/cxx/debug/keep new file mode 100644 index 000000000..b0e2aa073 --- /dev/null +++ b/lib_fiber/cxx/debug/keep @@ -0,0 +1 @@ +keepme diff --git a/lib_fiber/cxx/include/keep b/lib_fiber/cxx/include/keep new file mode 100644 index 000000000..b0e2aa073 --- /dev/null +++ b/lib_fiber/cxx/include/keep @@ -0,0 +1 @@ +keepme diff --git a/lib_fiber/cxx/keep b/lib_fiber/cxx/keep new file mode 100644 index 000000000..b0e2aa073 --- /dev/null +++ b/lib_fiber/cxx/keep @@ -0,0 +1 @@ +keepme diff --git a/lib_fiber/cxx/src/keep b/lib_fiber/cxx/src/keep new file mode 100644 index 000000000..b0e2aa073 --- /dev/null +++ b/lib_fiber/cxx/src/keep @@ -0,0 +1 @@ +keepme diff --git a/lib_fiber/samples/dns/main.c b/lib_fiber/samples/dns/main.c index 62e5ed2bb..2a7109539 100644 --- a/lib_fiber/samples/dns/main.c +++ b/lib_fiber/samples/dns/main.c @@ -92,7 +92,7 @@ int main(int argc, char *argv[]) acl_foreach(iter, tokens) { char* addr = (char* ) iter.data; - acl_fiber_create(nslookup, addr, 8192); + acl_fiber_create(nslookup, addr, 32000); } acl_fiber_schedule(); diff --git a/lib_fiber/samples/fiber/main.c b/lib_fiber/samples/fiber/main.c index bb36e04c9..b9f1a14f4 100644 --- a/lib_fiber/samples/fiber/main.c +++ b/lib_fiber/samples/fiber/main.c @@ -8,17 +8,31 @@ static int __max_loop = 1000; static int __max_fiber = 1000; +static int __display = 0; static __thread struct timeval __begin; static __thread int __left_fiber = 1000; +static void stack_dummy(ACL_FIBER *fiber acl_unused) +{ + char buf[81920]; + + memset(buf, 0, sizeof(buf)); +} + static void fiber_main(ACL_FIBER *fiber, void *ctx acl_unused) { int i; + if (0) + stack_dummy(fiber); + errno = acl_fiber_errno(fiber); for (i = 0; i < __max_loop; i++) { acl_fiber_yield(); + if (!__display) + continue; + if (i <= 2) printf("fiber-%d, errno: %d\r\n", acl_fiber_id(fiber), errno); @@ -55,7 +69,7 @@ static void *thread_main(void *ctx acl_unused) static void usage(const char *procname) { - printf("usage: %s -h [help] -n max_loop -c max_fiber -t max_threads\r\n", procname); + printf("usage: %s -h [help] -n max_loop -c max_fiber -t max_threads -e [if display]\r\n", procname); } int main(int argc, char *argv[]) @@ -64,7 +78,7 @@ int main(int argc, char *argv[]) acl_pthread_attr_t attr; acl_pthread_t *tids; - while ((ch = getopt(argc, argv, "hn:c:t:")) > 0) { + while ((ch = getopt(argc, argv, "hn:c:t:e")) > 0) { switch (ch) { case 'h': usage(argv[0]); @@ -80,6 +94,9 @@ int main(int argc, char *argv[]) if (nthreads <= 0) nthreads = 1; break; + case 'e': + __display = 1; + break; default: break; } diff --git a/lib_fiber/samples/https_server/main.cpp b/lib_fiber/samples/https_server/main.cpp index bad0c8410..614f68345 100644 --- a/lib_fiber/samples/https_server/main.cpp +++ b/lib_fiber/samples/https_server/main.cpp @@ -25,6 +25,8 @@ static void http_server(ACL_FIBER *, void *ctx) delete conn; return; } + +#if 0 if (ssl->handshake() == false) { printf("ssl handshake error\r\n"); @@ -34,11 +36,14 @@ static void http_server(ACL_FIBER *, void *ctx) } if (ssl->handshake_ok() == false) { - printf("ssl handshake_ok error\r\n"); + printf("ssl handshake error\r\n"); ssl->destroy(); delete conn; return; } +#endif + + printf("ssl handshake_ok\r\n"); acl::memcache_session session("127.0.0.1:11211"); http_servlet servlet(conn, &session); diff --git a/lib_fiber/samples/ping/benchmark.sh b/lib_fiber/samples/ping/benchmark.sh new file mode 100644 index 000000000..755bb6f57 --- /dev/null +++ b/lib_fiber/samples/ping/benchmark.sh @@ -0,0 +1,74 @@ +#!/bin/sh + + +./ping -d 0 -n 100 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ +127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 127.0.0.1 \ diff --git a/lib_fiber/samples/ping/main.c b/lib_fiber/samples/ping/main.c index 99fa2ad9a..f8b2b2e93 100644 --- a/lib_fiber/samples/ping/main.c +++ b/lib_fiber/samples/ping/main.c @@ -5,6 +5,8 @@ static int __nfibers = 0; static int __npkt = 10; +static int __delay_seconds = 1; /* 发送 ping 包的时间间隔(秒)*/ +static int __benchmark = 0; static void display_res(ICMP_CHAT *chat) { @@ -21,7 +23,6 @@ static void fiber_ping(ACL_FIBER *fiber acl_unused, void *arg) const char *dest = (const char *) arg; ACL_DNS_DB* dns_db; const char *ip; - int delay = 1; /* 发送 ping 包的时间间隔(秒)*/ ICMP_CHAT *chat; /* 通过域名解析出IP地址 */ @@ -44,9 +45,9 @@ static void fiber_ping(ACL_FIBER *fiber acl_unused, void *arg) /* 开始 PING */ if (strcmp(dest, ip) == 0) - icmp_ping_one(chat, NULL, ip, __npkt, delay, 1); + icmp_ping_one(chat, NULL, ip, __npkt, __delay_seconds, 1); else - icmp_ping_one(chat, dest, ip, __npkt, delay, 1); + icmp_ping_one(chat, dest, ip, __npkt, __delay_seconds, 1); acl_netdb_free(dns_db); /* 释放域名解析对象 */ display_res(chat); /* 显示 PING 结果 */ @@ -58,8 +59,12 @@ static void fiber_ping(ACL_FIBER *fiber acl_unused, void *arg) static void usage(const char* progname) { - printf("usage: %s [-h help] [-n npkt] [\"dest1 dest2 dest3...\"]\r\n", - progname); + printf("usage: %s -h help\r\n" + " -d delay\r\n" + " -z stack_size\r\n" + " -b benchmark [if > 0 dest will be ignored]\r\n" + " -n npkt dest1 dest2...\r\n", progname); + printf("example: %s -n 10 www.sina.com.cn www.qq.com\r\n", progname); } @@ -72,12 +77,12 @@ static void on_sigint(int signo acl_unused) int main(int argc, char* argv[]) { char ch; - int i; + int i, stack_size = 16000; signal(SIGINT, on_sigint); /* 用户按下 ctr + c 时中断 PING 程序 */ acl_msg_stdout_enable(1); /* 允许 acl_msg_xxx 记录的信息输出至屏幕 */ - while ((ch = getopt(argc, argv, "hn:")) > 0) { + while ((ch = getopt(argc, argv, "hn:d:z:b:")) > 0) { switch (ch) { case 'n': __npkt = atoi(optarg); @@ -85,24 +90,42 @@ int main(int argc, char* argv[]) case 'h': usage(argv[0]); return 0; + case 'z': + stack_size = atoi(optarg); + break; + case 'd': + __delay_seconds = atoi(optarg); + break; + case 'b': + __benchmark = atoi(optarg); + break; default: break; } } - if (optind == argc) { - usage(argv[0]); - return 0; - } - if (__npkt <= 0) __npkt = 10; - /* 记录要启动的协程的总数 */ - __nfibers = argc - optind; + if (__benchmark > 0) { + static char *localhost = "127.0.0.1"; - for (i = optind; i < argc; i++) - acl_fiber_create(fiber_ping, argv[i], 32000); + __nfibers = __benchmark; + + for (i = 0; i < __benchmark; i++) + acl_fiber_create(fiber_ping, localhost, stack_size); + } else { + if (optind == argc) { + usage(argv[0]); + return 0; + } + + /* 记录要启动的协程的总数 */ + __nfibers = argc - optind; + + for (i = optind; i < argc; i++) + acl_fiber_create(fiber_ping, argv[i], stack_size); + } acl_fiber_schedule(); diff --git a/lib_fiber/samples/ssl_client/Makefile b/lib_fiber/samples/ssl_client/Makefile new file mode 100644 index 000000000..326649e37 --- /dev/null +++ b/lib_fiber/samples/ssl_client/Makefile @@ -0,0 +1,3 @@ +include ../Makefile_cpp.in +EXTLIBS = -L../../../lib/linux64 -lpolarssl +PROG = client diff --git a/lib_fiber/samples/ssl_client/main.cpp b/lib_fiber/samples/ssl_client/main.cpp new file mode 100644 index 000000000..9777f8222 --- /dev/null +++ b/lib_fiber/samples/ssl_client/main.cpp @@ -0,0 +1,198 @@ +#include "stdafx.h" +#include +#include +#include "stamp.h" + +#define STACK_SIZE 32000 + +static int __rw_timeout = 0; +static int __conn_timeout = 0; +static int __max_fibers = 100; +static int __left_fibers = 100; +static int __max_loop = 100; +static struct timeval __begin; + +static acl::polarssl_conf *__ssl_conf = NULL; +static bool __check_ssl = false; + +static long long int __total_count = 0; +static int __total_clients = 0; +static int __total_error_clients = 0; + +static bool ssl_init(acl::socket_stream& conn) +{ + assert(__ssl_conf); + + acl::polarssl_io* ssl = new acl::polarssl_io(*__ssl_conf, false); + + if (conn.setup_hook(ssl) == ssl) + { + printf("setup_hook error\r\n"); + ssl->destroy(); + return false; + } + + if (!__check_ssl) + { + printf("ssl handshake_ok\r\n"); + return true; + } + + if (ssl->handshake() == false) + { + printf("ssl handshake error\r\n"); + ssl->destroy(); + return false; + } + if (ssl->handshake_ok() == false) + { + printf("ssl handshake error\r\n"); + ssl->destroy(); + return false; + } + + printf("ssl handshake_ok\r\n"); + return true; +} + +static void run(const char* addr) +{ + acl::socket_stream conn; + + if (conn.open(addr, __conn_timeout, __rw_timeout) == false) + { + printf("connect %s error %s\r\n", addr, acl::last_serror()); + __total_error_clients++; + return; + } + + if (__ssl_conf != NULL && ssl_init(conn) == false) + return; + + __total_clients++; + printf("fiber-%d: connect %s ok, clients: %d, fd: %d\r\n", + acl_fiber_self(), addr, __total_clients, conn.sock_handle()); + + acl::string buf; + const char req[] = "hello world\r\n"; + + for (int i = 0; i < __max_loop; i++) + { + if (conn.write(req, sizeof(req) - 1) == -1) + { + printf("write error: %s\r\n", acl::last_serror()); + break; + } + + if (conn.gets(buf, false) == false) + { + printf("gets error: %s\r\n", acl::last_serror()); + break; + } + buf.clear(); + __total_count++; + } + + printf("close one connection: %d, %s\r\n", + conn.sock_handle(), acl::last_serror()); +} + +static void fiber_connect(ACL_FIBER *fiber acl_unused, void *ctx) +{ + const char *addr = (const char *) ctx; + + run(addr); + + --__left_fibers; + printf("max_fibers: %d, left: %d\r\n", __max_fibers, __left_fibers); + + if (__left_fibers == 0) { + double spent; + struct timeval end; + + gettimeofday(&end, NULL); + spent = stamp_sub(&end, &__begin); + + printf("fibers: %d, clients: %d, error: %d, count: %lld, " + "spent: %.2f, speed: %.2f\r\n", __max_fibers, + __total_clients, __total_error_clients, + __total_count, spent, + (__total_count * 1000) / (spent > 0 ? spent : 1)); + + acl_fiber_stop(); + } +} + +static void fiber_main(ACL_FIBER *fiber acl_unused, void *ctx) +{ + char *addr = (char *) ctx; + int i; + + for (i = 0; i < __max_fibers; i++) + { + acl_fiber_create(fiber_connect, addr, 32768); + //acl_fiber_sleep(1); + } +} + +static void usage(const char* procname) +{ + printf("usage: %s -h [help]\r\n" + " -s listen_addr\r\n" + " -r rw_timeout\r\n" + " -c max_fibers\r\n" + " -C [if check ssl status]\r\n" + " -n max_loop\r\n", procname); +} + +int main(int argc, char *argv[]) +{ + acl::string addr("127.0.0.1:9001"); + bool use_ssl = true; + int ch; + + while ((ch = getopt(argc, argv, "hs:r:Pc:n:C")) > 0) + { + switch (ch) + { + case 'h': + usage(argv[0]); + return 0; + case 's': + addr = optarg; + break; + case 'r': + __rw_timeout = atoi(optarg); + break; + case 'P': + use_ssl = false; + break; + case 'c': + __max_fibers = atoi(optarg); + break; + case 'n': + __max_loop = atoi(optarg); + break; + case 'C': + __check_ssl = true; + break; + default: + break; + } + } + + acl::acl_cpp_init(); + acl::log::stdout_open(true); + + if (use_ssl) + __ssl_conf = new acl::polarssl_conf; + + gettimeofday(&__begin, NULL); + acl_fiber_create(fiber_main, addr.c_str(), 32768); + + acl_fiber_schedule(); + + delete __ssl_conf; + + return 0; +} diff --git a/lib_fiber/samples/ssl_client/stdafx.cpp b/lib_fiber/samples/ssl_client/stdafx.cpp new file mode 100644 index 000000000..f01a2ff42 --- /dev/null +++ b/lib_fiber/samples/ssl_client/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : 只包括标准包含文件的源文件 +// master_threads.pch 将成为预编译头 +// stdafx.obj 将包含预编译类型信息 + +#include "stdafx.h" + +// TODO: 在 STDAFX.H 中 +//引用任何所需的附加头文件,而不是在此文件中引用 diff --git a/lib_fiber/samples/ssl_client/stdafx.h b/lib_fiber/samples/ssl_client/stdafx.h new file mode 100644 index 000000000..ab94a5314 --- /dev/null +++ b/lib_fiber/samples/ssl_client/stdafx.h @@ -0,0 +1,20 @@ +// stdafx.h : 标准系统包含文件的包含文件, +// 或是常用但不常更改的项目特定的包含文件 +// + +#pragma once + + +//#include +//#include + +// TODO: 在此处引用程序要求的附加头文件 + +#include "lib_acl.h" +#include "fiber/lib_fiber.h" +#include "acl_cpp/lib_acl.hpp" + +#ifdef WIN32 +#define snprintf _snprintf +#endif + diff --git a/lib_fiber/samples/ssl_server/Makefile b/lib_fiber/samples/ssl_server/Makefile new file mode 100644 index 000000000..aaaeed361 --- /dev/null +++ b/lib_fiber/samples/ssl_server/Makefile @@ -0,0 +1,3 @@ +include ../Makefile_cpp.in +EXTLIBS = -L../../../lib/linux64 -lpolarssl +PROG = server diff --git a/lib_fiber/samples/ssl_server/main.cpp b/lib_fiber/samples/ssl_server/main.cpp new file mode 100644 index 000000000..f08e35e3d --- /dev/null +++ b/lib_fiber/samples/ssl_server/main.cpp @@ -0,0 +1,185 @@ +#include "stdafx.h" +#include +#include + +#define STACK_SIZE 32000 + +static int __rw_timeout = 0; +static acl::string __ssl_crt("../ssl_crt.pem"); +static acl::string __ssl_key("../ssl_key.pem"); +static acl::polarssl_conf *__ssl_conf = NULL; +static bool __check_ssl = false; + +static void http_server(ACL_FIBER *, void *ctx) +{ + acl::socket_stream *conn = (acl::socket_stream *) ctx; + + printf("start one server\r\n"); + + if (__ssl_conf != NULL) + { + acl::polarssl_io* ssl = + new acl::polarssl_io(*__ssl_conf, true, false); + + if (conn->setup_hook(ssl) == ssl) + { + printf("setup_hook error\r\n"); + ssl->destroy(); + delete conn; + return; + } + + if (__check_ssl) + { + if (ssl->handshake() == false) + { + printf("ssl handshake error\r\n"); + ssl->destroy(); + delete conn; + return; + } + if (ssl->handshake_ok() == false) + { + printf("ssl handshake error\r\n"); + ssl->destroy(); + delete conn; + return; + } + } + } + + printf("ssl handshake_ok\r\n"); + + acl::string buf; + + while (true) + { + if (conn->gets(buf, false) == false) + { + printf("gets error: %s\r\n", acl::last_serror()); + break; + } + + if (conn->write(buf) == -1) + { + printf("write error: %s\r\n", acl::last_serror()); + break; + } + } + + printf("close one connection: %d, %s\r\n", conn->sock_handle(), + acl::last_serror()); + delete conn; +} + +static acl::polarssl_conf* ssl_init(const acl::string& crt, + const acl::string& key) +{ + + acl::polarssl_conf* conf = new acl::polarssl_conf; + conf->enable_cache(1); + + if (conf->add_cert(crt) == false) + { + printf("load %s error\r\n", crt.c_str()); + delete conf; + return NULL; + } + + if (conf->set_key(key) == false) + { + printf("set_key %s error\r\n", key.c_str()); + delete conf; + return NULL; + } + + printf(">>> ssl_init ok, ssl_crt: %s, ssl_key: %s\r\n", + crt.c_str(), key.c_str()); + + return conf; +} + +static void fiber_accept(ACL_FIBER *, void *ctx) +{ + const char* addr = (const char* ) ctx; + acl::server_socket server; + + __ssl_conf = ssl_init(__ssl_crt, __ssl_key); + + if (server.open(addr) == false) + { + printf("open %s error\r\n", addr); + exit (1); + } + else + printf(">>> listen %s ok\r\n", addr); + + while (true) + { + acl::socket_stream* client = server.accept(); + if (client == NULL) + { + printf("accept failed: %s\r\n", acl::last_serror()); + break; + } + + client->set_rw_timeout(__rw_timeout); + printf("accept one: %d\r\n", client->sock_handle()); + acl_fiber_create(http_server, client, STACK_SIZE); + } + + delete __ssl_conf; + exit (0); +} + +static void usage(const char* procname) +{ + printf("usage: %s -h [help]\r\n" + " -s listen_addr\r\n" + " -r rw_timeout\r\n" + " -c ssl_crt.pem\r\n" + " -C [if check ssl status]\r\n" + " -k ssl_key.pem\r\n", procname); +} + +int main(int argc, char *argv[]) +{ + acl::string addr(":9001"); + int ch; + + while ((ch = getopt(argc, argv, "hs:r:c:k:C")) > 0) + { + switch (ch) + { + case 'h': + usage(argv[0]); + return 0; + case 's': + addr = optarg; + break; + case 'r': + __rw_timeout = atoi(optarg); + break; + case 'c': + __ssl_crt = optarg; + break; + case 'k': + __ssl_key = optarg; + break; + case 'C': + __check_ssl = true; + break; + default: + break; + } + } + + acl::acl_cpp_init(); + acl::log::stdout_open(true); + + acl_fiber_create(fiber_accept, addr.c_str(), STACK_SIZE); + + acl_fiber_schedule(); + + return 0; +} diff --git a/lib_fiber/samples/ssl_server/stdafx.cpp b/lib_fiber/samples/ssl_server/stdafx.cpp new file mode 100644 index 000000000..f01a2ff42 --- /dev/null +++ b/lib_fiber/samples/ssl_server/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : 只包括标准包含文件的源文件 +// master_threads.pch 将成为预编译头 +// stdafx.obj 将包含预编译类型信息 + +#include "stdafx.h" + +// TODO: 在 STDAFX.H 中 +//引用任何所需的附加头文件,而不是在此文件中引用 diff --git a/lib_fiber/samples/ssl_server/stdafx.h b/lib_fiber/samples/ssl_server/stdafx.h new file mode 100644 index 000000000..ab94a5314 --- /dev/null +++ b/lib_fiber/samples/ssl_server/stdafx.h @@ -0,0 +1,20 @@ +// stdafx.h : 标准系统包含文件的包含文件, +// 或是常用但不常更改的项目特定的包含文件 +// + +#pragma once + + +//#include +//#include + +// TODO: 在此处引用程序要求的附加头文件 + +#include "lib_acl.h" +#include "fiber/lib_fiber.h" +#include "acl_cpp/lib_acl.hpp" + +#ifdef WIN32 +#define snprintf _snprintf +#endif + diff --git a/lib_fiber/todo.txt b/lib_fiber/todo.txt index 8f42c0c8b..8585f0f88 100644 --- a/lib_fiber/todo.txt +++ b/lib_fiber/todo.txt @@ -1,5 +1,6 @@ 1) 增加针对协程调度器的监控机制 2) 增加更方便的协程异步调用接口 -3) 支持信号跳转方式 +3) 支持信号跳转方式 --- ok 4) 支持 read 读缓冲 +5) 支持栈空间的自动扩充及共享堆栈