added spl.h

changed SpinLock.hpp to use spl.h
This commit is contained in:
hyung-hwan 2018-01-31 10:34:38 +00:00
parent 4eff683036
commit be51ae8e61
7 changed files with 366 additions and 20 deletions

View File

@ -21,6 +21,7 @@ pkginclude_HEADERS = \
sck.h \
sinfo.h \
sio.h \
spl.h \
task.h \
thr.h \
tio.h

View File

@ -133,8 +133,8 @@ am__can_run_installinfo = \
esac
am__pkginclude_HEADERS_DIST = aio.h aio-pro.h aio-sck.h cnd.h dir.h \
fio.h fs.h glob.h intr.h log.h mtx.h mux.h nwad.h nwif.h \
nwio.h pio.h rwl.h sck.h sinfo.h sio.h task.h thr.h tio.h \
AppRoot.hpp SocketAddress.hpp Socket.hpp SpinLock.hpp \
nwio.h pio.h rwl.h sck.h sinfo.h sio.h spl.h task.h thr.h \
tio.h AppRoot.hpp SocketAddress.hpp Socket.hpp SpinLock.hpp \
Thread.hpp
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
@ -369,7 +369,8 @@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
pkginclude_HEADERS = aio.h aio-pro.h aio-sck.h cnd.h dir.h fio.h fs.h \
glob.h intr.h log.h mtx.h mux.h nwad.h nwif.h nwio.h pio.h \
rwl.h sck.h sinfo.h sio.h task.h thr.h tio.h $(am__append_1)
rwl.h sck.h sinfo.h sio.h spl.h task.h thr.h tio.h \
$(am__append_1)
all: all-am
.SUFFIXES:

View File

@ -30,8 +30,13 @@
#include <qse/Types.hpp>
#include <qse/Uncopyable.hpp>
#if defined(QSE_HAVE_SYNC_LOCK_TEST_AND_SET) && defined(QSE_HAVE_SYNC_LOCK_RELEASE)
// don't include anything
#undef QSE_SPL_NO_UNSUPPORTED_ERROR
#define QSE_SPL_NO_UNSUPPORTED_ERROR
#include <qse/si/spl.h>
#undef QSE_SPL_NO_UNSUPPORTED_ERROR
#if defined(QSE_SUPPORT_SPL)
// don't include anything else
#elif defined(QSE_LANG_CPP11)
// NOTE: <stdatomic.h> in C11 doesn't seem compatible due to lack of
// the keyword _Atomic in C++11
@ -43,12 +48,16 @@ QSE_BEGIN_NAMESPACE(QSE)
class SpinLock
{
public:
#if defined(QSE_SUPPORT_SPL)
SpinLock() QSE_CPP_NOEXCEPT: flag(QSE_SPL_INIT) {}
#else
SpinLock() QSE_CPP_NOEXCEPT: flag(0) {}
#endif
bool tryock() QSE_CPP_NOEXCEPT
{
#if defined(QSE_HAVE_SYNC_LOCK_TEST_AND_SET) && defined(QSE_HAVE_SYNC_LOCK_RELEASE)
return !__sync_lock_test_and_set(&this->flag, 1);
#if defined(QSE_SUPPORT_SPL)
return !qse_spl_trylock(&this->flag);
#elif defined(QSE_LANG_CPP11)
return !this->flag.test_and_set();
#else
@ -58,8 +67,8 @@ public:
void lock () QSE_CPP_NOEXCEPT
{
#if defined(QSE_HAVE_SYNC_LOCK_TEST_AND_SET) && defined(QSE_HAVE_SYNC_LOCK_RELEASE)
while (__sync_lock_test_and_set(&this->flag, 1)) { /* do nothing special */ }
#if defined(QSE_SUPPORT_SPL)
qse_spl_lock (&this->flag);
#elif defined(QSE_LANG_CPP11)
while (flag.test_and_set()) { /* do nothing sepcial */ }
#else
@ -69,8 +78,8 @@ public:
void unlock () QSE_CPP_NOEXCEPT
{
#if defined(QSE_HAVE_SYNC_LOCK_TEST_AND_SET) && defined(QSE_HAVE_SYNC_LOCK_RELEASE)
__sync_lock_release (&this->flag);
#if defined(QSE_SUPPORT_SPL)
qse_spl_unlock (&this->flag);
#elif defined(QSE_LANG_CPP11)
flag.clear ();
#else
@ -79,8 +88,8 @@ public:
}
protected:
#if defined(QSE_HAVE_SYNC_LOCK_TEST_AND_SET) && defined(QSE_HAVE_SYNC_LOCK_RELEASE)
volatile int flag;
#if defined(QSE_SUPPORT_SPL)
qse_spl_t flag;
#elif defined(QSE_LANG_CPP11)
std::atomic_flag flag;
#else

147
qse/include/qse/si/spl.h Normal file
View File

@ -0,0 +1,147 @@
/*
* $Id$
*
Copyright (c) 2006-2014 Chung, Hyung-Hwan. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EQSERESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _QSE_SI_SPL_H_
#define _QSE_SI_SPL_H_
#include <qse/types.h>
#include <qse/macros.h>
#define QSE_SUPPORT_SPL
typedef volatile qse_uint32_t qse_spl_t;
#define QSE_SPL_INIT (0)
#if defined(QSE_HAVE_INLINE)
static QSE_INLINE void qse_spl_init (qse_spl_t* spl) { *spl = QSE_SPL_INIT; }
#else
# define qse_spl_init(spl) ((*(spl)) = QSE_SPL_INIT)
#endif
#if defined(QSE_HAVE_SYNC_LOCK_TEST_AND_SET) && defined(QSE_HAVE_SYNC_LOCK_RELEASE)
/* =======================================================================
* MODERN COMPILERS WITH BUILTIN ATOMICS
* ======================================================================= */
#if defined(QSE_HAVE_INLINE)
static QSE_INLINE int qse_spl_trylock (qse_spl_t* spl) { return !__sync_lock_test_and_set(spl, 1); }
static QSE_INLINE void qse_spl_lock (qse_spl_t* spl) { do {} while(__sync_lock_test_and_set(spl, 1)); }
static QSE_INLINE void qse_spl_unlock (qse_spl_t* spl) { __sync_lock_release(spl); }
#else
# define qse_spl_trylock(spl) (!__sync_lock_test_and_set(spl, 1))
# define qse_spl_lock(spl) do {} while(__sync_lock_test_and_set(spl, 1))
# define qse_spl_unlock(spl) (__sync_lock_release(spl))
#endif
#elif defined(_SCO_DS)
/* =======================================================================
* SCO DEVELOPEMENT SYSTEM
*
* NOTE: when the asm macros were indented, the compiler/linker ended up
* with undefined symbols. never indent qse_spl_xxx macros.
* ======================================================================= */
asm int qse_spl_trylock (qse_spl_t* spl)
{
%reg spl
movl $1, %eax
xchgl (spl), %eax
xorl $1, %eax / return zero on failure, non-zero on success
%mem spl
movl spl, %ecx
movl $1, %eax
xchgl (%ecx), %eax
xorl $1, %eax / return zero on failure, non-zero on success
}
#if 0
/* i can't figure out how to make jump labels unique when there are
* multiple occurrences of qse_spl_lock(). so let me just use the while loop
* instead. */
asm void qse_spl_lock (qse_spl_t* spl)
{
%reg spl
.lock_set_loop:
movl $1, %eax
xchgl (spl), %eax
testl %eax, %eax / set ZF to 1 if eax is zero, 0 if eax is non-zero
jne .lock_set_loop / if ZF is 0(eax is non-zero), loop around
%mem spl
.lock_set_loop:
movl spl, %ecx
movl $1, %eax
xchgl (%ecx), %eax
testl %eax, %eax / set ZF to 1 if eax is zero, 0 if eax is non-zero
jne .lock_set_loop / if ZF is 0(eax is non-zero), loop around
}
#else
#define qse_spl_lock(x) do {} while(!spl_trylock(x))
#endif
#if 0
asm void qse_spl_unlock (moo_uint8_t* spl)
{
%reg spl
movl $0, %eax
xchgl (spl), %eax
%mem spl
movl spl, %ecx
movl $0, %eax
xchgl (%ecx), %eax
}
#else
asm void qse_spl_unlock (qse_spl_t* spl)
{
/* don't need xchg as movl on an aligned data is atomic */
/* mfence is 0F AE F0 */
%reg spl
.byte 0x0F
.byte 0xAE
.byte 0xF0
movl $0, (spl)
%mem spl
.byte 0x0F
.byte 0xAE
.byte 0xF0
movl spl, %ecx
movl $0, (%ecx)
}
#endif
#elif defined(QSE_SPL_NO_UNSUPPORTED_ERROR)
/* don't raise the compile time error */
#undef QSE_SUPPORT_SPL
#else
#undef QSE_SUPPORT_SPL
# error UNSUPPORTED
#endif
#endif

View File

@ -23,6 +23,7 @@ bin_PROGRAMS = \
sio01 \
sio02 \
sio03 \
spl01 \
task01 \
thr01
@ -53,6 +54,7 @@ rwl01_SOURCES = rwl01.c
sio01_SOURCES = sio01.c
sio02_SOURCES = sio02.c
sio03_SOURCES = sio03.c
spl01_SOURCES = spl01.c
task01_SOURCES = task01.c
thr01_SOURCES = thr01.c

View File

@ -92,8 +92,8 @@ bin_PROGRAMS = aio01$(EXEEXT) dir01$(EXEEXT) fio01$(EXEEXT) \
fio02$(EXEEXT) fs01$(EXEEXT) fs02$(EXEEXT) fs03$(EXEEXT) \
glob01$(EXEEXT) log01$(EXEEXT) nwad01$(EXEEXT) nwif01$(EXEEXT) \
nwif02$(EXEEXT) pio01$(EXEEXT) rwl01$(EXEEXT) sio01$(EXEEXT) \
sio02$(EXEEXT) sio03$(EXEEXT) task01$(EXEEXT) thr01$(EXEEXT) \
$(am__EXEEXT_1)
sio02$(EXEEXT) sio03$(EXEEXT) spl01$(EXEEXT) task01$(EXEEXT) \
thr01$(EXEEXT) $(am__EXEEXT_1)
@WCHAR_TRUE@@WIN32_TRUE@am__append_1 = $(UNICOWS_LIBS)
@ENABLE_CXX_TRUE@am__append_2 = thr02 spl02
subdir = samples/si
@ -190,6 +190,10 @@ am_sio03_OBJECTS = sio03.$(OBJEXT)
sio03_OBJECTS = $(am_sio03_OBJECTS)
sio03_LDADD = $(LDADD)
sio03_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
am_spl01_OBJECTS = spl01.$(OBJEXT)
spl01_OBJECTS = $(am_spl01_OBJECTS)
spl01_LDADD = $(LDADD)
spl01_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
am__spl02_SOURCES_DIST = spl02.cpp
@ENABLE_CXX_TRUE@am_spl02_OBJECTS = spl02.$(OBJEXT)
spl02_OBJECTS = $(am_spl02_OBJECTS)
@ -266,15 +270,17 @@ SOURCES = $(aio01_SOURCES) $(dir01_SOURCES) $(fio01_SOURCES) \
$(fs03_SOURCES) $(glob01_SOURCES) $(log01_SOURCES) \
$(nwad01_SOURCES) $(nwif01_SOURCES) $(nwif02_SOURCES) \
$(pio01_SOURCES) $(rwl01_SOURCES) $(sio01_SOURCES) \
$(sio02_SOURCES) $(sio03_SOURCES) $(spl02_SOURCES) \
$(task01_SOURCES) $(thr01_SOURCES) $(thr02_SOURCES)
$(sio02_SOURCES) $(sio03_SOURCES) $(spl01_SOURCES) \
$(spl02_SOURCES) $(task01_SOURCES) $(thr01_SOURCES) \
$(thr02_SOURCES)
DIST_SOURCES = $(aio01_SOURCES) $(dir01_SOURCES) $(fio01_SOURCES) \
$(fio02_SOURCES) $(fs01_SOURCES) $(fs02_SOURCES) \
$(fs03_SOURCES) $(glob01_SOURCES) $(log01_SOURCES) \
$(nwad01_SOURCES) $(nwif01_SOURCES) $(nwif02_SOURCES) \
$(pio01_SOURCES) $(rwl01_SOURCES) $(sio01_SOURCES) \
$(sio02_SOURCES) $(sio03_SOURCES) $(am__spl02_SOURCES_DIST) \
$(task01_SOURCES) $(thr01_SOURCES) $(am__thr02_SOURCES_DIST)
$(sio02_SOURCES) $(sio03_SOURCES) $(spl01_SOURCES) \
$(am__spl02_SOURCES_DIST) $(task01_SOURCES) $(thr01_SOURCES) \
$(am__thr02_SOURCES_DIST)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@ -507,6 +513,7 @@ rwl01_SOURCES = rwl01.c
sio01_SOURCES = sio01.c
sio02_SOURCES = sio02.c
sio03_SOURCES = sio03.c
spl01_SOURCES = spl01.c
task01_SOURCES = task01.c
thr01_SOURCES = thr01.c
@ENABLE_CXX_TRUE@CXXLIB = -lqsesixx -lqsecmnxx
@ -665,6 +672,10 @@ sio03$(EXEEXT): $(sio03_OBJECTS) $(sio03_DEPENDENCIES) $(EXTRA_sio03_DEPENDENCIE
@rm -f sio03$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(sio03_OBJECTS) $(sio03_LDADD) $(LIBS)
spl01$(EXEEXT): $(spl01_OBJECTS) $(spl01_DEPENDENCIES) $(EXTRA_spl01_DEPENDENCIES)
@rm -f spl01$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(spl01_OBJECTS) $(spl01_LDADD) $(LIBS)
spl02$(EXEEXT): $(spl02_OBJECTS) $(spl02_DEPENDENCIES) $(EXTRA_spl02_DEPENDENCIES)
@rm -f spl02$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(spl02_OBJECTS) $(spl02_LDADD) $(LIBS)
@ -704,6 +715,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sio01.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sio02.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sio03.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spl01.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spl02.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task01.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thr01.Po@am__quote@

174
qse/samples/si/spl01.c Normal file
View File

@ -0,0 +1,174 @@
#include <qse/si/spl.h>
#include <qse/si/thr.h>
#include <qse/si/sio.h>
#include <qse/cmn/mem.h>
#include <locale.h>
#if defined(_WIN32)
# include <windows.h>
#endif
#include <unistd.h>
#include <signal.h>
#include <string.h>
static int g_stopreq = 0;
struct thr_xtn_t
{
int stopreq;
qse_char_t name[32];
qse_spl_t* spl;
};
typedef struct thr_xtn_t thr_xtn_t;
static int thr_func (qse_thr_t* thr, void* ctx)
{
int i = 0;
thr_xtn_t* xtn = qse_thr_getxtn(thr);
while (!xtn->stopreq)
{
qse_spl_lock (xtn->spl);
qse_printf (QSE_T("%s: [% 16d] [% 16d] [% 16d]\n"), xtn->name, i, i, i);
qse_spl_unlock (xtn->spl);
i++;
//sleep (1);
}
return i;
}
static int test1 (void)
{
qse_thr_t* thr1, * thr2;
qse_spl_t spl;
thr_xtn_t* xtn1, * xtn2;
qse_spl_init (&spl);
thr1 = qse_thr_open (QSE_MMGR_GETDFL(), QSE_SIZEOF(thr_xtn_t));
if (!thr1)
{
qse_printf (QSE_T("cannot open thread1\n"));
return -1;
}
thr2 = qse_thr_open (QSE_MMGR_GETDFL(), QSE_SIZEOF(thr_xtn_t));
if (!thr2)
{
qse_printf (QSE_T("cannot open thread2\n"));
return -1;
}
xtn1 = qse_thr_getxtn(thr1);
xtn2 = qse_thr_getxtn(thr2);
qse_strcpy (xtn1->name, QSE_T("Thr-X"));
qse_strcpy (xtn2->name, QSE_T("Thr-Y"));
xtn1->spl = &spl;
xtn2->spl = &spl;
qse_thr_setstacksize (thr1, 64000);
qse_thr_setstacksize (thr2, 64000);
if (qse_thr_start(thr1, thr_func, QSE_NULL, QSE_THR_SIGNALS_BLOCKED) <= -1)
{
qse_printf (QSE_T("cannot start thread1\n"));
qse_thr_close (thr1 );
return -1;
}
if (qse_thr_start(thr2, thr_func, QSE_NULL, QSE_THR_SIGNALS_BLOCKED) <= -1)
{
qse_printf (QSE_T("cannot start thread1\n"));
qse_thr_close (thr1 );
return -1;
}
while (!g_stopreq)
{
if (qse_thr_getstate(thr1) == QSE_THR_TERMINATED &&
qse_thr_getstate(thr2) == QSE_THR_TERMINATED) break;
sleep (1);
}
if (g_stopreq)
{
xtn1->stopreq = 1;
xtn2->stopreq = 1;
}
qse_thr_join (thr1);
qse_thr_join (thr2);
qse_printf (QSE_T("thread1 ended with retcode %d\n"), qse_thr_getretcode(thr1));
qse_printf (QSE_T("thread2 ended with retcode %d\n"), qse_thr_getretcode(thr2));
qse_thr_close (thr1);
qse_thr_close (thr2);
return 0;
}
static void handle_sigint (int sig, siginfo_t* siginfo, void* ctx)
{
g_stopreq = 1;
}
static void set_signal (int sig, void(*handler)(int, siginfo_t*, void*))
{
struct sigaction sa;
memset (&sa, 0, sizeof(sa));
/*sa.sa_handler = handler;*/
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handler;
sigemptyset (&sa.sa_mask);
sigaction (sig, &sa, NULL);
}
static void set_signal_to_default (int sig)
{
struct sigaction sa;
memset (&sa, 0, sizeof(sa));
sa.sa_handler = SIG_DFL;
sa.sa_flags = 0;
sigemptyset (&sa.sa_mask);
sigaction (sig, &sa, NULL);
}
int main ()
{
#if defined(_WIN32)
char locale[100];
UINT codepage = GetConsoleOutputCP();
if (codepage == CP_UTF8)
{
/*SetConsoleOUtputCP (CP_UTF8);*/
qse_setdflcmgrbyid (QSE_CMGR_UTF8);
}
else
{
sprintf (locale, ".%u", (unsigned int)codepage);
setlocale (LC_ALL, locale);
/*qse_setdflcmgrbyid (QSE_CMGR_SLMB);*/
}
#else
setlocale (LC_ALL, "");
/*qse_setdflcmgrbyid (QSE_CMGR_SLMB);*/
#endif
set_signal (SIGINT, handle_sigint);
qse_open_stdsios ();
test1();
qse_close_stdsios ();
set_signal_to_default (SIGINT);
return 0;
}