From 5a2d6079eba1c7e2a9479cb10d714b5a97bbfe4f Mon Sep 17 00:00:00 2001 From: Kozlov Dmitry Date: Tue, 3 Aug 2010 13:28:53 +0400 Subject: initiating work on accel-pptpd, replacement of modified poptop --- accel-pptpd/triton/CMakeLists.txt | 13 ++ accel-pptpd/triton/conf_file.c | 185 +++++++++++++++++++++ accel-pptpd/triton/conf_file.h | 16 ++ accel-pptpd/triton/coroutine.c | 153 +++++++++++++++++ accel-pptpd/triton/event.c | 155 +++++++++++++++++ accel-pptpd/triton/list.h | 249 +++++++++++++++++++++++++++ accel-pptpd/triton/loader.c | 55 ++++++ accel-pptpd/triton/md.c | 342 ++++++++++++++++++++++++++++++++++++++ accel-pptpd/triton/options.c | 46 +++++ accel-pptpd/triton/timer.c | 244 +++++++++++++++++++++++++++ accel-pptpd/triton/triton.h | 78 +++++++++ accel-pptpd/triton/triton_p.h | 140 ++++++++++++++++ 12 files changed, 1676 insertions(+) create mode 100644 accel-pptpd/triton/CMakeLists.txt create mode 100644 accel-pptpd/triton/conf_file.c create mode 100644 accel-pptpd/triton/conf_file.h create mode 100644 accel-pptpd/triton/coroutine.c create mode 100644 accel-pptpd/triton/event.c create mode 100644 accel-pptpd/triton/list.h create mode 100644 accel-pptpd/triton/loader.c create mode 100644 accel-pptpd/triton/md.c create mode 100644 accel-pptpd/triton/options.c create mode 100644 accel-pptpd/triton/timer.c create mode 100644 accel-pptpd/triton/triton.h create mode 100644 accel-pptpd/triton/triton_p.h (limited to 'accel-pptpd/triton') diff --git a/accel-pptpd/triton/CMakeLists.txt b/accel-pptpd/triton/CMakeLists.txt new file mode 100644 index 0000000..868c3eb --- /dev/null +++ b/accel-pptpd/triton/CMakeLists.txt @@ -0,0 +1,13 @@ +SET(target triton) +SET(sources_c + md.c + conf_file.c + coroutine.c + event.c + timer.c + options.c + loader.c +) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +ADD_LIBRARY(${target} STATIC ${sources_c}) diff --git a/accel-pptpd/triton/conf_file.c b/accel-pptpd/triton/conf_file.c new file mode 100644 index 0000000..3ddb649 --- /dev/null +++ b/accel-pptpd/triton/conf_file.c @@ -0,0 +1,185 @@ +#include +#include +#include +#include + +#include "conf_file.h" +#include "triton_p.h" + +struct sect_t +{ + struct list_head entry; + + struct conf_file_sect_t *sect; +}; + +static LIST_HEAD(sections); + +static char* skip_space(char *str); +static char* skip_word(char *str); + +static struct conf_file_sect_t *find_sect(const char *name); +static struct conf_file_sect_t *create_sect(const char *name); +static void sect_add_item(struct conf_file_sect_t *sect,const char *name,const char *val); +static struct option_t *find_item(struct conf_file_sect_t *,const char *name); + +void conf_file_load(const char *fname) +{ + char *buf,*str,*str2; + char *path0,*path; + int cur_line=0; + static struct conf_file_sect_t *cur_sect=NULL; + FILE *f=fopen(fname,"r"); + if (!f) + { + perror("triton: open conf file"); + return; + } + + buf=(char*)malloc(1024); + path0=(char*)malloc(4096); + path=(char*)malloc(4096); + + getcwd(path0,1024); + + while(!feof(f)) + { + buf=fgets(buf,1024,f); + if (!buf) break; + ++cur_line; + if (buf[strlen(buf)-1]=='\n') + buf[strlen(buf)-1]=0; + + str=skip_space(buf); + if (*str=='#' || *str==0) continue; + if (strncmp(str,"$include",8)==0) + { + str=skip_word(str); + str=skip_space(str); + /*if (*str=='.') + { + strcpy(path,path0); + strcat(path,str+1); + str=path; + }*/ + conf_file_load(str); + continue; + } + if (*str=='[') + { + for (str2=++str; *str2 && *str2!=']'; str2++); + if (*str2!=']') + { +//L1: + printf("triton: sintax error in conf file %s line %i\n",fname,cur_line); + return; + } + *str2=0; + cur_sect=find_sect(str); + if (!cur_sect) cur_sect=create_sect(str); + continue; + } + if (!cur_sect) + { + printf("triton: no section opened in conf file %s line %i\n",fname,cur_line); + return; + } + str2=skip_word(str); + if (*str2==' ') + { + *str2=0; + ++str2; + } + str2=skip_space(str2); + if (*str2=='=' || *str2==',') + { + *str2=0; + str2=skip_space(str2+1); + if (*str2 && *(str2+1) && *str2=='$' && *(str2+1)=='{') + { + char *s; + struct option_t *opt; + for (s=str2+2; *s && *s!='}'; s++); + if (*s=='}') + { + *s=0; + str2+=2; + } + opt=find_item(cur_sect,str2); + if (!opt) + { + printf("triton: parent option not found int conf file %s line %i\n",fname,cur_line); + return; + } + str2=opt->val; + } + }else str2=NULL; + sect_add_item(cur_sect,str,str2); + } + + free(buf); + free(path); + free(path0); + fclose(f); +} + +static char* skip_space(char *str) +{ + for (; *str && *str==' '; str++); + return str; +} +static char* skip_word(char *str) +{ + for (; *str && (*str!=' ' && *str!='='); str++); + return str; +} + +static struct conf_file_sect_t *find_sect(const char *name) +{ + struct sect_t *s; + list_for_each_entry(s,§ions,entry) + { + if (strcmp(s->sect->name,name)==0) return s->sect; + } + return NULL; +} + +static struct conf_file_sect_t *create_sect(const char *name) +{ + struct sect_t *s=(struct sect_t *)malloc(sizeof(struct sect_t)); + + s->sect=(struct conf_file_sect_t*)malloc(sizeof(struct conf_file_sect_t)); + s->sect->name=(char*)strdup(name); + INIT_LIST_HEAD(&s->sect->items); + + list_add_tail(&s->entry,§ions); + + return s->sect; +} + +static void sect_add_item(struct conf_file_sect_t *sect,const char *name,const char *val) +{ + struct option_t *opt=(struct option_t *)malloc(sizeof(struct option_t)); + + opt->name=(char*)strdup(name); + opt->val=val?(char*)strdup(val):NULL; + + list_add_tail(&opt->entry,§->items); +} + +static struct option_t *find_item(struct conf_file_sect_t *sect,const char *name) +{ + struct option_t *opt; + list_for_each_entry(opt,§->items,entry) + { + if (strcmp(opt->name,name)==0) + return opt; + } + + return NULL; +} + +struct conf_file_sect_t *conf_file_get_section(const char *name) +{ + return find_sect(name); +} diff --git a/accel-pptpd/triton/conf_file.h b/accel-pptpd/triton/conf_file.h new file mode 100644 index 0000000..47ade31 --- /dev/null +++ b/accel-pptpd/triton/conf_file.h @@ -0,0 +1,16 @@ +#ifndef CONF_FILE_H +#define CONF_FILE_H + +#include "list.h" + +struct conf_file_sect_t +{ + const char *name; + + struct list_head items; +}; + +void conf_file_load(const char *fname); +struct conf_file_sect_t *conf_file_get_section(const char *name); + +#endif diff --git a/accel-pptpd/triton/coroutine.c b/accel-pptpd/triton/coroutine.c new file mode 100644 index 0000000..b2866d0 --- /dev/null +++ b/accel-pptpd/triton/coroutine.c @@ -0,0 +1,153 @@ +#include +#include +#include +#include +#include + +#include "triton_p.h" + +#ifdef USE_CORO + +static LIST_HEAD(coroutines); +asm(".hidden current_coro"); +struct coroutine_t *current_coro=NULL; +//asm(".hidden sched_uc"); +static ucontext_t sched_uc; + +asm(".hidden schedule"); +void schedule(void) +{ + struct coroutine_t *coro; + struct list_head *p; + while(1) + { + current_coro=NULL; + for(p=coroutines.next; p!=&coroutines; p=p->next) + { + coro=list_entry(p,typeof(*current_coro),entry); + if (coro->time.tv_sec) + { + if (!current_coro) current_coro=coro; + else if (coro->time.tv_sectime.tv_sec) continue; + else if (coro->time.tv_sec>current_coro->time.tv_sec || coro->time.tv_usec>current_coro->time.tv_usec) current_coro=coro; + } + } + if (current_coro) + { + get_time(¤t_coro->time); + swapcontext(&sched_uc,¤t_coro->uc); + //break; + }else + { + printf("triton: coroutine: bug: no current coro !!!\n"); + exit(-1); + } + } +} + +void coroutine_init(void) +{ + getcontext(&sched_uc); + sched_uc.uc_stack.ss_sp=malloc(DEF_COROUTINE_STACK); + sched_uc.uc_stack.ss_size=DEF_COROUTINE_STACK; + makecontext(&sched_uc,schedule,0); +} + +void triton_coroutine_schedule() +{ + memset(¤t_coro->time,0,sizeof(current_coro->time)); + memset(¤t_coro->timeout,0,sizeof(current_coro->timeout)); + swapcontext(¤t_coro->uc,&sched_uc); +} + +long int triton_coroutine_create(int stack_size,triton_coroutine_func func,void *arg,int run) +{ + struct coroutine_t *coro=malloc(sizeof(*coro)); + memset(coro,0,sizeof(*coro)); + + if (!stack_size) stack_size=DEF_COROUTINE_STACK;//+SIGSTKSZ; + + getcontext(&coro->uc); + coro->uc.uc_link=&sched_uc; + coro->uc.uc_stack.ss_sp=malloc(stack_size); + coro->uc.uc_stack.ss_size=stack_size; + makecontext(&coro->uc,(void (*)(void))func,1,arg); + + if (run) coro->time.tv_sec=1; + + list_add(&coro->entry,&coroutines); + + return (long int)coro; +} +void triton_coroutine_delete(long int id) +{ + struct coroutine_t *coro=(struct coroutine_t *)id; + + list_del(&coro->entry); + free(coro->uc.uc_stack.ss_sp); +} +int triton_coroutine_schedule_timeout(int msec) +{ + //current_coro->msleep=msec; + struct timeval tv; + int t; + get_time(¤t_coro->timeout); + current_coro->timeout.tv_sec+=msec/1000; + current_coro->timeout.tv_usec+=(msec%1000)*1000; + if (current_coro->timeout.tv_usec>=1000000) + { + current_coro->timeout.tv_sec++; + current_coro->timeout.tv_usec-=1000000; + } + //triton_coroutine_schedule(); + memset(¤t_coro->time,0,sizeof(current_coro->time)); + //memset(¤t_coro->timeout,0,sizeof(current_coro->timeout)); + swapcontext(¤t_coro->uc,&sched_uc); + get_time(&tv); + t=(current_coro->timeout.tv_sec-tv.tv_sec)*1000+(current_coro->timeout.tv_usec-tv.tv_usec)/1000; + if (t<0) t=0; + return t; +} +void triton_coroutine_wakeup(long int id) +{ + struct coroutine_t *coro=(struct coroutine_t *)id; + struct coroutine_t *cur_coro=current_coro; + get_time(¤t_coro->time); + current_coro=coro; + swapcontext(&cur_coro->uc,&coro->uc); +} + +asm(".hidden coroutine_get_timeout"); +int coroutine_get_timeout(struct timeval *tv) +{ + struct coroutine_t *coro; + struct list_head *p; + int twait,t=-1; + for(p=coroutines.next; p!=&coroutines; p=p->next) + { + coro=list_entry(p,typeof(*coro),entry); + if (coro->timeout.tv_sec) + { + twait=(coro->timeout.tv_sec-tv->tv_sec)*1000+(coro->timeout.tv_usec-tv->tv_usec)/1000; + if (t==-1 || twaitnext; + if (coro->timeout.tv_sec && (tv->tv_sec>coro->timeout.tv_sec || (tv->tv_sec==coro->timeout.tv_sec && tv->tv_usec>=coro->timeout.tv_usec))) + { + triton_coroutine_wakeup((long int)coro); + } + } +} + +#endif diff --git a/accel-pptpd/triton/event.c b/accel-pptpd/triton/event.c new file mode 100644 index 0000000..9daa226 --- /dev/null +++ b/accel-pptpd/triton/event.c @@ -0,0 +1,155 @@ +#include +#include +#include +#include + +#include "triton_p.h" + +#define EVENTS1_SIZE 1024 + +static __thread struct list_head events2; +static __thread struct event_t *events1; +static __thread long *args; + +asm(".hidden event_init"); + +static struct event_t *find_event(int ev_id); +static struct event_t *create_event(int ev_id); + +void event_init(void) +{ + int i; + args=malloc(MAX_ARGS*sizeof(long)); + events1=(struct event_t *)malloc(EVENTS1_SIZE*sizeof(struct event_t)); + + for (i=0; ievent_func=func; + if (arg_cnt) + { + va_list p; + va_start(p,arg_cnt); + ev_h->arg_cnt=arg_cnt; + ev_h->args=malloc(arg_cnt*sizeof(long)); + #ifdef BROKEN_GCC + for(i=0; iargs+i)=va_arg(p,long); + #else + memcpy(ev_h->args,p,arg_cnt*sizeof(long)); + #endif + va_end(p); + } + + list_add_tail(&ev_h->entry,&ev->handlers); +} +void triton_event_unregister_handler(int ev_id,triton_event_func func) +{ + struct event_t *ev; + struct event_handler_t *ev_h; + + ev=find_event(ev_id); + if (!ev) + return; + + list_for_each_entry(ev_h,&ev->handlers,entry) + { + if (ev_h->event_func==func) + { + list_del(&ev_h->entry); + if (ev_h->args) free(ev_h->args); + free(ev_h); + + if (list_empty(&ev->handlers) && ev_id>=EVENTS1_SIZE) + { + list_del(&ev->entry); + free(ev); + } + return; + } + } +} + +/*#define dyn_call(func,arg_cnt,args)\ + asm("movl %%esp,%%edi;\n\ + movl %0,%%esi;\n\ + movl %1,%%ecx;\n\ + cld;\n\ + rep movsl;\n\ + call *%2;\n"::"m" (args),"m" (arg_cnt),"m" (func):"%edi","%esi","%ecx");*/ + +void triton_event_fire(int ev_id,int arg_cnt,...) +{ + struct event_t *ev; + struct event_handler_t *ev_h; + struct list_head *p1,*p2; + va_list p; + //void *args_p=&args; + //char pp[ARG_OFFSET+MAX_ARGS*sizeof(int)]; + //memcpy(pp,__builtin_apply_args(),ARG_OFFSET); + + ev=find_event(ev_id); + if (!ev) + return; + + list_for_each_safe(p1,p2,&ev->handlers) + { + ev_h=list_entry(p1,struct event_handler_t,entry); + if (ev_h->arg_cnt) memcpy(args,ev_h->args,ev_h->arg_cnt*sizeof(long)); + va_start(p,arg_cnt); + #ifdef BROKEN_GCC + for(i=0; iarg_cnt+i]=va_arg(p,long); + #else + memcpy(args+ev_h->arg_cnt,p,arg_cnt*sizeof(long)); + #endif + //memcpy(pp+ARG_OFFSET,args,(ev_h->arg_cnt+arg_cnt)*sizeof(int)); + //__builtin_apply(ev_h->event_func,pp,ARG_OFFSET+(ev_h->arg_cnt+arg_cnt)*sizeof(int)); + //ev_h->event_func(ev_id,arg); + //__builtin_apply(ev_h->event_func,args_p,(ev_h->arg_cnt+arg_cnt)*sizeof(int)); + dyn_call(ev_h->event_func,ev_h->arg_cnt+arg_cnt,args); + } + + va_end(p); +} + +static struct event_t *find_event(int ev_id) +{ + struct event_t *ev; + if (ev_idev_id==ev_id) + return ev; + } + return NULL; +} +static struct event_t *create_event(int ev_id) +{ + struct event_t *ev=(struct event_t *)malloc(sizeof(struct event_t)); + + INIT_LIST_HEAD(&ev->handlers); + + list_add_tail(&ev->entry,&events2); + + return ev; +} diff --git a/accel-pptpd/triton/list.h b/accel-pptpd/triton/list.h new file mode 100644 index 0000000..d95dd71 --- /dev/null +++ b/accel-pptpd/triton/list.h @@ -0,0 +1,249 @@ +#ifndef _LINUX_LIST_H +#define _LINUX_LIST_H + +//#if defined(__KERNEL__) || defined(_LVM_H_INCLUDE) + +//#include + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +typedef struct list_head { + struct list_head *next, *prev; +} list_t; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +#define INIT_LIST_HEAD(ptr) do { \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ +} while (0) + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ + +static void inline prefetch(void *p){} + +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head *prev, struct list_head *next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty on entry does not return true after this, the entry is in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = (void *) 0; + entry->prev = (void *) 0; +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static inline void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} + +/** + * list_move - delete from one list and add as another's head + * @list: the entry to move + * @head: the head that will precede our entry + */ +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add(list, head); +} + +/** + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(struct list_head *head) +{ + return head->next == head; +} + +static inline void __list_splice(struct list_head *list, + struct list_head *head) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; +} + +/** + * list_splice - join two lists + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice(struct list_head *list, struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head); +} + +/** + * list_splice_init - join two lists and reinitialise the emptied list. + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +static inline void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head); + INIT_LIST_HEAD(list); + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next, prefetch(pos->next); pos != (head); \ + pos = pos->next, prefetch(pos->next)) + +/** + * __list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + * + * This variant differs from list_for_each() in that it's the + * simplest possible list iteration code, no prefetching is done. + * Use this for code that knows the list to be very short (empty + * or 1 entry) most of the time. + */ +#define __list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * list_for_each_prev - iterate over a list backwards + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \ + pos = pos->prev, prefetch(pos->prev)) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop counter. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + prefetch(pos->member.next); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member), \ + prefetch(pos->member.next)) + +//#endif /* __KERNEL__ || _LVM_H_INCLUDE */ + +#endif diff --git a/accel-pptpd/triton/loader.c b/accel-pptpd/triton/loader.c new file mode 100644 index 0000000..33d4831 --- /dev/null +++ b/accel-pptpd/triton/loader.c @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include + +#include "conf_file.h" +#include "triton_p.h" + +void md_init(void); +void event_init(void); +void timer_init(void); + +struct thread_arg_t +{ + int (*post_init)(void*); + void *arg; +}; + +void *thread(struct thread_arg_t *arg) +{ + printf("triton: starting new thread\n"); + #ifdef USE_CORO + coroutine_init(); + #endif + md_init(); + event_init(); + timer_init(); + + arg->post_init(arg->arg); + + free(arg); + + //conf_file_load(cf_name); + #ifdef USE_CORO + schedule(); + #else + md_run(); + #endif + + return NULL; +} + +int triton_init(const char *conf_file) +{ + return 0; +} +int triton_run(int (*post_init)(void*),void *arg) +{ + pthread_t thr; + struct thread_arg_t *thr_arg=malloc(sizeof(*thr_arg)); + thr_arg->post_init=post_init; + thr_arg->arg=arg; + return pthread_create(&thr,NULL,(void*(*)(void*))thread,thr_arg); +} diff --git a/accel-pptpd/triton/md.c b/accel-pptpd/triton/md.c new file mode 100644 index 0000000..a0d2fab --- /dev/null +++ b/accel-pptpd/triton/md.c @@ -0,0 +1,342 @@ +#include +#include +#include +#include +#include + +#include "triton_p.h" + +#define USE_GET_TIME + +static __thread struct list_head handlers; +static __thread fd_set read_fds; +static __thread fd_set write_fds; +static __thread fd_set read_fds0; +static __thread fd_set write_fds0; +static __thread int md_term; + +asm(".hidden md_init"); +asm(".hidden md_run"); +asm(".hidden md_terminate"); + +static void _triton_process_events(int wait); + +void md_init() +{ + INIT_LIST_HEAD(&handlers); + + FD_ZERO(&read_fds); + FD_ZERO(&write_fds); + + signal(SIGPIPE,SIG_IGN); + + #ifdef USE_CORO + triton_coroutine_create(0,md_run,0,1); + #endif +} +void md_run() +{ + md_term=0; + + while(!md_term) + { + _triton_process_events(1); + } +} + + +#ifdef USE_CORO +asm(".hidden cur_uc"); +ucontext_t cur_uc; +#endif + +static void _triton_process_events(int wait) +{ + int max_fd=0,t; + struct md_handler_t *md_h; + struct timeval tv1,tv2,twait0; + struct list_head *p1,*p2; + int twait,n; + int _break=0; + + gettimeofday(&tv1,NULL); + _break=0; + + if (wait) + { + twait=timer_prepare(&tv1); + #ifdef USE_CORO + t=coroutine_get_timeout(&tv1); + #else + t=-1; + #endif + if (t>=0 && (twait==-1 || tin_handler) continue; + if (md_h->handler->twait>=0 && (twait==-1 || md_h->handler->twaithandler->twait; + } + }else + { + twait=0; + } + + read_fds0=read_fds; write_fds0=write_fds; + + list_for_each_entry(md_h,&handlers,entry) + { + if (md_h->in_handler) + { + FD_CLR(md_h->fd,&read_fds0); + FD_CLR(md_h->fd,&write_fds0); + }else + { + if (md_h->fd>max_fd) max_fd=md_h->fd; + } + } + + twait0=(struct timeval){twait/1000,(twait%1000)*1000}; + n=select(max_fd+1,&read_fds0,&write_fds0,NULL,twait>=0?&twait0:NULL); + + gettimeofday(&tv2,NULL); + twait=(tv2.tv_sec-tv1.tv_sec)*1000+(tv2.tv_usec-tv1.tv_usec)/1000; + + list_for_each_safe(p1,p2,&handlers) + { + md_h=list_entry(p1,struct md_handler_t,entry); + //if (!md_h->del) + { + if (md_h->handler->twait>=0) + { + md_h->handler->twait-=twait; + if (md_h->handler->twait<=0) md_h->timeout=1; + } + } + } + + timer_check(&tv2); + gettimeofday(&tv2,NULL); + #ifdef USE_CORO + coroutine_check_timeout(&tv2); + #endif + + list_for_each_safe(p1,p2,&handlers) + { + md_h=list_entry(p1,struct md_handler_t,entry); + if (md_h->in_handler) continue; + if (!md_h->del) + { + if (md_h->timeout) + { + md_h->timeout=0; + #ifdef USE_CORO + md_h->in_handler=1; + if (md_h->coro) + { + long int id=(long int)md_h->coro; + md_h->coro=NULL; + triton_coroutine_wakeup(id); + }else + #endif + { + md_h->handler->timeout(md_h->handler); + } + md_h->in_handler=0; + if (_break) return; + } + } + } + + if (n<0) + { + perror("triton: md(select)"); + //goto check_timeout; + } + if (n>0) + { + list_for_each_safe(p1,p2,&handlers) + { + md_h=list_entry(p1,struct md_handler_t,entry); + if (md_h->in_handler) continue; + if (md_h->del) continue; + md_h->in_handler=1; + if (FD_ISSET(md_h->fd,&read_fds0)) + { + if (md_h->handler->read==md_h->handler->write) + FD_CLR(md_h->fd,&write_fds0); + + #ifdef USE_CORO + if (md_h->coro) + { + long int id=(long int)md_h->coro; + md_h->coro=NULL; + triton_coroutine_wakeup(id); + }else + #endif + { + md_h->handler->read(md_h->handler); + } + } + if (!md_h->del && FD_ISSET(md_h->fd,&write_fds0) && md_h->handler->write) + { + #ifdef USE_CORO + if (md_h->coro) + { + long int id=(long int)md_h->coro; + md_h->coro=NULL; + triton_coroutine_wakeup(id); + }else + #endif + { + md_h->handler->write(md_h->handler); + } + } + md_h->in_handler=0; + if (_break) return; + } + } +//check_timeout: + + for(p1=handlers.next; p1!=&handlers;) + { + md_h=list_entry(p1,struct md_handler_t,entry); + p1=p1->next; + if (md_h->del) + { + list_del(&md_h->entry); + free(md_h); + } + } + + if (!wait) _break=1; +} + +void triton_process_events(void) +{ + _triton_process_events(0); +} + +void md_terminate() +{ + md_term=1; +} + +void triton_md_register_handler(struct triton_md_handler_t *h) +{ + struct md_handler_t *md_h; + + list_for_each_entry(md_h,&handlers,entry) + { + if (md_h->handler==h) + { + if (!md_h->del) + { + printf("triton: bug: double triton_md_register_handler\n"); + abort(); + } + md_h->del=0; + md_h->in_handler=0; + md_h->coro=0; + md_h->fd=0; + return; + } + } + + md_h=(struct md_handler_t *)malloc(sizeof(struct md_handler_t)); + memset(md_h,0,sizeof(*md_h)); + md_h->handler=h; + + list_add_tail(&md_h->entry,&handlers); +} +void triton_md_unregister_handler(struct triton_md_handler_t *h) +{ + struct md_handler_t *md_h; + + list_for_each_entry(md_h,&handlers,entry) + { + if (md_h->handler==h) + { + triton_md_disable_handler(h,0); + /*list_del(&md_h->entry); + free(md_h); + return;*/ + md_h->del=1; + return; + } + } +} +void triton_md_enable_handler(struct triton_md_handler_t *h, int mode) +{ + struct md_handler_t *md_h; + + list_for_each_entry(md_h,&handlers,entry) + { + if (md_h->handler==h) + { + md_h->fd=h->fd; + break; + } + } + if (mode) + { + if (mode&MD_MODE_READ) + FD_SET(h->fd,&read_fds); + if (mode&MD_MODE_WRITE) + FD_SET(h->fd,&write_fds); + }else + { + FD_SET(h->fd,&read_fds); + FD_SET(h->fd,&write_fds); + } +} +void triton_md_disable_handler(struct triton_md_handler_t *h,int mode) +{ + if (mode) + { + if (mode&MD_MODE_READ) + FD_CLR(h->fd,&read_fds); + if (mode&MD_MODE_WRITE) + FD_CLR(h->fd,&write_fds); + }else + { + FD_CLR(h->fd,&read_fds); + FD_CLR(h->fd,&write_fds); + } +} + +#ifdef USE_CORO +int triton_md_wait(struct triton_md_handler_t *h) +{ + struct md_handler_t *md_h; + int res=0; + + list_for_each_entry(md_h,&handlers,entry) + { + if (md_h->handler==h) break; + } + + md_h->in_handler=0; + + md_h->coro=current_coro; + triton_coroutine_schedule(); + + if (FD_ISSET(md_h->fd,&read_fds0)) res|=MD_MODE_READ; + if (FD_ISSET(md_h->fd,&write_fds0)) res|=MD_MODE_WRITE; + return res; +} +int triton_md_wait2(int fd,int mode,int timeout) +{ + int r; + struct triton_md_handler_t h= + { + .fd=fd, + .twait=timeout, + }; + triton_md_register_handler(&h); + triton_md_enable_handler(&h,mode); + r=triton_md_wait(&h); + triton_md_unregister_handler(&h); + return r; +} +#endif diff --git a/accel-pptpd/triton/options.c b/accel-pptpd/triton/options.c new file mode 100644 index 0000000..ba7fc56 --- /dev/null +++ b/accel-pptpd/triton/options.c @@ -0,0 +1,46 @@ +#include +#include + +#include "triton_p.h" +#include "conf_file.h" + +static struct conf_file_sect_t *sect=NULL; + +static const char* find_option(const char *name) +{ + struct option_t *opt; + + if (!sect) + { + sect=conf_file_get_section("options"); + if (!sect) return 0; + } + + list_for_each_entry(opt,§->items,entry) + { + if (strcmp(opt->name,name)==0) + return opt->val; + } + + return NULL; +} +int triton_get_int_option(const char *str) +{ + const char *val=find_option(str); + if (!val) return 0; + + return atoi(val); +} +const char* triton_get_str_option(const char *str) +{ + const char *val=find_option(str); + + return val; +} +double triton_get_double_option(const char *str) +{ + const char *val=find_option(str); + if (!val) return 0; + + return atof(val); +} diff --git a/accel-pptpd/triton/timer.c b/accel-pptpd/triton/timer.c new file mode 100644 index 0000000..2ea36cb --- /dev/null +++ b/accel-pptpd/triton/timer.c @@ -0,0 +1,244 @@ +#include +#include +#include +#include + +#include "triton_p.h" + +static __thread struct list_head timers; +static __thread struct list_head timers_ss; +static __thread int in_timer; + +asm(".hidden timer_prepare"); +asm(".hidden timer_check"); +asm(".hidden timer_init"); + +static void tv_add(struct timeval *tv,int msec); + + +void timer_init(void) +{ + INIT_LIST_HEAD(&timers); + INIT_LIST_HEAD(&timers_ss); + in_timer=0; +} + +void triton_timer_add(struct triton_timer_t*tt) +{ + struct timer_t *t=(struct timer_t *)malloc(sizeof(struct timer_t)); + + t->del=0; + t->timer=tt; + tt->active=1; + + list_add_tail(&t->entry,&timers); +} +void triton_timer_del(struct triton_timer_t*tt) +{ + struct timer_t *t; + + list_for_each_entry(t,&timers,entry) + { + if (t->timer==tt) + { + tt->active=0; + if (in_timer) + { + t->del=1; + }else + { + list_del(&t->entry); + free(t); + } + return; + } + } +} +void triton_timer_single_shot1(int twait,triton_ss_func func,int arg_cnt,...) +{ + struct timeval tv; + struct timer_single_shot_t *t=(struct timer_single_shot_t *)malloc(sizeof(struct timer_single_shot_t)); + + memset(t,0,sizeof(*t)); + + gettimeofday(&tv,NULL); + + tv_add(&tv,twait); + + t->ss_func=func; + t->expire_tv=tv;//(struct timeval){tv.tv_sec+twait/1000,tv.tv_usec+(twait%1000)*1000000}; + if (arg_cnt) + { + va_list p; + va_start(p,arg_cnt); + t->arg_cnt=arg_cnt; + t->args=malloc(arg_cnt*sizeof(long)); + #ifdef BROKEN_GCC + for(i=0; iargs+i)=va_arg(p,long); + #else + memcpy(t->args,p,arg_cnt*sizeof(long)); + #endif + va_end(p); + } + + list_add_tail(&t->entry,&timers_ss); +} +void triton_timer_single_shot2(struct timeval *tv,triton_ss_func func,int arg_cnt,...) +{ + struct timer_single_shot_t *t=(struct timer_single_shot_t *)malloc(sizeof(struct timer_single_shot_t)); + + memset(t,0,sizeof(*t)); + + t->ss_func=func; + t->expire_tv=*tv;//(struct timeval){tv.tv_sec+twait/1000,tv.tv_usec+(twait%1000)*1000000}; + if (arg_cnt) + { + va_list p; + va_start(p,arg_cnt); + t->arg_cnt=arg_cnt; + t->args=malloc(arg_cnt*sizeof(long)); + #ifdef BROKEN_GCC + for(i=0; iargs+i)=va_arg(p,long); + #else + memcpy(t->args,p,arg_cnt*sizeof(long)); + #endif + va_end(p); + } + + list_add_tail(&t->entry,&timers_ss); +} +void triton_timer_single_shot3(int tv_sec,int tv_usec,triton_ss_func func,int arg_cnt,...) +{ + struct timer_single_shot_t *t=(struct timer_single_shot_t *)malloc(sizeof(struct timer_single_shot_t)); + + memset(t,0,sizeof(*t)); + + t->ss_func=func; + t->expire_tv.tv_sec=tv_sec; + t->expire_tv.tv_usec=tv_usec; + if (arg_cnt) + { + va_list p; + va_start(p,arg_cnt); + t->arg_cnt=arg_cnt; + t->args=malloc(arg_cnt*sizeof(long)); + #ifdef BROKEN_GCC + for(i=0; iargs+i)=va_arg(p,long); + #else + memcpy(t->args,p,arg_cnt*sizeof(long)); + #endif + va_end(p); + } + + list_add_tail(&t->entry,&timers_ss); +} + +int timer_prepare(struct timeval *tv) +{ + struct timer_t *t; + struct timer_single_shot_t *ss_t; + + int twait=-1,twait0; + + list_for_each_entry(t,&timers,entry) + { + twait0=(t->timer->expire_tv.tv_sec-tv->tv_sec)*1000+ + (t->timer->expire_tv.tv_usec-tv->tv_usec)/1000; + if (twait0<0) twait0=0; + if (twait0>=0 && (twait==-1 || twait0expire_tv.tv_sec-tv->tv_sec)*1000+ + (ss_t->expire_tv.tv_usec-tv->tv_usec)/1000; + if (twait0<0) twait0=0; + if (twait0>=0 && (twait==-1 || twait0del) continue; + twait0=(t->timer->expire_tv.tv_sec-tv->tv_sec)*1000+ + (t->timer->expire_tv.tv_usec-tv->tv_usec)/1000; + if (twait0<=0) + { + if (!t->timer->expire(t->timer)) + { + t->timer->active=0; + list_del(&t->entry); + free(t); + continue; + } + if (t->timer->period) + { + tv_add(&t->timer->expire_tv,t->timer->period); + } + } + } + + list_for_each_safe(p1,p2,&timers_ss) + { + ss_t=list_entry(p1,struct timer_single_shot_t,entry); + twait0=(ss_t->expire_tv.tv_sec-tv->tv_sec)*1000+ + (ss_t->expire_tv.tv_usec-tv->tv_usec)/1000; + if (twait0<=0) + { + list_del(&ss_t->entry); + if (ss_t->arg_cnt) + { + //args_p=&ss_t->args; + //memcpy(pp+ARG_OFFSET,ss_t->args,ss_t->arg_cnt*sizeof(int)); + //__builtin_apply(ss_t->ss_func,pp,ARG_OFFSET+ss_t->arg_cnt*sizeof(int)); + dyn_call(ss_t->ss_func,ss_t->arg_cnt,ss_t->args); + free(ss_t->args); + }else ss_t->ss_func(); + free(ss_t); + } + } + + list_for_each_safe(p1,p2,&timers) + { + t=list_entry(p1,struct timer_t,entry); + if (t->del) + { + list_del(&t->entry); + t->timer->active=0; + free(t); + } + } + in_timer=0; +} + +static void tv_add(struct timeval *tv,int msec) +{ + tv->tv_sec+=msec/1000; + tv->tv_usec+=(msec%1000)*1000; + if (tv->tv_usec>=1000000) + { + tv->tv_sec++; + tv->tv_usec-=1000000; + } +} diff --git a/accel-pptpd/triton/triton.h b/accel-pptpd/triton/triton.h new file mode 100644 index 0000000..b726076 --- /dev/null +++ b/accel-pptpd/triton/triton.h @@ -0,0 +1,78 @@ +#ifndef TRITON_H +#define TRITON_H + +#include + +struct triton_md_handler_t +{ + int fd; + int twait; + void *pd; + + void (*read)(struct triton_md_handler_t *h); + void (*write)(struct triton_md_handler_t *h); + void (*timeout)(struct triton_md_handler_t *h); +}; + +#define MD_MODE_READ 1 +#define MD_MODE_WRITE 2 +void triton_md_register_handler(struct triton_md_handler_t *h); +void triton_md_unregister_handler(struct triton_md_handler_t *h); +void triton_md_enable_handler(struct triton_md_handler_t *h, int mode); +void triton_md_disable_handler(struct triton_md_handler_t *h,int mode); +int triton_md_wait(struct triton_md_handler_t *h); +int triton_md_wait2(int fd,int mode,int timeout); + +struct triton_timer_t +{ + struct timeval expire_tv; + int period; + void *pd; + int active; + + int (*expire)(struct triton_timer_t*); +}; + +void triton_timer_add(struct triton_timer_t*); +void triton_timer_del(struct triton_timer_t*); + +typedef void (*triton_ss_func)(void); +void triton_timer_single_shot1(int twait,triton_ss_func,int argc,...); +void triton_timer_single_shot2(struct timeval *shot_tv,triton_ss_func,int argc,...); +void triton_timer_single_shot3(int tv_sec,int tv_usec,triton_ss_func,int argc,...); + +typedef void (*triton_event_func)(void); +void triton_event_register_handler(int ev_id,triton_event_func,int argc,...); +void triton_event_unregister_handler(int ev_id,triton_event_func); +void triton_event_fire(int ev_id,int argc,...); + +int triton_get_int_option(const char *str); +const char* triton_get_str_option(const char *str); +double triton_get_double_option(const char *str); + +void triton_terminate(void); +void triton_process_events(void); + +#ifdef USE_CORO +#define DEF_COROUTINE_STACK 64*1024 +typedef void (*triton_coroutine_func)(void*); +long int triton_coroutine_create(int stack_size,triton_coroutine_func func,void *arg,int run); +void triton_coroutine_delete(long int id); +void triton_coroutine_wakeup(long int id); +void triton_coroutine_schedule(); +int triton_coroutine_schedule_timeout(int msec); +#endif + +#define TRITON_OK 0 +#define TRITON_ERR_NOCOMP -1 +#define TRITON_ERR_NOSUPP -2 +#define TRITON_ERR_NOINTF -3 +#define TRITON_ERR_EXISTS -4 +#define TRITON_ERR_NOCHAN -5 +#define TRITON_ERR_NOMSG -6 +#define TRITON_ERR_BUSY -5 + +int triton_init(const char *conf_file); +int triton_run(int (*post_init)(void*),void *arg); + +#endif diff --git a/accel-pptpd/triton/triton_p.h b/accel-pptpd/triton/triton_p.h new file mode 100644 index 0000000..0602bfa --- /dev/null +++ b/accel-pptpd/triton/triton_p.h @@ -0,0 +1,140 @@ +#ifndef TRITON_P_H +#define TRITON_P_H + +#include "triton.h" +#include "list.h" + +#include +#include + +#define MAX_ARGS 32 + +struct option_t +{ + struct list_head entry; + + char *name; + char *val; +}; + +struct md_handler_t +{ + struct list_head entry; + + int fd; + int del; + int timeout; + int volatile in_handler; + + struct coroutine_t *coro; + + struct triton_md_handler_t *handler; +}; + +struct timer_t +{ + struct list_head entry; + int del; + struct triton_timer_t *timer; +}; + +struct timer_single_shot_t +{ + struct list_head entry; + + struct timeval expire_tv; + int arg_cnt; + void *args; + triton_ss_func ss_func; +}; + +struct event_handler_t +{ + struct list_head entry; + + int arg_cnt; + void *args; + triton_event_func event_func; +}; +struct event_t +{ + struct list_head entry; + + int ev_id; + struct list_head handlers; +}; + +struct coroutine_t +{ + struct list_head entry; + ucontext_t uc; + struct timeval timeout; + struct timeval time; +}; + + +extern struct list_head components; +extern void md_run(); +extern void md_terminate(); +extern int timer_prepare(struct timeval *tv); +extern void timer_check(struct timeval *tv); +extern int coroutine_get_timeout(struct timeval *tv); +extern void coroutine_check_timeout(struct timeval *tv); +extern void event_init(); +extern struct coroutine_t *current_coro; +void schedule(void); + +//#define BROKEN_GCC + +#ifdef BROKEN_GCC +#define dyn_call(func,arg_cnt,args)\ +{\ + switch(arg_cnt)\ + {\ + case 0: \ + {\ + typedef void (*func0)(void);\ + ((func0)func)();\ + break;\ + }\ + case 1: \ + {\ + typedef void (*func0)(long);\ + ((func0)func)(*((long*)args+0));\ + break;\ + }\ + case 2: \ + {\ + typedef void (*func0)(long,long);\ + ((func0)func)(*((long*)args+0),*((long*)args+1));\ + break;\ + }\ + case 3: \ + {\ + typedef void (*func0)(long,long,long);\ + ((func0)func)(*((long*)args+0),*((long*)args+1),*((long*)args+2));\ + break;\ + }\ + case 4: \ + {\ + typedef void (*func0)(long,long,long,long);\ + ((func0)func)(*((long*)args+0),*((long*)args+1),*((long*)args+2),*((long*)args+3));\ + break;\ + }\ + }\ +} +#else +#define dyn_call(func,arg_cnt,args)\ +{\ + int aaa=arg_cnt*sizeof(long);\ + asm("subl %2,%%esp; \n\ + movl %%esp,%%edi;\n\ + movl %0,%%esi;\n\ + cld;\n\ + rep movsl;\n\ + call *%1;\n\ + addl %2,%%esp\n"::"m" (args),"m" (func),"g" (aaa),"c"(arg_cnt):"%edi","%esi","%esp");\ +} +#endif + +#endif -- cgit v1.2.3