mirror of
https://github.com/Tencent/libco.git
synced 2025-05-08 19:51:15 +08:00
libco
Tencent libco
This commit is contained in:
commit
4b41ba0ce2
164
BUILD
Normal file
164
BUILD
Normal file
@ -0,0 +1,164 @@
|
||||
cc_library(
|
||||
name = 'colib',
|
||||
target_bases = [ 'comm',],
|
||||
srcs = [
|
||||
'co_hook_sys_call.cpp',
|
||||
'co_routine.cpp',
|
||||
'coctx.cpp',
|
||||
'coctx_swap.S',
|
||||
'co_epoll.cpp',
|
||||
|
||||
],
|
||||
deps = [
|
||||
],
|
||||
defs = [
|
||||
'LINUX',
|
||||
'_PTHREADS',
|
||||
'TIXML_USE_STL',
|
||||
],
|
||||
optimize = [
|
||||
#'O2',
|
||||
],
|
||||
extra_cppflags = [
|
||||
#'-O2' ,
|
||||
#'-Werror',
|
||||
],
|
||||
)
|
||||
cc_binary(
|
||||
name = 'global_sym',
|
||||
srcs = [
|
||||
'demangle.cpp',
|
||||
'global_sym.cpp'
|
||||
|
||||
],
|
||||
deps = [
|
||||
|
||||
|
||||
#GEN_SOURCE_POS__
|
||||
],
|
||||
defs = [
|
||||
'LINUX',
|
||||
'_PTHREADS',
|
||||
'TIXML_USE_STL',
|
||||
'_NEW_LIC',
|
||||
'_GNU_SOURCE',
|
||||
'_REENTRANT',
|
||||
|
||||
],
|
||||
optimize = [
|
||||
'O2',
|
||||
],
|
||||
extra_cppflags = [
|
||||
#'-Werror',
|
||||
#'-Werror',
|
||||
'-pipe',
|
||||
'-fPIC',
|
||||
'-Wno-deprecated',
|
||||
|
||||
],
|
||||
incs = [
|
||||
#INCS_POS__
|
||||
],
|
||||
)
|
||||
cc_binary(
|
||||
name = 'test_specific',
|
||||
srcs = [
|
||||
'test_specific.cpp',
|
||||
|
||||
],
|
||||
deps = [
|
||||
':colib',
|
||||
'//comm2/core:core',
|
||||
|
||||
#GEN_SOURCE_POS__
|
||||
],
|
||||
defs = [
|
||||
'LINUX',
|
||||
'_PTHREADS',
|
||||
'TIXML_USE_STL',
|
||||
'_NEW_LIC',
|
||||
'_GNU_SOURCE',
|
||||
'_REENTRANT',
|
||||
|
||||
],
|
||||
optimize = [
|
||||
'O2',
|
||||
],
|
||||
extra_cppflags = [
|
||||
#'-Werror',
|
||||
#'-Werror',
|
||||
'-pipe',
|
||||
'-fPIC',
|
||||
'-Wno-deprecated',
|
||||
|
||||
],
|
||||
incs = [
|
||||
#INCS_POS__
|
||||
],
|
||||
)
|
||||
cc_binary(
|
||||
name = 'echosvr',
|
||||
srcs = [
|
||||
'example_echosvr_copystack.cpp',
|
||||
|
||||
],
|
||||
deps = [
|
||||
':colib',
|
||||
'//comm2/core:core',
|
||||
|
||||
#GEN_SOURCE_POS__
|
||||
],
|
||||
defs = [
|
||||
'LINUX',
|
||||
'_PTHREADS',
|
||||
'TIXML_USE_STL',
|
||||
'_NEW_LIC',
|
||||
'_GNU_SOURCE',
|
||||
'_REENTRANT',
|
||||
|
||||
],
|
||||
optimize = [
|
||||
'O2',
|
||||
],
|
||||
extra_cppflags = [
|
||||
#'-Werror',
|
||||
#'-Werror',
|
||||
'-pipe',
|
||||
'-fPIC',
|
||||
'-Wno-deprecated',
|
||||
|
||||
],
|
||||
incs = [
|
||||
#INCS_POS__
|
||||
],
|
||||
)
|
||||
cc_binary(
|
||||
name = 'test_colib',
|
||||
srcs = [
|
||||
'test_colib.cpp',
|
||||
'test_xmm.S',
|
||||
],
|
||||
deps = [
|
||||
':colib',
|
||||
'//mm3rd/gtest:gtest',
|
||||
'#dl',
|
||||
#GEN_SOURCE_POS__
|
||||
],
|
||||
defs = [
|
||||
],
|
||||
optimize = [
|
||||
'O2',
|
||||
],
|
||||
extra_cppflags = [
|
||||
#'-Werror',
|
||||
#'-Werror',
|
||||
'-pipe',
|
||||
'-fPIC',
|
||||
'-Wno-deprecated',
|
||||
'-DLIBCO-USE-GETTICK',
|
||||
|
||||
],
|
||||
incs = [
|
||||
#INCS_POS__
|
||||
],
|
||||
)
|
BIN
LICENSE.txt
Normal file
BIN
LICENSE.txt
Normal file
Binary file not shown.
77
Makefile
Normal file
77
Makefile
Normal file
@ -0,0 +1,77 @@
|
||||
#
|
||||
# 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
|
||||
|
||||
LINKS += -g -L./lib -lcolib -lpthread -ldl
|
||||
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
86
co.mk
Normal file
86
co.mk
Normal 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.
|
||||
#
|
||||
|
||||
|
||||
|
||||
##### Makefile Rules ##########
|
||||
MAIL_ROOT=.
|
||||
SRCROOT=.
|
||||
|
||||
##define the compliers
|
||||
CPP = g++
|
||||
CC = gcc
|
||||
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)
|
92
co_closure.h
Normal file
92
co_closure.h
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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( _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( __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
|
||||
#define decl_typeof( i,a,... ) typedef typeof( a ) typeof_##a;
|
||||
#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
|
||||
|
325
co_epoll.cpp
Normal file
325
co_epoll.cpp
Normal file
@ -0,0 +1,325 @@
|
||||
/*
|
||||
* 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>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef __APPLE__
|
||||
|
||||
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
|
||||
|
||||
//gzrd_Lib_CPP_Version_ID--start
|
||||
#ifndef GZRD_SVN_ATTR
|
||||
#define GZRD_SVN_ATTR "0"
|
||||
#endif
|
||||
static char gzrd_Lib_CPP_Version_ID[] __attribute__((used))="$HeadURL: http://tc-svn.tencent.com/pub/pub_libco_rep/libco_proj/trunk/co_epoll.cpp $ $Id: co_epoll.cpp 39 2016-09-29 07:26:29Z leiffyli $ " GZRD_SVN_ATTR "__file__";
|
||||
// gzrd_Lib_CPP_Version_ID--end
|
||||
|
90
co_epoll.h
Normal file
90
co_epoll.h
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
#ifndef __APPLE__
|
||||
|
||||
#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,
|
||||
};
|
||||
#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
|
||||
|
||||
|
734
co_hook_sys_call.cpp
Normal file
734
co_hook_sys_call.cpp
Normal file
@ -0,0 +1,734 @@
|
||||
/*
|
||||
* 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 <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <poll.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <resolv.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include <time.h>
|
||||
#include "co_routine.h"
|
||||
#include "co_routine_inner.h"
|
||||
#include "co_routine_specific.h"
|
||||
|
||||
typedef long long ll64_t;
|
||||
|
||||
struct rpchook_t
|
||||
{
|
||||
int user_flag;
|
||||
struct sockaddr_in dest; //maybe sockaddr_un;
|
||||
int domain; //AF_LOCAL , AF_INET
|
||||
|
||||
struct timeval read_timeout;
|
||||
struct timeval write_timeout;
|
||||
};
|
||||
static inline pid_t GetPid()
|
||||
{
|
||||
char **p = (char**)pthread_self();
|
||||
return p ? *(pid_t*)(p + 18) : getpid();
|
||||
}
|
||||
static rpchook_t *g_rpchook_socket_fd[ 102400 ] = { 0 };
|
||||
|
||||
typedef int (*socket_pfn_t)(int domain, int type, int protocol);
|
||||
typedef int (*connect_pfn_t)(int socket, const struct sockaddr *address, socklen_t address_len);
|
||||
typedef int (*close_pfn_t)(int fd);
|
||||
|
||||
typedef ssize_t (*read_pfn_t)(int fildes, void *buf, size_t nbyte);
|
||||
typedef ssize_t (*write_pfn_t)(int fildes, const void *buf, size_t nbyte);
|
||||
|
||||
typedef ssize_t (*sendto_pfn_t)(int socket, const void *message, size_t length,
|
||||
int flags, const struct sockaddr *dest_addr,
|
||||
socklen_t dest_len);
|
||||
|
||||
typedef ssize_t (*recvfrom_pfn_t)(int socket, void *buffer, size_t length,
|
||||
int flags, struct sockaddr *address,
|
||||
socklen_t *address_len);
|
||||
|
||||
typedef size_t (*send_pfn_t)(int socket, const void *buffer, size_t length, int flags);
|
||||
typedef ssize_t (*recv_pfn_t)(int socket, void *buffer, size_t length, int flags);
|
||||
|
||||
typedef int (*poll_pfn_t)(struct pollfd fds[], nfds_t nfds, int timeout);
|
||||
typedef int (*setsockopt_pfn_t)(int socket, int level, int option_name,
|
||||
const void *option_value, socklen_t option_len);
|
||||
|
||||
typedef int (*fcntl_pfn_t)(int fildes, int cmd, ...);
|
||||
typedef struct tm *(*localtime_r_pfn_t)( const time_t *timep, struct tm *result );
|
||||
|
||||
typedef void *(*pthread_getspecific_pfn_t)(pthread_key_t key);
|
||||
typedef int (*pthread_setspecific_pfn_t)(pthread_key_t key, const void *value);
|
||||
|
||||
typedef hostent* (*gethostbyname_pfn_t)(const char *name);
|
||||
typedef res_state (*__res_state_pfn_t)();
|
||||
typedef int (*__poll_pfn_t)(struct pollfd fds[], nfds_t nfds, int timeout);
|
||||
|
||||
static socket_pfn_t g_sys_socket_func = (socket_pfn_t)dlsym(RTLD_NEXT,"socket");
|
||||
static connect_pfn_t g_sys_connect_func = (connect_pfn_t)dlsym(RTLD_NEXT,"connect");
|
||||
static close_pfn_t g_sys_close_func = (close_pfn_t)dlsym(RTLD_NEXT,"close");
|
||||
|
||||
static read_pfn_t g_sys_read_func = (read_pfn_t)dlsym(RTLD_NEXT,"read");
|
||||
static write_pfn_t g_sys_write_func = (write_pfn_t)dlsym(RTLD_NEXT,"write");
|
||||
|
||||
static sendto_pfn_t g_sys_sendto_func = (sendto_pfn_t)dlsym(RTLD_NEXT,"sendto");
|
||||
static recvfrom_pfn_t g_sys_recvfrom_func = (recvfrom_pfn_t)dlsym(RTLD_NEXT,"recvfrom");
|
||||
|
||||
static send_pfn_t g_sys_send_func = (send_pfn_t)dlsym(RTLD_NEXT,"send");
|
||||
static recv_pfn_t g_sys_recv_func = (recv_pfn_t)dlsym(RTLD_NEXT,"recv");
|
||||
|
||||
static poll_pfn_t g_sys_poll_func = (poll_pfn_t)dlsym(RTLD_NEXT,"poll");
|
||||
|
||||
static setsockopt_pfn_t g_sys_setsockopt_func
|
||||
= (setsockopt_pfn_t)dlsym(RTLD_NEXT,"setsockopt");
|
||||
static fcntl_pfn_t g_sys_fcntl_func = (fcntl_pfn_t)dlsym(RTLD_NEXT,"fcntl");
|
||||
|
||||
static __res_state_pfn_t g_sys___res_state_func = (__res_state_pfn_t)dlsym(RTLD_NEXT,"__res_state");
|
||||
|
||||
static gethostbyname_pfn_t g_sys_gethostbyname_func = (gethostbyname_pfn_t)dlsym(RTLD_NEXT, "gethostbyname");
|
||||
|
||||
static __poll_pfn_t g_sys___poll_func = (__poll_pfn_t)dlsym(RTLD_NEXT, "__poll");
|
||||
|
||||
|
||||
/*
|
||||
static pthread_getspecific_pfn_t g_sys_pthread_getspecific_func
|
||||
= (pthread_getspecific_pfn_t)dlsym(RTLD_NEXT,"pthread_getspecific");
|
||||
|
||||
static pthread_setspecific_pfn_t g_sys_pthread_setspecific_func
|
||||
= (pthread_setspecific_pfn_t)dlsym(RTLD_NEXT,"pthread_setspecific");
|
||||
|
||||
static pthread_rwlock_rdlock_pfn_t g_sys_pthread_rwlock_rdlock_func
|
||||
= (pthread_rwlock_rdlock_pfn_t)dlsym(RTLD_NEXT,"pthread_rwlock_rdlock");
|
||||
|
||||
static pthread_rwlock_wrlock_pfn_t g_sys_pthread_rwlock_wrlock_func
|
||||
= (pthread_rwlock_wrlock_pfn_t)dlsym(RTLD_NEXT,"pthread_rwlock_wrlock");
|
||||
|
||||
static pthread_rwlock_unlock_pfn_t g_sys_pthread_rwlock_unlock_func
|
||||
= (pthread_rwlock_unlock_pfn_t)dlsym(RTLD_NEXT,"pthread_rwlock_unlock");
|
||||
*/
|
||||
|
||||
|
||||
|
||||
static inline unsigned long long get_tick_count()
|
||||
{
|
||||
uint32_t lo, hi;
|
||||
__asm__ __volatile__ (
|
||||
"rdtscp" : "=a"(lo), "=d"(hi)
|
||||
);
|
||||
return ((unsigned long long)lo) | (((unsigned long long)hi) << 32);
|
||||
}
|
||||
|
||||
struct rpchook_connagent_head_t
|
||||
{
|
||||
unsigned char bVersion;
|
||||
struct in_addr iIP;
|
||||
unsigned short hPort;
|
||||
unsigned int iBodyLen;
|
||||
unsigned int iOssAttrID;
|
||||
unsigned char bIsRespNotExist;
|
||||
unsigned char sReserved[6];
|
||||
}__attribute__((packed));
|
||||
|
||||
|
||||
#define HOOK_SYS_FUNC(name) if( !g_sys_##name##_func ) { g_sys_##name##_func = (name##_pfn_t)dlsym(RTLD_NEXT,#name); }
|
||||
|
||||
static inline ll64_t diff_ms(struct timeval &begin,struct timeval &end)
|
||||
{
|
||||
ll64_t u = (end.tv_sec - begin.tv_sec) ;
|
||||
u *= 1000 * 10;
|
||||
u += ( end.tv_usec - begin.tv_usec ) / ( 100 );
|
||||
return u;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static inline rpchook_t * get_by_fd( int fd )
|
||||
{
|
||||
if( fd > -1 && fd < (int)sizeof(g_rpchook_socket_fd) / (int)sizeof(g_rpchook_socket_fd[0]) )
|
||||
{
|
||||
return g_rpchook_socket_fd[ fd ];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
static inline rpchook_t * alloc_by_fd( int fd )
|
||||
{
|
||||
if( fd > -1 && fd < (int)sizeof(g_rpchook_socket_fd) / (int)sizeof(g_rpchook_socket_fd[0]) )
|
||||
{
|
||||
rpchook_t *lp = (rpchook_t*)calloc( 1,sizeof(rpchook_t) );
|
||||
lp->read_timeout.tv_sec = 1;
|
||||
lp->write_timeout.tv_sec = 1;
|
||||
g_rpchook_socket_fd[ fd ] = lp;
|
||||
return lp;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
static inline void free_by_fd( int fd )
|
||||
{
|
||||
if( fd > -1 && fd < (int)sizeof(g_rpchook_socket_fd) / (int)sizeof(g_rpchook_socket_fd[0]) )
|
||||
{
|
||||
rpchook_t *lp = g_rpchook_socket_fd[ fd ];
|
||||
if( lp )
|
||||
{
|
||||
g_rpchook_socket_fd[ fd ] = NULL;
|
||||
free(lp);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
}
|
||||
int socket(int domain, int type, int protocol)
|
||||
{
|
||||
HOOK_SYS_FUNC( socket );
|
||||
|
||||
if( !co_is_enable_sys_hook() )
|
||||
{
|
||||
return g_sys_socket_func( domain,type,protocol );
|
||||
}
|
||||
int fd = g_sys_socket_func(domain,type,protocol);
|
||||
if( fd < 0 )
|
||||
{
|
||||
return fd;
|
||||
}
|
||||
|
||||
rpchook_t *lp = alloc_by_fd( fd );
|
||||
lp->domain = domain;
|
||||
|
||||
fcntl( fd, F_SETFL, g_sys_fcntl_func(fd, F_GETFL,0 ) );
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int co_accept( int fd, struct sockaddr *addr, socklen_t *len )
|
||||
{
|
||||
int cli = accept( fd,addr,len );
|
||||
if( cli < 0 )
|
||||
{
|
||||
return cli;
|
||||
}
|
||||
alloc_by_fd( cli );
|
||||
return cli;
|
||||
}
|
||||
|
||||
int connect(int fd, const struct sockaddr *address, socklen_t address_len)
|
||||
{
|
||||
HOOK_SYS_FUNC( connect );
|
||||
|
||||
if( !co_is_enable_sys_hook() )
|
||||
{
|
||||
return g_sys_connect_func(fd,address,address_len);
|
||||
}
|
||||
|
||||
int ret = g_sys_connect_func(fd,address,address_len);
|
||||
|
||||
|
||||
if( address_len == sizeof(sockaddr_un))
|
||||
{
|
||||
const struct sockaddr_un *p = (const struct sockaddr_un *)address;
|
||||
if( strstr( p->sun_path,"connagent_unix_domain_socket") ) ///tmp/connagent_unix_domain_socket
|
||||
{
|
||||
}
|
||||
}
|
||||
rpchook_t *lp = get_by_fd( fd );
|
||||
if( lp )
|
||||
{
|
||||
if( sizeof(lp->dest) >= address_len )
|
||||
{
|
||||
memcpy( &(lp->dest),address,(int)address_len );
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
int close(int fd)
|
||||
{
|
||||
HOOK_SYS_FUNC( close );
|
||||
|
||||
if( !co_is_enable_sys_hook() )
|
||||
{
|
||||
return g_sys_close_func( fd );
|
||||
}
|
||||
|
||||
free_by_fd( fd );
|
||||
int ret = g_sys_close_func(fd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
ssize_t read( int fd, void *buf, size_t nbyte )
|
||||
{
|
||||
HOOK_SYS_FUNC( read );
|
||||
|
||||
if( !co_is_enable_sys_hook() )
|
||||
{
|
||||
return g_sys_read_func( fd,buf,nbyte );
|
||||
}
|
||||
rpchook_t *lp = get_by_fd( fd );
|
||||
|
||||
if( !lp || ( O_NONBLOCK & lp->user_flag ) )
|
||||
{
|
||||
ssize_t ret = g_sys_read_func( fd,buf,nbyte );
|
||||
return ret;
|
||||
}
|
||||
int timeout = ( lp->read_timeout.tv_sec * 1000 )
|
||||
+ ( lp->read_timeout.tv_usec / 1000 );
|
||||
|
||||
struct pollfd pf = { 0 };
|
||||
pf.fd = fd;
|
||||
pf.events = ( POLLIN | POLLERR | POLLHUP );
|
||||
|
||||
int pollret = poll( &pf,1,timeout );
|
||||
|
||||
ssize_t readret = g_sys_read_func( fd,(char*)buf ,nbyte );
|
||||
|
||||
if( readret < 0 )
|
||||
{
|
||||
co_log_err("CO_ERR: read fd %d ret %ld errno %d poll ret %d timeout %d",
|
||||
fd,readret,errno,pollret,timeout);
|
||||
}
|
||||
|
||||
return readret;
|
||||
|
||||
}
|
||||
ssize_t write( int fd, const void *buf, size_t nbyte )
|
||||
{
|
||||
HOOK_SYS_FUNC( write );
|
||||
|
||||
if( !co_is_enable_sys_hook() )
|
||||
{
|
||||
return g_sys_write_func( fd,buf,nbyte );
|
||||
}
|
||||
rpchook_t *lp = get_by_fd( fd );
|
||||
|
||||
if( !lp || ( O_NONBLOCK & lp->user_flag ) )
|
||||
{
|
||||
ssize_t ret = g_sys_write_func( fd,buf,nbyte );
|
||||
return ret;
|
||||
}
|
||||
size_t wrotelen = 0;
|
||||
int timeout = ( lp->write_timeout.tv_sec * 1000 )
|
||||
+ ( lp->write_timeout.tv_usec / 1000 );
|
||||
|
||||
ssize_t writeret = g_sys_write_func( fd,(const char*)buf + wrotelen,nbyte - wrotelen );
|
||||
|
||||
if( writeret > 0 )
|
||||
{
|
||||
wrotelen += writeret;
|
||||
}
|
||||
while( wrotelen < nbyte )
|
||||
{
|
||||
|
||||
struct pollfd pf = { 0 };
|
||||
pf.fd = fd;
|
||||
pf.events = ( POLLOUT | POLLERR | POLLHUP );
|
||||
poll( &pf,1,timeout );
|
||||
|
||||
writeret = g_sys_write_func( fd,(const char*)buf + wrotelen,nbyte - wrotelen );
|
||||
|
||||
if( writeret <= 0 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
wrotelen += writeret ;
|
||||
}
|
||||
return wrotelen;
|
||||
}
|
||||
|
||||
ssize_t sendto(int socket, const void *message, size_t length,
|
||||
int flags, const struct sockaddr *dest_addr,
|
||||
socklen_t dest_len)
|
||||
{
|
||||
/*
|
||||
1.no enable sys call ? sys
|
||||
2.( !lp || lp is non block ) ? sys
|
||||
3.try
|
||||
4.wait
|
||||
5.try
|
||||
*/
|
||||
HOOK_SYS_FUNC( sendto );
|
||||
if( !co_is_enable_sys_hook() )
|
||||
{
|
||||
return g_sys_sendto_func( socket,message,length,flags,dest_addr,dest_len );
|
||||
}
|
||||
|
||||
rpchook_t *lp = get_by_fd( socket );
|
||||
if( !lp || ( O_NONBLOCK & lp->user_flag ) )
|
||||
{
|
||||
return g_sys_sendto_func( socket,message,length,flags,dest_addr,dest_len );
|
||||
}
|
||||
|
||||
ssize_t ret = g_sys_sendto_func( socket,message,length,flags,dest_addr,dest_len );
|
||||
if( ret < 0 && EAGAIN == errno )
|
||||
{
|
||||
int timeout = ( lp->write_timeout.tv_sec * 1000 )
|
||||
+ ( lp->write_timeout.tv_usec / 1000 );
|
||||
|
||||
|
||||
struct pollfd pf = { 0 };
|
||||
pf.fd = socket;
|
||||
pf.events = ( POLLOUT | POLLERR | POLLHUP );
|
||||
poll( &pf,1,timeout );
|
||||
|
||||
ret = g_sys_sendto_func( socket,message,length,flags,dest_addr,dest_len );
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t recvfrom(int socket, void *buffer, size_t length,
|
||||
int flags, struct sockaddr *address,
|
||||
socklen_t *address_len)
|
||||
{
|
||||
HOOK_SYS_FUNC( recvfrom );
|
||||
if( !co_is_enable_sys_hook() )
|
||||
{
|
||||
return g_sys_recvfrom_func( socket,buffer,length,flags,address,address_len );
|
||||
}
|
||||
|
||||
rpchook_t *lp = get_by_fd( socket );
|
||||
if( !lp || ( O_NONBLOCK & lp->user_flag ) )
|
||||
{
|
||||
return g_sys_recvfrom_func( socket,buffer,length,flags,address,address_len );
|
||||
}
|
||||
|
||||
int timeout = ( lp->read_timeout.tv_sec * 1000 )
|
||||
+ ( lp->read_timeout.tv_usec / 1000 );
|
||||
|
||||
|
||||
struct pollfd pf = { 0 };
|
||||
pf.fd = socket;
|
||||
pf.events = ( POLLIN | POLLERR | POLLHUP );
|
||||
poll( &pf,1,timeout );
|
||||
|
||||
ssize_t ret = g_sys_recvfrom_func( socket,buffer,length,flags,address,address_len );
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t send(int socket, const void *buffer, size_t length, int flags)
|
||||
{
|
||||
HOOK_SYS_FUNC( send );
|
||||
|
||||
if( !co_is_enable_sys_hook() )
|
||||
{
|
||||
return g_sys_send_func( socket,buffer,length,flags );
|
||||
}
|
||||
rpchook_t *lp = get_by_fd( socket );
|
||||
|
||||
if( !lp || ( O_NONBLOCK & lp->user_flag ) )
|
||||
{
|
||||
return g_sys_send_func( socket,buffer,length,flags );
|
||||
}
|
||||
size_t wrotelen = 0;
|
||||
int timeout = ( lp->write_timeout.tv_sec * 1000 )
|
||||
+ ( lp->write_timeout.tv_usec / 1000 );
|
||||
|
||||
ssize_t writeret = g_sys_send_func( socket,buffer,length,flags );
|
||||
|
||||
if( writeret > 0 )
|
||||
{
|
||||
wrotelen += writeret;
|
||||
}
|
||||
while( wrotelen < length )
|
||||
{
|
||||
|
||||
struct pollfd pf = { 0 };
|
||||
pf.fd = socket;
|
||||
pf.events = ( POLLOUT | POLLERR | POLLHUP );
|
||||
poll( &pf,1,timeout );
|
||||
|
||||
writeret = g_sys_send_func( socket,(const char*)buffer + wrotelen,length - wrotelen,flags );
|
||||
|
||||
if( writeret <= 0 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
wrotelen += writeret ;
|
||||
}
|
||||
|
||||
return wrotelen;
|
||||
}
|
||||
|
||||
ssize_t recv( int socket, void *buffer, size_t length, int flags )
|
||||
{
|
||||
HOOK_SYS_FUNC( recv );
|
||||
|
||||
if( !co_is_enable_sys_hook() )
|
||||
{
|
||||
return g_sys_recv_func( socket,buffer,length,flags );
|
||||
}
|
||||
rpchook_t *lp = get_by_fd( socket );
|
||||
|
||||
if( !lp || ( O_NONBLOCK & lp->user_flag ) )
|
||||
{
|
||||
return g_sys_recv_func( socket,buffer,length,flags );
|
||||
}
|
||||
int timeout = ( lp->read_timeout.tv_sec * 1000 )
|
||||
+ ( lp->read_timeout.tv_usec / 1000 );
|
||||
|
||||
struct pollfd pf = { 0 };
|
||||
pf.fd = socket;
|
||||
pf.events = ( POLLIN | POLLERR | POLLHUP );
|
||||
|
||||
int pollret = poll( &pf,1,timeout );
|
||||
|
||||
ssize_t readret = g_sys_recv_func( socket,buffer,length,flags );
|
||||
|
||||
if( readret < 0 )
|
||||
{
|
||||
co_log_err("CO_ERR: read fd %d ret %ld errno %d poll ret %d timeout %d",
|
||||
socket,readret,errno,pollret,timeout);
|
||||
}
|
||||
|
||||
return readret;
|
||||
|
||||
}
|
||||
|
||||
int poll(struct pollfd fds[], nfds_t nfds, int timeout)
|
||||
{
|
||||
|
||||
HOOK_SYS_FUNC( poll );
|
||||
|
||||
if( !co_is_enable_sys_hook() )
|
||||
{
|
||||
return g_sys_poll_func( fds,nfds,timeout );
|
||||
}
|
||||
|
||||
return co_poll( co_get_epoll_ct(),fds,nfds,timeout );
|
||||
|
||||
}
|
||||
int setsockopt(int fd, int level, int option_name,
|
||||
const void *option_value, socklen_t option_len)
|
||||
{
|
||||
HOOK_SYS_FUNC( setsockopt );
|
||||
|
||||
if( !co_is_enable_sys_hook() )
|
||||
{
|
||||
return g_sys_setsockopt_func( fd,level,option_name,option_value,option_len );
|
||||
}
|
||||
rpchook_t *lp = get_by_fd( fd );
|
||||
|
||||
if( lp && SOL_SOCKET == level )
|
||||
{
|
||||
struct timeval *val = (struct timeval*)option_value;
|
||||
if( SO_RCVTIMEO == option_name )
|
||||
{
|
||||
memcpy( &lp->read_timeout,val,sizeof(*val) );
|
||||
}
|
||||
else if( SO_SNDTIMEO == option_name )
|
||||
{
|
||||
memcpy( &lp->write_timeout,val,sizeof(*val) );
|
||||
}
|
||||
}
|
||||
return g_sys_setsockopt_func( fd,level,option_name,option_value,option_len );
|
||||
}
|
||||
|
||||
|
||||
int fcntl(int fildes, int cmd, ...)
|
||||
{
|
||||
HOOK_SYS_FUNC( fcntl );
|
||||
|
||||
if( fildes < 0 )
|
||||
{
|
||||
return __LINE__;
|
||||
}
|
||||
|
||||
va_list arg_list;
|
||||
va_start( arg_list,cmd );
|
||||
|
||||
int ret = -1;
|
||||
rpchook_t *lp = get_by_fd( fildes );
|
||||
switch( cmd )
|
||||
{
|
||||
case F_DUPFD:
|
||||
{
|
||||
int param = va_arg(arg_list,int);
|
||||
ret = g_sys_fcntl_func( fildes,cmd,param );
|
||||
break;
|
||||
}
|
||||
case F_GETFD:
|
||||
{
|
||||
ret = g_sys_fcntl_func( fildes,cmd );
|
||||
break;
|
||||
}
|
||||
case F_SETFD:
|
||||
{
|
||||
int param = va_arg(arg_list,int);
|
||||
ret = g_sys_fcntl_func( fildes,cmd,param );
|
||||
break;
|
||||
}
|
||||
case F_GETFL:
|
||||
{
|
||||
ret = g_sys_fcntl_func( fildes,cmd );
|
||||
break;
|
||||
}
|
||||
case F_SETFL:
|
||||
{
|
||||
int param = va_arg(arg_list,int);
|
||||
int flag = param;
|
||||
if( co_is_enable_sys_hook() && lp )
|
||||
{
|
||||
flag |= O_NONBLOCK;
|
||||
}
|
||||
ret = g_sys_fcntl_func( fildes,cmd,flag );
|
||||
if( 0 == ret && lp )
|
||||
{
|
||||
lp->user_flag = param;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case F_GETOWN:
|
||||
{
|
||||
ret = g_sys_fcntl_func( fildes,cmd );
|
||||
break;
|
||||
}
|
||||
case F_SETOWN:
|
||||
{
|
||||
int param = va_arg(arg_list,int);
|
||||
ret = g_sys_fcntl_func( fildes,cmd,param );
|
||||
break;
|
||||
}
|
||||
case F_GETLK:
|
||||
{
|
||||
struct flock *param = va_arg(arg_list,struct flock *);
|
||||
ret = g_sys_fcntl_func( fildes,cmd,param );
|
||||
break;
|
||||
}
|
||||
case F_SETLK:
|
||||
{
|
||||
struct flock *param = va_arg(arg_list,struct flock *);
|
||||
ret = g_sys_fcntl_func( fildes,cmd,param );
|
||||
break;
|
||||
}
|
||||
case F_SETLKW:
|
||||
{
|
||||
struct flock *param = va_arg(arg_list,struct flock *);
|
||||
ret = g_sys_fcntl_func( fildes,cmd,param );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
va_end( arg_list );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct res_state_wrap
|
||||
{
|
||||
struct __res_state state;
|
||||
};
|
||||
CO_ROUTINE_SPECIFIC(res_state_wrap, __co_state_wrap);
|
||||
|
||||
extern "C"
|
||||
{
|
||||
res_state __res_state()
|
||||
{
|
||||
HOOK_SYS_FUNC(__res_state);
|
||||
|
||||
if (!co_is_enable_sys_hook())
|
||||
{
|
||||
return g_sys___res_state_func();
|
||||
}
|
||||
|
||||
return &(__co_state_wrap->state);
|
||||
}
|
||||
int __poll(struct pollfd fds[], nfds_t nfds, int timeout)
|
||||
{
|
||||
return poll(fds, nfds, timeout);
|
||||
}
|
||||
}
|
||||
|
||||
struct hostbuf_wrap
|
||||
{
|
||||
struct hostent host;
|
||||
char* buffer;
|
||||
size_t iBufferSize;
|
||||
int host_errno;
|
||||
};
|
||||
|
||||
CO_ROUTINE_SPECIFIC(hostbuf_wrap, __co_hostbuf_wrap);
|
||||
|
||||
struct hostent *co_gethostbyname(const char *name)
|
||||
{
|
||||
if (!name)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (__co_hostbuf_wrap->buffer && __co_hostbuf_wrap->iBufferSize > 1024)
|
||||
{
|
||||
free(__co_hostbuf_wrap->buffer);
|
||||
__co_hostbuf_wrap->buffer = NULL;
|
||||
}
|
||||
if (!__co_hostbuf_wrap->buffer)
|
||||
{
|
||||
__co_hostbuf_wrap->buffer = (char*)malloc(1024);
|
||||
__co_hostbuf_wrap->iBufferSize = 1024;
|
||||
}
|
||||
|
||||
struct hostent *host = &__co_hostbuf_wrap->host;
|
||||
struct hostent *result = NULL;
|
||||
int *h_errnop = &(__co_hostbuf_wrap->host_errno);
|
||||
|
||||
int ret = -1;
|
||||
while (ret = gethostbyname_r(name, host, __co_hostbuf_wrap->buffer,
|
||||
__co_hostbuf_wrap->iBufferSize, &result, h_errnop) == ERANGE &&
|
||||
*h_errnop == NETDB_INTERNAL )
|
||||
{
|
||||
free(__co_hostbuf_wrap->buffer);
|
||||
__co_hostbuf_wrap->iBufferSize = __co_hostbuf_wrap->iBufferSize * 2;
|
||||
__co_hostbuf_wrap->buffer = (char*)malloc(__co_hostbuf_wrap->iBufferSize);
|
||||
}
|
||||
|
||||
if (ret == 0 && (host == result))
|
||||
{
|
||||
return host;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void co_enable_hook_sys() //这函数必须在这里,否则本文件会被忽略!!!
|
||||
{
|
||||
stCoRoutine_t *co = GetCurrThreadCo();
|
||||
if( co )
|
||||
{
|
||||
co->cEnableSysHook = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//gzrd_Lib_CPP_Version_ID--start
|
||||
#ifndef GZRD_SVN_ATTR
|
||||
#define GZRD_SVN_ATTR "0"
|
||||
#endif
|
||||
static char gzrd_Lib_CPP_Version_ID[] __attribute__((used))="$HeadURL$ $Id$ " GZRD_SVN_ATTR "__file__";
|
||||
// gzrd_Lib_CPP_Version_ID--end
|
||||
|
1125
co_routine.cpp
Normal file
1125
co_routine.cpp
Normal file
File diff suppressed because it is too large
Load Diff
89
co_routine.h
Normal file
89
co_routine.h
Normal 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.
|
||||
*/
|
||||
|
||||
#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 );
|
||||
|
||||
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);
|
||||
|
||||
void co_log_err( const char *fmt,... );
|
||||
#endif
|
||||
|
1631
co_routine.main.cpp
Normal file
1631
co_routine.main.cpp
Normal file
File diff suppressed because it is too large
Load Diff
119
co_routine.main.h
Normal file
119
co_routine.main.h
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
Author:sunny
|
||||
Date:2013.8
|
||||
*/
|
||||
#ifndef __CO_ROUTINE_H__
|
||||
#define __CO_ROUTINE_H__
|
||||
|
||||
#include <ucontext.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/poll.h>
|
||||
|
||||
//1.struct
|
||||
|
||||
struct stCoRoutine_t;
|
||||
struct stStackMemEnv_t;
|
||||
struct stCoRoutineAttr_t
|
||||
{
|
||||
int stack_size;
|
||||
char no_protect_stack;
|
||||
char use_share_stack;
|
||||
stStackMemEnv_t* stack_env;
|
||||
//char reserve[ 58 ];
|
||||
|
||||
}__attribute__ ((packed));
|
||||
|
||||
struct stCoRoutineStat_t
|
||||
{
|
||||
unsigned long long hit_count;
|
||||
unsigned long long not_hit_count;
|
||||
|
||||
unsigned long long alloc_buffer_size;
|
||||
|
||||
unsigned long long copy_out_size;
|
||||
unsigned long long copy_out_count;
|
||||
unsigned long long copy_in_size;
|
||||
unsigned long long copy_in_count;
|
||||
|
||||
unsigned long long copy_resume_count;
|
||||
unsigned long long normal_resume_count;
|
||||
unsigned long long yield_cnt;
|
||||
unsigned long long use_share_stack_cnt;
|
||||
};
|
||||
|
||||
struct stCoEpoll_t;
|
||||
typedef int (*pfn_co_eventloop_t)(void *);
|
||||
typedef void *(*pfn_co_routine_t)( void * );
|
||||
typedef void *(*pfn_sys_getspecific_t)( pthread_key_t key );
|
||||
typedef int (*pfn_sys_setspecific_t)( pthread_key_t key,const void *value );
|
||||
|
||||
typedef void (*pfn_co_eventloop_start_t)(int iEventCnt);
|
||||
typedef void (*pfn_co_eventloop_end_t)();
|
||||
typedef void (*pfn_before_yield_cb_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_yield_resume_ct( stCoRoutine_t *dest ); //ct = current thread
|
||||
void co_release( stCoRoutine_t *co );
|
||||
int co_add_persist_event( stCoEpoll_t *ctx, int fd , int events);
|
||||
|
||||
int co_yield_timeout(int timeout = 30000);
|
||||
stCoRoutine_t *co_self();
|
||||
bool co_is_main();
|
||||
|
||||
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 );
|
||||
|
||||
void co_reset_epolltimeout();
|
||||
|
||||
//3.specific
|
||||
|
||||
int co_setspecific( pthread_key_t key, const void *value );
|
||||
void * co_getspecific( pthread_key_t key );
|
||||
void co_set_sys_specific_func(pfn_sys_getspecific_t get, pfn_sys_setspecific_t set);
|
||||
void co_set_eventloop_stat(pfn_co_eventloop_start_t start, pfn_co_eventloop_end_t end);
|
||||
void co_set_before_yield_cb( pfn_before_yield_cb_t cb,void *arg );
|
||||
|
||||
//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();
|
||||
|
||||
|
||||
void co_log_err( const char *fmt,... );
|
||||
|
||||
void co_set_env_list( const char *name[],size_t cnt);
|
||||
|
||||
//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 );
|
||||
|
||||
typedef void (*pfn_co_before_yield)();
|
||||
typedef void (*pfn_co_after_yield)();
|
||||
void co_set_yield_func(pfn_co_after_yield before, pfn_co_after_yield after);
|
||||
|
||||
//protect
|
||||
void SetUseProtect(bool bUseProtect);
|
||||
void co_enable_share_stack(bool bEnableShareStack);
|
||||
|
||||
//for copy stack
|
||||
stCoRoutineStat_t* co_get_curr_stat();
|
||||
stStackMemEnv_t* co_alloc_stackmemenv(int iCount, int iStackSize);
|
||||
|
||||
#endif
|
||||
|
109
co_routine_inner.h
Normal file
109
co_routine_inner.h
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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* ocupy_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;
|
||||
|
||||
//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__
|
97
co_routine_inner.main.h
Normal file
97
co_routine_inner.main.h
Normal file
@ -0,0 +1,97 @@
|
||||
#ifndef __CO_ROUTINE_INNER_H__
|
||||
#define __CO_ROUTINE_INNER_H__
|
||||
|
||||
#include "co_routine.h"
|
||||
#include "coctx.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
struct stCoRoutineEnv_t;
|
||||
struct stCoSpec_t
|
||||
{
|
||||
void *value;
|
||||
};
|
||||
struct stStackMem_t;
|
||||
struct stStackMemEnv_t;
|
||||
struct stCoRoutine_t
|
||||
{
|
||||
stCoRoutineEnv_t *env;
|
||||
pfn_co_routine_t pfn;
|
||||
void *arg;
|
||||
//ucontext_t ctx;
|
||||
coctx_t ctx;
|
||||
char cStart;
|
||||
char cEnd;
|
||||
|
||||
//stCoSpec_t aSpecInner[ 128 ];
|
||||
//stCoSpec_t aSpecInner2[ 128 ];
|
||||
//stCoSpec_t *aSpecPtr[ 4096 / 128 ];// 2 ^ 7
|
||||
stCoSpec_t **aSpecPtr;
|
||||
|
||||
char cIsMain;
|
||||
char cEnableSysHook;
|
||||
|
||||
void *pvEnv;
|
||||
|
||||
char cNoProtectStack;
|
||||
|
||||
stStackMem_t* pDynamicStack;
|
||||
|
||||
//for copy stack;
|
||||
stStackMemEnv_t* pStackEnv;
|
||||
char *pRunStackSP;
|
||||
char *pBuffer;
|
||||
int iStackCapacity;
|
||||
int iStackLen;
|
||||
|
||||
//char sRunStack[ 1 ]; //the last field!!
|
||||
/*************/
|
||||
/* forbidden */
|
||||
/*************/
|
||||
//in the hell
|
||||
char *pRunStack;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//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)();
|
||||
|
||||
//event
|
||||
struct stCoEvent_t;
|
||||
typedef void* (*pfn_co_event_call_back)(int fd, int revent, void* args);
|
||||
stCoEvent_t* co_alloc_event();
|
||||
int co_free_event(stCoEvent_t* coevent);
|
||||
int co_get_eventfd(stCoEvent_t* coevent);
|
||||
int co_add_event(stCoEvent_t* coevent, int fd, pfn_co_event_call_back pfn, void* args, unsigned int events, int timeout);
|
||||
|
||||
|
||||
int co_accept( int fd, struct sockaddr *addr, socklen_t *len );
|
||||
#endif
|
||||
|
68
co_routine_specific.h
Normal file
68
co_routine_specific.h
Normal file
@ -0,0 +1,68 @@
|
||||
#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;
|
||||
|
146
coctx.cpp
Normal file
146
coctx.cpp
Normal file
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* 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 <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,
|
||||
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 ;
|
||||
param->s1 = s;
|
||||
param->s2 = s1;
|
||||
|
||||
memset(ctx->regs, 0, sizeof(ctx->regs));
|
||||
|
||||
ctx->regs[ kESP ] = (char*)(sp) - sizeof(void*);
|
||||
ctx->regs[ kEIP ] = (char*)pfn;
|
||||
|
||||
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;
|
||||
sp = (char*) ((unsigned long)sp & -16LL );
|
||||
|
||||
memset(ctx->regs, 0, sizeof(ctx->regs));
|
||||
|
||||
ctx->regs[ kRSP ] = sp - 8;
|
||||
|
||||
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
|
||||
|
||||
|
||||
//gzrd_Lib_CPP_Version_ID--start
|
||||
#ifndef GZRD_SVN_ATTR
|
||||
#define GZRD_SVN_ATTR "0"
|
||||
#endif
|
||||
static char gzrd_Lib_CPP_Version_ID[] __attribute__((used))="$HeadURL: http://tc-svn.tencent.com/pub/pub_libco_rep/libco_proj/trunk/coctx.cpp $ $Id: coctx.cpp 39 2016-09-29 07:26:29Z leiffyli $ " GZRD_SVN_ATTR "__file__";
|
||||
// gzrd_Lib_CPP_Version_ID--end
|
||||
|
42
coctx.h
Normal file
42
coctx.h
Normal 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
|
95
coctx_swap.S
Normal file
95
coctx_swap.S
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* 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__)
|
||||
leal 4(%esp), %eax //sp
|
||||
movl 4(%esp), %esp
|
||||
leal 32(%esp), %esp //parm a : ®s[7] + sizeof(void*)
|
||||
|
||||
pushl %eax //esp ->parm a
|
||||
|
||||
pushl %ebp
|
||||
pushl %esi
|
||||
pushl %edi
|
||||
pushl %edx
|
||||
pushl %ecx
|
||||
pushl %ebx
|
||||
pushl -4(%eax)
|
||||
|
||||
|
||||
movl 4(%eax), %esp //parm b -> ®s[0]
|
||||
|
||||
popl %eax //ret func addr
|
||||
popl %ebx
|
||||
popl %ecx
|
||||
popl %edx
|
||||
popl %edi
|
||||
popl %esi
|
||||
popl %ebp
|
||||
popl %esp
|
||||
pushl %eax //set ret func addr
|
||||
|
||||
xorl %eax, %eax
|
||||
ret
|
||||
|
||||
#elif defined(__x86_64__)
|
||||
leaq 8(%rsp),%rax
|
||||
leaq 112(%rdi),%rsp
|
||||
pushq %rax
|
||||
pushq %rbx
|
||||
pushq %rcx
|
||||
pushq %rdx
|
||||
|
||||
pushq -8(%rax) //ret func addr
|
||||
|
||||
pushq %rsi
|
||||
pushq %rdi
|
||||
pushq %rbp
|
||||
pushq %r8
|
||||
pushq %r9
|
||||
pushq %r12
|
||||
pushq %r13
|
||||
pushq %r14
|
||||
pushq %r15
|
||||
|
||||
movq %rsi, %rsp
|
||||
popq %r15
|
||||
popq %r14
|
||||
popq %r13
|
||||
popq %r12
|
||||
popq %r9
|
||||
popq %r8
|
||||
popq %rbp
|
||||
popq %rdi
|
||||
popq %rsi
|
||||
popq %rax //ret func addr
|
||||
popq %rdx
|
||||
popq %rcx
|
||||
popq %rbx
|
||||
popq %rsp
|
||||
pushq %rax
|
||||
|
||||
xorl %eax, %eax
|
||||
ret
|
||||
#endif
|
69
example_closure.cpp
Normal file
69
example_closure.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
#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;
|
||||
|
||||
int total = 100;
|
||||
vector<int> v2;
|
||||
co_ref( ref,total,v2 );
|
||||
for(int i=0;i<10;i++)
|
||||
{
|
||||
co_func( f,ref,i )
|
||||
{
|
||||
printf("ref.total %d i %d\n",ref.total,i );
|
||||
//lock
|
||||
ref.v2.push_back( i );
|
||||
//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;
|
||||
}
|
||||
|
||||
|
65
example_cond.cpp
Normal file
65
example_cond.cpp
Normal file
@ -0,0 +1,65 @@
|
||||
#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;
|
||||
}
|
44
example_copystack.cpp
Normal file
44
example_copystack.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/epoll.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 < 3; 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
example_echocli.cpp
Normal file
218
example_echocli.cpp
Normal 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*/
|
234
example_echosvr.cpp
Normal file
234
example_echosvr.cpp
Normal file
@ -0,0 +1,234 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
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 )
|
||||
{
|
||||
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[])
|
||||
{
|
||||
const char *ip = argv[1];
|
||||
int port = atoi( argv[2] );
|
||||
int cnt = atoi( argv[3] );
|
||||
int proccnt = atoi( argv[4] );
|
||||
|
||||
g_listen_fd = CreateTcpSocket( port,ip,true );
|
||||
listen( g_listen_fd,1024 );
|
||||
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);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
206
example_poll.cpp
Normal file
206
example_poll.cpp
Normal file
@ -0,0 +1,206 @@
|
||||
/*
|
||||
* 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>
|
||||
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<ret;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
|
||||
|
43
example_specific.cpp
Normal file
43
example_specific.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
#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
example_thread.cpp
Normal file
56
example_thread.cpp
Normal 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;
|
||||
}
|
||||
|
BIN
lib/libcolib.a
Normal file
BIN
lib/libcolib.a
Normal file
Binary file not shown.
BIN
solib/libcolib.so
Normal file
BIN
solib/libcolib.so
Normal file
Binary file not shown.
224
test_colib.cpp
Normal file
224
test_colib.cpp
Normal file
@ -0,0 +1,224 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include "coctx.h"
|
||||
#include "co_routine.h"
|
||||
#include "co_routine_inner.h"
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
extern "C"
|
||||
{
|
||||
extern void coctx_swap(coctx_t*, coctx_t*) asm("coctx_swap");
|
||||
extern void test_xmm(char*, char*) asm("test_xmm");
|
||||
}
|
||||
|
||||
|
||||
void Test1()
|
||||
{
|
||||
char a16[16] __attribute__ ((aligned (16)))= "0123456789abcde";
|
||||
char b16[16] __attribute__ ((aligned (16))) = "abcde012345789";
|
||||
test_xmm( a16, b16);
|
||||
printf("(%p : %s) (%p : %s) \n", &a16, a16, &b16, b16);
|
||||
return;
|
||||
}
|
||||
|
||||
void* RoutineFunc(void* args1, void* args2)
|
||||
{
|
||||
coctx_t* main = (coctx_t*)(args1);
|
||||
coctx_t* self = (coctx_t*)args2;
|
||||
printf("%s:%d args1 %p args2 %p main %p self %p\n", __func__, __LINE__, &args1, &args2, main ,self);
|
||||
coctx_swap(self, main);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* TestXMMFunc(void* args1, void* args2)
|
||||
{
|
||||
Test1();
|
||||
|
||||
coctx_t* main = (coctx_t*)(args1);
|
||||
coctx_t* self = (coctx_t*)args2;
|
||||
char s = 's';
|
||||
printf("%s:%d args1 %p args2 %p main %p self %p\n", __func__, __LINE__, &args1, &args2, main ,self);
|
||||
|
||||
coctx_swap(self, main);
|
||||
|
||||
}
|
||||
|
||||
|
||||
TEST(Coctx, normal)
|
||||
{
|
||||
coctx_t main;
|
||||
coctx_init(&main);
|
||||
|
||||
int i = 5;
|
||||
coctx_t ctx;
|
||||
coctx_init(&ctx);
|
||||
ctx.ss_size = 1024 * 128;
|
||||
ctx.ss_sp = (char*)malloc(ctx.ss_size);
|
||||
coctx_make(&ctx, RoutineFunc, (void*)&main, (void*)&ctx);
|
||||
|
||||
coctx_swap(&main, &ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
TEST(Coctx, xmm)
|
||||
{
|
||||
coctx_t main;
|
||||
coctx_init(&main);
|
||||
|
||||
coctx_t self;
|
||||
coctx_init(&self);
|
||||
self.ss_size = 1024 * 128;
|
||||
self.ss_sp = (char*)malloc(self.ss_size);
|
||||
coctx_make(&self, TestXMMFunc, (void*)&main, (void*)&self);
|
||||
coctx_swap(&main, &self);
|
||||
|
||||
printf("%s:%d end\n", __func__, __LINE__);
|
||||
}
|
||||
int g_iExitEventLoop = 0;
|
||||
int TickFunc(void* args)
|
||||
{
|
||||
if (g_iExitEventLoop == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void* RoutineFunc1(void* args)
|
||||
{
|
||||
co_enable_hook_sys();
|
||||
int* piRoutineID = (int*)args;
|
||||
int iRoutinedID = *piRoutineID;
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
poll(NULL, 0, 1000);
|
||||
printf("%s:%d iRoutinedID (%p:%d)\n", __func__, __LINE__, &iRoutinedID, iRoutinedID);
|
||||
}
|
||||
g_iExitEventLoop--;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TEST(CopyStack, ResumeFromMain)
|
||||
{
|
||||
stShareStack_t* env = co_alloc_sharestack(1, 1024 * 128);
|
||||
int iCount = 2;
|
||||
g_iExitEventLoop = iCount;
|
||||
stCoRoutine_t* co[2];
|
||||
int iRoutineID[2];
|
||||
for (int i = 0; i < iCount; i++)
|
||||
{
|
||||
stCoRoutineAttr_t attr;
|
||||
attr.share_stack = env;
|
||||
iRoutineID[i] = i;
|
||||
co_create(&co[0], &attr, RoutineFunc1, iRoutineID + i);
|
||||
co_resume(co[0]);
|
||||
}
|
||||
co_eventloop(co_get_epoll_ct(), TickFunc, NULL);
|
||||
}
|
||||
|
||||
void* Sender(void* ptArgs)
|
||||
{
|
||||
co_enable_hook_sys();
|
||||
stCoRoutine_t* recever = (stCoRoutine_t*)ptArgs;
|
||||
while (true)
|
||||
{
|
||||
char s[128];
|
||||
strcpy(s, "from sender\n");
|
||||
co_resume(recever);
|
||||
poll(NULL, 0, 1000);
|
||||
printf("%s:%d %p %s", __func__, __LINE__, s, s);
|
||||
g_iExitEventLoop--;
|
||||
if (g_iExitEventLoop == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
void* Recever(void* ptArgs)
|
||||
{
|
||||
co_enable_hook_sys();
|
||||
while (true)
|
||||
{
|
||||
char s[128];
|
||||
strcpy(s, "from recever\n");
|
||||
co_yield_ct();
|
||||
printf("%s:%d %p %s", __func__, __LINE__, s, s);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(CopyStack, ResumeFromSender)
|
||||
{
|
||||
g_iExitEventLoop = 2;
|
||||
|
||||
stShareStack_t* env = co_alloc_sharestack(1, 1024 * 128);
|
||||
|
||||
stCoRoutineAttr_t attr;
|
||||
attr.share_stack = env;
|
||||
|
||||
stCoRoutine_t* recever;
|
||||
co_create(&recever, &attr, Recever, NULL);
|
||||
co_resume(recever);
|
||||
|
||||
stCoRoutine_t* sender;
|
||||
co_create(&sender, &attr, Sender, (void*)recever);
|
||||
co_resume(sender);
|
||||
|
||||
co_eventloop(co_get_epoll_ct(), TickFunc, NULL);
|
||||
}
|
||||
TEST(NoCopyStack, ResumeFromMain)
|
||||
{
|
||||
stShareStack_t* env = co_alloc_sharestack(1, 1024 * 128);
|
||||
int iCount = 2;
|
||||
g_iExitEventLoop = iCount;
|
||||
stCoRoutine_t* co[2];
|
||||
int iRoutineID[2];
|
||||
for (int i = 0; i < iCount; i++)
|
||||
{
|
||||
stCoRoutineAttr_t attr;
|
||||
attr.share_stack = env;
|
||||
iRoutineID[i] = i;
|
||||
co_create(&co[0], &attr, RoutineFunc1, iRoutineID + i);
|
||||
co_resume(co[0]);
|
||||
}
|
||||
co_eventloop(co_get_epoll_ct(), TickFunc, NULL);
|
||||
}
|
||||
TEST(NoCopyStack, ResumeFromSender)
|
||||
{
|
||||
g_iExitEventLoop = 2;
|
||||
|
||||
stShareStack_t* env = co_alloc_sharestack(1, 1024 * 128);
|
||||
|
||||
stCoRoutineAttr_t attr;
|
||||
attr.share_stack = env;
|
||||
|
||||
stCoRoutine_t* recever;
|
||||
co_create(&recever, &attr, Recever, NULL);
|
||||
co_resume(recever);
|
||||
|
||||
stCoRoutine_t* sender;
|
||||
co_create(&sender, &attr, Sender, (void*)recever);
|
||||
co_resume(sender);
|
||||
|
||||
co_eventloop(co_get_epoll_ct(), TickFunc, NULL);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
printf("size %d\n", sizeof(stCoRoutine_t));
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
//gzrd_Lib_CPP_Version_ID--start
|
||||
#ifndef GZRD_SVN_ATTR
|
||||
#define GZRD_SVN_ATTR "0"
|
||||
#endif
|
||||
static char gzrd_Lib_CPP_Version_ID[] __attribute__((used))="$HeadURL: http://scm-gy.tencent.com/gzrd/gzrd_mail_rep/QQMailcore_proj/trunk/basic/colib/test/test_colib.cpp $ $Id: test_colib.cpp 1650485 2016-06-28 06:34:38Z leiffyli $ " GZRD_SVN_ATTR "__file__";
|
||||
// gzrd_Lib_CPP_Version_ID--end
|
||||
|
14
test_xmm.S
Normal file
14
test_xmm.S
Normal file
@ -0,0 +1,14 @@
|
||||
.globl test_xmm
|
||||
test_xmm:
|
||||
#if defined(__i386__)
|
||||
movl 4(%esp), %eax
|
||||
movl 8(%esp), %ecx
|
||||
movaps (%eax),%xmm0
|
||||
movaps %xmm0,(%ecx)
|
||||
#elif defined(__x86_64__)
|
||||
movaps (%rdi),%xmm0
|
||||
movaps %xmm0,(%rsi)
|
||||
#endif
|
||||
ret
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user