mirror of
https://gitee.com/acl-dev/acl.git
synced 2024-12-02 03:47:53 +08:00
Add C++ API for fiber mutex deadlock checking.
This commit is contained in:
parent
758dd3852a
commit
3ef3fa8128
@ -32,7 +32,7 @@ typedef struct ACL_FIBER_MUTEX_STATS {
|
||||
|
||||
|
||||
FIBER_API void acl_fiber_mutex_profile(void);
|
||||
FIBER_API ACL_FIBER_MUTEX_STATS *acl_fiber_mutex_deadcheck(void);
|
||||
FIBER_API ACL_FIBER_MUTEX_STATS *acl_fiber_mutex_deadlock(void);
|
||||
FIBER_API void acl_fiber_mutex_stats_free(ACL_FIBER_MUTEX_STATS *stats);
|
||||
FIBER_API void acl_fiber_mutex_stats_show(const ACL_FIBER_MUTEX_STATS *stats);
|
||||
|
||||
|
@ -259,7 +259,6 @@ static ACL_FIBER_MUTEX_STATS *check_deadlock2(MUTEX_CHECK *check)
|
||||
SNPRINTF(hkey, sizeof(hkey), "%d", acl_fiber_id(fiber));
|
||||
if (htable_find(table, hkey) != NULL) {
|
||||
deadlocked = 1;
|
||||
printf("DeadLock happened!\r\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -314,7 +313,7 @@ static ACL_FIBER_MUTEX_STATS *check_deadlock(THREAD_MUTEXES *mutexes)
|
||||
return stats;
|
||||
}
|
||||
|
||||
ACL_FIBER_MUTEX_STATS *acl_fiber_mutex_deadcheck(void)
|
||||
ACL_FIBER_MUTEX_STATS *acl_fiber_mutex_deadlock(void)
|
||||
{
|
||||
if (__locks != NULL) {
|
||||
ACL_FIBER_MUTEX_STATS *stats;
|
||||
|
@ -17,9 +17,8 @@ typedef enum
|
||||
FIBER_EVENT_T_IO_URING, // Linux
|
||||
} fiber_event_t;
|
||||
|
||||
class FIBER_CPP_API fiber_frame
|
||||
struct FIBER_CPP_API fiber_frame
|
||||
{
|
||||
public:
|
||||
fiber_frame(void) : pc(0), off(0) {}
|
||||
~fiber_frame(void) {}
|
||||
|
||||
@ -34,6 +33,9 @@ public:
|
||||
class FIBER_CPP_API fiber
|
||||
{
|
||||
public:
|
||||
fiber(void);
|
||||
fiber(ACL_FIBER *fb);
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
* @param running {bool} 当为 true 时,则表示当前协程已启动,仅是声明
|
||||
@ -41,7 +43,8 @@ public:
|
||||
* 象的 start 方法启动新协程; 当为 false 时,则需要调用 start 方法来
|
||||
* 启动新协程
|
||||
*/
|
||||
fiber(bool running = false);
|
||||
fiber(bool running);
|
||||
|
||||
virtual ~fiber(void);
|
||||
|
||||
/**
|
||||
@ -87,6 +90,12 @@ public:
|
||||
*/
|
||||
static unsigned int self(void);
|
||||
|
||||
/**
|
||||
* 获得指定协程对象的ID号
|
||||
* @return {unsigned int}
|
||||
*/
|
||||
static unsigned int id(const fiber& fb);
|
||||
|
||||
/**
|
||||
* 获得当前协程在执行某个系统 API 出错时的错误号
|
||||
* return {int}
|
||||
|
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include "fiber_cpp_define.hpp"
|
||||
#include "fiber_mutex_stat.hpp"
|
||||
|
||||
struct ACL_FIBER_MUTEX;
|
||||
|
||||
@ -12,7 +14,13 @@ namespace acl {
|
||||
class FIBER_CPP_API fiber_mutex
|
||||
{
|
||||
public:
|
||||
fiber_mutex(void);
|
||||
/**
|
||||
* 构造函数
|
||||
* @param mutex {ACL_FIBER_MUTEX*} 非空时,将用 C 的锁对象创建 C++ 锁
|
||||
* 对象,否则内部自动创建 C 锁对象;如果非空时,在本对象析构时该传入的
|
||||
* C 锁对象需由应用层自行释放.
|
||||
*/
|
||||
fiber_mutex(ACL_FIBER_MUTEX* mutex = NULL);
|
||||
~fiber_mutex(void);
|
||||
|
||||
/**
|
||||
@ -43,8 +51,16 @@ public:
|
||||
return mutex_;
|
||||
}
|
||||
|
||||
/**
|
||||
* 进行全局死锁检测
|
||||
* @param out {fiber_mutex_stats&} 存储结果集
|
||||
* @return {bool} 返回 true 表示存在死锁问题, 死锁信息存放在 out 中
|
||||
*/
|
||||
static bool deadlock(fiber_mutex_stats& out);
|
||||
|
||||
private:
|
||||
ACL_FIBER_MUTEX* mutex_;
|
||||
ACL_FIBER_MUTEX* mutex_internal_;
|
||||
|
||||
fiber_mutex(const fiber_mutex&);
|
||||
void operator=(const fiber_mutex&);
|
||||
|
27
lib_fiber/cpp/include/fiber/fiber_mutex_stat.hpp
Normal file
27
lib_fiber/cpp/include/fiber/fiber_mutex_stat.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
struct ACL_FIBER_MUTEX;
|
||||
|
||||
namespace acl {
|
||||
|
||||
class fiber;
|
||||
|
||||
struct FIBER_CPP_API fiber_mutex_stat
|
||||
{
|
||||
fiber_mutex_stat(void) : fb(NULL), waiting(NULL) {}
|
||||
~fiber_mutex_stat(void) {}
|
||||
|
||||
fiber *fb;
|
||||
ACL_FIBER_MUTEX *waiting;
|
||||
std::vector<ACL_FIBER_MUTEX*> holding;
|
||||
};
|
||||
|
||||
struct FIBER_CPP_API fiber_mutex_stats
|
||||
{
|
||||
fiber_mutex_stats(void) {}
|
||||
~fiber_mutex_stats(void);
|
||||
|
||||
std::vector<fiber_mutex_stat> stats;
|
||||
};
|
||||
|
||||
} // namespace acl
|
@ -4,6 +4,8 @@
|
||||
|
||||
#include "fiber_lock.hpp"
|
||||
#include "fiber_event.hpp"
|
||||
#include "fiber_mutex.hpp"
|
||||
#include "fiber_mutex_stat.hpp"
|
||||
#include "fiber_cond.hpp"
|
||||
#include "wait_group.hpp"
|
||||
#include "fiber_sem.hpp"
|
||||
|
@ -315,6 +315,8 @@
|
||||
<ClInclude Include="include\fiber\fiber_cpp_define.hpp" />
|
||||
<ClInclude Include="include\fiber\fiber_event.hpp" />
|
||||
<ClInclude Include="include\fiber\fiber_lock.hpp" />
|
||||
<ClInclude Include="include\fiber\fiber_mutex.hpp" />
|
||||
<ClInclude Include="include\fiber\fiber_mutex_stat.hpp" />
|
||||
<ClInclude Include="include\fiber\fiber_redis_pipeline.hpp" />
|
||||
<ClInclude Include="include\fiber\fiber_sem.hpp" />
|
||||
<ClInclude Include="include\fiber\fiber_tbox.hpp" />
|
||||
@ -331,6 +333,8 @@
|
||||
<ClCompile Include="src\fiber_cond.cpp" />
|
||||
<ClCompile Include="src\fiber_event.cpp" />
|
||||
<ClCompile Include="src\fiber_lock.cpp" />
|
||||
<ClCompile Include="src\fiber_mutex.cpp" />
|
||||
<ClCompile Include="src\fiber_mutex_stat.cpp" />
|
||||
<ClCompile Include="src\fiber_redis_pipeline.cpp" />
|
||||
<ClCompile Include="src\fiber_sem.cpp" />
|
||||
<ClCompile Include="src\fiber_server.cpp" />
|
||||
|
@ -45,6 +45,12 @@
|
||||
<ClInclude Include="include\fiber\fiber_lock.hpp">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\fiber\fiber_mutex.hpp">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\fiber\fiber_mutex_stat.hpp">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\fiber\fiber_redis_pipeline.hpp">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
@ -83,6 +89,12 @@
|
||||
<ClCompile Include="src\fiber_lock.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\fiber_mutex.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\fiber_mutex_stat.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\fiber_redis_pipeline.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
|
@ -309,6 +309,8 @@
|
||||
<ClInclude Include="include\fiber\fiber_cpp_define.hpp" />
|
||||
<ClInclude Include="include\fiber\fiber_event.hpp" />
|
||||
<ClInclude Include="include\fiber\fiber_lock.hpp" />
|
||||
<ClInclude Include="include\fiber\fiber_mutex.hpp" />
|
||||
<ClInclude Include="include\fiber\fiber_mutex_stat.hpp" />
|
||||
<ClInclude Include="include\fiber\fiber_redis_pipeline.hpp" />
|
||||
<ClInclude Include="include\fiber\fiber_sem.hpp" />
|
||||
<ClInclude Include="include\fiber\fiber_tbox.hpp" />
|
||||
@ -325,6 +327,8 @@
|
||||
<ClCompile Include="src\fiber_cond.cpp" />
|
||||
<ClCompile Include="src\fiber_event.cpp" />
|
||||
<ClCompile Include="src\fiber_lock.cpp" />
|
||||
<ClCompile Include="src\fiber_mutex.cpp" />
|
||||
<ClCompile Include="src\fiber_mutex_stat.cpp" />
|
||||
<ClCompile Include="src\fiber_redis_pipeline.cpp" />
|
||||
<ClCompile Include="src\fiber_sem.cpp" />
|
||||
<ClCompile Include="src\fiber_server.cpp" />
|
||||
|
@ -36,6 +36,12 @@
|
||||
<ClCompile Include="src\fiber_lock.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\fiber_mutex.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\fiber_mutex_stat.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\fiber_redis_pipeline.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
@ -74,6 +80,12 @@
|
||||
<ClInclude Include="include\fiber\fiber_lock.hpp">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\fiber\fiber_mutex.hpp">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\fiber\fiber_mutex_stat.hpp">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\fiber\fiber_redis_pipeline.hpp">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
|
@ -316,6 +316,7 @@
|
||||
<ClInclude Include="include\fiber\fiber_event.hpp" />
|
||||
<ClInclude Include="include\fiber\fiber_lock.hpp" />
|
||||
<ClInclude Include="include\fiber\fiber_mutex.hpp" />
|
||||
<ClInclude Include="include\fiber\fiber_mutex_stat.hpp" />
|
||||
<ClInclude Include="include\fiber\fiber_redis_pipeline.hpp" />
|
||||
<ClInclude Include="include\fiber\fiber_sem.hpp" />
|
||||
<ClInclude Include="include\fiber\fiber_tbox.hpp" />
|
||||
@ -345,6 +346,7 @@
|
||||
<ClCompile Include="src\fiber_event.cpp" />
|
||||
<ClCompile Include="src\fiber_lock.cpp" />
|
||||
<ClCompile Include="src\fiber_mutex.cpp" />
|
||||
<ClCompile Include="src\fiber_mutex_stat.cpp" />
|
||||
<ClCompile Include="src\fiber_redis_pipeline.cpp" />
|
||||
<ClCompile Include="src\fiber_sem.cpp" />
|
||||
<ClCompile Include="src\fiber_server.cpp" />
|
||||
|
@ -75,6 +75,9 @@
|
||||
<ClCompile Include="src\fiber_mutex.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\fiber_mutex_stat.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\tcp_keeper.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
@ -140,6 +143,9 @@
|
||||
<ClInclude Include="include\fiber\fiber_mutex.hpp">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\fiber\fiber_mutex_stat.hpp">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\fiber\http_server.hpp">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
|
@ -4,7 +4,17 @@
|
||||
|
||||
namespace acl {
|
||||
|
||||
fiber::fiber(bool running /* = false */)
|
||||
fiber::fiber(void)
|
||||
{
|
||||
f_ = NULL;
|
||||
}
|
||||
|
||||
fiber::fiber(ACL_FIBER *f)
|
||||
{
|
||||
f_ = f;
|
||||
}
|
||||
|
||||
fiber::fiber(bool running)
|
||||
{
|
||||
if (running) {
|
||||
f_ = acl_fiber_running();
|
||||
@ -31,6 +41,12 @@ unsigned int fiber::self(void)
|
||||
return acl_fiber_self();
|
||||
}
|
||||
|
||||
unsigned int fiber::id(const fiber& fb)
|
||||
{
|
||||
ACL_FIBER *f = fb.get_fiber();
|
||||
return f ? acl_fiber_id(f) : 0;
|
||||
}
|
||||
|
||||
int fiber::get_errno(void) const
|
||||
{
|
||||
return f_ ? acl_fiber_errno(f_) : -1;
|
||||
|
@ -1,16 +1,24 @@
|
||||
#include "stdafx.hpp"
|
||||
#include "fiber/fiber.hpp"
|
||||
#include "fiber/fiber_mutex.hpp"
|
||||
|
||||
namespace acl {
|
||||
|
||||
fiber_mutex::fiber_mutex(void)
|
||||
fiber_mutex::fiber_mutex(ACL_FIBER_MUTEX *mutex /* NULL */)
|
||||
{
|
||||
mutex_ = acl_fiber_mutex_create(0);
|
||||
if (mutex) {
|
||||
mutex_ = mutex;
|
||||
mutex_internal_ = NULL;
|
||||
} else {
|
||||
mutex_internal_ = mutex_ = acl_fiber_mutex_create(0);
|
||||
}
|
||||
}
|
||||
|
||||
fiber_mutex::~fiber_mutex(void)
|
||||
{
|
||||
acl_fiber_mutex_free(mutex_);
|
||||
if (mutex_internal_) {
|
||||
acl_fiber_mutex_free(mutex_internal_);
|
||||
}
|
||||
}
|
||||
|
||||
bool fiber_mutex::lock(void)
|
||||
@ -30,4 +38,29 @@ bool fiber_mutex::unlock(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fiber_mutex::deadlock(fiber_mutex_stats& out)
|
||||
{
|
||||
ACL_FIBER_MUTEX_STATS *stats = acl_fiber_mutex_deadlock();
|
||||
|
||||
if (stats == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < stats->count; i++) {
|
||||
fiber_mutex_stat stat;
|
||||
stat.fb = new fiber(stats->stats[i].fiber);
|
||||
stat.waiting = stats->stats[i].waiting;
|
||||
|
||||
for (size_t j = 0; j < stats->stats[i].count; j++) {
|
||||
ACL_FIBER_MUTEX* mutex = stats->stats[i].holding[j];
|
||||
stat.holding.push_back(mutex);
|
||||
}
|
||||
|
||||
out.stats.push_back(stat);
|
||||
}
|
||||
|
||||
acl_fiber_mutex_stats_free(stats);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace acl
|
||||
|
16
lib_fiber/cpp/src/fiber_mutex_stat.cpp
Normal file
16
lib_fiber/cpp/src/fiber_mutex_stat.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
#include "stdafx.hpp"
|
||||
#include "fiber/fiber.hpp"
|
||||
#include "fiber/fiber_mutex.hpp"
|
||||
#include "fiber/fiber_mutex_stat.hpp"
|
||||
|
||||
namespace acl {
|
||||
|
||||
fiber_mutex_stats::~fiber_mutex_stats(void)
|
||||
{
|
||||
for (std::vector<fiber_mutex_stat>::iterator it = stats.begin();
|
||||
it != stats.end(); ++it) {
|
||||
delete (*it).fb;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace acl
|
@ -65,7 +65,7 @@ static void fiber_check(ACL_FIBER *fb, void *ctx)
|
||||
sleep(1);
|
||||
printf("\r\n");
|
||||
//acl_fiber_mutex_profile();
|
||||
stats = acl_fiber_mutex_deadcheck();
|
||||
stats = acl_fiber_mutex_deadlock();
|
||||
if (stats) {
|
||||
acl_fiber_mutex_stats_show(stats);
|
||||
acl_fiber_mutex_stats_free(stats);
|
||||
|
6
lib_fiber/samples/dead_lock2/Makefile
Normal file
6
lib_fiber/samples/dead_lock2/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
# Don't build the sample on MacOS because libunwind don't support it.
|
||||
include ./Makefile.in
|
||||
ifeq ($(findstring Linux, $(UNIXNAME)), Linux)
|
||||
SYSLIB += -lunwind -lunwind-x86_64
|
||||
endif
|
||||
PROG = dead_lock
|
174
lib_fiber/samples/dead_lock2/Makefile.in
Normal file
174
lib_fiber/samples/dead_lock2/Makefile.in
Normal file
@ -0,0 +1,174 @@
|
||||
CC = g++
|
||||
|
||||
CFLAGS = -c -g -W -Wall -Wcast-qual -Wcast-align \
|
||||
-Wno-long-long -Wpointer-arith -Werror -Wshadow -O0 \
|
||||
-D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS -D_USE_FAST_MACRO
|
||||
|
||||
###########################################################
|
||||
#Check system:
|
||||
# Linux, SunOS, Solaris, BSD variants, AIX, HP-UX
|
||||
SYSLIB = -ldl -lpthread -lz
|
||||
CHECKSYSRES = @echo "Unknow system type!";exit 1
|
||||
UNIXNAME = $(shell uname -sm)
|
||||
OSTYPE = $(shell uname -p)
|
||||
RPATH = linux64
|
||||
|
||||
ifeq ($(CC),)
|
||||
CC = g++
|
||||
endif
|
||||
|
||||
OS_ENV=$(shell uname -a)
|
||||
ifeq ($(findstring WSL, $(OS_ENV)), WSL)
|
||||
SYSLIB += -liconv
|
||||
endif
|
||||
|
||||
ifeq ($(findstring ubuntu, $(OS_ENV)), ubuntu)
|
||||
SYSLIB += -liconv
|
||||
endif
|
||||
|
||||
ifeq ($(findstring Alpine, $(shell uname -a)), Alpine)
|
||||
SYSLIB += -lucontext
|
||||
endif
|
||||
|
||||
ifeq ($(findstring g++, $(CC)), g++)
|
||||
GCC_VERSION:=$(shell echo `gcc --version|grep ^gcc|cut -d' ' -f3`)
|
||||
GCC_MAJOR:=$(shell echo "$(GCC_VERSION)" | cut -d'.' -f1)
|
||||
GCC_MINOR:=$(shell echo "$(GCC_VERSION)" | cut -d'.' -f2)
|
||||
GCC_VER:=$(shell [ $(GCC_MAJOR) -gt 4 -o \( $(GCC_MAJOR) -eq 4 -a $(GCC_MINOR) -ge 7 \) ] && echo true)
|
||||
ifeq ($(GCC_VER), true)
|
||||
CFLAGS += -std=c++11 -DACL_USE_CPP11
|
||||
endif
|
||||
endif
|
||||
|
||||
# For FreeBSD
|
||||
ifeq ($(findstring FreeBSD, $(UNIXNAME)), FreeBSD)
|
||||
ifeq ($(findstring gcc, $(CC)), gcc)
|
||||
CFLAGS += -Wstrict-prototypes
|
||||
endif
|
||||
CFLAGS += -DFREEBSD -D_REENTRANT
|
||||
SYSLIB = -lcrypt -lpthread -lz
|
||||
RPATH = freebsd
|
||||
endif
|
||||
|
||||
# For Darwin
|
||||
ifeq ($(findstring Darwin, $(UNIXNAME)), Darwin)
|
||||
# CC += -arch x86_64 -arch arm64
|
||||
CFLAGS += -DMACOSX -Wno-invalid-source-encoding \
|
||||
-Wno-invalid-offsetof
|
||||
UNIXTYPE = MACOSX
|
||||
SYSLIB += -liconv -rdynamic
|
||||
RPATH = macos
|
||||
endif
|
||||
|
||||
#Path for Linux
|
||||
ifeq ($(findstring Linux, $(UNIXNAME)), Linux)
|
||||
ifeq ($CC, "gcc")
|
||||
CFLAGS += -Wstrict-prototypes
|
||||
endif
|
||||
ifeq ($(findstring i686, $(OSTYPE)), i686)
|
||||
RPATH = linux32
|
||||
endif
|
||||
ifeq ($(findstring x86_64, $(OSTYPE)), x86_64)
|
||||
RPATH = linux64
|
||||
endif
|
||||
ifeq ($(HAS_IO_URING), yes)
|
||||
SYSLIB += -luring
|
||||
endif
|
||||
ifeq ($(has_io_uring), yes)
|
||||
SYSLIB += -luring
|
||||
endif
|
||||
# CFLAGS += -DLINUX2 -D_REENTRANT
|
||||
CFLAGS += -D_REENTRANT
|
||||
SYSLIB += -lcrypt
|
||||
endif
|
||||
|
||||
#Path for SunOS
|
||||
ifeq ($(findstring SunOS, $(UNIXNAME)), SunOS)
|
||||
ifeq ($(findstring 86, $(UNIXNAME)), 86)
|
||||
SYSLIB += -lsocket -lnsl -lrt
|
||||
endif
|
||||
ifeq ($(findstring sun4u, $(UNIXNAME)), sun4u)
|
||||
SYSLIB += -lsocket -lnsl -lrt
|
||||
endif
|
||||
ifeq ($CC, "gcc")
|
||||
CFLAGS += -Wstrict-prototypes
|
||||
endif
|
||||
CFLAGS += -DSUNOS5 -D_REENTRANT
|
||||
RPATH = sunos_x86
|
||||
endif
|
||||
|
||||
#Path for HP-UX
|
||||
ifeq ($(findstring HP-UX, $(UNIXNAME)), HP-UX)
|
||||
ifeq ($CC, "gcc")
|
||||
CFLAGS += -Wstrict-prototypes
|
||||
endif
|
||||
CFLAGS += -DHP_UX -DHPUX11
|
||||
PLAT_NAME=hp-ux
|
||||
endif
|
||||
|
||||
# For CYGWIN
|
||||
ifeq ($(findstring CYGWIN, $(UNIXNAME)), CYGWIN)
|
||||
SYSLIB = -lpthread -rdynamic
|
||||
CFLAGS += -DLINUX2 -DMINGW
|
||||
UNIXTYPE = LINUX
|
||||
endif
|
||||
|
||||
# For MINGW
|
||||
ifeq ($(findstring MINGW, $(UNIXNAME)), MINGW)
|
||||
SYSLIB = -lpthread -rdynamic
|
||||
CFLAGS += -DLINUX2 -DMINGW
|
||||
UNIXTYPE = LINUX
|
||||
endif
|
||||
|
||||
# For MSYS
|
||||
ifeq ($(findstring MSYS, $(UNIXNAME)), MSYS)
|
||||
SYSLIB = -lpthread -rdynamic
|
||||
CFLAGS += -DLINUX2 -DMINGW
|
||||
UNIXTYPE = LINUX
|
||||
endif
|
||||
|
||||
#Find system type.
|
||||
ifneq ($(SYSPATH),)
|
||||
CHECKSYSRES = @echo "System is $(shell uname -sm)"
|
||||
endif
|
||||
###########################################################
|
||||
|
||||
CFLAGS += -I.. -I../../../lib_acl/include -I../../../lib_protocol/include -I../../../lib_acl_cpp/include \
|
||||
-I../../../lib_fiber/c/include -I../../../lib_fiber/cpp/include
|
||||
EXTLIBS =
|
||||
LDFLAGS = -L../../../lib_fiber/lib -lfiber_cpp \
|
||||
-L../../../lib_acl_cpp/lib -lacl_cpp \
|
||||
-L../../../lib_protocol/lib -lprotocol \
|
||||
-L../../../lib_acl/lib -lacl \
|
||||
-lfiber $(EXTLIBS) $(SYSLIB)
|
||||
|
||||
COMPILE = $(CC) $(CFLAGS)
|
||||
LINK = $(CC) $(OBJ) $(LDFLAGS)
|
||||
###########################################################
|
||||
OBJ_PATH = .
|
||||
|
||||
#Project's objs
|
||||
SRC = $(wildcard *.cpp)
|
||||
OBJ = $(patsubst %.cpp, $(OBJ_PATH)/%.o, $(notdir $(SRC)))
|
||||
|
||||
$(OBJ_PATH)/%.o: %.cpp
|
||||
$(COMPILE) $< -o $@
|
||||
|
||||
.PHONY = all clean
|
||||
all: RM $(OBJ)
|
||||
$(LINK) -o $(PROG)
|
||||
@echo ""
|
||||
@echo "All ok! Output:$(PROG)"
|
||||
@echo ""
|
||||
RM:
|
||||
rm -f $(PROG)
|
||||
clean cl:
|
||||
rm -f $(PROG)
|
||||
rm -f $(OBJ)
|
||||
|
||||
rebuild rb: clean all
|
||||
|
||||
install:
|
||||
cp $(PROG) ../../../dist/master/libexec/$(RPATH)/
|
||||
cp $(PROG).cf ../../../dist/master/conf/service/
|
||||
###########################################################
|
152
lib_fiber/samples/dead_lock2/main.cpp
Normal file
152
lib_fiber/samples/dead_lock2/main.cpp
Normal file
@ -0,0 +1,152 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include "fiber/libfiber.h"
|
||||
#include "fiber/libfiber.hpp"
|
||||
|
||||
class myfiber : public acl::fiber {
|
||||
public:
|
||||
myfiber(std::vector<acl::fiber_mutex*>& locks) : locks_(locks) {}
|
||||
~myfiber(void) {}
|
||||
|
||||
private:
|
||||
std::vector<acl::fiber_mutex*>& locks_;
|
||||
|
||||
// @override
|
||||
void run(void) {
|
||||
size_t i = acl::fiber::self() % locks_.size();
|
||||
acl::fiber_mutex* lock = locks_[i];
|
||||
|
||||
printf("fiber-%d wait, locks[%zd]=%p\r\n",
|
||||
acl::fiber::self(), i, lock);
|
||||
lock->lock();
|
||||
printf("fiber-%d locked, locks[%ld]=%p\r\n",
|
||||
acl::fiber::self(), i, lock);
|
||||
|
||||
sleep(1);
|
||||
|
||||
i = (acl::fiber::self() + 1) % locks_.size();
|
||||
lock = locks_[i];
|
||||
|
||||
printf("fiber-%d wait,locks[%zd]=%p\r\n",
|
||||
acl::fiber::self(), i, lock);
|
||||
lock->lock();
|
||||
printf("fiber-%d locked, locks[%zd]=%p\r\n",
|
||||
acl::fiber::self(), i, lock);
|
||||
}
|
||||
};
|
||||
|
||||
class fiber_check : public acl::fiber {
|
||||
public:
|
||||
fiber_check(void) {}
|
||||
~fiber_check(void) {}
|
||||
|
||||
private:
|
||||
// @override
|
||||
void run(void) {
|
||||
while (true) {
|
||||
sleep(2);
|
||||
printf("\r\n");
|
||||
acl::fiber_mutex_stats stats;
|
||||
if (acl::fiber_mutex::deadlock(stats)) {
|
||||
printf("Deadlock happened!\r\n\r\n");
|
||||
show(stats);
|
||||
} else {
|
||||
printf("No deadlock happened!\r\n");
|
||||
}
|
||||
printf("=======================================\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
void show(const acl::fiber_mutex_stats& stats) {
|
||||
for (std::vector<acl::fiber_mutex_stat>::const_iterator
|
||||
cit = stats.stats.begin(); cit != stats.stats.end();
|
||||
++cit) {
|
||||
show(*cit);
|
||||
printf("\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
void show(const acl::fiber_mutex_stat& stat) {
|
||||
printf("fiber-%d:\r\n", acl::fiber::id(*stat.fb));
|
||||
|
||||
std::vector<acl::fiber_frame> stack;
|
||||
acl::fiber::stacktrace(*stat.fb, stack, 50);
|
||||
show_stack(stack);
|
||||
|
||||
for (std::vector<ACL_FIBER_MUTEX*>::const_iterator
|
||||
cit = stat.holding.begin();
|
||||
cit != stat.holding.end(); ++cit) {
|
||||
printf("Holding mutex=%p\r\n", *cit);
|
||||
}
|
||||
printf("Waiting for mutex=%p\r\n", stat.waiting);
|
||||
}
|
||||
|
||||
void show_stack(const std::vector<acl::fiber_frame>& stack)
|
||||
{
|
||||
for (std::vector<acl::fiber_frame>::const_iterator
|
||||
cit = stack.begin(); cit != stack.end(); ++cit) {
|
||||
printf("0x%lx(%s)+0x%lx\r\n",
|
||||
(*cit).pc, (*cit).func.c_str(), (*cit).off);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static void usage(const char *procname)
|
||||
{
|
||||
printf("usage: %s -h [help] -c fibers_count -n locks_count\r\n", procname);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i, ch, nlocks = 2, nfibers = 2;
|
||||
std::vector<acl::fiber_mutex*> locks;
|
||||
|
||||
while ((ch = getopt(argc, argv, "hc:n:")) > 0) {
|
||||
switch (ch) {
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
return 0;
|
||||
case 'c':
|
||||
nfibers = atoi(optarg);
|
||||
break;
|
||||
case 'n':
|
||||
nlocks = atoi(optarg);
|
||||
if (nlocks <= 0) {
|
||||
nlocks = 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < nlocks; i++) {
|
||||
acl::fiber_mutex* lock = new acl::fiber_mutex;
|
||||
locks.push_back(lock);
|
||||
}
|
||||
|
||||
std::vector<acl::fiber*> fibers;
|
||||
|
||||
for (i = 0; i < nfibers; i++) {
|
||||
acl::fiber* fb = new myfiber(locks);
|
||||
fibers.push_back(fb);
|
||||
fb->start();
|
||||
}
|
||||
|
||||
fiber_check check;
|
||||
check.start();
|
||||
|
||||
acl::fiber::schedule();
|
||||
|
||||
for (std::vector<acl::fiber_mutex*>::iterator it = locks.begin();
|
||||
it != locks.end(); ++it) {
|
||||
delete *it;
|
||||
}
|
||||
|
||||
for (std::vector<acl::fiber*>::iterator it = fibers.begin();
|
||||
it != fibers.end(); ++it) {
|
||||
delete *it;
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -50,14 +50,12 @@ private:
|
||||
|
||||
void run(void)
|
||||
{
|
||||
std::vector<acl::fiber_frame> stack;
|
||||
|
||||
for (int i = 0; i < count_; i++) {
|
||||
std::vector<acl::fiber_frame> stack;
|
||||
acl::fiber::stacktrace(*fb_, stack, 50);
|
||||
show_stack(stack);
|
||||
printf("\r\n");
|
||||
|
||||
stack.clear();
|
||||
sleep(2);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user