added qse_setintrhandler() & qse_clearintrhandler()
This commit is contained in:
@ -7,6 +7,7 @@ AM_CPPFLAGS = \
|
||||
lib_LTLIBRARIES = libqsesys.la
|
||||
libqsesys_la_SOURCES = \
|
||||
cnd.c \
|
||||
intr.c \
|
||||
mtx.c \
|
||||
rwl.c \
|
||||
thr.c \
|
||||
|
@ -127,7 +127,7 @@ am__uninstall_files_from_dir = { \
|
||||
am__installdirs = "$(DESTDIR)$(libdir)"
|
||||
LTLIBRARIES = $(lib_LTLIBRARIES)
|
||||
libqsesys_la_DEPENDENCIES =
|
||||
am_libqsesys_la_OBJECTS = cnd.lo mtx.lo rwl.lo thr.lo
|
||||
am_libqsesys_la_OBJECTS = cnd.lo intr.lo mtx.lo rwl.lo thr.lo
|
||||
libqsesys_la_OBJECTS = $(am_libqsesys_la_OBJECTS)
|
||||
AM_V_lt = $(am__v_lt_@AM_V@)
|
||||
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
|
||||
@ -408,6 +408,7 @@ AM_CPPFLAGS = \
|
||||
lib_LTLIBRARIES = libqsesys.la $(am__append_1)
|
||||
libqsesys_la_SOURCES = \
|
||||
cnd.c \
|
||||
intr.c \
|
||||
mtx.c \
|
||||
rwl.c \
|
||||
thr.c \
|
||||
@ -504,6 +505,7 @@ distclean-compile:
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SocketAddress.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cnd.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/intr.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mtx.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rwl.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thr.Plo@am__quote@
|
||||
|
@ -258,7 +258,7 @@ void qse_cnd_broadcast (qse_cnd_t* cnd)
|
||||
#endif
|
||||
}
|
||||
|
||||
void qse_cnd_wait (qse_cnd_t* cnd, qse_mtx_t* mutex, qse_ntime_t* waiting_time)
|
||||
void qse_cnd_wait (qse_cnd_t* cnd, qse_mtx_t* mutex, const qse_ntime_t* waiting_time)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
unsigned int was_waiting, was_gone;
|
||||
|
162
qse/lib/sys/intr.c
Normal file
162
qse/lib/sys/intr.c
Normal file
@ -0,0 +1,162 @@
|
||||
/*
|
||||
* $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 EXPRESS 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.
|
||||
*/
|
||||
|
||||
#include <qse/sys/intr.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
# include <windows.h>
|
||||
|
||||
#elif defined(__OS2__)
|
||||
# define INCL_DOSPROCESS
|
||||
# define INCL_DOSEXCEPTIONS
|
||||
# define INCL_ERRORS
|
||||
# include <os2.h>
|
||||
|
||||
#elif defined(__DOS__)
|
||||
# include <dos.h>
|
||||
# include <signal.h>
|
||||
#else
|
||||
# include <unistd.h>
|
||||
# include <signal.h>
|
||||
# include <errno.h>
|
||||
#endif
|
||||
|
||||
static qse_intr_handler_t intr_handler = QSE_NULL;
|
||||
static void* intr_handler_arg = QSE_NULL;
|
||||
|
||||
#if defined(_WIN32)
|
||||
static BOOL WINAPI __intr_handler (DWORD ctrl_type)
|
||||
{
|
||||
if (ctrl_type == CTRL_C_EVENT ||
|
||||
ctrl_type == CTRL_CLOSE_EVENT)
|
||||
{
|
||||
if (intr_handler) intr_handler (intr_handler_arg);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#elif defined(__OS2__)
|
||||
|
||||
static EXCEPTIONREGISTRATIONRECORD os2_excrr = { 0 };
|
||||
|
||||
static ULONG _System __intr_handler (
|
||||
PEXCEPTIONREPORTRECORD p1,
|
||||
PEXCEPTIONREGISTRATIONRECORD p2,
|
||||
PCONTEXTRECORD p3,
|
||||
PVOID pv)
|
||||
{
|
||||
if (p1->ExceptionNum == XCPT_SIGNAL)
|
||||
{
|
||||
if (p1->ExceptionInfo[0] == XCPT_SIGNAL_INTR ||
|
||||
p1->ExceptionInfo[0] == XCPT_SIGNAL_KILLPROC ||
|
||||
p1->ExceptionInfo[0] == XCPT_SIGNAL_BREAK)
|
||||
{
|
||||
APIRET rc;
|
||||
|
||||
if (intr_handler) intr_handler (intr_handler_arg);
|
||||
|
||||
rc = DosAcknowledgeSignalException (p1->ExceptionInfo[0]);
|
||||
return (rc != NO_ERROR)? 1: XCPT_CONTINUE_EXECUTION;
|
||||
}
|
||||
}
|
||||
|
||||
return XCPT_CONTINUE_SEARCH; /* exception not resolved */
|
||||
}
|
||||
|
||||
#elif defined(__DOS__)
|
||||
|
||||
static void __intr_handler (void)
|
||||
{
|
||||
if (intr_handler) intr_handler (intr_handler_arg);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void __intr_handler (int sig)
|
||||
{
|
||||
if (intr_handler) intr_handler (intr_handler_arg);
|
||||
}
|
||||
|
||||
static int setsignal (int sig, void(*handler)(int), int restart)
|
||||
{
|
||||
struct sigaction sa_int;
|
||||
|
||||
sa_int.sa_handler = handler;
|
||||
sigemptyset (&sa_int.sa_mask);
|
||||
|
||||
sa_int.sa_flags = 0;
|
||||
|
||||
if (restart)
|
||||
{
|
||||
#if defined(SA_RESTART)
|
||||
sa_int.sa_flags |= SA_RESTART;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(SA_INTERRUPT)
|
||||
sa_int.sa_flags |= SA_INTERRUPT;
|
||||
#endif
|
||||
}
|
||||
return sigaction (sig, &sa_int, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
void qse_setintrhandler (qse_intr_handler_t handler, void* arg)
|
||||
{
|
||||
intr_handler = handler;
|
||||
intr_handler_arg = arg;
|
||||
|
||||
#if defined(_WIN32)
|
||||
SetConsoleCtrlHandler (__intr_handler, TRUE);
|
||||
#elif defined(__OS2__)
|
||||
os2_excrr.ExceptionHandler = (ERR)__intr_handler;
|
||||
DosSetExceptionHandler (&os2_excrr); /* TODO: check if NO_ERROR is returned */
|
||||
#elif defined(__DOS__)
|
||||
signal (SIGINT, __intr_handler);
|
||||
#else
|
||||
/*setsignal (SIGINT, __intr_handler, 1); TO BE MORE COMPATIBLE WITH WIN32*/
|
||||
setsignal (SIGINT, __intr_handler, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void qse_clearintrhandler (void)
|
||||
{
|
||||
intr_handler = QSE_NULL;
|
||||
intr_handler_arg = QSE_NULL;
|
||||
|
||||
#if defined(_WIN32)
|
||||
SetConsoleCtrlHandler (__intr_handler, FALSE);
|
||||
#elif defined(__OS2__)
|
||||
DosUnsetExceptionHandler (&os2_excrr);
|
||||
#elif defined(__DOS__)
|
||||
signal (SIGINT, SIG_DFL);
|
||||
#else
|
||||
setsignal (SIGINT, SIG_DFL, 1);
|
||||
#endif
|
||||
}
|
@ -154,7 +154,7 @@ void* qse_mtx_getxtn (qse_mtx_t* mtx)
|
||||
return QSE_XTN (mtx);
|
||||
}
|
||||
|
||||
int qse_mtx_lock (qse_mtx_t* mtx, qse_ntime_t* waiting_time)
|
||||
int qse_mtx_lock (qse_mtx_t* mtx, const qse_ntime_t* waiting_time)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
/*
|
||||
|
@ -100,7 +100,7 @@ void* qse_rwl_getxtn (qse_rwl_t* rwl)
|
||||
return QSE_XTN (rwl);
|
||||
}
|
||||
|
||||
int qse_rwl_lockr (qse_rwl_t* rwl, qse_ntime_t* waiting_time)
|
||||
int qse_rwl_lockr (qse_rwl_t* rwl, const qse_ntime_t* waiting_time)
|
||||
{
|
||||
qse_ntime_t dead_line, now, rem, zero;
|
||||
|
||||
@ -164,7 +164,7 @@ int qse_rwl_unlockr (qse_rwl_t* rwl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qse_rwl_lockw (qse_rwl_t* rwl, qse_ntime_t* waiting_time)
|
||||
int qse_rwl_lockw (qse_rwl_t* rwl, const qse_ntime_t* waiting_time)
|
||||
{
|
||||
qse_ntime_t dead_line, now, rem, zero;
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
#include "thr.h"
|
||||
#include "../cmn/mem.h"
|
||||
#include <qse/cmn/time.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#if (!defined(__unix__) && !defined(__unix)) || defined(HAVE_PTHREAD)
|
||||
@ -98,7 +99,9 @@ void qse_thr_setstacksize (qse_thr_t* thr, qse_size_t num)
|
||||
thr->__stacksize = num;
|
||||
}
|
||||
|
||||
#if defined(__BEOS__)
|
||||
#if defined(__OS2__)
|
||||
static void __thread_main (void* arg)
|
||||
#elif defined(__BEOS__)
|
||||
static int32 __thread_main (void* arg)
|
||||
#else
|
||||
static void* __thread_main (void* arg)
|
||||
@ -110,9 +113,11 @@ static void* __thread_main (void* arg)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
Sleep (0);
|
||||
#elif defined(__OS2__)
|
||||
DosSleep (0);
|
||||
#elif defined(HAVE_NANOSLEEP)
|
||||
struct timespec ts;
|
||||
ts.tv_sec =0;
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 0;
|
||||
nanosleep (&ts, &ts);
|
||||
#else
|
||||
@ -120,7 +125,7 @@ static void* __thread_main (void* arg)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(_WIN32) && !defined(__BEOS__)
|
||||
#if defined(HAVE_PTHREAD)
|
||||
/*
|
||||
* the asynchronous cancel-type is used to better emulate
|
||||
* the bad effect of WIN32's TerminateThread using pthread_cancel
|
||||
@ -135,13 +140,24 @@ static void* __thread_main (void* arg)
|
||||
#if defined(_WIN32)
|
||||
_endthreadex (thr->__return_code);
|
||||
return QSE_NULL;
|
||||
|
||||
#elif defined(__OS2__)
|
||||
_endthread ();
|
||||
/* no return statement */
|
||||
|
||||
#elif defined(__DOS__)
|
||||
/* not implemented */
|
||||
return QSE_NULL;
|
||||
|
||||
#elif defined(__BEOS__)
|
||||
exit_thread (thr->__return_code);
|
||||
return 0;
|
||||
|
||||
#else
|
||||
pthread_exit (&thr->__return_code);
|
||||
return QSE_NULL;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static int __create_thread (qse_thr_t* thr)
|
||||
@ -153,6 +169,19 @@ static int __create_thread (qse_thr_t* thr)
|
||||
|
||||
thr->__handle = (HANDLE)_beginthreadex (QSE_NULL, 0, (unsigned int (__stdcall*)(void*))__thread_main, thr, 0, &tid);
|
||||
if (thr->__handle == 0) return -1;
|
||||
|
||||
#elif defined(__OS2__)
|
||||
TID tid;
|
||||
|
||||
/* default stack size to 81920(4096 * 20) */
|
||||
tid = _beginthread (__thread_main, NULL, (thr->__stacksize > 0? thr->__stacksize: 81920), thr);
|
||||
if (tid == -1) return -1;
|
||||
|
||||
thr->__handle = tid;
|
||||
|
||||
#elif defined(__DOS__)
|
||||
/* not implemented */
|
||||
|
||||
#elif defined(__BEOS__)
|
||||
thread_id tid;
|
||||
|
||||
@ -161,6 +190,7 @@ static int __create_thread (qse_thr_t* thr)
|
||||
|
||||
thr->__handle = tid;
|
||||
resume_thread(thr->__handle);
|
||||
|
||||
#elif defined(HAVE_PTHREAD)
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init (&attr);
|
||||
@ -197,6 +227,10 @@ static int __cancel_thread (qse_thr_t* thr)
|
||||
if (thr->__state != QSE_THR_RUNNING) return -1;
|
||||
#if defined(_WIN32)
|
||||
if (TerminateThread (thr->__handle, 0) == 0) return -1;
|
||||
#elif defined(__OS2__)
|
||||
if (DosKillThread (thr->__handle) != NO_ERROR) return -1;
|
||||
#elif defined(__DOS__)
|
||||
/* not implemented */
|
||||
#elif defined(__BEOS__)
|
||||
if (kill_thread (thr->__handle) < B_OK) return -1;
|
||||
#elif defined(HAVE_PTHREAD)
|
||||
@ -251,11 +285,18 @@ int qse_thr_join (qse_thr_t* thr)
|
||||
#if defined(_WIN32)
|
||||
if (thr->__state == QSE_THR_RUNNING)
|
||||
{
|
||||
if (WaitForSingleObject (
|
||||
thr->__handle, INFINITE) == WAIT_FAILED) return -1;
|
||||
if (WaitForSingleObject (thr->__handle, INFINITE) == WAIT_FAILED) return -1;
|
||||
}
|
||||
|
||||
#elif defined(__OS2__)
|
||||
if (DosWaitThread (&thr->__handle, DCWW_WAIT) != NO_ERROR) return -1;
|
||||
|
||||
#elif defined(__DOS__)
|
||||
/* not implemented */
|
||||
|
||||
#elif defined(__BEOS__)
|
||||
if (wait_for_thread(thr->__handle, QSE_NULL) < B_OK) return -1;
|
||||
|
||||
#elif defined(HAVE_PTHREAD)
|
||||
if (pthread_join(thr->__handle, QSE_NULL) != 0) return -1;
|
||||
#endif
|
||||
@ -279,6 +320,8 @@ int qse_thr_detach (qse_thr_t* thr)
|
||||
|
||||
int qse_thr_kill (qse_thr_t* thr, int sig)
|
||||
{
|
||||
/* this function is to send a signal to a thread.
|
||||
* don't get confused by the name */
|
||||
if (thr->__state != QSE_THR_RUNNING) return -1;
|
||||
|
||||
#if defined(HAVE_PTHREAD)
|
||||
@ -341,7 +384,7 @@ int qse_thr_unblockallsigs (qse_thr_t* thr)
|
||||
#endif
|
||||
|
||||
if (thr->__state != QSE_THR_RUNNING) return -1;
|
||||
|
||||
|
||||
#if defined(HAVE_PTHREAD)
|
||||
sigfillset (&mask);
|
||||
if (pthread_sigmask (SIG_UNBLOCK, &mask, QSE_NULL) != 0) return -1;
|
||||
@ -369,7 +412,12 @@ qse_thr_hnd_t qse_getcurthrhnd (void)
|
||||
#if defined(_WIN32)
|
||||
return GetCurrentThread ();
|
||||
#elif defined(__OS2__)
|
||||
return QSE_THR_HND_INVALID; /* TODO: implement this */
|
||||
PTIB ptib;
|
||||
PPIB ppib;
|
||||
|
||||
if (DosGetInfoBlocks (&ptib, &ppib) != NO_ERROR) return QSE_THR_HND_INVALID;
|
||||
return ptib->tib_ptib2->tib2_ultid;
|
||||
|
||||
#elif defined(__DOS__)
|
||||
return QSE_THR_HND_INVALID; /* TODO: implement this */
|
||||
#elif defined(__BEOS__)
|
||||
|
@ -36,16 +36,22 @@
|
||||
# include <windows.h>
|
||||
# include <process.h>
|
||||
# define QSE_THR_HND_INVALID INVALID_HANDLE_VALUE
|
||||
|
||||
#elif defined(__OS2__)
|
||||
/* not implemented */
|
||||
# define INCL_DOSPROCESS
|
||||
# define INCL_DOSDATETIME
|
||||
# define INCL_DOSERRORS
|
||||
# include <os2.h>
|
||||
# include <process.h>
|
||||
# define QSE_THR_HND_INVALID (-1)
|
||||
|
||||
#elif defined(__DOS__)
|
||||
|
||||
/* not implemented */
|
||||
|
||||
#elif defined(__BEOS__)
|
||||
# include <be/kernel/OS.h>
|
||||
# define QSE_THR_HND_INVALID (-1)
|
||||
|
||||
#else
|
||||
# if defined(AIX) && defined(__GNUC__)
|
||||
typedef int crid_t;
|
||||
|
Reference in New Issue
Block a user