feature merge bs-coreoptimize->trunk: Atomic Operations, Threading, Spinlock implemnetation. [commit 1/2, windows will followup]
- Added Abstractions for Atomic Operations (lock instructions.. windows guy's may now this as Interlocked* stuff ..) - Added Threading api abstraction for Pthread based OS's and Windows - Added Spinlock Implementation (uses CAS / if you need more informations - just read the source - its simple.) - Due to Interlocked(Compare)Exchange64 .. we now require at least i686 (Pentium Pro) for 32Bit Builds :) youll also may feel some performance improvements when using 32bit builsd due to "newer" minimal arch the compiler is now able to use CMOV's .... ================================================================ = Important Warning: ================================================================ Dont use threading at the moment athena is not threadsafe! you'll mess up everthing when accessing data from other threads .., no synchronization is provided. A way to process tasks asynchronously will come up after / with the new socket system. git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@16221 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
parent
024deea2ac
commit
04165cfcff
@ -28,6 +28,7 @@ endif
|
||||
map_sql \
|
||||
tools \
|
||||
import \
|
||||
test \
|
||||
clean help
|
||||
|
||||
all: $(ALL_DEPENDS)
|
||||
@ -55,6 +56,9 @@ map_sql: $(MAP_SQL_DEPENDS)
|
||||
tools:
|
||||
@$(MAKE) -C src/tool
|
||||
|
||||
test:
|
||||
@$(MAKE) -C src/test
|
||||
|
||||
import:
|
||||
# 1) create conf/import folder
|
||||
# 2) add missing files
|
||||
@ -72,6 +76,7 @@ clean:
|
||||
@$(MAKE) -C src/char $@
|
||||
@$(MAKE) -C src/map $@
|
||||
@$(MAKE) -C src/tool $@
|
||||
@$(MAKE) -C src/test $@
|
||||
|
||||
help:
|
||||
@echo "most common targets are 'all' 'sql' 'conf' 'clean' 'help'"
|
||||
@ -87,6 +92,7 @@ help:
|
||||
@echo "'all' - builds all the above targets"
|
||||
@echo "'sql' - builds sql servers (targets 'common_sql' 'login_sql' 'char_sql'"
|
||||
@echo " 'map_sql' and 'import')"
|
||||
@echo "'test' - builds tests"
|
||||
@echo "'clean' - cleans builds and objects"
|
||||
@echo "'help' - outputs this message"
|
||||
|
||||
|
381
configure
vendored
381
configure
vendored
@ -1,5 +1,5 @@
|
||||
#! /bin/sh
|
||||
# From configure.in Revision: 16200 .
|
||||
# From configure.in Revision: 16203 .
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.67.
|
||||
#
|
||||
@ -2126,6 +2126,8 @@ ac_config_files="$ac_config_files src/char/Makefile src/login/Makefile"
|
||||
|
||||
ac_config_files="$ac_config_files src/map/Makefile src/tool/Makefile"
|
||||
|
||||
ac_config_files="$ac_config_files src/test/Makefile"
|
||||
|
||||
|
||||
ac_ext=c
|
||||
ac_cpp='$CPP $CPPFLAGS'
|
||||
@ -4666,6 +4668,46 @@ $as_echo "$pointers_fit_in_ints" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
#
|
||||
# check if we're producing 32bit code - so well produce binarys for at least i686 (speedup: cmovs, and cmpchg8 support)
|
||||
#
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC produces 32bit code" >&5
|
||||
$as_echo_n "checking whether $CC produces 32bit code... " >&6; }
|
||||
if test "$cross_compiling" = yes; then :
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: guessing no" >&5
|
||||
$as_echo "guessing no" >&6; }
|
||||
|
||||
|
||||
else
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
int main(int argc, char **argv){
|
||||
if(sizeof(void*) == 4) return 0;
|
||||
else return 1;
|
||||
}
|
||||
|
||||
_ACEOF
|
||||
if ac_fn_c_try_run "$LINENO"; then :
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
CFLAGS="$CFLAGS -march=i686"
|
||||
LDFLAGS="$LDFLAGS -march=i686"
|
||||
|
||||
else
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
|
||||
fi
|
||||
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
|
||||
conftest.$ac_objext conftest.beam conftest.$ac_ext
|
||||
fi
|
||||
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wno-unused-parameter" >&5
|
||||
$as_echo_n "checking whether $CC supports -Wno-unused-parameter... " >&6; }
|
||||
OLD_CFLAGS="$CFLAGS"
|
||||
@ -5284,6 +5326,342 @@ fi
|
||||
fi
|
||||
|
||||
|
||||
#
|
||||
# pthread
|
||||
#
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5
|
||||
$as_echo_n "checking for pthread_create in -lpthread... " >&6; }
|
||||
if test "${ac_cv_lib_pthread_pthread_create+set}" = set; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lpthread $LIBS"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char pthread_create ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return pthread_create ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_lib_pthread_pthread_create=yes
|
||||
else
|
||||
ac_cv_lib_pthread_pthread_create=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5
|
||||
$as_echo "$ac_cv_lib_pthread_pthread_create" >&6; }
|
||||
if test "x$ac_cv_lib_pthread_pthread_create" = x""yes; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_LIBPTHREAD 1
|
||||
_ACEOF
|
||||
|
||||
LIBS="-lpthread $LIBS"
|
||||
|
||||
else
|
||||
as_fn_error $? "pthread library not found or incompatible" "$LINENO" 5
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_sigmask in -lpthread" >&5
|
||||
$as_echo_n "checking for pthread_sigmask in -lpthread... " >&6; }
|
||||
if test "${ac_cv_lib_pthread_pthread_sigmask+set}" = set; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lpthread $LIBS"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char pthread_sigmask ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return pthread_sigmask ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_lib_pthread_pthread_sigmask=yes
|
||||
else
|
||||
ac_cv_lib_pthread_pthread_sigmask=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_sigmask" >&5
|
||||
$as_echo "$ac_cv_lib_pthread_pthread_sigmask" >&6; }
|
||||
if test "x$ac_cv_lib_pthread_pthread_sigmask" = x""yes; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_LIBPTHREAD 1
|
||||
_ACEOF
|
||||
|
||||
LIBS="-lpthread $LIBS"
|
||||
|
||||
else
|
||||
as_fn_error $? "pthread library not found or incompatible" "$LINENO" 5
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_attr_init in -lpthread" >&5
|
||||
$as_echo_n "checking for pthread_attr_init in -lpthread... " >&6; }
|
||||
if test "${ac_cv_lib_pthread_pthread_attr_init+set}" = set; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lpthread $LIBS"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char pthread_attr_init ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return pthread_attr_init ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_lib_pthread_pthread_attr_init=yes
|
||||
else
|
||||
ac_cv_lib_pthread_pthread_attr_init=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_attr_init" >&5
|
||||
$as_echo "$ac_cv_lib_pthread_pthread_attr_init" >&6; }
|
||||
if test "x$ac_cv_lib_pthread_pthread_attr_init" = x""yes; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_LIBPTHREAD 1
|
||||
_ACEOF
|
||||
|
||||
LIBS="-lpthread $LIBS"
|
||||
|
||||
else
|
||||
as_fn_error $? "pthread library not found or incompatible" "$LINENO" 5
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_attr_setstacksize in -lpthread" >&5
|
||||
$as_echo_n "checking for pthread_attr_setstacksize in -lpthread... " >&6; }
|
||||
if test "${ac_cv_lib_pthread_pthread_attr_setstacksize+set}" = set; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lpthread $LIBS"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char pthread_attr_setstacksize ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return pthread_attr_setstacksize ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_lib_pthread_pthread_attr_setstacksize=yes
|
||||
else
|
||||
ac_cv_lib_pthread_pthread_attr_setstacksize=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_attr_setstacksize" >&5
|
||||
$as_echo "$ac_cv_lib_pthread_pthread_attr_setstacksize" >&6; }
|
||||
if test "x$ac_cv_lib_pthread_pthread_attr_setstacksize" = x""yes; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_LIBPTHREAD 1
|
||||
_ACEOF
|
||||
|
||||
LIBS="-lpthread $LIBS"
|
||||
|
||||
else
|
||||
as_fn_error $? "pthread library not found or incompatible" "$LINENO" 5
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_attr_destroy in -lpthread" >&5
|
||||
$as_echo_n "checking for pthread_attr_destroy in -lpthread... " >&6; }
|
||||
if test "${ac_cv_lib_pthread_pthread_attr_destroy+set}" = set; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lpthread $LIBS"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char pthread_attr_destroy ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return pthread_attr_destroy ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_lib_pthread_pthread_attr_destroy=yes
|
||||
else
|
||||
ac_cv_lib_pthread_pthread_attr_destroy=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_attr_destroy" >&5
|
||||
$as_echo "$ac_cv_lib_pthread_pthread_attr_destroy" >&6; }
|
||||
if test "x$ac_cv_lib_pthread_pthread_attr_destroy" = x""yes; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_LIBPTHREAD 1
|
||||
_ACEOF
|
||||
|
||||
LIBS="-lpthread $LIBS"
|
||||
|
||||
else
|
||||
as_fn_error $? "pthread library not found or incompatible" "$LINENO" 5
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_cancel in -lpthread" >&5
|
||||
$as_echo_n "checking for pthread_cancel in -lpthread... " >&6; }
|
||||
if test "${ac_cv_lib_pthread_pthread_cancel+set}" = set; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lpthread $LIBS"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char pthread_cancel ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return pthread_cancel ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_lib_pthread_pthread_cancel=yes
|
||||
else
|
||||
ac_cv_lib_pthread_pthread_cancel=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_cancel" >&5
|
||||
$as_echo "$ac_cv_lib_pthread_pthread_cancel" >&6; }
|
||||
if test "x$ac_cv_lib_pthread_pthread_cancel" = x""yes; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_LIBPTHREAD 1
|
||||
_ACEOF
|
||||
|
||||
LIBS="-lpthread $LIBS"
|
||||
|
||||
else
|
||||
as_fn_error $? "pthread library not found or incompatible" "$LINENO" 5
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join in -lpthread" >&5
|
||||
$as_echo_n "checking for pthread_join in -lpthread... " >&6; }
|
||||
if test "${ac_cv_lib_pthread_pthread_join+set}" = set; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lpthread $LIBS"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char pthread_join ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return pthread_join ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_lib_pthread_pthread_join=yes
|
||||
else
|
||||
ac_cv_lib_pthread_pthread_join=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_join" >&5
|
||||
$as_echo "$ac_cv_lib_pthread_pthread_join" >&6; }
|
||||
if test "x$ac_cv_lib_pthread_pthread_join" = x""yes; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_LIBPTHREAD 1
|
||||
_ACEOF
|
||||
|
||||
LIBS="-lpthread $LIBS"
|
||||
|
||||
else
|
||||
as_fn_error $? "pthread library not found or incompatible" "$LINENO" 5
|
||||
fi
|
||||
|
||||
|
||||
LDFLAGS="$LDFLAGS -lpthread"
|
||||
|
||||
|
||||
#
|
||||
# MySQL library
|
||||
#
|
||||
@ -6304,6 +6682,7 @@ do
|
||||
"src/login/Makefile") CONFIG_FILES="$CONFIG_FILES src/login/Makefile" ;;
|
||||
"src/map/Makefile") CONFIG_FILES="$CONFIG_FILES src/map/Makefile" ;;
|
||||
"src/tool/Makefile") CONFIG_FILES="$CONFIG_FILES src/tool/Makefile" ;;
|
||||
"src/test/Makefile") CONFIG_FILES="$CONFIG_FILES src/test/Makefile" ;;
|
||||
|
||||
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;;
|
||||
esac
|
||||
|
40
configure.in
40
configure.in
@ -9,6 +9,7 @@ AC_CONFIG_FILES([Makefile src/common/Makefile])
|
||||
AC_CONFIG_FILES([3rdparty/mt19937ar/Makefile 3rdparty/libconfig/Makefile])
|
||||
AC_CONFIG_FILES([src/char/Makefile src/login/Makefile])
|
||||
AC_CONFIG_FILES([src/map/Makefile src/tool/Makefile])
|
||||
AC_CONFIG_FILES([src/test/Makefile])
|
||||
|
||||
AC_GNU_SOURCE
|
||||
|
||||
@ -337,6 +338,31 @@ if test "$enable_64bit" = "no" ; then
|
||||
fi
|
||||
|
||||
|
||||
#
|
||||
# check if we're producing 32bit code - so well produce binarys for at least i686 (speedup: cmovs, and cmpchg8 support)
|
||||
#
|
||||
AC_MSG_CHECKING([whether $CC produces 32bit code])
|
||||
AC_RUN_IFELSE(
|
||||
[
|
||||
int main(int argc, char **argv){
|
||||
if(sizeof(void*) == 4) return 0;
|
||||
else return 1;
|
||||
}
|
||||
],
|
||||
[
|
||||
AC_MSG_RESULT([yes])
|
||||
CFLAGS="$CFLAGS -march=i686"
|
||||
LDFLAGS="$LDFLAGS -march=i686"
|
||||
],
|
||||
[
|
||||
AC_MSG_RESULT([no])
|
||||
],
|
||||
[
|
||||
AC_MSG_RESULT([guessing no])
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
AC_MSG_CHECKING([whether $CC supports -Wno-unused-parameter])
|
||||
OLD_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -Wno-unused-parameter"
|
||||
@ -636,6 +662,20 @@ if test "$ac_cv_search_clock_gettime" != "no" ; then
|
||||
fi
|
||||
|
||||
|
||||
#
|
||||
# pthread
|
||||
#
|
||||
AC_CHECK_LIB([pthread], [pthread_create], [], [AC_MSG_ERROR([pthread library not found or incompatible])])
|
||||
AC_CHECK_LIB([pthread], [pthread_sigmask], [], [AC_MSG_ERROR([pthread library not found or incompatible])])
|
||||
AC_CHECK_LIB([pthread], [pthread_attr_init], [], [AC_MSG_ERROR([pthread library not found or incompatible])])
|
||||
AC_CHECK_LIB([pthread], [pthread_attr_setstacksize], [], [AC_MSG_ERROR([pthread library not found or incompatible])])
|
||||
AC_CHECK_LIB([pthread], [pthread_attr_destroy], [], [AC_MSG_ERROR([pthread library not found or incompatible])])
|
||||
AC_CHECK_LIB([pthread], [pthread_cancel], [], [AC_MSG_ERROR([pthread library not found or incompatible])])
|
||||
AC_CHECK_LIB([pthread], [pthread_join], [], [AC_MSG_ERROR([pthread library not found or incompatible])])
|
||||
|
||||
LDFLAGS="$LDFLAGS -lpthread"
|
||||
|
||||
|
||||
#
|
||||
# MySQL library
|
||||
#
|
||||
|
@ -3,7 +3,7 @@ COMMON_OBJ = obj_all/core.o obj_all/socket.o obj_all/timer.o obj_all/db.o obj_al
|
||||
obj_all/nullpo.o obj_all/malloc.o obj_all/showmsg.o obj_all/strlib.o obj_all/utils.o \
|
||||
obj_all/grfio.o obj_all/mapindex.o obj_all/ers.o obj_all/md5calc.o \
|
||||
obj_all/minicore.o obj_all/minisocket.o obj_all/minimalloc.o obj_all/random.o obj_all/des.o \
|
||||
obj_all/conf.o
|
||||
obj_all/conf.o obj_all/thread.o
|
||||
|
||||
COMMON_H = $(shell ls ../common/*.h)
|
||||
|
||||
|
157
src/common/atomic.h
Normal file
157
src/common/atomic.h
Normal file
@ -0,0 +1,157 @@
|
||||
#ifndef _rA_ATOMIC_H_
|
||||
#define _rA_ATOMIC_H_
|
||||
|
||||
// Atomic Operations
|
||||
// (Interlocked CompareExchange, Add .. and so on ..)
|
||||
//
|
||||
// Implementation varies / depends on:
|
||||
// - Architecture
|
||||
// - Compiler
|
||||
// - Operating System
|
||||
//
|
||||
// our Abstraction is fully API-Compatible to Microsofts implementation @ NT5.0+
|
||||
//
|
||||
#include "../common/cbasetypes.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include "../common/winapi.h"
|
||||
|
||||
#if !defined(_M_X64)
|
||||
// When compiling for windows 32bit, the 8byte interlocked operations are not provided by microsoft
|
||||
// (because they need at least i586 so its not generic enough.. ... )
|
||||
forceinline int64 InterlockedCompareExchange64(volatile int64 *dest, int64 exch, int64 _cmp){
|
||||
_asm{
|
||||
lea esi,_cmp;
|
||||
lea edi,exch;
|
||||
|
||||
mov eax,[esi];
|
||||
mov edx,4[esi];
|
||||
mov ebx,[edi];
|
||||
mov ecx,4[edi];
|
||||
mov esi,dest;
|
||||
|
||||
lock CMPXCHG8B [esi];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
forceinline volatile int64 InterlockedIncrement64(volatile int64 *addend){
|
||||
__int64 old;
|
||||
do{
|
||||
old = *addend;
|
||||
}while(InterlockedCompareExchange64(addend, (old+1), old) != old);
|
||||
|
||||
return (old + 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
forceinline volatile int64 InterlockedDecrement64(volatile int64 *addend){
|
||||
__int64 old;
|
||||
|
||||
do{
|
||||
old = *addend;
|
||||
}while(InterlockedCompareExchange64(addend, (old-1), old) != old);
|
||||
|
||||
return (old - 1);
|
||||
}
|
||||
|
||||
forceinline volatile int64 InterlockedExchangeAdd64(volatile int64 *addend, int64 increment){
|
||||
__int64 old;
|
||||
|
||||
do{
|
||||
old = *addend;
|
||||
}while(InterlockedCompareExchange64(addend, (old + increment), old) != old);
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
forceinline volatile int64 InterlockedExchange64(volatile int64 *target, int64 val){
|
||||
__int64 old;
|
||||
do{
|
||||
old = *target;
|
||||
}while(InterlockedCompareExchange64(target, val, old) != old);
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
#endif //endif 32bit windows
|
||||
|
||||
#elif defined(__GNUC__)
|
||||
|
||||
#if !defined(__x86_64__) && !defined(__i386__)
|
||||
#error Your Target Platfrom is not supported
|
||||
#endif
|
||||
|
||||
static forceinline volatile int64 InterlockedExchangeAdd64(volatile int64 *addend, int64 increment){
|
||||
return __sync_fetch_and_add(addend, increment);
|
||||
}//end: InterlockedExchangeAdd64()
|
||||
|
||||
|
||||
static forceinline volatile int32 InterlockedExchangeAdd(volatile int32 *addend, int32 increment){
|
||||
return __sync_fetch_and_add(addend, increment);
|
||||
}//end: InterlockedExchangeAdd()
|
||||
|
||||
|
||||
static forceinline volatile int64 InterlockedIncrement64(volatile int64 *addend){
|
||||
return __sync_add_and_fetch(addend, 1);
|
||||
}//end: InterlockedIncrement64()
|
||||
|
||||
|
||||
static forceinline volatile int32 InterlockedIncrement(volatile int32 *addend){
|
||||
return __sync_add_and_fetch(addend, 1);
|
||||
}//end: InterlockedIncrement()
|
||||
|
||||
|
||||
static forceinline volatile int64 InterlockedDecrement64(volatile int64 *addend){
|
||||
return __sync_sub_and_fetch(addend, 1);
|
||||
}//end: InterlockedDecrement64()
|
||||
|
||||
|
||||
static forceinline volatile int32 InterlockedDecrement(volatile int32 *addend){
|
||||
return __sync_sub_and_fetch(addend, 1);
|
||||
}//end: InterlockedDecrement()
|
||||
|
||||
|
||||
static forceinline volatile int64 InterlockedCompareExchange64(volatile int64 *dest, int64 exch, int64 cmp){
|
||||
return __sync_val_compare_and_swap(dest, cmp, exch);
|
||||
}//end: InterlockedCompareExchange64()
|
||||
|
||||
|
||||
static forceinline volatile int32 InterlockedCompareExchange(volatile int32 *dest, int32 exch, int32 cmp){
|
||||
return __sync_val_compare_and_swap(dest, cmp, exch);
|
||||
}//end: InterlockedCompareExchnage()
|
||||
|
||||
|
||||
static forceinline volatile int64 InterlockedExchange64(volatile int64 *target, int64 val){
|
||||
int ret;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"lock xchg %2, (%1)"
|
||||
:"=r" (ret)
|
||||
:"r" (target), "0" (val)
|
||||
:"memory"
|
||||
);
|
||||
|
||||
return ret;
|
||||
}//end: InterlockedExchange64()
|
||||
|
||||
|
||||
static forceinline volatile int32 InterlockedExchange(volatile int32 *target, int32 val){
|
||||
int ret;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"lock xchgl %2, (%1)"
|
||||
:"=r" (ret)
|
||||
:"r" (target), "0" (val)
|
||||
:"memory"
|
||||
);
|
||||
|
||||
return ret;
|
||||
}//end: InterlockedExchange()
|
||||
|
||||
|
||||
#endif //endif compiler decission
|
||||
|
||||
|
||||
#endif
|
@ -9,6 +9,7 @@
|
||||
#include "../common/db.h"
|
||||
#include "../common/socket.h"
|
||||
#include "../common/timer.h"
|
||||
#include "../common/thread.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
@ -278,6 +279,8 @@ int main (int argc, char **argv)
|
||||
display_title();
|
||||
usercheck();
|
||||
|
||||
rathread_init();
|
||||
|
||||
db_init();
|
||||
signals_init();
|
||||
|
||||
@ -303,6 +306,8 @@ int main (int argc, char **argv)
|
||||
timer_final();
|
||||
socket_final();
|
||||
db_final();
|
||||
|
||||
rathread_final();
|
||||
#endif
|
||||
|
||||
malloc_final();
|
||||
|
104
src/common/spinlock.h
Normal file
104
src/common/spinlock.h
Normal file
@ -0,0 +1,104 @@
|
||||
#pragma once
|
||||
#ifndef _rA_SPINLOCK_H_
|
||||
#define _rA_SPINLOCK_H_
|
||||
|
||||
//
|
||||
// CAS based Spinlock Implementation
|
||||
//
|
||||
// CamelCase names are choosen to be consistent with microsofts winapi
|
||||
// which implements CriticalSection by this naming...
|
||||
//
|
||||
// Author: Florian Wilkemeyer <fw@f-ws.de>
|
||||
//
|
||||
// Copyright (c) rAthena Project (www.rathena.org) - Licensed under GNU GPL
|
||||
// For more information, see LICENCE in the main folder
|
||||
//
|
||||
//
|
||||
|
||||
#ifdef WIN32
|
||||
#include "../common/winapi.h"
|
||||
#endif
|
||||
|
||||
#include "../common/cbasetypes.h"
|
||||
#include "../common/atomic.h"
|
||||
#include "../common/thread.h"
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
typedef struct __declspec( align(64) ) SPIN_LOCK{
|
||||
volatile LONG lock;
|
||||
volatile LONG nest;
|
||||
volatile LONG sync_lock;
|
||||
} SPIN_LOCK, *PSPIN_LOCK;
|
||||
#else
|
||||
typedef struct SPIN_LOCK{
|
||||
volatile int32 lock;
|
||||
volatile int32 nest; // nesting level.
|
||||
|
||||
volatile int32 sync_lock;
|
||||
} __attribute__((aligned(64))) SPIN_LOCK, *PSPIN_LOCK;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static forceinline void InitializeSpinLock(PSPIN_LOCK lck){
|
||||
lck->lock = 0;
|
||||
lck->nest = 0;
|
||||
lck->sync_lock = 0;
|
||||
}
|
||||
|
||||
static forceinline void FinalizeSpinLock(PSPIN_LOCK lck){
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
#define getsynclock(l) { while(1){ if(InterlockedCompareExchange(l, 1, 0) == 0) break; rathread_yield(); } }
|
||||
#define dropsynclock(l) { InterlockedExchange(l, 0); }
|
||||
|
||||
static forceinline void EnterSpinLock(PSPIN_LOCK lck){
|
||||
int tid = rathread_get_tid();
|
||||
|
||||
// Get Sync Lock && Check if the requester thread already owns the lock.
|
||||
// if it owns, increase nesting level
|
||||
getsynclock(&lck->sync_lock);
|
||||
if(InterlockedCompareExchange(&lck->lock, tid, tid) == tid){
|
||||
InterlockedIncrement(&lck->nest);
|
||||
dropsynclock(&lck->sync_lock);
|
||||
return; // Got Lock
|
||||
}
|
||||
// drop sync lock
|
||||
dropsynclock(&lck->sync_lock);
|
||||
|
||||
|
||||
// Spin until we've got it !
|
||||
while(1){
|
||||
|
||||
if(InterlockedCompareExchange(&lck->lock, tid, 0) == 0){
|
||||
|
||||
InterlockedIncrement(&lck->nest);
|
||||
return; // Got Lock
|
||||
}
|
||||
|
||||
rathread_yield(); // Force ctxswitch to another thread.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static forceinline void LeaveSpinLock(PSPIN_LOCK lck){
|
||||
int tid = rathread_get_tid();
|
||||
|
||||
getsynclock(&lck->sync_lock);
|
||||
|
||||
if(InterlockedCompareExchange(&lck->lock, tid, tid) == tid){ // this thread owns the lock.
|
||||
if(InterlockedDecrement(&lck->nest) == 0)
|
||||
InterlockedExchange(&lck->lock, 0); // Unlock!
|
||||
}
|
||||
|
||||
dropsynclock(&lck->sync_lock);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
270
src/common/thread.c
Normal file
270
src/common/thread.c
Normal file
@ -0,0 +1,270 @@
|
||||
|
||||
#ifdef WIN32
|
||||
#include "../common/winapi.h"
|
||||
#define getpagesize() 4096 // @TODO: implement this properly (GetSystemInfo .. dwPageSize..). (Atm as on all supported win platforms its 4k its static.)
|
||||
#define __thread __declspec( thread )
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#endif
|
||||
|
||||
#include "cbasetypes.h"
|
||||
#include "malloc.h"
|
||||
#include "showmsg.h"
|
||||
#include "thread.h"
|
||||
|
||||
|
||||
#define RA_THREADS_MAX 64
|
||||
|
||||
struct rAthread {
|
||||
unsigned int myID;
|
||||
|
||||
RATHREAD_PRIO prio;
|
||||
rAthreadProc proc;
|
||||
void *param;
|
||||
|
||||
#ifdef WIN32
|
||||
HANDLE hThread;
|
||||
#else
|
||||
pthread_t hThread;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
__thread int g_rathread_ID = -1;
|
||||
|
||||
|
||||
///
|
||||
/// Subystem Code
|
||||
///
|
||||
static struct rAthread l_threads[RA_THREADS_MAX];
|
||||
|
||||
void rathread_init(){
|
||||
register unsigned int i;
|
||||
memset(&l_threads, 0x00, RA_THREADS_MAX * sizeof(struct rAthread) );
|
||||
|
||||
for(i = 0; i < RA_THREADS_MAX; i++){
|
||||
l_threads[i].myID = i;
|
||||
}
|
||||
|
||||
// now lets init thread id 0, which represnts the main thread
|
||||
g_rathread_ID = 0;
|
||||
l_threads[0].prio = RAT_PRIO_NORMAL;
|
||||
l_threads[0].proc = (rAthreadProc)0xDEADCAFE;
|
||||
|
||||
}//end: rathread_init()
|
||||
|
||||
|
||||
|
||||
void rathread_final(){
|
||||
register unsigned int i;
|
||||
|
||||
// Unterminated Threads Left?
|
||||
// Should'nt happen ..
|
||||
// Kill 'em all!
|
||||
//
|
||||
for(i = 1; i < RA_THREADS_MAX; i++){
|
||||
if(l_threads[i].proc != NULL){
|
||||
ShowWarning("rAthread_final: unterminated Thread (tid %u entryPoint %p) - forcing to terminate (kill)\n", i, l_threads[i].proc);
|
||||
rathread_destroy(&l_threads[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}//end: rathread_final()
|
||||
|
||||
|
||||
|
||||
// gets called whenever a thread terminated ..
|
||||
static void rat_thread_terminated( rAthread handle ){
|
||||
|
||||
int id_backup = handle->myID;
|
||||
|
||||
// Simply set all members to 0 (except the id)
|
||||
memset(handle, 0x00, sizeof(struct rAthread));
|
||||
|
||||
handle->myID = id_backup; // done ;)
|
||||
|
||||
}//end: rat_thread_terminated()
|
||||
|
||||
#ifdef WIN32
|
||||
DWORD WINAPI _raThreadMainRedirector(LPVOID p){
|
||||
#else
|
||||
static void *_raThreadMainRedirector( void *p ){
|
||||
sigset_t set; // on Posix Thread platforms
|
||||
#endif
|
||||
void *ret;
|
||||
|
||||
// Update myID @ TLS to right id.
|
||||
g_rathread_ID = ((rAthread)p)->myID;
|
||||
|
||||
#ifndef WIN32
|
||||
// When using posix threads
|
||||
// the threads inherits the Signal mask from the thread which's spawned
|
||||
// this thread
|
||||
// so we've to block everything we dont care about.
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set, SIGINT);
|
||||
sigaddset(&set, SIGTERM);
|
||||
sigaddset(&set, SIGPIPE);
|
||||
|
||||
pthread_sigmask(SIG_BLOCK, &set, NULL);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
ret = ((rAthread)p)->proc( ((rAthread)p)->param ) ;
|
||||
|
||||
#ifdef WIN32
|
||||
CloseHandle( ((rAthread)p)->hThread );
|
||||
#endif
|
||||
|
||||
rat_thread_terminated( (rAthread)p );
|
||||
#ifdef WIN32
|
||||
return (DWORD)ret;
|
||||
#else
|
||||
return ret;
|
||||
#endif
|
||||
}//end: _raThreadMainRedirector()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// API Level
|
||||
///
|
||||
rAthread rathread_create( rAthreadProc entryPoint, void *param ){
|
||||
return rathread_createEx( entryPoint, param, (1<<23) /*8MB*/, RAT_PRIO_NORMAL );
|
||||
}//end: rathread_create()
|
||||
|
||||
|
||||
rAthread rathread_createEx( rAthreadProc entryPoint, void *param, size_t szStack, RATHREAD_PRIO prio ){
|
||||
#ifndef WIN32
|
||||
pthread_attr_t attr;
|
||||
#endif
|
||||
size_t tmp;
|
||||
unsigned int i;
|
||||
rAthread handle = NULL;
|
||||
|
||||
|
||||
// given stacksize aligned to systems pagesize?
|
||||
tmp = szStack % getpagesize();
|
||||
if(tmp != 0)
|
||||
szStack += tmp;
|
||||
|
||||
|
||||
// Get a free Thread Slot.
|
||||
for(i = 0; i < RA_THREADS_MAX; i++){
|
||||
if(l_threads[i].proc == NULL){
|
||||
handle = &l_threads[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(handle == NULL){
|
||||
ShowError("rAthread: cannot create new thread (entryPoint: %p) - no free thread slot found!", entryPoint);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
handle->proc = entryPoint;
|
||||
handle->param = param;
|
||||
|
||||
#ifdef WIN32
|
||||
handle->hThread = CreateThread(NULL, szStack, _raThreadMainRedirector, (void*)handle, 0, NULL);
|
||||
#else
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setstacksize(&attr, szStack);
|
||||
|
||||
if(pthread_create(&handle->hThread, &attr, _raThreadMainRedirector, (void*)handle) != 0){
|
||||
handle->proc = NULL;
|
||||
handle->param = NULL;
|
||||
return NULL;
|
||||
}
|
||||
pthread_attr_destroy(&attr);
|
||||
#endif
|
||||
|
||||
rathread_prio_set( handle, prio );
|
||||
|
||||
return handle;
|
||||
}//end: rathread_createEx
|
||||
|
||||
|
||||
void rathread_destroy ( rAthread handle ){
|
||||
#ifdef WIN32
|
||||
if( TerminateThread(handle->hThread, 0) != FALSE){
|
||||
CloseHandle(handle->hThread);
|
||||
rat_thread_terminated(handle);
|
||||
}
|
||||
#else
|
||||
if( pthread_cancel( handle->hThread ) == 0){
|
||||
|
||||
// We have to join it, otherwise pthread wont re-cycle its internal ressources assoc. with this thread.
|
||||
//
|
||||
pthread_join( handle->hThread, NULL );
|
||||
|
||||
// Tell our manager to release ressources ;)
|
||||
rat_thread_terminated(handle);
|
||||
}
|
||||
#endif
|
||||
}//end: rathread_destroy()
|
||||
|
||||
rAthread rathread_self( ){
|
||||
rAthread handle = &l_threads[g_rathread_ID];
|
||||
|
||||
if(handle->proc != NULL) // entry point set, so its used!
|
||||
return handle;
|
||||
|
||||
return NULL;
|
||||
}//end: rathread_self()
|
||||
|
||||
|
||||
int rathread_get_tid(){
|
||||
|
||||
return g_rathread_ID;
|
||||
|
||||
}//end: rathread_get_tid()
|
||||
|
||||
|
||||
bool rathread_wait( rAthread handle, void* *out_exitCode ){
|
||||
|
||||
// Hint:
|
||||
// no thread data cleanup routine call here!
|
||||
// its managed by the callProxy itself..
|
||||
//
|
||||
#ifdef WIN32
|
||||
WaitForSingleObject(handle->hThread, INFINITE);
|
||||
return true;
|
||||
#else
|
||||
if(pthread_join(handle->hThread, out_exitCode) == 0)
|
||||
return true;
|
||||
return false;
|
||||
#endif
|
||||
|
||||
}//end: rathread_wait()
|
||||
|
||||
|
||||
void rathread_prio_set( rAthread handle, RATHREAD_PRIO prio ){
|
||||
handle->prio = RAT_PRIO_NORMAL;
|
||||
//@TODO
|
||||
}//end: rathread_prio_set()
|
||||
|
||||
|
||||
RATHREAD_PRIO rathread_prio_get( rAthread handle){
|
||||
return handle->prio;
|
||||
}//end: rathread_prio_get()
|
||||
|
||||
|
||||
void rathread_yield(){
|
||||
#ifdef WIN32
|
||||
SwitchToThread();
|
||||
#else
|
||||
sched_yield();
|
||||
#endif
|
||||
}//end: rathread_yield()
|
115
src/common/thread.h
Normal file
115
src/common/thread.h
Normal file
@ -0,0 +1,115 @@
|
||||
#pragma once
|
||||
#ifndef _rA_THREAD_H_
|
||||
#define _rA_THREAD_H_
|
||||
|
||||
#include "../common/cbasetypes.h"
|
||||
|
||||
typedef struct rAthread *rAthread;
|
||||
typedef void* (*rAthreadProc)(void*);
|
||||
|
||||
typedef enum RATHREAD_PRIO {
|
||||
RAT_PRIO_LOW = 0,
|
||||
RAT_PRIO_NORMAL,
|
||||
RAT_PRIO_HIGH
|
||||
} RATHREAD_PRIO;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new Thread
|
||||
*
|
||||
* @param entyPoint - entryProc,
|
||||
* @param param - general purpose parameter, would be given as parameter to the thread's entrypoint.
|
||||
*
|
||||
* @return not NULL if success
|
||||
*/
|
||||
rAthread rathread_create( rAthreadProc entryPoint, void *param );
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new Thread (with more creation options)
|
||||
*
|
||||
* @param entyPoint - entryProc,
|
||||
* @param param - general purpose parameter, would be given as parameter to the thread's entrypoint
|
||||
* @param szStack - stack Size in bytes
|
||||
* @param prio - Priority of the Thread @ OS Scheduler..
|
||||
*
|
||||
* @return not NULL if success
|
||||
*/
|
||||
rAthread rathread_createEx( rAthreadProc entryPoint, void *param, size_t szStack, RATHREAD_PRIO prio );
|
||||
|
||||
|
||||
/**
|
||||
* Destroys the given Thread immediatly
|
||||
*
|
||||
* @note The Handle gets invalid after call! dont use it afterwards.
|
||||
*
|
||||
* @param handle - thread to destroy.
|
||||
*/
|
||||
void rathread_destroy ( rAthread handle );
|
||||
|
||||
|
||||
/**
|
||||
* Returns the thread handle of the thread calling this function
|
||||
*
|
||||
* @note this wont work @ programms main thread
|
||||
* @note the underlying implementation might not perform very well, cache the value received!
|
||||
*
|
||||
* @return not NULL if success
|
||||
*/
|
||||
rAthread rathread_self( );
|
||||
|
||||
|
||||
/**
|
||||
* Returns own thrad id (TID)
|
||||
*
|
||||
* @note this is not the operating system THREAD ID!
|
||||
*
|
||||
* @return -1 when fails, otherwise >= 0
|
||||
*/
|
||||
int rathread_get_tid();
|
||||
|
||||
|
||||
/**
|
||||
* Waits for the given thread to terminate
|
||||
*
|
||||
* @param handle - thread to wait (join) for
|
||||
* @param out_Exitcode - [OPTIONAL] - if given => Exitcode (value) of the given thread - if it's terminated
|
||||
*
|
||||
* @return true - if the given thread has been terminated.
|
||||
*/
|
||||
bool rathread_wait( rAthread handle, void* *out_exitCode );
|
||||
|
||||
|
||||
/**
|
||||
* Sets the given PRIORITY @ OS Task Scheduler
|
||||
*
|
||||
* @param handle - thread to set prio for
|
||||
* @param rio - the priority (RAT_PRIO_LOW ... )
|
||||
*/
|
||||
void rathread_prio_set( rAthread handle, RATHREAD_PRIO prio );
|
||||
|
||||
|
||||
/**
|
||||
* Gets the current Prio of the given trhead
|
||||
*
|
||||
* @param handle - the thread to get the prio for.
|
||||
*/
|
||||
RATHREAD_PRIO rathread_prio_get( rAthread handle);
|
||||
|
||||
|
||||
/**
|
||||
* Tells the OS scheduler to yield the execution of the calling thread
|
||||
*
|
||||
* @note: this will not "pause" the thread,
|
||||
* it just allows the OS to spent the remaining time
|
||||
* of the slice to another thread.
|
||||
*/
|
||||
void rathread_yield();
|
||||
|
||||
|
||||
|
||||
void rathread_init();
|
||||
void rathread_final();
|
||||
|
||||
|
||||
#endif
|
61
src/test/Makefile.in
Normal file
61
src/test/Makefile.in
Normal file
@ -0,0 +1,61 @@
|
||||
|
||||
COMMON_H = $(shell ls ../common/*.h)
|
||||
|
||||
MT19937AR_OBJ = ../../3rdparty/mt19937ar/mt19937ar.o
|
||||
MT19937AR_H = ../../3rdparty/mt19937ar/mt19937ar.h
|
||||
MT19937AR_INCLUDE = -I../../3rdparty/mt19937ar
|
||||
|
||||
LIBCONFIG_OBJ = ../../3rdparty/libconfig/libconfig.o ../../3rdparty/libconfig/grammar.o \
|
||||
../../3rdparty/libconfig/scanctx.o ../../3rdparty/libconfig/scanner.o ../../3rdparty/libconfig/strbuf.o
|
||||
LIBCONFIG_H = ../../3rdparty/libconfig/libconfig.h ../../3rdparty/libconfig/grammar.h \
|
||||
../../3rdparty/libconfig/parsectx.h ../../3rdparty/libconfig/scanctx.h ../../3rdparty/libconfig/scanner.h \
|
||||
../../3rdparty/libconfig/strbuf.h ../../3rdparty/libconfig/wincompat.h
|
||||
LIBCONFIG_INCLUDE = -I../../3rdparty/libconfig
|
||||
|
||||
TEST_SPINLOCK_OBJ=obj/test_spinlock.o
|
||||
TEST_SPINLOCK_H=
|
||||
TEST_SPINLOCK_DEPENDS=obj $(TEST_SPINLOCK_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a $(MT19937AR_OBJ)
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
#####################################################################
|
||||
.PHONY :all test_spinlock
|
||||
|
||||
all: test_spinlock
|
||||
|
||||
clean:
|
||||
@echo " CLEAN test"
|
||||
@rm -rf *.o obj ../../test_spinlock@EXEEXT@
|
||||
|
||||
#####################################################################
|
||||
|
||||
# object directories
|
||||
|
||||
obj:
|
||||
@echo " MKDIR obj"
|
||||
@-mkdir obj
|
||||
|
||||
#executables
|
||||
|
||||
test_spinlock: $(TEST_SPINLOCK_DEPENDS)
|
||||
@echo " LD $@"
|
||||
@@CC@ @LDFLAGS@ -o ../../test_spinlock@EXEEXT@ $(TEST_SPINLOCK_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @MYSQL_LIBS@
|
||||
|
||||
# login object files
|
||||
|
||||
obj/%.o: %.c $(COMMON_H) $(MT19937AR_H) $(LIBCONFIG_H)
|
||||
@echo " CC $<"
|
||||
@@CC@ @CFLAGS@ $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) -DWITH_SQL @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
|
||||
|
||||
# missing object files
|
||||
../common/obj_all/common.a:
|
||||
@$(MAKE) -C ../common sql
|
||||
|
||||
../common/obj_sql/common_sql.a:
|
||||
@$(MAKE) -C ../common sql
|
||||
|
||||
MT19937AR_OBJ:
|
||||
@$(MAKE) -C ../../3rdparty/mt19937ar
|
||||
|
||||
LIBCONFIG_OBJ:
|
||||
@$(MAKE) -C ../../3rdparty/libconfig
|
117
src/test/test_spinlock.c
Normal file
117
src/test/test_spinlock.c
Normal file
@ -0,0 +1,117 @@
|
||||
|
||||
#include "../common/core.h"
|
||||
#include "../common/atomic.h"
|
||||
#include "../common/thread.h"
|
||||
#include "../common/spinlock.h"
|
||||
#include "../common/showmsg.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
//
|
||||
// Simple test for the spinlock implementation to see if it works properly..
|
||||
//
|
||||
|
||||
|
||||
|
||||
#define THRC 32 //thread Count
|
||||
#define PERINC 100000
|
||||
#define LOOPS 47
|
||||
|
||||
|
||||
static SPIN_LOCK lock;
|
||||
static int val = 0;
|
||||
static volatile int32 done_threads = 0;
|
||||
|
||||
static void *worker(void *p){
|
||||
register int i;
|
||||
|
||||
for(i = 0; i < PERINC; i++){
|
||||
EnterSpinLock(&lock);
|
||||
EnterSpinLock(&lock);
|
||||
|
||||
val++;
|
||||
|
||||
LeaveSpinLock(&lock);
|
||||
LeaveSpinLock(&lock);
|
||||
}
|
||||
|
||||
InterlockedIncrement(&done_threads);
|
||||
|
||||
return NULL;
|
||||
}//end: worker()
|
||||
|
||||
|
||||
int do_init(int argc, char **argv){
|
||||
rAthread t[THRC];
|
||||
int j, i;
|
||||
int ok;
|
||||
|
||||
ShowStatus("==========\n");
|
||||
ShowStatus("TEST: %u Runs, (%u Threads)\n", LOOPS, THRC);
|
||||
ShowStatus("This can take a while\n");
|
||||
ShowStatus("\n\n");
|
||||
|
||||
ok =0;
|
||||
for(j = 0; j < LOOPS; j++){
|
||||
val = 0;
|
||||
done_threads = 0;
|
||||
|
||||
InitializeSpinLock(&lock);
|
||||
|
||||
|
||||
for(i =0; i < THRC; i++){
|
||||
t[i] = rathread_createEx( worker, NULL, 1024*512, RAT_PRIO_NORMAL);
|
||||
}
|
||||
|
||||
|
||||
while(1){
|
||||
if(InterlockedCompareExchange(&done_threads, THRC, THRC) == THRC)
|
||||
break;
|
||||
|
||||
rathread_yield();
|
||||
}
|
||||
|
||||
FinalizeSpinLock(&lock);
|
||||
|
||||
// Everything fine?
|
||||
if(val != (THRC*PERINC) ){
|
||||
printf("FAILED! (Result: %u, Expected: %u)\n", val, (THRC*PERINC) );
|
||||
}else{
|
||||
printf("OK! (Result: %u, Expected: %u)\n", val, (THRC*PERINC) );
|
||||
ok++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if(ok != LOOPS){
|
||||
ShowFatalError("Test failed.\n");
|
||||
exit(1);
|
||||
}else{
|
||||
ShowStatus("Test passed.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}//end: do_init()
|
||||
|
||||
|
||||
void do_abort(){
|
||||
}//end: do_abort()
|
||||
|
||||
|
||||
void set_server_type(){
|
||||
SERVER_TYPE = ATHENA_SERVER_NONE;
|
||||
}//end: set_server_type()
|
||||
|
||||
|
||||
void do_final(){
|
||||
}//end: do_final()
|
||||
|
||||
|
||||
int parse_console(const char* command){
|
||||
return 0;
|
||||
}//end: parse_console
|
||||
|
Loading…
x
Reference in New Issue
Block a user