From ecc0992eb11b48fe6bc5f9b0e218cb4204fef830 Mon Sep 17 00:00:00 2001 From: zsxxsz Date: Wed, 26 Feb 2014 22:57:09 +0800 Subject: [PATCH] =?UTF-8?q?=E6=80=A7=E8=83=BD=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib_acl/changes.txt | 12 ++ lib_acl/src/event/events.h | 2 + lib_acl/src/event/events_epoll_thr.c | 119 ++++++++++++++++-- .../src/master/template/acl_threads_server.c | 2 +- .../acl_cpp/master/master_threads2.hpp | 2 +- lib_acl_cpp/src/master/master_threads2.cpp | 3 +- 6 files changed, 124 insertions(+), 16 deletions(-) diff --git a/lib_acl/changes.txt b/lib_acl/changes.txt index 6a7c54742..b7f9d11fe 100644 --- a/lib_acl/changes.txt +++ b/lib_acl/changes.txt @@ -1,6 +1,18 @@ 修改历史列表: ------------------------------------------------------------------------ +430) 2014.2.26 +430.1) performance: events.h 将自旋锁的方式关闭,否则在32位机器上会造成 CPU +过高 + +429) 2014.2.24 +429.1) bugfix: events_epoll_thr.c 当流对象有缓存数据需要事件引擎从应用级触发时, +为了防止主线程在子线程的函数 event_enable_read 中修改 fdtabs 和调用 +epoll_ctl/EPOLL_CTL_ADD 之间调用了 event_disable_readwrite 中的 +epoll_ctl/EPOLL_CTL_DEL 而出错,需要在 event_enable_read 区分处理互斥锁的位置 + +------------------------------------------------------------------------ + 428) 2014.2.22 428.1) bugfix: events_iocp.c 关闭未决状态的完成端口在 WIN XP 下存在 BUG,应该 在套接字关闭前先取得完成端口状态 diff --git a/lib_acl/src/event/events.h b/lib_acl/src/event/events.h index 4b994a975..68ae46024 100644 --- a/lib_acl/src/event/events.h +++ b/lib_acl/src/event/events.h @@ -155,9 +155,11 @@ struct ACL_EVENT { }; /* 如果采用自旋锁,必须保持加锁时间非常短 */ +/* #ifdef ACL_HAS_SPINLOCK #define EVENT_USE_SPINLOCK #endif +*/ typedef struct EVENT_THR { ACL_EVENT event; diff --git a/lib_acl/src/event/events_epoll_thr.c b/lib_acl/src/event/events_epoll_thr.c index e8a9b8da1..96f9a6752 100644 --- a/lib_acl/src/event/events_epoll_thr.c +++ b/lib_acl/src/event/events_epoll_thr.c @@ -50,6 +50,14 @@ static void event_enable_read(ACL_EVENT *eventp, ACL_VSTREAM *stream, ACL_EVENT_FDTABLE *fdp; ACL_SOCKET sockfd; struct epoll_event ev; + int fd_ready; + + if (ACL_VSTREAM_BFRD_CNT(stream) > 0 + || (stream->flag & ACL_VSTREAM_FLAG_BAD)) + { + fd_ready = 1; + } else + fd_ready = 0; sockfd = ACL_VSTREAM_SOCK(stream); fdp = (ACL_EVENT_FDTABLE*) stream->fdp; @@ -80,13 +88,20 @@ static void event_enable_read(ACL_EVENT *eventp, ACL_VSTREAM *stream, } if ((fdp->flag & EVENT_FDTABLE_FLAG_READ) != 0) + { + acl_msg_info("has set read"); return; + } stream->nrefer++; fdp->flag = EVENT_FDTABLE_FLAG_READ | EVENT_FDTABLE_FLAG_EXPT; memset(&ev, 0, sizeof(ev)); +#if 0 ev.events = EPOLLIN | EPOLLHUP | EPOLLERR | EPOLLET; +#else + ev.events = EPOLLIN | EPOLLHUP | EPOLLERR; +#endif ev.data.ptr = fdp; THREAD_LOCK(&event_thr->event.tb_mutex); @@ -94,11 +109,39 @@ static void event_enable_read(ACL_EVENT *eventp, ACL_VSTREAM *stream, fdp->fdidx = eventp->fdcnt; eventp->fdtabs[eventp->fdcnt++] = fdp; - THREAD_UNLOCK(&event_thr->event.tb_mutex); + if (fd_ready) { + if (epoll_ctl(event_thr->handle, EPOLL_CTL_ADD, + sockfd, &ev) < 0) + { + if (errno == EEXIST) + acl_msg_warn("%s: epoll_ctl: %s, fd: %d", + myname, acl_last_serror(), sockfd); + else + acl_msg_fatal("%s: epoll_ctl: %s, fd: %d", + myname, acl_last_serror(), sockfd); + } - if (epoll_ctl(event_thr->handle, EPOLL_CTL_ADD, sockfd, &ev) < 0) - acl_msg_fatal("%s: epoll_ctl: %s, fd: %d", - myname, acl_last_serror(), sockfd); + THREAD_UNLOCK(&event_thr->event.tb_mutex); + + if (event_thr->event.blocked && event_thr->event.evdog + && event_dog_client(event_thr->event.evdog) != stream) + { + event_dog_notify(event_thr->event.evdog); + } + } else { + THREAD_UNLOCK(&event_thr->event.tb_mutex); + + if (epoll_ctl(event_thr->handle, EPOLL_CTL_ADD, + sockfd, &ev) < 0) + { + if (errno == EEXIST) + acl_msg_warn("%s: epoll_ctl: %s, fd: %d", + myname, acl_last_serror(), sockfd); + else + acl_msg_fatal("%s: epoll_ctl: %s, fd: %d", + myname, acl_last_serror(), sockfd); + } + } } static void event_enable_listen(ACL_EVENT *eventp, ACL_VSTREAM *stream, @@ -155,9 +198,14 @@ static void event_enable_listen(ACL_EVENT *eventp, ACL_VSTREAM *stream, THREAD_UNLOCK(&event_thr->event.tb_mutex); - if (epoll_ctl(event_thr->handle, EPOLL_CTL_ADD, sockfd, &ev) < 0) - acl_msg_fatal("%s: epool_ctl: %s, fd: %d", - myname, acl_last_serror(), sockfd); + if (epoll_ctl(event_thr->handle, EPOLL_CTL_ADD, sockfd, &ev) < 0) { + if (errno == EEXIST) + acl_msg_warn("%s: epool_ctl: %s, fd: %d", + myname, acl_last_serror(), sockfd); + else + acl_msg_fatal("%s: epool_ctl: %s, fd: %d", + myname, acl_last_serror(), sockfd); + } } static void event_enable_write(ACL_EVENT *eventp, ACL_VSTREAM *stream, @@ -168,6 +216,12 @@ static void event_enable_write(ACL_EVENT *eventp, ACL_VSTREAM *stream, ACL_EVENT_FDTABLE *fdp; ACL_SOCKET sockfd; struct epoll_event ev; + int fd_ready; + + if ((stream->flag & ACL_VSTREAM_FLAG_BAD)) + fd_ready = 1; + else + fd_ready = 0; sockfd = ACL_VSTREAM_SOCK(stream); fdp = (ACL_EVENT_FDTABLE*) stream->fdp; @@ -212,11 +266,33 @@ static void event_enable_write(ACL_EVENT *eventp, ACL_VSTREAM *stream, fdp->fdidx = eventp->fdcnt; eventp->fdtabs[eventp->fdcnt++] = fdp; - THREAD_UNLOCK(&event_thr->event.tb_mutex); + if (fd_ready) { + if (epoll_ctl(event_thr->handle, EPOLL_CTL_ADD, + sockfd, &ev) < 0) + { + if (errno == EEXIST) + acl_msg_warn("%s: epoll_ctl: %s, fd: %d", + myname, acl_last_serror(), sockfd); + else + acl_msg_fatal("%s: epoll_ctl: %s, fd: %d", + myname, acl_last_serror(), sockfd); + } - if (epoll_ctl(event_thr->handle, EPOLL_CTL_ADD, sockfd, &ev) < 0) - acl_msg_fatal("%s: epoll_ctl: %s, fd: %d", - myname, acl_last_serror(), sockfd); + THREAD_UNLOCK(&event_thr->event.tb_mutex); + } else { + THREAD_UNLOCK(&event_thr->event.tb_mutex); + + if (epoll_ctl(event_thr->handle, EPOLL_CTL_ADD, + sockfd, &ev) < 0) + { + if (errno == EEXIST) + acl_msg_warn("%s: epoll_ctl: %s, fd: %d", + myname, acl_last_serror(), sockfd); + else + acl_msg_fatal("%s: epoll_ctl: %s, fd: %d", + myname, acl_last_serror(), sockfd); + } + } } /* event_disable_readwrite - disable request for read or write events */ @@ -262,13 +338,22 @@ static void event_disable_readwrite(ACL_EVENT *eventp, ACL_VSTREAM *stream) if (fdp->flag & EVENT_FDTABLE_FLAG_READ) stream->nrefer--; + else + acl_msg_info("not set read"); + if (fdp->flag & EVENT_FDTABLE_FLAG_WRITE) stream->nrefer--; event_fdtable_reset(fdp); - if (epoll_ctl(event_thr->handle, EPOLL_CTL_DEL, sockfd, NULL) < 0) - acl_msg_fatal("%s: epoll_ctl: %s", myname, acl_last_serror()); + if (epoll_ctl(event_thr->handle, EPOLL_CTL_DEL, sockfd, NULL) < 0) { + if (errno == ENOENT) + acl_msg_warn("%s: epoll_ctl: %s, fd: %d", + myname, acl_last_serror(), sockfd); + else + acl_msg_fatal("%s: epoll_ctl: %s, fd: %d", + myname, acl_last_serror(), sockfd); + } } static int event_isrset(ACL_EVENT *eventp acl_unused, ACL_VSTREAM *stream) @@ -438,6 +523,13 @@ TAG_DONE: event_thr_fire(eventp); } +static void event_add_dog(ACL_EVENT *eventp) +{ + EVENT_EPOLL_THR *event_thr = (EVENT_EPOLL_THR*) eventp; + + event_thr->event.evdog = event_dog_create((ACL_EVENT*) event_thr, 1); +} + static void event_free(ACL_EVENT *eventp) { const char *myname = "event_free"; @@ -468,6 +560,7 @@ ACL_EVENT *event_epoll_alloc_thr(int fdsize acl_unused) event_thr->event.event.use_thread = 1; event_thr->event.event.loop_fn = event_loop; event_thr->event.event.free_fn = event_free; + event_thr->event.event.add_dog_fn = event_add_dog; event_thr->event.event.enable_read_fn = event_enable_read; event_thr->event.event.enable_write_fn = event_enable_write; event_thr->event.event.enable_listen_fn = event_enable_listen; diff --git a/lib_acl/src/master/template/acl_threads_server.c b/lib_acl/src/master/template/acl_threads_server.c index 529b7362e..3fac083e8 100644 --- a/lib_acl/src/master/template/acl_threads_server.c +++ b/lib_acl/src/master/template/acl_threads_server.c @@ -748,7 +748,7 @@ static ACL_EVENT *event_open(int event_mode, acl_pthread_pool_t *threads) acl_event_set_fire_hook(event, event_fire_begin, event_fire_end, threads); - if (acl_var_threads_check_inter > 0) + if (acl_var_threads_check_inter >= 0) acl_event_set_check_inter(event, acl_var_threads_check_inter); if (acl_var_threads_qlen_warn > 0) diff --git a/lib_acl_cpp/include/acl_cpp/master/master_threads2.hpp b/lib_acl_cpp/include/acl_cpp/master/master_threads2.hpp index 73d0ce2f8..c0df5bdb0 100644 --- a/lib_acl_cpp/include/acl_cpp/master/master_threads2.hpp +++ b/lib_acl_cpp/include/acl_cpp/master/master_threads2.hpp @@ -136,7 +136,7 @@ private: static void service_exit(void*); // 当线程创建后调用的回调函数 - static void thread_init(void*); + static int thread_init(void*); // 当线程退出前调用的回调函数 static void thread_exit(void*); diff --git a/lib_acl_cpp/src/master/master_threads2.cpp b/lib_acl_cpp/src/master/master_threads2.cpp index 5dde5adce..3f06348ab 100644 --- a/lib_acl_cpp/src/master/master_threads2.cpp +++ b/lib_acl_cpp/src/master/master_threads2.cpp @@ -258,10 +258,11 @@ void master_threads2::service_exit(void*) __mt->proc_on_exit(); } -void master_threads2::thread_init(void*) +int master_threads2::thread_init(void*) { acl_assert(__mt != NULL); __mt->thread_on_init(); + return 0; } void master_threads2::thread_exit(void*)