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 \
|
map_sql \
|
||||||
tools \
|
tools \
|
||||||
import \
|
import \
|
||||||
|
test \
|
||||||
clean help
|
clean help
|
||||||
|
|
||||||
all: $(ALL_DEPENDS)
|
all: $(ALL_DEPENDS)
|
||||||
@ -55,6 +56,9 @@ map_sql: $(MAP_SQL_DEPENDS)
|
|||||||
tools:
|
tools:
|
||||||
@$(MAKE) -C src/tool
|
@$(MAKE) -C src/tool
|
||||||
|
|
||||||
|
test:
|
||||||
|
@$(MAKE) -C src/test
|
||||||
|
|
||||||
import:
|
import:
|
||||||
# 1) create conf/import folder
|
# 1) create conf/import folder
|
||||||
# 2) add missing files
|
# 2) add missing files
|
||||||
@ -72,6 +76,7 @@ clean:
|
|||||||
@$(MAKE) -C src/char $@
|
@$(MAKE) -C src/char $@
|
||||||
@$(MAKE) -C src/map $@
|
@$(MAKE) -C src/map $@
|
||||||
@$(MAKE) -C src/tool $@
|
@$(MAKE) -C src/tool $@
|
||||||
|
@$(MAKE) -C src/test $@
|
||||||
|
|
||||||
help:
|
help:
|
||||||
@echo "most common targets are 'all' 'sql' 'conf' 'clean' 'help'"
|
@echo "most common targets are 'all' 'sql' 'conf' 'clean' 'help'"
|
||||||
@ -87,6 +92,7 @@ help:
|
|||||||
@echo "'all' - builds all the above targets"
|
@echo "'all' - builds all the above targets"
|
||||||
@echo "'sql' - builds sql servers (targets 'common_sql' 'login_sql' 'char_sql'"
|
@echo "'sql' - builds sql servers (targets 'common_sql' 'login_sql' 'char_sql'"
|
||||||
@echo " 'map_sql' and 'import')"
|
@echo " 'map_sql' and 'import')"
|
||||||
|
@echo "'test' - builds tests"
|
||||||
@echo "'clean' - cleans builds and objects"
|
@echo "'clean' - cleans builds and objects"
|
||||||
@echo "'help' - outputs this message"
|
@echo "'help' - outputs this message"
|
||||||
|
|
||||||
|
381
configure
vendored
381
configure
vendored
@ -1,5 +1,5 @@
|
|||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# From configure.in Revision: 16200 .
|
# From configure.in Revision: 16203 .
|
||||||
# Guess values for system-dependent variables and create Makefiles.
|
# Guess values for system-dependent variables and create Makefiles.
|
||||||
# Generated by GNU Autoconf 2.67.
|
# 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/map/Makefile src/tool/Makefile"
|
||||||
|
|
||||||
|
ac_config_files="$ac_config_files src/test/Makefile"
|
||||||
|
|
||||||
|
|
||||||
ac_ext=c
|
ac_ext=c
|
||||||
ac_cpp='$CPP $CPPFLAGS'
|
ac_cpp='$CPP $CPPFLAGS'
|
||||||
@ -4666,6 +4668,46 @@ $as_echo "$pointers_fit_in_ints" >&6; }
|
|||||||
fi
|
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 "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wno-unused-parameter" >&5
|
||||||
$as_echo_n "checking whether $CC supports -Wno-unused-parameter... " >&6; }
|
$as_echo_n "checking whether $CC supports -Wno-unused-parameter... " >&6; }
|
||||||
OLD_CFLAGS="$CFLAGS"
|
OLD_CFLAGS="$CFLAGS"
|
||||||
@ -5284,6 +5326,342 @@ fi
|
|||||||
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
|
# MySQL library
|
||||||
#
|
#
|
||||||
@ -6304,6 +6682,7 @@ do
|
|||||||
"src/login/Makefile") CONFIG_FILES="$CONFIG_FILES src/login/Makefile" ;;
|
"src/login/Makefile") CONFIG_FILES="$CONFIG_FILES src/login/Makefile" ;;
|
||||||
"src/map/Makefile") CONFIG_FILES="$CONFIG_FILES src/map/Makefile" ;;
|
"src/map/Makefile") CONFIG_FILES="$CONFIG_FILES src/map/Makefile" ;;
|
||||||
"src/tool/Makefile") CONFIG_FILES="$CONFIG_FILES src/tool/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 ;;
|
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;;
|
||||||
esac
|
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([3rdparty/mt19937ar/Makefile 3rdparty/libconfig/Makefile])
|
||||||
AC_CONFIG_FILES([src/char/Makefile src/login/Makefile])
|
AC_CONFIG_FILES([src/char/Makefile src/login/Makefile])
|
||||||
AC_CONFIG_FILES([src/map/Makefile src/tool/Makefile])
|
AC_CONFIG_FILES([src/map/Makefile src/tool/Makefile])
|
||||||
|
AC_CONFIG_FILES([src/test/Makefile])
|
||||||
|
|
||||||
AC_GNU_SOURCE
|
AC_GNU_SOURCE
|
||||||
|
|
||||||
@ -337,6 +338,31 @@ if test "$enable_64bit" = "no" ; then
|
|||||||
fi
|
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])
|
AC_MSG_CHECKING([whether $CC supports -Wno-unused-parameter])
|
||||||
OLD_CFLAGS="$CFLAGS"
|
OLD_CFLAGS="$CFLAGS"
|
||||||
CFLAGS="$CFLAGS -Wno-unused-parameter"
|
CFLAGS="$CFLAGS -Wno-unused-parameter"
|
||||||
@ -636,6 +662,20 @@ if test "$ac_cv_search_clock_gettime" != "no" ; then
|
|||||||
fi
|
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
|
# 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/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/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/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)
|
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/db.h"
|
||||||
#include "../common/socket.h"
|
#include "../common/socket.h"
|
||||||
#include "../common/timer.h"
|
#include "../common/timer.h"
|
||||||
|
#include "../common/thread.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -278,6 +279,8 @@ int main (int argc, char **argv)
|
|||||||
display_title();
|
display_title();
|
||||||
usercheck();
|
usercheck();
|
||||||
|
|
||||||
|
rathread_init();
|
||||||
|
|
||||||
db_init();
|
db_init();
|
||||||
signals_init();
|
signals_init();
|
||||||
|
|
||||||
@ -303,6 +306,8 @@ int main (int argc, char **argv)
|
|||||||
timer_final();
|
timer_final();
|
||||||
socket_final();
|
socket_final();
|
||||||
db_final();
|
db_final();
|
||||||
|
|
||||||
|
rathread_final();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
malloc_final();
|
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