summaryrefslogtreecommitdiff
path: root/accel-pptpd/triton
diff options
context:
space:
mode:
authorKozlov Dmitry <dima@server>2010-08-03 13:28:53 +0400
committerKozlov Dmitry <dima@server>2010-08-03 13:28:53 +0400
commit5a2d6079eba1c7e2a9479cb10d714b5a97bbfe4f (patch)
treee72134e47e1491580af15e3eccbba451f13fdd42 /accel-pptpd/triton
parentba8e1a64e75930a161afac9048e7d03b7f880644 (diff)
downloadaccel-ppp-xebd-5a2d6079eba1c7e2a9479cb10d714b5a97bbfe4f.tar.gz
accel-ppp-xebd-5a2d6079eba1c7e2a9479cb10d714b5a97bbfe4f.zip
initiating work on accel-pptpd, replacement of modified poptop
Diffstat (limited to 'accel-pptpd/triton')
-rw-r--r--accel-pptpd/triton/CMakeLists.txt13
-rw-r--r--accel-pptpd/triton/conf_file.c185
-rw-r--r--accel-pptpd/triton/conf_file.h16
-rw-r--r--accel-pptpd/triton/coroutine.c153
-rw-r--r--accel-pptpd/triton/event.c155
-rw-r--r--accel-pptpd/triton/list.h249
-rw-r--r--accel-pptpd/triton/loader.c55
-rw-r--r--accel-pptpd/triton/md.c342
-rw-r--r--accel-pptpd/triton/options.c46
-rw-r--r--accel-pptpd/triton/timer.c244
-rw-r--r--accel-pptpd/triton/triton.h78
-rw-r--r--accel-pptpd/triton/triton_p.h140
12 files changed, 1676 insertions, 0 deletions
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 <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#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,&sections,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,&sections);
+
+ 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,&sect->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,&sect->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 <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <string.h>
+
+#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_sec<current_coro->time.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(&current_coro->time);
+ swapcontext(&sched_uc,&current_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(&current_coro->time,0,sizeof(current_coro->time));
+ memset(&current_coro->timeout,0,sizeof(current_coro->timeout));
+ swapcontext(&current_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(&current_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(&current_coro->time,0,sizeof(current_coro->time));
+ //memset(&current_coro->timeout,0,sizeof(current_coro->timeout));
+ swapcontext(&current_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(&current_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 || twait<t) t=twait;
+ }
+ }
+ return t;
+}
+asm(".hidden coroutine_check_timeout");
+void coroutine_check_timeout(struct timeval *tv)
+{
+ struct coroutine_t *coro;
+ struct list_head *p;
+ for(p=coroutines.next; p!=&coroutines;)
+ {
+ coro=list_entry(p,typeof(*coro),entry);
+ p=p->next;
+ 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 <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#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; i<EVENTS1_SIZE; i++)
+ {
+ events1[i].ev_id=i;
+ INIT_LIST_HEAD(&events1[i].handlers);
+ }
+
+ INIT_LIST_HEAD(&events2);
+}
+
+void triton_event_register_handler(int ev_id,triton_event_func func,int arg_cnt,...)
+{
+ struct event_t *ev;
+ struct event_handler_t *ev_h;
+
+ ev=find_event(ev_id);
+ if (!ev)
+ ev=create_event(ev_id);
+
+ ev_h=(struct event_handler_t*)malloc(sizeof(struct event_handler_t));
+ memset(ev_h,0,sizeof(*ev_h));
+ ev_h->event_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; i<arg_cnt; i++)
+ *((int*)ev_h->args+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; i<arg_cnt; i++)
+ args[ev_h->arg_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_id<EVENTS1_SIZE)
+ return events1+ev_id;
+
+ list_for_each_entry(ev,&events2,entry)
+ {
+ if (ev->ev_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 <linux/prefetch.h>
+
+/*
+ * 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 <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <pthread.h>
+
+#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 <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <string.h>
+
+#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 || t<twait)) twait=t;
+
+ list_for_each_entry(md_h,&handlers,entry)
+ {
+ if (md_h->in_handler) continue;
+ if (md_h->handler->twait>=0 && (twait==-1 || md_h->handler->twait<twait)) twait=md_h->handler->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 <stdlib.h>
+#include <string.h>
+
+#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,&sect->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 <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <string.h>
+
+#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; i<arg_cnt; i++)
+ *((long*)t->args+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; i<arg_cnt; i++)
+ *((long*)t->args+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; i<arg_cnt; i++)
+ *((int*)t->args+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 || twait0<twait))
+ twait=twait0;
+ }
+
+ if (twait)
+ {
+ list_for_each_entry(ss_t,&timers_ss,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) twait0=0;
+ if (twait0>=0 && (twait==-1 || twait0<twait))
+ twait=twait0;
+ }
+ }
+
+ return twait;
+}
+
+
+void timer_check(struct timeval *tv)
+{
+ struct timer_t *t;
+ struct timer_single_shot_t *ss_t;
+ struct list_head *p1,*p2;
+ int twait0;
+
+ in_timer=1;
+
+ list_for_each_safe(p1,p2,&timers)
+ {
+ t=list_entry(p1,struct timer_t,entry);
+ if (t->del) 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 <sys/time.h>
+
+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 <stdarg.h>
+#include <ucontext.h>
+
+#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