8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 21:23:04 +01:00

Splitting thd.cpp into 2 files

ThreadData.cpp - thread control class to use in Client
thd.cpp -  thread control class to use in Server
To avoid making global visibility of a lot of THD_* ISC_event and so functions in libfbclient.so
(Can be breakable but needed)
This commit is contained in:
kkuznetsov 2005-03-01 15:49:10 +00:00
parent 3f5f279585
commit e78207ddba
12 changed files with 578 additions and 484 deletions

View File

@ -27,7 +27,7 @@
# Contributor(s):
#
#
# $Id: Makefile.in.client.gfix,v 1.11 2005-02-05 10:30:48 fsg Exp $
# $Id: Makefile.in.client.gfix,v 1.12 2005-03-01 15:49:09 kkuznetsov Exp $
#
ROOT=..
ObjModuleType=std
@ -40,7 +40,7 @@ include $(ROOT)/gen/make.shared.variables
@SET_MAKE@
GFIX_Other_Sources = jrd/isc.cpp jrd/thd.cpp \
GFIX_Other_Sources = jrd/isc.cpp jrd/ThreadData.cpp \
common/classes/fb_string.cpp common/classes/alloc.cpp common/fb_exception.cpp
GFIX_Files = alice_meta.epp alice.cpp all.cpp exe.cpp tdr.cpp

View File

@ -42,7 +42,7 @@ include $(ROOT)/gen/make.shared.variables
GFIX_Files = alice_meta.epp \
alice.cpp all.cpp exe.cpp tdr.cpp
GFIX_Other_Sources += jrd/isc.cpp jrd/thd.cpp \
GFIX_Other_Sources += jrd/isc.cpp jrd/ThreadData.cpp \
common/classes/fb_string.cpp common/classes/alloc.cpp common/fb_exception.cpp
GFIX_Sources = $(addprefix alice/, $(GFIX_Files)) $(GFIX_Other_Sources)

View File

@ -349,7 +349,9 @@ global:
KEYWORD_getTokens;
#--------------------------------------
#functions needed by Solaris utilyties
#functions needed by Solaris utilityes
SCH_ast;
#commented it out with new style of thd //Konstantin
#
# THD_mutex_lock;

View File

@ -19,7 +19,7 @@ WHY_Sources = why.cpp
JRD_ClientFiles = alt.cpp cvt.cpp dsc.cpp dls.cpp \
enc.cpp gds.cpp isc.cpp isc_file.cpp \
isc_sync.cpp perf.cpp sch.cpp sdl.cpp status.cpp \
thd.cpp utl.cpp \
ThreadData.cpp utl.cpp \
$(WHY_Sources)
# These are in the win32 release but not unix one for super?
@ -42,7 +42,7 @@ JRD_ServerFiles= blob_filter.cpp dpm.epp dyn.epp dyn_def.epp \
rng.cpp rpb_chain.cpp rse.cpp \
sdw.cpp shut.cpp sort.cpp sort_mem.cpp sqz.cpp \
svc.cpp sym.cpp tpc.cpp tra.cpp validation.cpp vio.cpp \
nodebug.cpp nbak.cpp sha.cpp $(Physical_IO_Module)
nodebug.cpp nbak.cpp sha.cpp $(Physical_IO_Module) ThreadData.cpp thd.cpp
JRD_Files = $(JRD_ClientFiles) $(JRD_ServerFiles)

View File

@ -25,7 +25,7 @@ DEV_FLAGS=-ggdb -march=i586 -mcpu=i686 -DMINGW -mno-cygwin -Wall -Wshadow -Wunde
PLATFORM_PATH=jrd/os/win32
JRDBOOT_Extra_Files=isc_sync.cpp thd.cpp
JRDBOOT_Extra_Files=isc_sync.cpp ThreadData.cpp
OS_SPECIFIC_Files=thd_priority.cpp

View File

@ -50,7 +50,7 @@ DEV_FLAGS= $(CFLAGS_COMMON) $(SFIO_FLAGS) $(COMMON_GCC_CFLAGS) $(DEBUG_GCC_FLAGS
$(LOCAL_CFLAGS)
# extra modules needed on this platform during bootstrap phase
JRDBOOT_Extra_Files=isc_sync.cpp thd.cpp
JRDBOOT_Extra_Files=isc_sync.cpp ThreadData.cpp
OS_ServerFiles=inet_server.cpp

View File

@ -19,7 +19,7 @@
#
# Use SOLX86 to identify x86 version of Solaris. Neil McCalden
#
# $Id: prefix.solx86,v 1.24 2004-02-13 10:14:39 stryqx Exp $
# $Id: prefix.solx86,v 1.25 2005-03-01 15:49:10 kkuznetsov Exp $
#
# Start of file prefix.solaris X 86 : $(VERSION) $(PLATFORM)
# 2 Oct 2002, Nickolay Samofatov - Major Cleanup
@ -57,7 +57,7 @@ DEV_FLAGS=$(COMM_SOLX_FLAGS) -g $(WARNINGS)
OS_ServerFiles=inet_server.cpp
#still ugly hack - becouse can not move it to configure.in
GPRECOMMON_Files= ../jrd/thd.cpp ../jrd/isc_sync.cpp
GPRECOMMON_Files= ../jrd/ThreadData.cpp ../jrd/isc_sync.cpp
GPRECommon_Sources= $(GPRECOMMON_Files)
LIB_LINK_OPTIONS:= -G
LIB_LINK_RPATH:=-R

View File

@ -18,7 +18,7 @@
#
# Use SOLX86 to identify x86 version of Solaris. Neil McCalden
#
# $Id: prefix.solx86gcc,v 1.14 2004-09-15 08:35:12 kkuznetsov Exp $
# $Id: prefix.solx86gcc,v 1.15 2005-03-01 15:49:10 kkuznetsov Exp $
#
# Start of file prefix.solaris X 86 : $(VERSION) $(PLATFORM)
# 2 Oct 2002, Nickolay Samofatov - Major Cleanup
@ -56,12 +56,13 @@ DEV_FLAGS=$(COMM_SOLX_FLAGS) -ggdb -g3 -p $(WARNINGS)
OS_ServerFiles=inet_server.cpp
#still ugly hack - becouse can not move it to configure.in
GPRECOMMON_Files= ../jrd/thd.cpp ../jrd/isc_sync.cpp
GPRECOMMON_Files= ../jrd/ThreadData.cpp ../jrd/isc_sync.cpp
GPRECommon_Sources= $(GPRECOMMON_Files)
GFIX_Other_Sources= jrd/isc_sync.cpp jrd/os/posix/isc_ipc.cpp
#needed by thd.cpp on Solaris
DROP_Other_Sources= jrd/sch.cpp jrd/thd.cpp
LOCKPRINT_Other_Sources=jrd/sch.cpp jrd/thd.cpp
DROP_Other_Sources= jrd/ThreadData.cpp
LOCKPRINT_Other_Sources= jrd/ThreadData.cpp
#jrd/sch.cpp jrd/ThreadData.cpp
Server_main_dummy = os/sun/server_main_dummy.cpp
#REMOTE_ClientFiles = $(Server_main_dummy)

555
src/jrd/ThreadData.cpp Normal file
View File

@ -0,0 +1,555 @@
/*
* PROGRAM: JRD Access Method
* MODULE: thd.cpp
* DESCRIPTION: Thread support routines
*
* The contents of this file are subject to the Interbase Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy
* of the License at http://www.Inprise.com/IPL.html
*
* Software distributed under the License is distributed on an
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
* or implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code was created by Inprise Corporation
* and its predecessors. Portions created by Inprise Corporation are
* Copyright (C) Inprise Corporation.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*
* 2002.10.28 Sean Leyne - Completed removal of obsolete "DGUX" port
*
* 2002.10.29 Sean Leyne - Removed obsolete "Netware" port
*
*/
#include "firebird.h"
#include <stdio.h>
#include <errno.h>
#include "../jrd/common.h"
#include "../jrd/thd.h"
#include "../jrd/isc.h"
#include "../jrd/os/thd_priority.h"
#include "../jrd/gds_proto.h"
#include "../jrd/isc_s_proto.h"
#include "../jrd/gdsassert.h"
#include "../common/classes/fb_tls.h"
#ifdef WIN_NT
#include <process.h>
#include <windows.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef SOLARIS_MT
#include <thread.h>
#include <signal.h>
#endif
#ifdef NOT_USED_OR_REPLACED
#ifdef VMS
// THE SOLE PURPOSE OF THE FOLLOWING DECLARATION IS TO ALLOW THE VMS KIT TO
// COMPILE. IT IS NOT CORRECT AND MUST BE REMOVED AT SOME POINT.
ThreadData* gdbb;
#endif
#endif
#include "../common/classes/locks.h"
#include "../common/classes/rwlock.h"
Firebird::Mutex ib_mutex;
namespace {
TLS_DECLARE (void*, tSpecific);
TLS_DECLARE (ThreadData*, tData);
}
int API_ROUTINE gds__thread_start(
ThreadEntryPoint* entrypoint,
void *arg,
int priority, int flags, void *thd_id)
{
/**************************************
*
* g d s _ $ t h r e a d _ s t a r t
*
**************************************
*
* Functional description
* Start a thread.
*
**************************************/
int rc = 0;
try {
ThreadData::start(entrypoint, arg, priority, flags, thd_id);
}
catch(const Firebird::status_exception& status) {
rc = status.value()[1];
}
return rc;
}
FB_THREAD_ID ThreadData::getId(void)
{
/**************************************
*
* T H D _ g e t _ t h r e a d _ i d
*
**************************************
*
* Functional description
* Get platform's notion of a thread ID.
*
**************************************/
FB_THREAD_ID id = 1;
#ifdef WIN_NT
id = GetCurrentThreadId();
#endif
#ifdef SOLARIS_MT
id = thr_self();
#endif
#ifdef USE_POSIX_THREADS
/* The following is just a temp. decision.
*/
#ifdef HP10
id = (FB_THREAD_ID) (pthread_self().field1);
#else
id = (FB_THREAD_ID) pthread_self();
#endif /* HP10 */
#endif /* USE_POSIX_THREADS */
return id;
}
ThreadData* ThreadData::getSpecific(void)
{
/**************************************
*
* T H D _ g e t _ s p e c i f i c
*
**************************************
*
* Functional description
* Gets thread specific data and returns
* a pointer to it.
*
**************************************/
return TLS_GET(tData);
}
void ThreadData::getSpecificData(void **t_data)
{
/**************************************
*
* T H D _ g e t s p e c i f i c _ d a t a
*
**************************************
*
* Functional description
* return the previously stored t_data.
*
**************************************/
*t_data = TLS_GET(tSpecific);
}
void ThreadData::putSpecific()
{
/**************************************
*
* T H D _ p u t _ s p e c i f i c
*
**************************************
*
* Functional description
*
**************************************/
threadDataPriorContext = TLS_GET(tData);
TLS_SET(tData, this);
}
void ThreadData::putSpecificData(void *t_data)
{
/**************************************
*
* T H D _ p u t s p e c i f i c _ d a t a
*
**************************************
*
* Functional description
* Store the passed t_data
*
**************************************/
TLS_SET(tSpecific, t_data);
}
void ThreadData::restoreSpecific()
{
/**************************************
*
* T H D _ r e s t o r e _ s p e c i f i c
*
**************************************
*
* Functional description
*
**************************************/
ThreadData* current_context = getSpecific();
TLS_SET(tData, current_context->threadDataPriorContext);
}
namespace
{
#ifdef THREAD_PSCHED
THREAD_ENTRY_DECLARE threadStart(THREAD_ENTRY_PARAM arg) {
fb_assert(arg);
Firebird::ContextPoolHolder mainThreadContext(getDefaultMemoryPool());
{
ThreadPriorityScheduler* tps =
reinterpret_cast<ThreadPriorityScheduler*>(arg);
try {
tps->run();
}
catch (...) {
tps->detach();
throw;
}
tps->detach();
return 0;
}
}
#define THREAD_ENTRYPOINT threadStart
#define THREAD_ARG tps
#else //THREAD_PSCHED
// due to same names of parameters for various ThreadData::start(...),
// we may use common macro for various platforms
#define THREAD_ENTRYPOINT threadStart
#define THREAD_ARG reinterpret_cast<THREAD_ENTRY_PARAM> (FB_NEW(*getDefaultMemoryPool()) \
ThreadArgs(reinterpret_cast<THREAD_ENTRY_RETURN (THREAD_ENTRY_CALL *) (THREAD_ENTRY_PARAM)>(routine), \
reinterpret_cast<THREAD_ENTRY_PARAM>(arg)))
class ThreadArgs
{
public:
typedef THREAD_ENTRY_RETURN (THREAD_ENTRY_CALL *Routine) (THREAD_ENTRY_PARAM);
typedef THREAD_ENTRY_PARAM Arg;
private:
Routine routine;
Arg arg;
public:
ThreadArgs(Routine r, Arg a) : routine(r), arg(a) { }
ThreadArgs(const ThreadArgs& t) : routine(t.routine), arg(t.arg) { }
void run() {routine(arg);}
private:
ThreadArgs& operator=(const ThreadArgs&);
};
THREAD_ENTRY_DECLARE threadStart(THREAD_ENTRY_PARAM arg) {
fb_assert(arg);
Firebird::ContextPoolHolder mainThreadContext(getDefaultMemoryPool());
ThreadArgs localArgs(*reinterpret_cast<ThreadArgs*>(arg));
delete reinterpret_cast<ThreadArgs*>(arg);
localArgs.run();
return 0;
}
#endif //THREAD_PSCHED
} // anonymous namespace
#ifdef ANY_THREADING
#ifdef USE_POSIX_THREADS
#define START_THREAD
void ThreadData::start(ThreadEntryPoint* routine,
void *arg,
int priority_arg,
int flags,
void *thd_id)
{
/**************************************
*
* t h r e a d _ s t a r t ( P O S I X )
*
**************************************
*
* Functional description
* Start a new thread. Return 0 if successful,
* status if not.
*
**************************************/
pthread_t thread;
pthread_attr_t pattr;
int state;
#if ( !defined HP10 && !defined LINUX && !defined FREEBSD )
state = pthread_attr_init(&pattr);
if (state)
Firebird::system_call_failed::raise("pthread_attr_init", state);
// Do not make thread bound for superserver/client
#if (!defined (SUPERCLIENT) && !defined (SUPERSERVER))
pthread_attr_setscope(&pattr, PTHREAD_SCOPE_SYSTEM);
#endif
pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_DETACHED);
state = pthread_create(&thread, &pattr, THREAD_ENTRYPOINT, THREAD_ARG);
pthread_attr_destroy(&pattr);
if (state)
Firebird::system_call_failed::raise("pthread_create", state);
#else
#if ( defined LINUX || defined FREEBSD )
if (state = pthread_create(&thread, NULL, THREAD_ENTRYPOINT, THREAD_ARG))
Firebird::system_call_failed::raise("pthread_create", state);
if (state = pthread_detach(thread))
Firebird::system_call_failed::raise("pthread_detach", state);
#else
long stack_size;
state = pthread_attr_create(&pattr);
if (state)
Firebird::system_call_failed::raise("pthread_attr_create", state);
/* The default HP's stack size is too small. HP's documentation
says it is "machine specific". My test showed it was less
than 64K. We definitly need more stack to be able to execute
concurrently many (at least 100) copies of the same request
(like, for example in case of recursive stored prcedure).
The following code sets threads stack size up to 256K if the
default stack size is less than this number
*/
stack_size = pthread_attr_getstacksize(pattr);
if (stack_size == -1)
Firebird::system_call_failed::raise("pthread_attr_getstacksize");
if (stack_size < 0x40000L) {
state = pthread_attr_setstacksize(&pattr, 0x40000L);
if (state)
Firebird::system_call_failed::raise("pthread_attr_setstacksize", state);
}
/* HP's Posix threads implementation does not support
bound attribute. It just a user level library.
*/
state = pthread_create(&thread, pattr, THREAD_ENTRYPOINT, THREAD_ARG);
if (state)
Firebird::system_call_failed::raise("pthread_create", state);
state = pthread_detach(&thread);
if (state)
Firebird::system_call_failed::raise("pthread_detach", state);
state = pthread_attr_delete(&pattr);
if (state)
Firebird::system_call_failed::raise("pthread_attr_delete", state);
#endif /* linux */
#endif /* HP10 */
}
#endif /* USE_POSIX_THREADS */
#ifdef SOLARIS_MT
#define START_THREAD
void ThreadData::start(ThreadEntryPoint* routine,
void *arg,
int priority_arg,
int flags,
void *thd_id)
{
/**************************************
*
* t h r e a d _ s t a r t ( S o l a r i s )
*
**************************************
*
* Functional description
* Start a new thread. Return 0 if successful,
* status if not.
*
**************************************/
int rval;
thread_t thread_id;
sigset_t new_mask, orig_mask;
sigfillset(&new_mask);
sigdelset(&new_mask, SIGALRM);
if (rval = thr_sigsetmask(SIG_SETMASK, &new_mask, &orig_mask))
Firebird::system_call_failed::raise("thr_sigsetmask", rval);
#if (defined SUPERCLIENT || defined SUPERSERVER)
rval = thr_create(NULL, 0, THREAD_ENTRYPOINT, THREAD_ARG, THR_DETACHED | THR_NEW_LWP,
&thread_id);
#else
rval =
thr_create(NULL, 0, THREAD_ENTRYPOINT, THREAD_ARG, THR_DETACHED | THR_BOUND,
&thread_id);
#endif
thr_sigsetmask(SIG_SETMASK, &orig_mask, NULL);
if (rval)
Firebird::system_call_failed::raise("thr_create", rval);
}
#endif
#endif
#ifdef WIN_NT
#define START_THREAD
void ThreadData::start(ThreadEntryPoint* routine,
void *arg,
int priority_arg,
int flags,
void *thd_id)
{
/**************************************
*
* t h r e a d _ s t a r t ( W I N _ N T )
*
**************************************
*
* Functional description
* Start a new thread. Return 0 if successful,
* status if not.
*
**************************************/
int priority;
switch (priority_arg) {
case THREAD_critical:
priority = THREAD_PRIORITY_TIME_CRITICAL;
break;
case THREAD_high:
priority = THREAD_PRIORITY_HIGHEST;
break;
case THREAD_medium_high:
priority = THREAD_PRIORITY_ABOVE_NORMAL;
break;
case THREAD_medium:
priority = THREAD_PRIORITY_NORMAL;
break;
case THREAD_medium_low:
priority = THREAD_PRIORITY_BELOW_NORMAL;
break;
case THREAD_low:
default:
priority = THREAD_PRIORITY_LOWEST;
break;
}
#ifdef THREAD_PSCHED
ThreadPriorityScheduler::Init();
ThreadPriorityScheduler *tps = FB_NEW(*getDefaultMemoryPool())
ThreadPriorityScheduler(routine, arg,
ThreadPriorityScheduler::adjustPriority(priority));
#endif //THREAD_PSCHED
/* I have changed the CreateThread here to _beginthreadex() as using
* CreateThread() can lead to memory leaks caused by C-runtime library.
* Advanced Windows by Richter pg. # 109. */
DWORD thread_id;
unsigned long real_handle =
_beginthreadex(NULL, 0, THREAD_ENTRYPOINT, THREAD_ARG, CREATE_SUSPENDED,
reinterpret_cast<unsigned*>(&thread_id));
if (!real_handle)
{
Firebird::system_call_failed::raise("_beginthreadex", GetLastError());
}
HANDLE handle = reinterpret_cast<HANDLE>(real_handle);
SetThreadPriority(handle, priority);
if (! (flags & THREAD_wait))
{
ResumeThread(handle);
}
if (thd_id)
{
*(HANDLE *) thd_id = handle;
}
else
{
CloseHandle(handle);
}
}
#endif
#ifdef ANY_THREADING
#ifdef VMS
#ifndef USE_POSIX_THREADS
#define START_THREAD
/**************************************
*
* t h r e a d _ s t a r t ( V M S )
*
**************************************
*
* Functional description
* Start a new thread. Return 0 if successful,
* status if not. This routine is coded in macro.
*
**************************************/
#endif
#endif
#endif
#ifndef START_THREAD
void ThreadData::start(ThreadEntryPoint* routine,
void *arg,
int priority_arg,
int flags,
void *thd_id)
{
/**************************************
*
* t h r e a d _ s t a r t ( G e n e r i c )
*
**************************************
*
* Functional description
* Wrong attempt to start a new thread.
*
**************************************/
}
#endif

View File

@ -30,7 +30,7 @@
#define JRD_ISC_S_PROTO_H
#include "../jrd/isc.h"
extern "C" {
BOOLEAN ISC_check_restart(void);
int ISC_event_blocked(USHORT, struct event_t **, SLONG *);
SLONG ISC_event_clear(struct event_t *);
@ -83,5 +83,6 @@ void ISC_reset_timer(FPTR_VOID_PTR, void *, SLONG *, void **);
void ISC_set_timer(SLONG, FPTR_VOID_PTR, void *, SLONG *, void **);
void ISC_unmap_file(ISC_STATUS *, struct sh_mem *, USHORT);
#endif // JRD_ISC_S_PROTO_H
#endif // JRD_ISC_S_PROTO_H
}

View File

@ -56,7 +56,10 @@ int API_ROUTINE gds__thread_wait(int (*)(), SLONG);
struct thread;
void SCH_abort(void);
extern "C"
void SCH_ast(enum ast_t);
thread* SCH_current_thread(void);
void SCH_enter(void);
void SCH_exit(void);

View File

@ -129,116 +129,6 @@ int THD_mutex_unlock(MUTX_T * mutex)
#endif //NOT_USED_OR_REPLACED
#include "../common/classes/locks.h"
#include "../common/classes/rwlock.h"
Firebird::Mutex ib_mutex;
namespace {
TLS_DECLARE (void*, tSpecific);
TLS_DECLARE (ThreadData*, tData);
}
int API_ROUTINE gds__thread_start(
ThreadEntryPoint* entrypoint,
void *arg,
int priority, int flags, void *thd_id)
{
/**************************************
*
* g d s _ $ t h r e a d _ s t a r t
*
**************************************
*
* Functional description
* Start a thread.
*
**************************************/
int rc = 0;
try {
ThreadData::start(entrypoint, arg, priority, flags, thd_id);
}
catch(const Firebird::status_exception& status) {
rc = status.value()[1];
}
return rc;
}
FB_THREAD_ID ThreadData::getId(void)
{
/**************************************
*
* T H D _ g e t _ t h r e a d _ i d
*
**************************************
*
* Functional description
* Get platform's notion of a thread ID.
*
**************************************/
FB_THREAD_ID id = 1;
#ifdef WIN_NT
id = GetCurrentThreadId();
#endif
#ifdef SOLARIS_MT
id = thr_self();
#endif
#ifdef USE_POSIX_THREADS
/* The following is just a temp. decision.
*/
#ifdef HP10
id = (FB_THREAD_ID) (pthread_self().field1);
#else
id = (FB_THREAD_ID) pthread_self();
#endif /* HP10 */
#endif /* USE_POSIX_THREADS */
return id;
}
ThreadData* ThreadData::getSpecific(void)
{
/**************************************
*
* T H D _ g e t _ s p e c i f i c
*
**************************************
*
* Functional description
* Gets thread specific data and returns
* a pointer to it.
*
**************************************/
return TLS_GET(tData);
}
void ThreadData::getSpecificData(void **t_data)
{
/**************************************
*
* T H D _ g e t s p e c i f i c _ d a t a
*
**************************************
*
* Functional description
* return the previously stored t_data.
*
**************************************/
*t_data = TLS_GET(tSpecific);
}
int THD_wlck_lock(WLCK_T* wlock, WLCK_type type)
{
@ -311,57 +201,6 @@ int THD_wlck_unlock(WLCK_T* wlock)
}
void ThreadData::putSpecific()
{
/**************************************
*
* T H D _ p u t _ s p e c i f i c
*
**************************************
*
* Functional description
*
**************************************/
threadDataPriorContext = TLS_GET(tData);
TLS_SET(tData, this);
}
void ThreadData::putSpecificData(void *t_data)
{
/**************************************
*
* T H D _ p u t s p e c i f i c _ d a t a
*
**************************************
*
* Functional description
* Store the passed t_data
*
**************************************/
TLS_SET(tSpecific, t_data);
}
void ThreadData::restoreSpecific()
{
/**************************************
*
* T H D _ r e s t o r e _ s p e c i f i c
*
**************************************
*
* Functional description
*
**************************************/
ThreadData* current_context = getSpecific();
TLS_SET(tData, current_context->threadDataPriorContext);
}
#ifdef SUPERSERVER
int THD_rec_mutex_destroy(REC_MUTX_T * rec_mutex)
{
@ -615,292 +454,6 @@ void THD_yield(void)
#endif /* ANY_THREADING */
}
namespace
{
#ifdef THREAD_PSCHED
THREAD_ENTRY_DECLARE threadStart(THREAD_ENTRY_PARAM arg) {
fb_assert(arg);
Firebird::ContextPoolHolder mainThreadContext(getDefaultMemoryPool());
{
ThreadPriorityScheduler* tps =
reinterpret_cast<ThreadPriorityScheduler*>(arg);
try {
tps->run();
}
catch (...) {
tps->detach();
throw;
}
tps->detach();
return 0;
}
}
#define THREAD_ENTRYPOINT threadStart
#define THREAD_ARG tps
#else //THREAD_PSCHED
// due to same names of parameters for various ThreadData::start(...),
// we may use common macro for various platforms
#define THREAD_ENTRYPOINT threadStart
#define THREAD_ARG reinterpret_cast<THREAD_ENTRY_PARAM> (FB_NEW(*getDefaultMemoryPool()) \
ThreadArgs(reinterpret_cast<THREAD_ENTRY_RETURN (THREAD_ENTRY_CALL *) (THREAD_ENTRY_PARAM)>(routine), \
reinterpret_cast<THREAD_ENTRY_PARAM>(arg)))
class ThreadArgs
{
public:
typedef THREAD_ENTRY_RETURN (THREAD_ENTRY_CALL *Routine) (THREAD_ENTRY_PARAM);
typedef THREAD_ENTRY_PARAM Arg;
private:
Routine routine;
Arg arg;
public:
ThreadArgs(Routine r, Arg a) : routine(r), arg(a) { }
ThreadArgs(const ThreadArgs& t) : routine(t.routine), arg(t.arg) { }
void run() {routine(arg);}
private:
ThreadArgs& operator=(const ThreadArgs&);
};
THREAD_ENTRY_DECLARE threadStart(THREAD_ENTRY_PARAM arg) {
fb_assert(arg);
Firebird::ContextPoolHolder mainThreadContext(getDefaultMemoryPool());
ThreadArgs localArgs(*reinterpret_cast<ThreadArgs*>(arg));
delete reinterpret_cast<ThreadArgs*>(arg);
localArgs.run();
return 0;
}
#endif //THREAD_PSCHED
} // anonymous namespace
#ifdef ANY_THREADING
#ifdef USE_POSIX_THREADS
#define START_THREAD
void ThreadData::start(ThreadEntryPoint* routine,
void *arg,
int priority_arg,
int flags,
void *thd_id)
{
/**************************************
*
* t h r e a d _ s t a r t ( P O S I X )
*
**************************************
*
* Functional description
* Start a new thread. Return 0 if successful,
* status if not.
*
**************************************/
pthread_t thread;
pthread_attr_t pattr;
int state;
#if ( !defined HP10 && !defined LINUX && !defined FREEBSD )
state = pthread_attr_init(&pattr);
if (state)
Firebird::system_call_failed::raise("pthread_attr_init", state);
// Do not make thread bound for superserver/client
#if (!defined (SUPERCLIENT) && !defined (SUPERSERVER))
pthread_attr_setscope(&pattr, PTHREAD_SCOPE_SYSTEM);
#endif
pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_DETACHED);
state = pthread_create(&thread, &pattr, THREAD_ENTRYPOINT, THREAD_ARG);
pthread_attr_destroy(&pattr);
if (state)
Firebird::system_call_failed::raise("pthread_create", state);
#else
#if ( defined LINUX || defined FREEBSD )
if (state = pthread_create(&thread, NULL, THREAD_ENTRYPOINT, THREAD_ARG))
Firebird::system_call_failed::raise("pthread_create", state);
if (state = pthread_detach(thread))
Firebird::system_call_failed::raise("pthread_detach", state);
#else
long stack_size;
state = pthread_attr_create(&pattr);
if (state)
Firebird::system_call_failed::raise("pthread_attr_create", state);
/* The default HP's stack size is too small. HP's documentation
says it is "machine specific". My test showed it was less
than 64K. We definitly need more stack to be able to execute
concurrently many (at least 100) copies of the same request
(like, for example in case of recursive stored prcedure).
The following code sets threads stack size up to 256K if the
default stack size is less than this number
*/
stack_size = pthread_attr_getstacksize(pattr);
if (stack_size == -1)
Firebird::system_call_failed::raise("pthread_attr_getstacksize");
if (stack_size < 0x40000L) {
state = pthread_attr_setstacksize(&pattr, 0x40000L);
if (state)
Firebird::system_call_failed::raise("pthread_attr_setstacksize", state);
}
/* HP's Posix threads implementation does not support
bound attribute. It just a user level library.
*/
state = pthread_create(&thread, pattr, THREAD_ENTRYPOINT, THREAD_ARG);
if (state)
Firebird::system_call_failed::raise("pthread_create", state);
state = pthread_detach(&thread);
if (state)
Firebird::system_call_failed::raise("pthread_detach", state);
state = pthread_attr_delete(&pattr);
if (state)
Firebird::system_call_failed::raise("pthread_attr_delete", state);
#endif /* linux */
#endif /* HP10 */
}
#endif /* USE_POSIX_THREADS */
#ifdef SOLARIS_MT
#define START_THREAD
void ThreadData::start(ThreadEntryPoint* routine,
void *arg,
int priority_arg,
int flags,
void *thd_id)
{
/**************************************
*
* t h r e a d _ s t a r t ( S o l a r i s )
*
**************************************
*
* Functional description
* Start a new thread. Return 0 if successful,
* status if not.
*
**************************************/
int rval;
thread_t thread_id;
sigset_t new_mask, orig_mask;
sigfillset(&new_mask);
sigdelset(&new_mask, SIGALRM);
if (rval = thr_sigsetmask(SIG_SETMASK, &new_mask, &orig_mask))
Firebird::system_call_failed::raise("thr_sigsetmask", rval);
#if (defined SUPERCLIENT || defined SUPERSERVER)
rval = thr_create(NULL, 0, THREAD_ENTRYPOINT, THREAD_ARG, THR_DETACHED | THR_NEW_LWP,
&thread_id);
#else
rval =
thr_create(NULL, 0, THREAD_ENTRYPOINT, THREAD_ARG, THR_DETACHED | THR_BOUND,
&thread_id);
#endif
thr_sigsetmask(SIG_SETMASK, &orig_mask, NULL);
if (rval)
Firebird::system_call_failed::raise("thr_create", rval);
}
#endif
#endif
#ifdef WIN_NT
#define START_THREAD
void ThreadData::start(ThreadEntryPoint* routine,
void *arg,
int priority_arg,
int flags,
void *thd_id)
{
/**************************************
*
* t h r e a d _ s t a r t ( W I N _ N T )
*
**************************************
*
* Functional description
* Start a new thread. Return 0 if successful,
* status if not.
*
**************************************/
int priority;
switch (priority_arg) {
case THREAD_critical:
priority = THREAD_PRIORITY_TIME_CRITICAL;
break;
case THREAD_high:
priority = THREAD_PRIORITY_HIGHEST;
break;
case THREAD_medium_high:
priority = THREAD_PRIORITY_ABOVE_NORMAL;
break;
case THREAD_medium:
priority = THREAD_PRIORITY_NORMAL;
break;
case THREAD_medium_low:
priority = THREAD_PRIORITY_BELOW_NORMAL;
break;
case THREAD_low:
default:
priority = THREAD_PRIORITY_LOWEST;
break;
}
#ifdef THREAD_PSCHED
ThreadPriorityScheduler::Init();
ThreadPriorityScheduler *tps = FB_NEW(*getDefaultMemoryPool())
ThreadPriorityScheduler(routine, arg,
ThreadPriorityScheduler::adjustPriority(priority));
#endif //THREAD_PSCHED
/* I have changed the CreateThread here to _beginthreadex() as using
* CreateThread() can lead to memory leaks caused by C-runtime library.
* Advanced Windows by Richter pg. # 109. */
DWORD thread_id;
unsigned long real_handle =
_beginthreadex(NULL, 0, THREAD_ENTRYPOINT, THREAD_ARG, CREATE_SUSPENDED,
reinterpret_cast<unsigned*>(&thread_id));
if (!real_handle)
{
Firebird::system_call_failed::raise("_beginthreadex", GetLastError());
}
HANDLE handle = reinterpret_cast<HANDLE>(real_handle);
SetThreadPriority(handle, priority);
if (! (flags & THREAD_wait))
{
ResumeThread(handle);
}
if (thd_id)
{
*(HANDLE *) thd_id = handle;
}
else
{
CloseHandle(handle);
}
}
#endif
#ifdef ANY_THREADING
#ifdef VMS
#ifndef USE_POSIX_THREADS
@ -921,25 +474,4 @@ void ThreadData::start(ThreadEntryPoint* routine,
#endif
#ifndef START_THREAD
void ThreadData::start(ThreadEntryPoint* routine,
void *arg,
int priority_arg,
int flags,
void *thd_id)
{
/**************************************
*
* t h r e a d _ s t a r t ( G e n e r i c )
*
**************************************
*
* Functional description
* Wrong attempt to start a new thread.
*
**************************************/
}
#endif