1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

use libco instead of state-thread(st), still have some bug

This commit is contained in:
xiaozhihong 2020-02-16 21:07:54 +08:00
parent 51d6c367f5
commit 7c8a35aea9
88 changed files with 4836 additions and 19273 deletions

1
trunk/3rdparty/libco/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
README.md

55
trunk/3rdparty/libco/CMakeLists.txt vendored Normal file
View file

@ -0,0 +1,55 @@
cmake_minimum_required(VERSION 2.8)
project(libco)
# This for mac osx only
set(CMAKE_MACOSX_RPATH 0)
# Set lib version
set(LIBCO_VERSION 0.5)
# Set cflags
set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} -g -fno-strict-aliasing -O2 -Wall -export-dynamic -Wall -pipe -D_GNU_SOURCE -D_REENTRANT -fPIC -Wno-deprecated -m64)
# Use c and asm
enable_language(C ASM)
# Add source files
set(SOURCE_FILES
co_epoll.cpp
co_hook_sys_call.cpp
co_routine.cpp
coctx.cpp
coctx_swap.S)
# Add static and shared library target
add_library(colib_static STATIC ${SOURCE_FILES})
add_library(colib_shared SHARED ${SOURCE_FILES})
# Set library output name
set_target_properties(colib_static PROPERTIES OUTPUT_NAME colib)
set_target_properties(colib_shared PROPERTIES OUTPUT_NAME colib)
set_target_properties(colib_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
set_target_properties(colib_shared PROPERTIES CLEAN_DIRECT_OUTPUT 1)
# Set shared library version, will generate libcolib.${LIBCO_VERSION}.so and a symbol link named libcolib.so
# For mac osx, the extension name will be .dylib
set_target_properties(colib_shared PROPERTIES VERSION ${LIBCO_VERSION} SOVERSION ${LIBCO_VERSION})
# Macro for add example target
macro(add_example_target EXAMPLE_TARGET)
add_executable("example_${EXAMPLE_TARGET}" "example_${EXAMPLE_TARGET}.cpp")
target_link_libraries("example_${EXAMPLE_TARGET}" colib_static pthread dl)
endmacro(add_example_target)
add_example_target(closure)
add_example_target(cond)
add_example_target(copystack)
add_example_target(echocli)
add_example_target(echosvr)
add_example_target(poll)
add_example_target(setenv)
add_example_target(specific)
add_example_target(thread)

BIN
trunk/3rdparty/libco/LICENSE.txt vendored Normal file

Binary file not shown.

84
trunk/3rdparty/libco/Makefile vendored Normal file
View file

@ -0,0 +1,84 @@
#
# Tencent is pleased to support the open source community by making Libco available.
#
# Copyright (C) 2014 THL A29 Limited, a Tencent company. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
COMM_MAKE = 1
COMM_ECHO = 1
version=0.5
v=debug
include co.mk
########## options ##########
CFLAGS += -g -fno-strict-aliasing -O2 -Wall -export-dynamic \
-Wall -pipe -D_GNU_SOURCE -D_REENTRANT -fPIC -Wno-deprecated -m64
UNAME := $(shell uname -s)
ifeq ($(UNAME), FreeBSD)
LINKS += -g -L./lib -lcolib -lpthread
else
LINKS += -g -L./lib -lcolib -lpthread -ldl
endif
COLIB_OBJS=co_epoll.o co_routine.o co_hook_sys_call.o coctx_swap.o coctx.o
#co_swapcontext.o
PROGS = colib example_poll example_echosvr example_echocli example_thread example_cond example_specific example_copystack example_closure
all:$(PROGS)
colib:libcolib.a libcolib.so
libcolib.a: $(COLIB_OBJS)
$(ARSTATICLIB)
libcolib.so: $(COLIB_OBJS)
$(BUILDSHARELIB)
example_echosvr:example_echosvr.o
$(BUILDEXE)
example_echocli:example_echocli.o
$(BUILDEXE)
example_thread:example_thread.o
$(BUILDEXE)
example_poll:example_poll.o
$(BUILDEXE)
example_exit:example_exit.o
$(BUILDEXE)
example_cond:example_cond.o
$(BUILDEXE)
example_specific:example_specific.o
$(BUILDEXE)
example_copystack:example_copystack.o
$(BUILDEXE)
example_setenv:example_setenv.o
$(BUILDEXE)
example_closure:example_closure.o
$(BUILDEXE)
dist: clean libco-$(version).src.tar.gz
libco-$(version).src.tar.gz:
@find . -type f | grep -v CVS | grep -v .svn | sed s:^./:libco-$(version)/: > MANIFEST
@(cd ..; ln -s libco_pub libco-$(version))
(cd ..; tar cvf - `cat libco_pub/MANIFEST` | gzip > libco_pub/libco-$(version).src.tar.gz)
@(cd ..; rm libco-$(version))
clean:
$(CLEAN) *.o $(PROGS)
rm -fr MANIFEST lib solib libco-$(version).src.tar.gz libco-$(version)

85
trunk/3rdparty/libco/co.mk vendored Normal file
View file

@ -0,0 +1,85 @@
#
# Tencent is pleased to support the open source community by making Libco available.
#
# Copyright (C) 2014 THL A29 Limited, a Tencent company. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##### Makefile Rules ##########
MAIL_ROOT=.
SRCROOT=.
##define the compliers
CPP = $(CXX)
AR = ar -rc
RANLIB = ranlib
CPPSHARE = $(CPP) -fPIC -shared -O2 -pipe -L$(SRCROOT)/solib/ -o
CSHARE = $(CC) -fPIC -shared -O2 -pipe -L$(SRCROOT)/solib/ -o
ifeq ($v,release)
CFLAGS= -O2 $(INCLS) -fPIC -DLINUX -pipe -Wno-deprecated -c
else
CFLAGS= -g $(INCLS) -fPIC -DLINUX -pipe -c -fno-inline
endif
ifneq ($v,release)
BFLAGS= -g
endif
STATICLIBPATH=$(SRCROOT)/lib
DYNAMICLIBPATH=$(SRCROOT)/solib
INCLS += -I$(SRCROOT)
## default links
ifeq ($(LINKS_DYNAMIC), 1)
LINKS += -L$(DYNAMICLIBPATH) -L$(STATICLIBPATH)
else
LINKS += -L$(STATICLIBPATH)
endif
CPPSRCS = $(wildcard *.cpp)
CSRCS = $(wildcard *.c)
CPPOBJS = $(patsubst %.cpp,%.o,$(CPPSRCS))
COBJS = $(patsubst %.c,%.o,$(CSRCS))
SRCS = $(CPPSRCS) $(CSRCS)
OBJS = $(CPPOBJS) $(COBJS)
CPPCOMPI=$(CPP) $(CFLAGS) -Wno-deprecated
CCCOMPI=$(CC) $(CFLAGS)
BUILDEXE = $(CPP) $(BFLAGS) -o $@ $^ $(LINKS)
CLEAN = rm -f *.o
CPPCOMPILE = $(CPPCOMPI) $< $(FLAGS) $(INCLS) $(MTOOL_INCL) -o $@
CCCOMPILE = $(CCCOMPI) $< $(FLAGS) $(INCLS) $(MTOOL_INCL) -o $@
ARSTATICLIB = $(AR) $@.tmp $^ $(AR_FLAGS); \
if [ $$? -ne 0 ]; then exit 1; fi; \
test -d $(STATICLIBPATH) || mkdir -p $(STATICLIBPATH); \
mv -f $@.tmp $(STATICLIBPATH)/$@;
BUILDSHARELIB = $(CPPSHARE) $@.tmp $^ $(BS_FLAGS); \
if [ $$? -ne 0 ]; then exit 1; fi; \
test -d $(DYNAMICLIBPATH) || mkdir -p $(DYNAMICLIBPATH); \
mv -f $@.tmp $(DYNAMICLIBPATH)/$@;
.cpp.o:
$(CPPCOMPILE)
.c.o:
$(CCCOMPILE)

96
trunk/3rdparty/libco/co_closure.h vendored Normal file
View file

@ -0,0 +1,96 @@
/*
* Tencent is pleased to support the open source community by making Libco available.
* Copyright (C) 2014 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CO_CLOSURE_H__
#define __CO_CLOSURE_H__
struct stCoClosure_t
{
public:
virtual void exec() = 0;
};
//1.base
//-- 1.1 comac_argc
#define comac_get_args_cnt( ... ) comac_arg_n( __VA_ARGS__ )
#define comac_arg_n( _0,_1,_2,_3,_4,_5,_6,_7,N,...) N
#define comac_args_seqs() 7,6,5,4,3,2,1,0
#define comac_join_1( x,y ) x##y
#define comac_argc( ... ) comac_get_args_cnt( 0,##__VA_ARGS__,comac_args_seqs() )
#define comac_join( x,y) comac_join_1( x,y )
//-- 1.2 repeat
#define repeat_0( fun,a,... )
#define repeat_1( fun,a,... ) fun( 1,a,__VA_ARGS__ ) repeat_0( fun,__VA_ARGS__ )
#define repeat_2( fun,a,... ) fun( 2,a,__VA_ARGS__ ) repeat_1( fun,__VA_ARGS__ )
#define repeat_3( fun,a,... ) fun( 3,a,__VA_ARGS__ ) repeat_2( fun,__VA_ARGS__ )
#define repeat_4( fun,a,... ) fun( 4,a,__VA_ARGS__ ) repeat_3( fun,__VA_ARGS__ )
#define repeat_5( fun,a,... ) fun( 5,a,__VA_ARGS__ ) repeat_4( fun,__VA_ARGS__ )
#define repeat_6( fun,a,... ) fun( 6,a,__VA_ARGS__ ) repeat_5( fun,__VA_ARGS__ )
#define repeat( n,fun,... ) comac_join( repeat_,n )( fun,__VA_ARGS__)
//2.implement
#if __cplusplus <= 199711L
#define decl_typeof( i,a,... ) typedef typeof( a ) typeof_##a;
#else
#define decl_typeof( i,a,... ) typedef decltype( a ) typeof_##a;
#endif
#define impl_typeof( i,a,... ) typeof_##a & a;
#define impl_typeof_cpy( i,a,... ) typeof_##a a;
#define con_param_typeof( i,a,... ) typeof_##a & a##r,
#define param_init_typeof( i,a,... ) a(a##r),
//2.1 reference
#define co_ref( name,... )\
repeat( comac_argc(__VA_ARGS__) ,decl_typeof,__VA_ARGS__ )\
class type_##name\
{\
public:\
repeat( comac_argc(__VA_ARGS__) ,impl_typeof,__VA_ARGS__ )\
int _member_cnt;\
type_##name( \
repeat( comac_argc(__VA_ARGS__),con_param_typeof,__VA_ARGS__ ) ... ): \
repeat( comac_argc(__VA_ARGS__),param_init_typeof,__VA_ARGS__ ) _member_cnt(comac_argc(__VA_ARGS__)) \
{}\
} name( __VA_ARGS__ ) ;
//2.2 function
#define co_func(name,...)\
repeat( comac_argc(__VA_ARGS__) ,decl_typeof,__VA_ARGS__ )\
class name:public stCoClosure_t\
{\
public:\
repeat( comac_argc(__VA_ARGS__) ,impl_typeof_cpy,__VA_ARGS__ )\
int _member_cnt;\
public:\
name( repeat( comac_argc(__VA_ARGS__),con_param_typeof,__VA_ARGS__ ) ... ): \
repeat( comac_argc(__VA_ARGS__),param_init_typeof,__VA_ARGS__ ) _member_cnt(comac_argc(__VA_ARGS__))\
{}\
void exec()
#define co_func_end }
#endif

318
trunk/3rdparty/libco/co_epoll.cpp vendored Normal file
View file

@ -0,0 +1,318 @@
/*
* Tencent is pleased to support the open source community by making Libco available.
* Copyright (C) 2014 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "co_epoll.h"
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#if !defined( __APPLE__ ) && !defined( __FreeBSD__ )
int co_epoll_wait( int epfd,struct co_epoll_res *events,int maxevents,int timeout )
{
return epoll_wait( epfd,events->events,maxevents,timeout );
}
int co_epoll_ctl( int epfd,int op,int fd,struct epoll_event * ev )
{
return epoll_ctl( epfd,op,fd,ev );
}
int co_epoll_create( int size )
{
return epoll_create( size );
}
struct co_epoll_res *co_epoll_res_alloc( int n )
{
struct co_epoll_res * ptr =
(struct co_epoll_res *)malloc( sizeof( struct co_epoll_res ) );
ptr->size = n;
ptr->events = (struct epoll_event*)calloc( 1,n * sizeof( struct epoll_event ) );
return ptr;
}
void co_epoll_res_free( struct co_epoll_res * ptr )
{
if( !ptr ) return;
if( ptr->events ) free( ptr->events );
free( ptr );
}
#else
class clsFdMap // million of fd , 1024 * 1024
{
private:
static const int row_size = 1024;
static const int col_size = 1024;
void **m_pp[ 1024 ];
public:
clsFdMap()
{
memset( m_pp,0,sizeof(m_pp) );
}
~clsFdMap()
{
for(int i=0;i<sizeof(m_pp)/sizeof(m_pp[0]);i++)
{
if( m_pp[i] )
{
free( m_pp[i] );
m_pp[i] = NULL;
}
}
}
inline int clear( int fd )
{
set( fd,NULL );
return 0;
}
inline int set( int fd,const void * ptr )
{
int idx = fd / row_size;
if( idx < 0 || idx >= sizeof(m_pp)/sizeof(m_pp[0]) )
{
assert( __LINE__ == 0 );
return -__LINE__;
}
if( !m_pp[ idx ] )
{
m_pp[ idx ] = (void**)calloc( 1,sizeof(void*) * col_size );
}
m_pp[ idx ][ fd % col_size ] = (void*)ptr;
return 0;
}
inline void *get( int fd )
{
int idx = fd / row_size;
if( idx < 0 || idx >= sizeof(m_pp)/sizeof(m_pp[0]) )
{
return NULL;
}
void **lp = m_pp[ idx ];
if( !lp ) return NULL;
return lp[ fd % col_size ];
}
};
__thread clsFdMap *s_fd_map = NULL;
static inline clsFdMap *get_fd_map()
{
if( !s_fd_map )
{
s_fd_map = new clsFdMap();
}
return s_fd_map;
}
struct kevent_pair_t
{
int fire_idx;
int events;
uint64_t u64;
};
int co_epoll_create( int size )
{
return kqueue();
}
int co_epoll_wait( int epfd,struct co_epoll_res *events,int maxevents,int timeout )
{
struct timespec t = { 0 };
if( timeout > 0 )
{
t.tv_sec = timeout;
}
int ret = kevent( epfd,
NULL, 0, //register null
events->eventlist, maxevents,//just retrival
( -1 == timeout ) ? NULL : &t );
int j = 0;
for(int i=0;i<ret;i++)
{
struct kevent &kev = events->eventlist[i];
struct kevent_pair_t *ptr = (struct kevent_pair_t*)kev.udata;
struct epoll_event *ev = events->events + i;
if( 0 == ptr->fire_idx )
{
ptr->fire_idx = i + 1;
memset( ev,0,sizeof(*ev) );
++j;
}
else
{
ev = events->events + ptr->fire_idx - 1;
}
if( EVFILT_READ == kev.filter )
{
ev->events |= EPOLLIN;
}
else if( EVFILT_WRITE == kev.filter )
{
ev->events |= EPOLLOUT;
}
ev->data.u64 = ptr->u64;
}
for(int i=0;i<ret;i++)
{
(( struct kevent_pair_t* )(events->eventlist[i].udata) )->fire_idx = 0;
}
return j;
}
int co_epoll_del( int epfd,int fd )
{
struct timespec t = { 0 };
struct kevent_pair_t *ptr = ( struct kevent_pair_t* )get_fd_map()->get( fd );
if( !ptr ) return 0;
if( EPOLLIN & ptr->events )
{
struct kevent kev = { 0 };
kev.ident = fd;
kev.filter = EVFILT_READ;
kev.flags = EV_DELETE;
kevent( epfd,&kev,1, NULL,0,&t );
}
if( EPOLLOUT & ptr->events )
{
struct kevent kev = { 0 };
kev.ident = fd;
kev.filter = EVFILT_WRITE;
kev.flags = EV_DELETE;
kevent( epfd,&kev,1, NULL,0,&t );
}
get_fd_map()->clear( fd );
free( ptr );
return 0;
}
int co_epoll_ctl( int epfd,int op,int fd,struct epoll_event * ev )
{
if( EPOLL_CTL_DEL == op )
{
return co_epoll_del( epfd,fd );
}
const int flags = ( EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLHUP );
if( ev->events & ~flags )
{
return -1;
}
if( EPOLL_CTL_ADD == op && get_fd_map()->get( fd ) )
{
errno = EEXIST;
return -1;
}
else if( EPOLL_CTL_MOD == op && !get_fd_map()->get( fd ) )
{
errno = ENOENT;
return -1;
}
struct kevent_pair_t *ptr = (struct kevent_pair_t*)get_fd_map()->get( fd );
if( !ptr )
{
ptr = (kevent_pair_t*)calloc(1,sizeof(kevent_pair_t));
get_fd_map()->set( fd,ptr );
}
int ret = 0;
struct timespec t = { 0 };
// printf("ptr->events 0x%X\n",ptr->events);
if( EPOLL_CTL_MOD == op )
{
//1.delete if exists
if( ptr->events & EPOLLIN )
{
struct kevent kev = { 0 };
EV_SET( &kev,fd,EVFILT_READ,EV_DELETE,0,0,NULL );
kevent( epfd, &kev,1, NULL,0, &t );
}
//1.delete if exists
if( ptr->events & EPOLLOUT )
{
struct kevent kev = { 0 };
EV_SET( &kev,fd,EVFILT_WRITE,EV_DELETE,0,0,NULL );
ret = kevent( epfd, &kev,1, NULL,0, &t );
// printf("delete write ret %d\n",ret );
}
}
do
{
if( ev->events & EPOLLIN )
{
//2.add
struct kevent kev = { 0 };
EV_SET( &kev,fd,EVFILT_READ,EV_ADD,0,0,ptr );
ret = kevent( epfd, &kev,1, NULL,0, &t );
if( ret ) break;
}
if( ev->events & EPOLLOUT )
{
//2.add
struct kevent kev = { 0 };
EV_SET( &kev,fd,EVFILT_WRITE,EV_ADD,0,0,ptr );
ret = kevent( epfd, &kev,1, NULL,0, &t );
if( ret ) break;
}
} while( 0 );
if( ret )
{
get_fd_map()->clear( fd );
free( ptr );
return ret;
}
ptr->events = ev->events;
ptr->u64 = ev->data.u64;
return ret;
}
struct co_epoll_res *co_epoll_res_alloc( int n )
{
struct co_epoll_res * ptr =
(struct co_epoll_res *)malloc( sizeof( struct co_epoll_res ) );
ptr->size = n;
ptr->events = (struct epoll_event*)calloc( 1,n * sizeof( struct epoll_event ) );
ptr->eventlist = (struct kevent*)calloc( 1,n * sizeof( struct kevent) );
return ptr;
}
void co_epoll_res_free( struct co_epoll_res * ptr )
{
if( !ptr ) return;
if( ptr->events ) free( ptr->events );
if( ptr->eventlist ) free( ptr->eventlist );
free( ptr );
}
#endif

93
trunk/3rdparty/libco/co_epoll.h vendored Normal file
View file

@ -0,0 +1,93 @@
/*
* Tencent is pleased to support the open source community by making Libco available.
* Copyright (C) 2014 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CO_EPOLL_H__
#define __CO_EPOLL_H__
#include <stdint.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#include <time.h>
#if !defined( __APPLE__ ) && !defined( __FreeBSD__ )
#include <sys/epoll.h>
struct co_epoll_res
{
int size;
struct epoll_event *events;
struct kevent *eventlist;
};
int co_epoll_wait( int epfd,struct co_epoll_res *events,int maxevents,int timeout );
int co_epoll_ctl( int epfd,int op,int fd,struct epoll_event * );
int co_epoll_create( int size );
struct co_epoll_res *co_epoll_res_alloc( int n );
void co_epoll_res_free( struct co_epoll_res * );
#else
#include <sys/event.h>
enum EPOLL_EVENTS
{
EPOLLIN = 0X001,
EPOLLPRI = 0X002,
EPOLLOUT = 0X004,
EPOLLERR = 0X008,
EPOLLHUP = 0X010,
EPOLLRDNORM = 0x40,
EPOLLWRNORM = 0x004,
};
#define EPOLL_CTL_ADD 1
#define EPOLL_CTL_DEL 2
#define EPOLL_CTL_MOD 3
typedef union epoll_data
{
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;
struct epoll_event
{
uint32_t events;
epoll_data_t data;
};
struct co_epoll_res
{
int size;
struct epoll_event *events;
struct kevent *eventlist;
};
int co_epoll_wait( int epfd,struct co_epoll_res *events,int maxevents,int timeout );
int co_epoll_ctl( int epfd,int op,int fd,struct epoll_event * );
int co_epoll_create( int size );
struct co_epoll_res *co_epoll_res_alloc( int n );
void co_epoll_res_free( struct co_epoll_res * );
#endif
#endif

1003
trunk/3rdparty/libco/co_hook_sys_call.cpp vendored Normal file

File diff suppressed because it is too large Load diff

1196
trunk/3rdparty/libco/co_routine.cpp vendored Normal file

File diff suppressed because it is too large Load diff

93
trunk/3rdparty/libco/co_routine.h vendored Normal file
View file

@ -0,0 +1,93 @@
/*
* Tencent is pleased to support the open source community by making Libco available.
* Copyright (C) 2014 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CO_ROUTINE_H__
#define __CO_ROUTINE_H__
#include <stdint.h>
#include <sys/poll.h>
#include <pthread.h>
//1.struct
struct stCoRoutine_t;
struct stShareStack_t;
struct stCoRoutineAttr_t
{
int stack_size;
stShareStack_t* share_stack;
stCoRoutineAttr_t()
{
stack_size = 128 * 1024;
share_stack = NULL;
}
}__attribute__ ((packed));
struct stCoEpoll_t;
typedef int (*pfn_co_eventloop_t)(void *);
typedef void *(*pfn_co_routine_t)( void * );
//2.co_routine
int co_create( stCoRoutine_t **co,const stCoRoutineAttr_t *attr,void *(*routine)(void*),void *arg );
void co_resume( stCoRoutine_t *co );
void co_yield( stCoRoutine_t *co );
void co_yield_ct(); //ct = current thread
void co_release( stCoRoutine_t *co );
void co_reset(stCoRoutine_t * co);
stCoRoutine_t *co_self();
int co_poll( stCoEpoll_t *ctx,struct pollfd fds[], nfds_t nfds, int timeout_ms );
void co_eventloop( stCoEpoll_t *ctx,pfn_co_eventloop_t pfn,void *arg );
//3.specific
int co_setspecific( pthread_key_t key, const void *value );
void * co_getspecific( pthread_key_t key );
//4.event
stCoEpoll_t * co_get_epoll_ct(); //ct = current thread
//5.hook syscall ( poll/read/write/recv/send/recvfrom/sendto )
void co_enable_hook_sys();
void co_disable_hook_sys();
bool co_is_enable_sys_hook();
//6.sync
struct stCoCond_t;
stCoCond_t *co_cond_alloc();
int co_cond_free( stCoCond_t * cc );
int co_cond_signal( stCoCond_t * );
int co_cond_broadcast( stCoCond_t * );
int co_cond_timedwait( stCoCond_t *,int timeout_ms );
//7.share stack
stShareStack_t* co_alloc_sharestack(int iCount, int iStackSize);
//8.init envlist for hook get/set env
void co_set_env_list( const char *name[],size_t cnt);
void co_log_err( const char *fmt,... );
#endif

111
trunk/3rdparty/libco/co_routine_inner.h vendored Normal file
View file

@ -0,0 +1,111 @@
/*
* Tencent is pleased to support the open source community by making Libco available.
* Copyright (C) 2014 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CO_ROUTINE_INNER_H__
#include "co_routine.h"
#include "coctx.h"
struct stCoRoutineEnv_t;
struct stCoSpec_t
{
void *value;
};
struct stStackMem_t
{
stCoRoutine_t* occupy_co;
int stack_size;
char* stack_bp; //stack_buffer + stack_size
char* stack_buffer;
};
struct stShareStack_t
{
unsigned int alloc_idx;
int stack_size;
int count;
stStackMem_t** stack_array;
};
struct stCoRoutine_t
{
stCoRoutineEnv_t *env;
pfn_co_routine_t pfn;
void *arg;
coctx_t ctx;
char cStart;
char cEnd;
char cIsMain;
char cEnableSysHook;
char cIsShareStack;
void *pvEnv;
//char sRunStack[ 1024 * 128 ];
stStackMem_t* stack_mem;
//save satck buffer while confilct on same stack_buffer;
char* stack_sp;
unsigned int save_size;
char* save_buffer;
stCoSpec_t aSpec[1024];
};
//1.env
void co_init_curr_thread_env();
stCoRoutineEnv_t * co_get_curr_thread_env();
//2.coroutine
void co_free( stCoRoutine_t * co );
void co_yield_env( stCoRoutineEnv_t *env );
//3.func
//-----------------------------------------------------------------------------------------------
struct stTimeout_t;
struct stTimeoutItem_t ;
stTimeout_t *AllocTimeout( int iSize );
void FreeTimeout( stTimeout_t *apTimeout );
int AddTimeout( stTimeout_t *apTimeout,stTimeoutItem_t *apItem ,uint64_t allNow );
struct stCoEpoll_t;
stCoEpoll_t * AllocEpoll();
void FreeEpoll( stCoEpoll_t *ctx );
stCoRoutine_t * GetCurrThreadCo();
void SetEpoll( stCoRoutineEnv_t *env,stCoEpoll_t *ev );
typedef void (*pfnCoRoutineFunc_t)();
#endif
#define __CO_ROUTINE_INNER_H__

View file

@ -0,0 +1,86 @@
/*
* Tencent is pleased to support the open source community by making Libco available.
* Copyright (C) 2014 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <pthread.h>
#include <stdlib.h>
/*
invoke only once in the whole program
CoRoutineSetSpecificCallBack(CoRoutineGetSpecificFunc_t pfnGet,CoRoutineSetSpecificFunc_t pfnSet)
struct MyData_t
{
int iValue;
char szValue[100];
};
CO_ROUTINE_SPECIFIC( MyData_t,__routine );
int main()
{
CoRoutineSetSpecificCallBack( co_getspecific,co_setspecific );
__routine->iValue = 10;
strcpy( __routine->szValue,"hello world" );
return 0;
}
*/
extern int co_setspecific( pthread_key_t key, const void *value );
extern void * co_getspecific( pthread_key_t key );
#define CO_ROUTINE_SPECIFIC( name,y ) \
\
static pthread_once_t _routine_once_##name = PTHREAD_ONCE_INIT; \
static pthread_key_t _routine_key_##name;\
static int _routine_init_##name = 0;\
static void _routine_make_key_##name() \
{\
(void) pthread_key_create(&_routine_key_##name, NULL); \
}\
template <class T>\
class clsRoutineData_routine_##name\
{\
public:\
inline T *operator->()\
{\
if( !_routine_init_##name ) \
{\
pthread_once( &_routine_once_##name,_routine_make_key_##name );\
_routine_init_##name = 1;\
}\
T* p = (T*)co_getspecific( _routine_key_##name );\
if( !p )\
{\
p = (T*)calloc(1,sizeof( T ));\
int ret = co_setspecific( _routine_key_##name,p) ;\
if ( ret )\
{\
if ( p )\
{\
free(p);\
p = NULL;\
}\
}\
}\
return p;\
}\
};\
\
static clsRoutineData_routine_##name<name> y;

132
trunk/3rdparty/libco/coctx.cpp vendored Normal file
View file

@ -0,0 +1,132 @@
/*
* Tencent is pleased to support the open source community by making Libco
available.
* Copyright (C) 2014 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "coctx.h"
#include <stdio.h>
#include <string.h>
#define ESP 0
#define EIP 1
#define EAX 2
#define ECX 3
// -----------
#define RSP 0
#define RIP 1
#define RBX 2
#define RDI 3
#define RSI 4
#define RBP 5
#define R12 6
#define R13 7
#define R14 8
#define R15 9
#define RDX 10
#define RCX 11
#define R8 12
#define R9 13
//----- --------
// 32 bit
// | regs[0]: ret |
// | regs[1]: ebx |
// | regs[2]: ecx |
// | regs[3]: edx |
// | regs[4]: edi |
// | regs[5]: esi |
// | regs[6]: ebp |
// | regs[7]: eax | = esp
enum {
kEIP = 0,
kEBP = 6,
kESP = 7,
};
//-------------
// 64 bit
// low | regs[0]: r15 |
// | regs[1]: r14 |
// | regs[2]: r13 |
// | regs[3]: r12 |
// | regs[4]: r9 |
// | regs[5]: r8 |
// | regs[6]: rbp |
// | regs[7]: rdi |
// | regs[8]: rsi |
// | regs[9]: ret | //ret func addr
// | regs[10]: rdx |
// | regs[11]: rcx |
// | regs[12]: rbx |
// hig | regs[13]: rsp |
enum {
kRDI = 7,
kRSI = 8,
kRETAddr = 9,
kRSP = 13,
};
// 64 bit
extern "C" {
extern void coctx_swap(coctx_t*, coctx_t*) asm("coctx_swap");
};
#if defined(__i386__)
int coctx_init(coctx_t* ctx) {
memset(ctx, 0, sizeof(*ctx));
return 0;
}
int coctx_make(coctx_t* ctx, coctx_pfn_t pfn, const void* s, const void* s1) {
// make room for coctx_param
char* sp = ctx->ss_sp + ctx->ss_size - sizeof(coctx_param_t);
sp = (char*)((unsigned long)sp & -16L);
coctx_param_t* param = (coctx_param_t*)sp;
void** ret_addr = (void**)(sp - sizeof(void*) * 2);
*ret_addr = (void*)pfn;
param->s1 = s;
param->s2 = s1;
memset(ctx->regs, 0, sizeof(ctx->regs));
ctx->regs[kESP] = (char*)(sp) - sizeof(void*) * 2;
return 0;
}
#elif defined(__x86_64__)
int coctx_make(coctx_t* ctx, coctx_pfn_t pfn, const void* s, const void* s1) {
char* sp = ctx->ss_sp + ctx->ss_size - sizeof(void*);
sp = (char*)((unsigned long)sp & -16LL);
memset(ctx->regs, 0, sizeof(ctx->regs));
void** ret_addr = (void**)(sp);
*ret_addr = (void*)pfn;
ctx->regs[kRSP] = sp;
ctx->regs[kRETAddr] = (char*)pfn;
ctx->regs[kRDI] = (char*)s;
ctx->regs[kRSI] = (char*)s1;
return 0;
}
int coctx_init(coctx_t* ctx) {
memset(ctx, 0, sizeof(*ctx));
return 0;
}
#endif

42
trunk/3rdparty/libco/coctx.h vendored Normal file
View file

@ -0,0 +1,42 @@
/*
* Tencent is pleased to support the open source community by making Libco available.
* Copyright (C) 2014 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CO_CTX_H__
#define __CO_CTX_H__
#include <stdlib.h>
typedef void* (*coctx_pfn_t)( void* s, void* s2 );
struct coctx_param_t
{
const void *s1;
const void *s2;
};
struct coctx_t
{
#if defined(__i386__)
void *regs[ 8 ];
#else
void *regs[ 14 ];
#endif
size_t ss_size;
char *ss_sp;
};
int coctx_init( coctx_t *ctx );
int coctx_make( coctx_t *ctx,coctx_pfn_t pfn,const void *s,const void *s1 );
#endif

83
trunk/3rdparty/libco/coctx_swap.S vendored Normal file
View file

@ -0,0 +1,83 @@
/*
* Tencent is pleased to support the open source community by making Libco available.
* Copyright (C) 2014 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
.globl coctx_swap
#if !defined( __APPLE__ )
.type coctx_swap, @function
#endif
coctx_swap:
#if defined(__i386__)
movl 4(%esp), %eax
movl %esp, 28(%eax)
movl %ebp, 24(%eax)
movl %esi, 20(%eax)
movl %edi, 16(%eax)
movl %edx, 12(%eax)
movl %ecx, 8(%eax)
movl %ebx, 4(%eax)
movl 8(%esp), %eax
movl 4(%eax), %ebx
movl 8(%eax), %ecx
movl 12(%eax), %edx
movl 16(%eax), %edi
movl 20(%eax), %esi
movl 24(%eax), %ebp
movl 28(%eax), %esp
ret
#elif defined(__x86_64__)
leaq (%rsp),%rax
movq %rax, 104(%rdi)
movq %rbx, 96(%rdi)
movq %rcx, 88(%rdi)
movq %rdx, 80(%rdi)
movq 0(%rax), %rax
movq %rax, 72(%rdi)
movq %rsi, 64(%rdi)
movq %rdi, 56(%rdi)
movq %rbp, 48(%rdi)
movq %r8, 40(%rdi)
movq %r9, 32(%rdi)
movq %r12, 24(%rdi)
movq %r13, 16(%rdi)
movq %r14, 8(%rdi)
movq %r15, (%rdi)
xorq %rax, %rax
movq 48(%rsi), %rbp
movq 104(%rsi), %rsp
movq (%rsi), %r15
movq 8(%rsi), %r14
movq 16(%rsi), %r13
movq 24(%rsi), %r12
movq 32(%rsi), %r9
movq 40(%rsi), %r8
movq 56(%rsi), %rdi
movq 80(%rsi), %rdx
movq 88(%rsi), %rcx
movq 96(%rsi), %rbx
leaq 8(%rsp), %rsp
pushq 72(%rsi)
movq 64(%rsi), %rsi
ret
#endif

View file

@ -0,0 +1,91 @@
/*
* Tencent is pleased to support the open source community by making Libco available.
* Copyright (C) 2014 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "co_closure.h"
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <pthread.h>
#include <unistd.h>
using namespace std;
static void *thread_func( void * arg )
{
stCoClosure_t *p = (stCoClosure_t*) arg;
p->exec();
return 0;
}
static void batch_exec( vector<stCoClosure_t*> &v )
{
vector<pthread_t> ths;
for( size_t i=0;i<v.size();i++ )
{
pthread_t tid;
pthread_create( &tid,0,thread_func,v[i] );
ths.push_back( tid );
}
for( size_t i=0;i<v.size();i++ )
{
pthread_join( ths[i],0 );
}
}
int main( int argc,char *argv[] )
{
vector< stCoClosure_t* > v;
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
int total = 100;
vector<int> v2;
co_ref( ref,total,v2,m);
for(int i=0;i<10;i++)
{
co_func( f,ref,i )
{
printf("ref.total %d i %d\n",ref.total,i );
//lock
pthread_mutex_lock(&ref.m);
ref.v2.push_back( i );
pthread_mutex_unlock(&ref.m);
//unlock
}
co_func_end;
v.push_back( new f( ref,i ) );
}
for(int i=0;i<2;i++)
{
co_func( f2,i )
{
printf("i: %d\n",i);
for(int j=0;j<2;j++)
{
usleep( 1000 );
printf("i %d j %d\n",i,j);
}
}
co_func_end;
v.push_back( new f2( i ) );
}
batch_exec( v );
printf("done\n");
return 0;
}

83
trunk/3rdparty/libco/example_cond.cpp vendored Normal file
View file

@ -0,0 +1,83 @@
/*
* Tencent is pleased to support the open source community by making Libco available.
* Copyright (C) 2014 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <queue>
#include "co_routine.h"
using namespace std;
struct stTask_t
{
int id;
};
struct stEnv_t
{
stCoCond_t* cond;
queue<stTask_t*> task_queue;
};
void* Producer(void* args)
{
co_enable_hook_sys();
stEnv_t* env= (stEnv_t*)args;
int id = 0;
while (true)
{
stTask_t* task = (stTask_t*)calloc(1, sizeof(stTask_t));
task->id = id++;
env->task_queue.push(task);
printf("%s:%d produce task %d\n", __func__, __LINE__, task->id);
co_cond_signal(env->cond);
poll(NULL, 0, 1000);
}
return NULL;
}
void* Consumer(void* args)
{
co_enable_hook_sys();
stEnv_t* env = (stEnv_t*)args;
while (true)
{
if (env->task_queue.empty())
{
co_cond_timedwait(env->cond, -1);
continue;
}
stTask_t* task = env->task_queue.front();
env->task_queue.pop();
printf("%s:%d consume task %d\n", __func__, __LINE__, task->id);
free(task);
}
return NULL;
}
int main()
{
stEnv_t* env = new stEnv_t;
env->cond = co_cond_alloc();
stCoRoutine_t* consumer_routine;
co_create(&consumer_routine, NULL, Consumer, env);
co_resume(consumer_routine);
stCoRoutine_t* producer_routine;
co_create(&producer_routine, NULL, Producer, env);
co_resume(producer_routine);
co_eventloop(co_get_epoll_ct(), NULL, NULL);
return 0;
}

View file

@ -0,0 +1,61 @@
/*
* Tencent is pleased to support the open source community by making Libco available.
* Copyright (C) 2014 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <errno.h>
#include <string.h>
#include "coctx.h"
#include "co_routine.h"
#include "co_routine_inner.h"
void* RoutineFunc(void* args)
{
co_enable_hook_sys();
int* routineid = (int*)args;
while (true)
{
char sBuff[128];
sprintf(sBuff, "from routineid %d stack addr %p\n", *routineid, sBuff);
printf("%s", sBuff);
poll(NULL, 0, 1000); //sleep 1s
}
return NULL;
}
int main()
{
stShareStack_t* share_stack= co_alloc_sharestack(1, 1024 * 128);
stCoRoutineAttr_t attr;
attr.stack_size = 0;
attr.share_stack = share_stack;
stCoRoutine_t* co[2];
int routineid[2];
for (int i = 0; i < 2; i++)
{
routineid[i] = i;
co_create(&co[i], &attr, RoutineFunc, routineid + i);
co_resume(co[i]);
}
co_eventloop(co_get_epoll_ct(), NULL, NULL);
return 0;
}

218
trunk/3rdparty/libco/example_echocli.cpp vendored Normal file
View file

@ -0,0 +1,218 @@
/*
* Tencent is pleased to support the open source community by making Libco available.
* Copyright (C) 2014 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "co_routine.h"
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
#include <stack>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <signal.h>
using namespace std;
struct stEndPoint
{
char *ip;
unsigned short int port;
};
static void SetAddr(const char *pszIP,const unsigned short shPort,struct sockaddr_in &addr)
{
bzero(&addr,sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(shPort);
int nIP = 0;
if( !pszIP || '\0' == *pszIP
|| 0 == strcmp(pszIP,"0") || 0 == strcmp(pszIP,"0.0.0.0")
|| 0 == strcmp(pszIP,"*")
)
{
nIP = htonl(INADDR_ANY);
}
else
{
nIP = inet_addr(pszIP);
}
addr.sin_addr.s_addr = nIP;
}
static int iSuccCnt = 0;
static int iFailCnt = 0;
static int iTime = 0;
void AddSuccCnt()
{
int now = time(NULL);
if (now >iTime)
{
printf("time %d Succ Cnt %d Fail Cnt %d\n", iTime, iSuccCnt, iFailCnt);
iTime = now;
iSuccCnt = 0;
iFailCnt = 0;
}
else
{
iSuccCnt++;
}
}
void AddFailCnt()
{
int now = time(NULL);
if (now >iTime)
{
printf("time %d Succ Cnt %d Fail Cnt %d\n", iTime, iSuccCnt, iFailCnt);
iTime = now;
iSuccCnt = 0;
iFailCnt = 0;
}
else
{
iFailCnt++;
}
}
static void *readwrite_routine( void *arg )
{
co_enable_hook_sys();
stEndPoint *endpoint = (stEndPoint *)arg;
char str[8]="sarlmol";
char buf[ 1024 * 16 ];
int fd = -1;
int ret = 0;
for(;;)
{
if ( fd < 0 )
{
fd = socket(PF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr;
SetAddr(endpoint->ip, endpoint->port, addr);
ret = connect(fd,(struct sockaddr*)&addr,sizeof(addr));
if ( errno == EALREADY || errno == EINPROGRESS )
{
struct pollfd pf = { 0 };
pf.fd = fd;
pf.events = (POLLOUT|POLLERR|POLLHUP);
co_poll( co_get_epoll_ct(),&pf,1,200);
//check connect
int error = 0;
uint32_t socklen = sizeof(error);
errno = 0;
ret = getsockopt(fd, SOL_SOCKET, SO_ERROR,(void *)&error, &socklen);
if ( ret == -1 )
{
//printf("getsockopt ERROR ret %d %d:%s\n", ret, errno, strerror(errno));
close(fd);
fd = -1;
AddFailCnt();
continue;
}
if ( error )
{
errno = error;
//printf("connect ERROR ret %d %d:%s\n", error, errno, strerror(errno));
close(fd);
fd = -1;
AddFailCnt();
continue;
}
}
}
ret = write( fd,str, 8);
if ( ret > 0 )
{
ret = read( fd,buf, sizeof(buf) );
if ( ret <= 0 )
{
//printf("co %p read ret %d errno %d (%s)\n",
// co_self(), ret,errno,strerror(errno));
close(fd);
fd = -1;
AddFailCnt();
}
else
{
//printf("echo %s fd %d\n", buf,fd);
AddSuccCnt();
}
}
else
{
//printf("co %p write ret %d errno %d (%s)\n",
// co_self(), ret,errno,strerror(errno));
close(fd);
fd = -1;
AddFailCnt();
}
}
return 0;
}
int main(int argc,char *argv[])
{
stEndPoint endpoint;
endpoint.ip = argv[1];
endpoint.port = atoi(argv[2]);
int cnt = atoi( argv[3] );
int proccnt = atoi( argv[4] );
struct sigaction sa;
sa.sa_handler = SIG_IGN;
sigaction( SIGPIPE, &sa, NULL );
for(int k=0;k<proccnt;k++)
{
pid_t pid = fork();
if( pid > 0 )
{
continue;
}
else if( pid < 0 )
{
break;
}
for(int i=0;i<cnt;i++)
{
stCoRoutine_t *co = 0;
co_create( &co,NULL,readwrite_routine, &endpoint);
co_resume( co );
}
co_eventloop( co_get_epoll_ct(),0,0 );
exit(0);
}
return 0;
}
/*./example_echosvr 127.0.0.1 10000 100 50*/

255
trunk/3rdparty/libco/example_echosvr.cpp vendored Normal file
View file

@ -0,0 +1,255 @@
/*
* Tencent is pleased to support the open source community by making Libco available.
* Copyright (C) 2014 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "co_routine.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/time.h>
#include <stack>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>
#ifdef __FreeBSD__
#include <cstring>
#include <sys/types.h>
#include <sys/wait.h>
#endif
using namespace std;
struct task_t
{
stCoRoutine_t *co;
int fd;
};
static stack<task_t*> g_readwrite;
static int g_listen_fd = -1;
static int SetNonBlock(int iSock)
{
int iFlags;
iFlags = fcntl(iSock, F_GETFL, 0);
iFlags |= O_NONBLOCK;
iFlags |= O_NDELAY;
int ret = fcntl(iSock, F_SETFL, iFlags);
return ret;
}
static void *readwrite_routine( void *arg )
{
co_enable_hook_sys();
task_t *co = (task_t*)arg;
char buf[ 1024 * 16 ];
for(;;)
{
if( -1 == co->fd )
{
g_readwrite.push( co );
co_yield_ct();
continue;
}
int fd = co->fd;
co->fd = -1;
for(;;)
{
struct pollfd pf = { 0 };
pf.fd = fd;
pf.events = (POLLIN|POLLERR|POLLHUP);
co_poll( co_get_epoll_ct(),&pf,1,1000);
int ret = read( fd,buf,sizeof(buf) );
if( ret > 0 )
{
ret = write( fd,buf,ret );
}
if( ret > 0 || ( -1 == ret && EAGAIN == errno ) )
{
continue;
}
close( fd );
break;
}
}
return 0;
}
int co_accept(int fd, struct sockaddr *addr, socklen_t *len );
static void *accept_routine( void * )
{
co_enable_hook_sys();
printf("accept_routine\n");
fflush(stdout);
for(;;)
{
//printf("pid %ld g_readwrite.size %ld\n",getpid(),g_readwrite.size());
if( g_readwrite.empty() )
{
printf("empty\n"); //sleep
struct pollfd pf = { 0 };
pf.fd = -1;
poll( &pf,1,1000);
continue;
}
struct sockaddr_in addr; //maybe sockaddr_un;
memset( &addr,0,sizeof(addr) );
socklen_t len = sizeof(addr);
int fd = co_accept(g_listen_fd, (struct sockaddr *)&addr, &len);
if( fd < 0 )
{
struct pollfd pf = { 0 };
pf.fd = g_listen_fd;
pf.events = (POLLIN|POLLERR|POLLHUP);
co_poll( co_get_epoll_ct(),&pf,1,1000 );
continue;
}
if( g_readwrite.empty() )
{
close( fd );
continue;
}
SetNonBlock( fd );
task_t *co = g_readwrite.top();
co->fd = fd;
g_readwrite.pop();
co_resume( co->co );
}
return 0;
}
static void SetAddr(const char *pszIP,const unsigned short shPort,struct sockaddr_in &addr)
{
bzero(&addr,sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(shPort);
int nIP = 0;
if( !pszIP || '\0' == *pszIP
|| 0 == strcmp(pszIP,"0") || 0 == strcmp(pszIP,"0.0.0.0")
|| 0 == strcmp(pszIP,"*")
)
{
nIP = htonl(INADDR_ANY);
}
else
{
nIP = inet_addr(pszIP);
}
addr.sin_addr.s_addr = nIP;
}
static int CreateTcpSocket(const unsigned short shPort /* = 0 */,const char *pszIP /* = "*" */,bool bReuse /* = false */)
{
int fd = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);
if( fd >= 0 )
{
if(shPort != 0)
{
if(bReuse)
{
int nReuseAddr = 1;
setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&nReuseAddr,sizeof(nReuseAddr));
}
struct sockaddr_in addr ;
SetAddr(pszIP,shPort,addr);
int ret = bind(fd,(struct sockaddr*)&addr,sizeof(addr));
if( ret != 0)
{
close(fd);
return -1;
}
}
}
return fd;
}
int main(int argc,char *argv[])
{
if(argc<5){
printf("Usage:\n"
"example_echosvr [IP] [PORT] [TASK_COUNT] [PROCESS_COUNT]\n"
"example_echosvr [IP] [PORT] [TASK_COUNT] [PROCESS_COUNT] -d # daemonize mode\n");
return -1;
}
const char *ip = argv[1];
int port = atoi( argv[2] );
int cnt = atoi( argv[3] );
int proccnt = atoi( argv[4] );
bool deamonize = argc >= 6 && strcmp(argv[5], "-d") == 0;
g_listen_fd = CreateTcpSocket( port,ip,true );
listen( g_listen_fd,1024 );
if(g_listen_fd==-1){
printf("Port %d is in use\n", port);
return -1;
}
printf("listen %d %s:%d\n",g_listen_fd,ip,port);
SetNonBlock( g_listen_fd );
for(int k=0;k<proccnt;k++)
{
pid_t pid = fork();
if( pid > 0 )
{
continue;
}
else if( pid < 0 )
{
break;
}
for(int i=0;i<cnt;i++)
{
task_t * task = (task_t*)calloc( 1,sizeof(task_t) );
task->fd = -1;
co_create( &(task->co),NULL,readwrite_routine,task );
co_resume( task->co );
}
stCoRoutine_t *accept_co = NULL;
co_create( &accept_co,NULL,accept_routine,0 );
co_resume( accept_co );
co_eventloop( co_get_epoll_ct(),0,0 );
exit(0);
}
if(!deamonize) wait(NULL);
return 0;
}

211
trunk/3rdparty/libco/example_poll.cpp vendored Normal file
View file

@ -0,0 +1,211 @@
/*
* Tencent is pleased to support the open source community by making Libco available.
* Copyright (C) 2014 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "co_routine.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/time.h>
#include <stack>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <errno.h>
#include <vector>
#include <set>
#include <unistd.h>
#ifdef __FreeBSD__
#include <cstring>
#endif
using namespace std;
struct task_t
{
stCoRoutine_t *co;
int fd;
struct sockaddr_in addr;
};
static int SetNonBlock(int iSock)
{
int iFlags;
iFlags = fcntl(iSock, F_GETFL, 0);
iFlags |= O_NONBLOCK;
iFlags |= O_NDELAY;
int ret = fcntl(iSock, F_SETFL, iFlags);
return ret;
}
static void SetAddr(const char *pszIP,const unsigned short shPort,struct sockaddr_in &addr)
{
bzero(&addr,sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(shPort);
int nIP = 0;
if( !pszIP || '\0' == *pszIP
|| 0 == strcmp(pszIP,"0") || 0 == strcmp(pszIP,"0.0.0.0")
|| 0 == strcmp(pszIP,"*")
)
{
nIP = htonl(INADDR_ANY);
}
else
{
nIP = inet_addr(pszIP);
}
addr.sin_addr.s_addr = nIP;
}
static int CreateTcpSocket(const unsigned short shPort = 0 ,const char *pszIP = "*" ,bool bReuse = false )
{
int fd = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);
if( fd >= 0 )
{
if(shPort != 0)
{
if(bReuse)
{
int nReuseAddr = 1;
setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&nReuseAddr,sizeof(nReuseAddr));
}
struct sockaddr_in addr ;
SetAddr(pszIP,shPort,addr);
int ret = bind(fd,(struct sockaddr*)&addr,sizeof(addr));
if( ret != 0)
{
close(fd);
return -1;
}
}
}
return fd;
}
static void *poll_routine( void *arg )
{
co_enable_hook_sys();
vector<task_t> &v = *(vector<task_t>*)arg;
for(size_t i=0;i<v.size();i++)
{
int fd = CreateTcpSocket();
SetNonBlock( fd );
v[i].fd = fd;
int ret = connect(fd,(struct sockaddr*)&v[i].addr,sizeof( v[i].addr ));
printf("co %p connect i %ld ret %d errno %d (%s)\n",
co_self(),i,ret,errno,strerror(errno));
}
struct pollfd *pf = (struct pollfd*)calloc( 1,sizeof(struct pollfd) * v.size() );
for(size_t i=0;i<v.size();i++)
{
pf[i].fd = v[i].fd;
pf[i].events = ( POLLOUT | POLLERR | POLLHUP );
}
set<int> setRaiseFds;
size_t iWaitCnt = v.size();
for(;;)
{
int ret = poll( pf,iWaitCnt,1000 );
printf("co %p poll wait %ld ret %d\n",
co_self(),iWaitCnt,ret);
for(int i=0;i<(int)iWaitCnt;i++)
{
printf("co %p fire fd %d revents 0x%X POLLOUT 0x%X POLLERR 0x%X POLLHUP 0x%X\n",
co_self(),
pf[i].fd,
pf[i].revents,
POLLOUT,
POLLERR,
POLLHUP
);
setRaiseFds.insert( pf[i].fd );
}
if( setRaiseFds.size() == v.size())
{
break;
}
if( ret <= 0 )
{
break;
}
iWaitCnt = 0;
for(size_t i=0;i<v.size();i++)
{
if( setRaiseFds.find( v[i].fd ) == setRaiseFds.end() )
{
pf[ iWaitCnt ].fd = v[i].fd;
pf[ iWaitCnt ].events = ( POLLOUT | POLLERR | POLLHUP );
++iWaitCnt;
}
}
}
for(size_t i=0;i<v.size();i++)
{
close( v[i].fd );
v[i].fd = -1;
}
printf("co %p task cnt %ld fire %ld\n",
co_self(),v.size(),setRaiseFds.size() );
return 0;
}
int main(int argc,char *argv[])
{
vector<task_t> v;
for(int i=1;i<argc;i+=2)
{
task_t task = { 0 };
SetAddr( argv[i],atoi(argv[i+1]),task.addr );
v.push_back( task );
}
//------------------------------------------------------------------------------------
printf("--------------------- main -------------------\n");
vector<task_t> v2 = v;
poll_routine( &v2 );
printf("--------------------- routine -------------------\n");
for(int i=0;i<10;i++)
{
stCoRoutine_t *co = 0;
vector<task_t> *v2 = new vector<task_t>();
*v2 = v;
co_create( &co,NULL,poll_routine,v2 );
printf("routine i %d\n",i);
co_resume( co );
}
co_eventloop( co_get_epoll_ct(),0,0 );
return 0;
}
//./example_poll 127.0.0.1 12365 127.0.0.1 12222 192.168.1.1 1000 192.168.1.2 1111

89
trunk/3rdparty/libco/example_setenv.cpp vendored Normal file
View file

@ -0,0 +1,89 @@
/*
* Tencent is pleased to support the open source community by making Libco available.
* Copyright (C) 2014 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <queue>
#include "co_routine.h"
const char* CGI_ENV_HOOK_LIST [] =
{
"CGINAME",
};
struct stRoutineArgs_t
{
int iRoutineID;
};
void SetAndGetEnv(int iRoutineID)
{
printf("routineid %d begin\n", iRoutineID);
//use poll as sleep
poll(NULL, 0, 500);
char sBuf[128];
sprintf(sBuf, "cgi_routine_%d", iRoutineID);
int ret = setenv("CGINAME", sBuf, 1);
if (ret)
{
printf("%s:%d set env err ret %d errno %d %s\n", __func__, __LINE__,
ret, errno, strerror(errno));
return;
}
printf("routineid %d set env CGINAME %s\n", iRoutineID, sBuf);
poll(NULL, 0, 500);
char* env = getenv("CGINAME");
if (!env)
{
printf("%s:%d get env err errno %d %s\n", __func__, __LINE__,
errno, strerror(errno));
return;
}
printf("routineid %d get env CGINAME %s\n", iRoutineID, env);
}
void* RoutineFunc(void* args)
{
co_enable_hook_sys();
stRoutineArgs_t* g = (stRoutineArgs_t*)args;
SetAndGetEnv(g->iRoutineID);
return NULL;
}
int main(int argc, char* argv[])
{
co_set_env_list(CGI_ENV_HOOK_LIST, sizeof(CGI_ENV_HOOK_LIST) / sizeof(char*));
stRoutineArgs_t args[3];
for (int i = 0; i < 3; i++)
{
stCoRoutine_t* co = NULL;
args[i].iRoutineID = i;
co_create(&co, NULL, RoutineFunc, &args[i]);
co_resume(co);
}
co_eventloop(co_get_epoll_ct(), NULL, NULL);
return 0;
}

View file

@ -0,0 +1,61 @@
/*
* Tencent is pleased to support the open source community by making Libco available.
* Copyright (C) 2014 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "co_routine_specific.h"
#include "co_routine.h"
#include <unistd.h>
#include <stdio.h>
#include <vector>
#include <iostream>
using namespace std;
struct stRoutineArgs_t
{
stCoRoutine_t* co;
int routine_id;
};
struct stRoutineSpecificData_t
{
int idx;
};
CO_ROUTINE_SPECIFIC(stRoutineSpecificData_t, __routine);
void* RoutineFunc(void* args)
{
co_enable_hook_sys();
stRoutineArgs_t* routine_args = (stRoutineArgs_t*)args;
__routine->idx = routine_args->routine_id;
while (true)
{
printf("%s:%d routine specific data idx %d\n", __func__, __LINE__, __routine->idx);
poll(NULL, 0, 1000);
}
return NULL;
}
int main()
{
stRoutineArgs_t args[10];
for (int i = 0; i < 10; i++)
{
args[i].routine_id = i;
co_create(&args[i].co, NULL, RoutineFunc, (void*)&args[i]);
co_resume(args[i].co);
}
co_eventloop(co_get_epoll_ct(), NULL, NULL);
return 0;
}

56
trunk/3rdparty/libco/example_thread.cpp vendored Normal file
View file

@ -0,0 +1,56 @@
/*
* Tencent is pleased to support the open source community by making Libco available.
* Copyright (C) 2014 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "co_routine.h"
#include "co_routine_inner.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <pthread.h>
#include <unistd.h>
int loop(void *)
{
return 0;
}
static void *routine_func( void * )
{
stCoEpoll_t * ev = co_get_epoll_ct(); //ct = current thread
co_eventloop( ev,loop,0 );
return 0;
}
int main(int argc,char *argv[])
{
int cnt = atoi( argv[1] );
pthread_t tid[ cnt ];
for(int i=0;i<cnt;i++)
{
pthread_create( tid + i,NULL,routine_func,0);
}
for(;;)
{
sleep(1);
}
return 0;
}