diff options
author | Dmitry Kozlov <xeb@mail.ru> | 2011-01-05 15:18:59 +0300 |
---|---|---|
committer | Dmitry Kozlov <xeb@mail.ru> | 2011-01-05 15:18:59 +0300 |
commit | f28cb1b0a926f1ea98700b7871537ad1793511fd (patch) | |
tree | baf35570bc6b38b6fab5b6524e8f19f58f71e57f /accel-pppd/triton/md.c | |
parent | 2fdf3586c13a72c36f9530084962e29d57dc0329 (diff) | |
download | accel-ppp-f28cb1b0a926f1ea98700b7871537ad1793511fd.tar.gz accel-ppp-f28cb1b0a926f1ea98700b7871537ad1793511fd.zip |
rename accel-pptp to accel-ppp
Diffstat (limited to 'accel-pppd/triton/md.c')
-rw-r--r-- | accel-pppd/triton/md.c | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/accel-pppd/triton/md.c b/accel-pppd/triton/md.c new file mode 100644 index 00000000..84073d05 --- /dev/null +++ b/accel-pppd/triton/md.c @@ -0,0 +1,216 @@ +#include <stdio.h> +#include <stdlib.h> +#include <sys/time.h> +#include <signal.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> + +#include "triton_p.h" + +#include "memdebug.h" + +extern int max_events; + +static int epoll_fd; +static struct epoll_event *epoll_events; + +static pthread_t md_thr; +static void *md_thread(void *arg); + +static mempool_t *md_pool; + +static pthread_mutex_t freed_list_lock = PTHREAD_MUTEX_INITIALIZER; +static LIST_HEAD(freed_list); +static LIST_HEAD(freed_list2); + +int md_init(void) +{ + epoll_fd = epoll_create(1); + if (epoll_fd < 0) { + perror("md:epoll_create"); + return -1; + } + + epoll_events = _malloc(max_events * sizeof(struct epoll_event)); + if (!epoll_events) { + fprintf(stderr,"md:cann't allocate memory\n"); + return -1; + } + + md_pool = mempool_create(sizeof(struct _triton_md_handler_t)); + + return 0; +} +void md_run(void) +{ + if (pthread_create(&md_thr, NULL, md_thread, NULL)) { + triton_log_error("md:pthread_create: %s", strerror(errno)); + _exit(-1); + } +} + +void md_terminate(void) +{ + pthread_cancel(md_thr); + pthread_join(md_thr, NULL); +} + +static void *md_thread(void *arg) +{ + int i,n,r; + struct _triton_md_handler_t *h; + sigset_t set; + + sigfillset(&set); + sigdelset(&set, SIGKILL); + sigdelset(&set, SIGSTOP); + pthread_sigmask(SIG_BLOCK, &set, NULL); + + while(1) { + n = epoll_wait(epoll_fd, epoll_events, max_events, -1); + if (n < 0) { + if (errno == EINTR) + continue; + triton_log_error("md:epoll_wait: %s\n", strerror(errno)); + _exit(-1); + } + + for(i = 0; i < n; i++) { + h = (struct _triton_md_handler_t *)epoll_events[i].data.ptr; + if (!h->ud) + continue; + spin_lock(&h->ctx->lock); + if (h->ud) { + h->trig_epoll_events |= epoll_events[i].events; + if (!h->pending) { + list_add_tail(&h->entry2, &h->ctx->pending_handlers); + h->pending = 1; + __sync_add_and_fetch(&triton_stat.md_handler_pending, 1); + r = triton_queue_ctx(h->ctx); + } else + r = 0; + } else + r = 0; + spin_unlock(&h->ctx->lock); + if (r) + triton_thread_wakeup(h->ctx->thread); + } + + while (!list_empty(&freed_list2)) { + h = list_entry(freed_list2.next, typeof(*h), entry); + list_del(&h->entry); + mempool_free(h); + } + + pthread_mutex_lock(&freed_list_lock); + while (!list_empty(&freed_list)) { + h = list_entry(freed_list.next, typeof(*h), entry); + list_del(&h->entry); + list_add(&h->entry, &freed_list2); + } + pthread_mutex_unlock(&freed_list_lock); + } + + return NULL; +} + +void __export triton_md_register_handler(struct triton_context_t *ctx, struct triton_md_handler_t *ud) +{ + struct _triton_md_handler_t *h = mempool_alloc(md_pool); + memset(h, 0, sizeof(*h)); + h->ud = ud; + h->epoll_event.data.ptr = h; + if (ctx) + h->ctx = (struct _triton_context_t *)ctx->tpd; + else + h->ctx = (struct _triton_context_t *)default_ctx.tpd; + ud->tpd = h; + spin_lock(&h->ctx->lock); + list_add_tail(&h->entry, &h->ctx->handlers); + spin_unlock(&h->ctx->lock); + + triton_stat.md_handler_count++; +} +void __export triton_md_unregister_handler(struct triton_md_handler_t *ud) +{ + struct _triton_md_handler_t *h = (struct _triton_md_handler_t *)ud->tpd; + triton_md_disable_handler(ud, MD_MODE_READ | MD_MODE_WRITE); + + spin_lock(&h->ctx->lock); + h->ud = NULL; + list_del(&h->entry); + if (h->pending) { + list_del(&h->entry2); + __sync_sub_and_fetch(&triton_stat.md_handler_pending, 1); + } + spin_unlock(&h->ctx->lock); + + sched_yield(); + + pthread_mutex_lock(&freed_list_lock); + list_add_tail(&h->entry, &freed_list); + pthread_mutex_unlock(&freed_list_lock); + + triton_stat.md_handler_count--; +} +int __export triton_md_enable_handler(struct triton_md_handler_t *ud, int mode) +{ + struct _triton_md_handler_t *h = (struct _triton_md_handler_t *)ud->tpd; + int r; + int events = h->epoll_event.events; + + if (mode & MD_MODE_READ) + h->epoll_event.events |= EPOLLIN; + if (mode & MD_MODE_WRITE) + h->epoll_event.events |= EPOLLOUT; + + if (!h->trig_level) + h->epoll_event.events |= EPOLLET; + + if (events) + r = epoll_ctl(epoll_fd, EPOLL_CTL_MOD, h->ud->fd, &h->epoll_event); + else + r = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, h->ud->fd, &h->epoll_event); + + if (r) { + triton_log_error("md:epoll_ctl: %s\n",strerror(errno)); + abort(); + } + + return r; +} +int __export triton_md_disable_handler(struct triton_md_handler_t *ud,int mode) +{ + struct _triton_md_handler_t *h = (struct _triton_md_handler_t *)ud->tpd; + int r=0; + + if (!h->epoll_event.events) + return -1; + + if (mode & MD_MODE_READ) + h->epoll_event.events &= ~EPOLLIN; + if (mode & MD_MODE_WRITE) + h->epoll_event.events &= ~EPOLLOUT; + + if (h->epoll_event.events & (EPOLLIN | EPOLLOUT)) + r = epoll_ctl(epoll_fd, EPOLL_CTL_MOD, h->ud->fd, &h->epoll_event); + else { + h->epoll_event.events = 0; + r = epoll_ctl(epoll_fd, EPOLL_CTL_DEL, h->ud->fd, NULL); + } + + if (r) { + triton_log_error("md:epoll_ctl: %s\n",strerror(errno)); + abort(); + } + + return r; +} + +void __export triton_md_set_trig(struct triton_md_handler_t *ud, int mode) +{ + struct _triton_md_handler_t *h = (struct _triton_md_handler_t *)ud->tpd; + h->trig_level = mode; +} + |