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

Fix SuperServer 1-minute lock-up under contention bug.

With previous logic all spare threads were notified and performed
expensive loop on each request arrival. New logic wakes up only
one thread per request. (the same fix was performed in 2.0 SS lock manager
to avoid waking up all blocked threads on each lock request resolution).
As an (unexpected) result of this changes SS performance significantly
improved. Some artificial tests show timing improvements by
factor between 2 and 3.
This commit is contained in:
skidder 2003-09-16 20:59:45 +00:00
parent f7a60de04e
commit 30d8ca94f2
3 changed files with 27 additions and 8 deletions

View File

@ -36,6 +36,10 @@
#include "../jrd/thd_proto.h"
#include "../common/config/config.h"
#ifdef REMOTE_DEBUG
IMPLEMENT_TRACE_ROUTINE(remote_trace, "REMOTE");
#endif
extern int xdrmem_create(XDR *, SCHAR *, u_int, enum xdr_op);
extern "C" {

View File

@ -44,6 +44,16 @@
#endif /* !VMS || !WIN_NT */
// Uncomment this line if you need to trace module activity
//#define REMOTE_DEBUG
#ifdef REMOTE_DEBUG
DEFINE_TRACE_ROUTINE(remote_trace);
#define REMOTE_TRACE(args) remote_trace args
#else
#define REMOTE_TRACE(args) /* nothing */
#endif
#ifdef DEV_BUILD
/* Debug packet/XDR memory allocation */

View File

@ -38,6 +38,7 @@
#include "../jrd/isc.h"
#include "../jrd/license.h"
#include "../jrd/jrd_time.h"
#include "../common/classes/semaphore.h"
#include "../remote/merge_proto.h"
#include "../remote/parse_proto.h"
#include "../remote/remot_proto.h"
@ -170,9 +171,10 @@ static SLONG extra_threads = 0;
static SERVER_REQ request_que = NULL;
static SERVER_REQ free_requests = NULL;
static SERVER_REQ active_requests = NULL;
static EVENT_T thread_event[1];
static SRVR servers;
static Firebird::Semaphore requests_semaphore;
static const UCHAR request_info[] =
{
@ -267,7 +269,6 @@ void SRVR_multi_thread( PORT main_port, USHORT flags)
gds__thread_enable(-1);
ISC_event_init(thread_event, 0, 0);
THREAD_ENTER;
SET_THREAD_DATA;
@ -421,6 +422,7 @@ void SRVR_multi_thread( PORT main_port, USHORT flags)
/* No port to assign request to, add it to the waiting queue and wake up a
* thread to handle it
*/
REMOTE_TRACE(("Enqueue request %p", request));
pending_requests = append_request_next(request, &request_que);
port->port_requests_queued++;
#ifdef DEBUG_REMOTE_MEMORY
@ -448,7 +450,8 @@ void SRVR_multi_thread( PORT main_port, USHORT flags)
0);
}
ISC_event_post(thread_event);
REMOTE_TRACE(("Post event"));
requests_semaphore.release();
}
finished:
;
@ -4683,8 +4686,6 @@ static int THREAD_ROUTINE thread(void* flags)
**************************************/
SERVER_REQ request, next, *req_ptr;
PORT port, parent_port;
SLONG value;
EVENT ptr;
SCHAR *thread;
USHORT inactive_count;
USHORT timedout_count;
@ -4704,11 +4705,11 @@ static int THREAD_ROUTINE thread(void* flags)
for (;;)
{
value = ISC_event_clear(thread_event);
if (request = request_que)
{
inactive_count = 0;
timedout_count = 0;
REMOTE_TRACE(("Dequeue request %p", request_que));
request_que = request->req_next;
while (request)
{
@ -4812,11 +4813,15 @@ static int THREAD_ROUTINE thread(void* flags)
}
threads_waiting++;
ptr = thread_event;
THREAD_EXIT;
/* Wait for 1 minute (60 seconds) on a new request */
if (ISC_event_wait(1, &ptr, &value, 60 * 1000000, 0, 0))
REMOTE_TRACE(("Wait for event"));
if (!requests_semaphore.tryEnter(60)) {
REMOTE_TRACE(("timeout!"));
timedout_count++;
} else {
REMOTE_TRACE(("got it"));
}
THREAD_ENTER;
--threads_waiting;
}