1
/* Copyright (c) 2005 PrimeBase Technologies GmbH
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
* 2005-01-03 Paul McCullagh
24
#ifndef __xt_thread_h__
25
#define __xt_thread_h__
29
#include <sys/param.h>
35
#include "linklist_xt.h"
36
#include "memory_xt.h"
37
#include "xactlog_xt.h"
38
#include "datalog_xt.h"
40
#include "locklist_xt.h"
41
#include "sortedlist_xt.h"
44
* -----------------------------------------------------------------------
48
#define XT_ERR_MSG_SIZE (PATH_MAX + 200)
51
#define ASSERT(expr) ((expr) ? TRUE : xt_assert(self, #expr, __FUNC__, __FILE__, __LINE__))
53
#define ASSERT(expr) ((void) 0)
57
#define ASSUME(expr) ((expr) ? TRUE : xt_assume(self, #expr, __FUNC__, __FILE__, __LINE__))
59
#define ASSUME(expr) ((void) 0)
63
#define ASSERT_NS(expr) ((expr) ? TRUE : xt_assert(NULL, #expr, __FUNC__, __FILE__, __LINE__))
65
#define ASSERT_NS(expr) ((void) 0)
68
#define STATIC_ASSERT(condition) typedef struct { \
69
char static_assertion[condition ? 1 : -1]; \
72
#define XT_THROW_ASSERTION(str) xt_throw_assertion(self, __FUNC__, __FILE__, __LINE__, str)
75
#define XT_LOG_DEFAULT -1
76
#define XT_LOG_PROTOCOL 0
77
#define XT_LOG_FATAL 1
78
#define XT_LOG_ERROR 2
79
#define XT_LOG_WARNING 3
81
#define XT_LOG_TRACE 5
83
#define XT_PROTOCOL self, "", NULL, 0, XT_LOG_PROTOCOL
84
#define XT_WARNING self, "", NULL, 0, XT_LOG_WARNING
85
#define XT_INFO self, "", NULL, 0, XT_LOG_INFO
86
#define XT_ERROR self, "", NULL, 0, XT_LOG_ERROR
87
#define XT_TRACE self, "", NULL, 0, XT_LOG_TRACE
89
#define XT_NT_PROTOCOL NULL, "", NULL, 0, XT_LOG_PROTOCOL
90
#define XT_NT_WARNING NULL, "", NULL, 0, XT_LOG_WARNING
91
#define XT_NT_INFO NULL, "", NULL, 0, XT_LOG_INFO
92
#define XT_NT_ERROR NULL, "", NULL, 0, XT_LOG_ERROR
93
#define XT_NT_TRACE NULL, "", NULL, 0, XT_LOG_TRACE
95
#define XT_ERROR_CONTEXT(func) self, __FUNC__, __FILE__, __LINE__, XT_LOG_ERROR
98
#define XT_THREAD_MAIN 0
99
#define XT_THREAD_WORKER 1
101
/* Thread Priorities: */
102
#define XT_PRIORITY_LOW 0
103
#define XT_PRIORITY_NORMAL 1
104
#define XT_PRIORITY_HIGH 2
106
#define XT_CONTEXT self, __FUNC__, __FILE__, __LINE__
107
#define XT_NS_CONTEXT NULL, __FUNC__, __FILE__, __LINE__
108
#define XT_REG_CONTEXT __FUNC__, __FILE__, __LINE__
110
#define XT_MAX_JMP 20
111
#define XT_MAX_CALL_STACK 100 /* The number of functions recorded by enter_() and exit() */
112
#define XT_RES_STACK_SIZE 4000 /* The size of the stack resource stack in bytes. */
113
#define XT_MAX_RESOURCE_USAGE 5 /* The maximum number of temp slots used per routine. */
114
#define XT_CATCH_TRACE_SIZE 1024
115
#define XT_MAX_FUNC_NAME_SIZE 120
116
#define XT_SOURCE_FILE_NAME_SIZE 40
117
#define XT_THR_NAME_SIZE 80
119
typedef struct XTException {
120
int e_xt_err; /* The XT error number (ALWAYS non-zero on error, else zero) */
121
int e_sys_err; /* The system error number (0 if none) */
122
char e_err_msg[XT_ERR_MSG_SIZE]; /* The error message text (0 terminated string) */
123
char e_func_name[XT_MAX_FUNC_NAME_SIZE]; /* The name of the function in which the exception occurred */
124
char e_source_file[XT_SOURCE_FILE_NAME_SIZE]; /* The source file in which the exception was thrown */
125
u_int e_source_line; /* The source code line number on which the exception was thrown */
126
char e_catch_trace[XT_CATCH_TRACE_SIZE]; /* A string of the catch trace. */
127
} XTExceptionRec, *XTExceptionPtr;
136
typedef void (*XTThreadFreeFunc)(struct XTThread *self, void *data);
138
typedef struct XTResourceArgs {
141
} XTResourceArgsRec, *XTResourceArgsPtr;
143
/* This structure represents a temporary resource on the resource stack.
144
* Resource are automatically freed if an exception occurs.
146
typedef struct XTResource {
147
xtWord4 r_prev_size; /* The size of the previous resource on the stack (must be first!) */
148
void *r_data; /* A pointer to the resource data (this may be on the resource stack) */
149
XTThreadFreeFunc r_free_func; /* The function used to free the resource. */
150
} XTResourceRec, *XTResourcePtr;
152
typedef struct XTJumpBuf {
153
XTResourcePtr jb_res_top;
156
} XTJumpBufRec, *XTJumpBufPtr;
158
typedef struct XTCallStack {
162
} XTCallStackRec, *XTCallStackPtr;
164
typedef struct XTIOStats {
165
u_int ts_read; /* The number of bytes read. */
166
u_int ts_write; /* The number of bytes written. */
167
xtWord8 ts_flush_time; /* The accumulated flush time. */
168
xtWord8 ts_flush_start; /* Start time, non-zero if a timer is running. */
169
#ifdef XT_TIME_DISK_WRITES
170
xtWord8 ts_write_time; /* The accumulated write time. */
171
xtWord8 ts_write_start; /* Start write time, non-zero if a timer is running. */
173
#ifdef XT_TIME_DISK_READS
174
xtWord8 ts_read_time; /* The accumulated read time. */
175
xtWord8 ts_read_start; /* Start read time, non-zero if a timer is running. */
177
u_int ts_flush; /* The number of flush operations. */
178
} XTIOStatsRec, *XTIOStatsPtr;
180
#ifdef XT_TIME_DISK_WRITES
181
#define ACC_WRITE_TIME(x, y) (x).ts_write_time += (y).ts_write_time;
183
#define ACC_WRITE_TIME(x, y)
186
#ifdef XT_TIME_DISK_WRITES
187
#define ACC_READ_TIME(x, y) (x).ts_read_time += (y).ts_read_time;
189
#define ACC_READ_TIME(x, y)
192
#define XT_ADD_STATS(x, y) { \
193
(x).ts_read += (y).ts_read; \
194
ACC_WRITE_TIME(x, y) \
195
ACC_READ_TIME(x, y) \
196
(x).ts_write += (y).ts_write; \
197
(x).ts_flush_time += (y).ts_flush_time; \
198
(x).ts_flush += (y).ts_flush; \
201
typedef struct XTStatistics {
208
u_int st_rec_cache_hit;
209
u_int st_rec_cache_miss;
210
u_int st_rec_cache_frees;
213
u_int st_ind_cache_hit;
214
u_int st_ind_cache_miss;
215
XTIOStatsRec st_ilog;
217
XTIOStatsRec st_xlog;
218
u_int st_xlog_cache_hit;
219
u_int st_xlog_cache_miss;
221
XTIOStatsRec st_data;
232
u_int st_wait_for_xact;
233
u_int st_retry_index_scan;
234
u_int st_reread_record_list;
235
XTIOStatsRec st_ind_flush_time;
236
xtInt8 st_ind_cache_dirty;
237
} XTStatisticsRec, *XTStatisticsPtr;
242
/* Run a task. The thread input is the thread that is running the task. */
243
typedef xtBool (*XTDoTaskFunc)(struct XTTask *task_data, struct XTThread *thread);
244
typedef void (*XTFreeTaskFunc)(struct XTTask *task_data);
249
tk_task_list_next(NULL),
252
tk_out_of_memory(false),
255
tk_waiting_threads.pl_setup_ns();
256
tk_notify_threads.pl_setup_ns();
261
xt_free_ns(tk_exception);
262
tk_waiting_threads.pl_exit();
263
tk_notify_threads.pl_exit();
266
virtual void tk_init(struct XTThread *) { }
267
virtual void tk_exit() { delete this; }
268
virtual void tk_lock() { }
269
virtual void tk_unlock() { }
270
virtual void tk_reference() { }
271
virtual void tk_release() { }
273
virtual bool tk_is_running() { return tk_running; }
274
virtual xtBool tk_task(struct XTThread *) { return OK; } /* Function called to performance the work of the task. */
276
XTPointerList tk_waiting_threads; /* A list of threads waiting for task completion. */
277
XTPointerList tk_notify_threads; /* A list of threads waiting for "early" notification. */
279
/* Linked list of tasks to be done by the thread pool: */
280
XTTask *tk_task_list_next;
282
/* Result of task: */
284
bool tk_success; /* TRUE if the task succeeded. */
285
bool tk_out_of_memory; /* TRUE of ran out of memory when trying to allocate the exception.
286
* In this case, the error will be logged.
288
XTExceptionPtr tk_exception; /* The exception details (NULL if no exception). */
291
class XTLockTask : public XTTask {
292
xt_mutex_type lt_mutex;
295
virtual void tk_init(struct XTThread *self);
296
virtual void tk_exit();
297
virtual void tk_lock();
298
virtual void tk_unlock();
302
* PBXT supports COMMITTED READ and REPEATABLE READ.
304
* As Jim says, multi-versioning cannot implement SERIALIZABLE. Basically
305
* you need locking to do this. Although phantom reads do not occur with
306
* MVCC, it is still not serializable.
308
* This can be seen from the following example:
310
* T1: INSERT t1 VALUE (1, 1);
311
* T2: INSERT t1 VALUE (2, 2);
312
* T1: UPDATE t1 SET b = 3 WHERE a IN (1, 2);
313
* T2: UPDATE t1 SET b = 4 WHERE a IN (1, 2);
314
* Serialized result (T1, T2) or (T2, T1):
318
* Non-serialized (MVCC) result:
323
#define XT_XACT_UNCOMMITTED_READ 0
324
#define XT_XACT_COMMITTED_READ 1
325
#define XT_XACT_REPEATABLE_READ 2 /* Guarentees rows already read will not change. */
326
#define XT_XACT_SERIALIZABLE 3
328
#define XT_IMP_NO_IMPORT 0
329
#define XT_IMP_COPY_TABLE 1 /* An import statement that copies all data in the table. */
330
#define XT_IMP_LOAD_TABLE 2 /* The LOAD DATA INFILE STATEMENT. */
332
typedef struct XTThread {
333
XTLinkedItemRec t_links; /* Required to be a member of a double-linked list. */
335
char t_name[XT_THR_NAME_SIZE]; /* The name of the thread. */
336
xtBool t_main; /* TRUE if this is the main (initial) thread */
337
xtBool t_quit; /* TRUE if this thread should stop running. */
338
xtBool t_daemon; /* TRUE if this thread is a daemon. */
339
xtThreadID t_id; /* The thread ID (0=main), index into thread array. */
340
pthread_t t_pthread; /* The pthread associated with xt thread */
341
xtBool t_disable_interrupts; /* TRUE if interrupts are disabled. */
342
int t_delayed_signal; /* Throw this signal as soon as you can! */
344
void *t_data; /* Data passed to the thread. */
345
XTThreadFreeFunc t_free_data; /* Routine used to free the thread data */
347
int t_call_top; /* A pointer to the top of the call stack. */
348
XTCallStackRec t_call_stack[XT_MAX_CALL_STACK];/* Records the function under execution (to be output on error). */
350
XTResourcePtr t_res_top; /* The top of the resource stack (reference next free space). */
352
char t_res_stack[XT_RES_STACK_SIZE]; /* Temporary data to be freed if an exception occurs. */
353
xtWord4 t_align_res_stack;
356
int t_jmp_depth; /* The current jump depth */
357
XTJumpBufRec t_jmp_env[XT_MAX_JMP]; /* The process environment to be restored on exception */
358
int t_in_handler; /* True if we are in the exception handler. */
359
XTExceptionRec t_exception; /* The exception details. */
361
xt_cond_type t_cond; /* The pthread condition used for suspending the thread. */
362
xt_mutex_type t_lock; /* Thread lock, used for operations on a thread that may be done by other threads.
363
* for example xt_unuse_database().
366
/* Async tasks and thread pool. */
367
XTPointerList st_tasks_todo; /* Store the list of tasks to be done here. */
368
XTPointerList st_tasks_done; /* Store the list of results here. */
369
struct XTThread *st_pool_next; /* Next in the thread pool. */
371
/* Application specific data: */
372
struct XTDatabase *st_database; /* The database in use by the thread. */
373
u_int st_lock_count; /* We count the number of locks MySQL has set in order to know when they are all released. */
374
u_int st_stat_count; /* start statement count. */
375
xtWord4 st_visible_time; /* Transactions committed before this time are visible. */
376
XTDataLogBufferRec st_dlog_buf;
378
/* A list of the last 10 transactions run by this connection: */
379
#ifdef XT_WAIT_FOR_CLEANUP
381
xtXactID st_prev_xact[XT_MAX_XACT_BEHIND];
384
struct XTXactData *st_xact_data; /* The transaction data, not NULL if the transaction performs an update. */
385
time_t st_xact_write_time; /* Approximate first write time (uses xt_db_approximate_time). */
386
int st_xact_mode; /* The transaction mode. */
387
xtBool1 st_xact_writer; /* TRUE if the transaction has written somthing to the log. */
388
xtBool1 st_xact_long_running; /* TRUE if this is a long running writer transaction. */
390
xtBool1 st_ignore_fkeys; /* TRUE if we must ignore foreign keys. */
391
xtBool1 st_auto_commit; /* TRUE if this is an auto-commit transaction. */
392
xtBool1 st_table_trans; /* TRUE transactions is a result of LOCK TABLES. */
393
xtBool1 st_abort_trans; /* TRUE if the transaction should be aborted. */
394
xtBool1 st_stat_ended; /* TRUE if the statement was ended. */
395
xtBool1 st_stat_trans; /* TRUE if a statement transaction is running (started on UPDATE). */
396
xtBool1 st_stat_modify; /* TRUE if the statement is an INSERT/UPDATE/DELETE */
397
xtBool1 st_non_temp_opened; /* TRUE if a non-temp tables was opened! */
398
xtWord1 st_import_stat; /* Non-zero if this is an import statement (ALTER, LOAD, REPAIR, etc). */
399
#ifdef XT_IMPLEMENT_NO_ACTION
400
XTBasicListRec st_restrict_list; /* These records have been deleted and should have no reference. */
402
/* Local thread list. */
403
u_int st_thread_list_count;
404
u_int st_thread_list_size;
405
xtThreadID *st_thread_list;
407
/* Used to prevent a record from being updated twice in one statement. */
408
struct XTOpenTable *st_is_update; /* TRUE if this is an UPDATE statement. {UPDATE-STACK} */
410
XTRowLockListRec st_lock_list; /* The thread row lock list (drop locks on transaction end). */
411
XTStatisticsRec st_statistics; /* Accumulated statistics for this thread. */
412
#ifdef XT_THREAD_LOCK_INFO
413
/* list of locks (spins, mutextes, etc) that this thread currently holds (debugging) */
414
XTThreadLockInfoPtr st_thread_lock_list[XT_THREAD_LOCK_INFO_MAX_COUNT];
415
int st_thread_lock_count;
417
} XTThreadRec, *XTThreadPtr;
419
typedef struct XTWaitThread {
420
/* The wait condition of the thread. */
421
xt_mutex_type wt_lock;
422
xt_cond_type wt_cond;
424
/* The list of threads waiting for this thread. */
425
XTSpinLockRec wt_wait_list_lock;
426
u_int wt_wait_list_count;
427
u_int wt_wait_list_size;
428
xtThreadID *wt_wait_list;
429
} XTWaitThreadRec, *XTWaitThreadPtr;
431
typedef struct XTThreadData {
432
XTThreadPtr td_thread;
433
XTWaitThreadPtr td_waiting;
434
} XTThreadDataRec, *XTThreadDataPtr;
437
* -----------------------------------------------------------------------
441
#define XT_INIT_CHECK_STACK char xt_chk_buffer[512]; memset(xt_chk_buffer, 0xFE, 512);
442
#define XT_RE_CHECK_STACK memset(xt_chk_buffer, 0xFE, 512);
445
* This macro must be placed at the start of every function.
446
* It records the current context so that we can
447
* dump a type of stack trace later if necessary.
449
* It also sets up the current thread pointer 'self'.
452
#define XT_STACK_TRACE
456
* These macros generate a stack trace which can be used
457
* to locate an error on exception.
459
#ifdef XT_STACK_TRACE
462
* Place this call at the top of a function,
463
* after the declaration of local variable, and
464
* before the first code is executed.
466
#define enter_() int xt_frame = self->t_call_top++; \
468
if (xt_frame < XT_MAX_CALL_STACK) { \
469
self->t_call_stack[xt_frame].cs_func = __FUNC__; \
470
self->t_call_stack[xt_frame].cs_file = __FILE__; \
471
self->t_call_stack[xt_frame].cs_line = __LINE__; \
475
#define outer_() self->t_call_top = xt_frame;
478
* On exit to a function, either exit_() or
479
* return_() must be called.
481
#define exit_() do { \
486
#define return_(x) do { \
491
#define returnc_(x, typ) do { \
499
* Sets the line number before a call to get a better
502
#define call_(x) do { self->t_call_stack[xt_frame].cs_line = __LINE__; x; } while (0)
507
#define exit_() return;
508
#define return_(x) return (x)
509
#define returnc_(x, typ) return (x)
514
* -----------------------------------------------------------------------
515
* Throwing and catching
518
int prof_setjmp(void);
520
#define TX_CHK_JMP() if ((self)->t_jmp_depth < 0 || (self)->t_jmp_depth >= XT_MAX_JMP) xt_throw_xterr(self, __FUNC__, __FILE__, __LINE__, XT_ERR_JUMP_OVERFLOW)
522
#define profile_setjmp prof_setjmp()
524
#define profile_setjmp
527
#define try_(n) TX_CHK_JMP(); \
528
(self)->t_jmp_env[(self)->t_jmp_depth].jb_res_top = (self)->t_res_top; \
529
(self)->t_jmp_env[(self)->t_jmp_depth].jb_call_top = (self)->t_call_top; \
530
(self)->t_jmp_depth++; profile_setjmp; if (setjmp((self)->t_jmp_env[(self)->t_jmp_depth-1].jb_buffer)) goto catch_##n;
531
#define catch_(n) (self)->t_jmp_depth--; goto cont_##n; catch_##n: (self)->t_jmp_depth--; xt_caught(self);
532
#define cont_(n) cont_##n:
533
#define throw_() xt_throw(self)
536
* -----------------------------------------------------------------------
540
//#define DEBUG_RESOURCE_STACK
542
#ifdef DEBUG_RESOURCE_STACK
543
#define CHECK_RS if ((char *) (self)->t_res_top < (self)->x.t_res_stack) xt_bug(self);
544
#define CHECK_NS_RS { XTThreadPtr self = xt_get_self(); CHECK_RS; }
546
#define CHECK_RS remove this!
547
#define CHECK_NS_RS remove this!
551
* Allocate a resource on the resource stack. The resource will be freed
552
* automatocally if an exception occurs. Before exiting the current
553
* procedure you must free the resource using popr_() or freer_().
554
* v = value to be set to the resource,
555
* f = function which frees the resource,
556
* s = the size of the resource,
559
/* GOTCHA: My experience is that contructs such as *((xtWordPS *) &(v)) = (xtWordPS) (x)
560
* cause optimised versions to crash?!
562
#define allocr_(v, f, s, t) do { \
563
if (((char *) (self)->t_res_top) > (self)->x.t_res_stack + XT_RES_STACK_SIZE - sizeof(XTResourceRec) + (s) + 4) \
564
xt_throw_xterr(self, __FUNC__, __FILE__, __LINE__, XT_ERR_RES_STACK_OVERFLOW); \
565
v = (t) (((char *) (self)->t_res_top) + sizeof(XTResourceRec)); \
566
(self)->t_res_top->r_data = (v); \
567
(self)->t_res_top->r_free_func = (XTThreadFreeFunc) (f); \
568
(self)->t_res_top = (XTResourcePtr) (((char *) (self)->t_res_top) + sizeof(XTResourceRec) + (s)); \
569
(self)->t_res_top->r_prev_size = sizeof(XTResourceRec) + (s); \
572
#define alloczr_(v, f, s, t) do { allocr_(v, f, s, t); \
573
memset(v, 0, s); } while (0)
575
/* Push and set a resource:
576
* v = value to be set to the resource,
577
* f = function which frees the resource,
579
* NOTE: the expression (r) must come first because it may contain
580
* calls which use the resource stack!!
582
#define pushsr_(v, f, r) do { \
583
if (((char *) (self)->t_res_top) > (self)->x.t_res_stack + XT_RES_STACK_SIZE - sizeof(XTResourceRec) + 4) \
584
xt_throw_xterr(self, __FUNC__, __FILE__, __LINE__, XT_ERR_RES_STACK_OVERFLOW); \
586
(self)->t_res_top->r_data = (v); \
587
(self)->t_res_top->r_free_func = (XTThreadFreeFunc) (f); \
588
(self)->t_res_top = (XTResourcePtr) (((char *) (self)->t_res_top) + sizeof(XTResourceRec)); \
589
(self)->t_res_top->r_prev_size = sizeof(XTResourceRec); \
592
/* Push a resource. In the event of an exception it will be freed
594
* f = function which frees the resource,
595
* r = a pointer to the resource,
597
#define pushr_(f, r) do { \
598
if (((char *) (self)->t_res_top) > (self)->x.t_res_stack + XT_RES_STACK_SIZE - sizeof(XTResourceRec) + 4) \
599
xt_throw_xterr(self, __FUNC__, __FILE__, __LINE__, XT_ERR_RES_STACK_OVERFLOW); \
600
(self)->t_res_top->r_data = (r); \
601
(self)->t_res_top->r_free_func = (XTThreadFreeFunc) (f); \
602
(self)->t_res_top = (XTResourcePtr) (((char *) (self)->t_res_top) + sizeof(XTResourceRec)); \
603
(self)->t_res_top->r_prev_size = sizeof(XTResourceRec); \
606
/* Pop a resource without freeing it: */
607
#ifdef DEBUG_RESOURCE_STACK
608
#define popr_() do { \
609
(self)->t_res_top = (XTResourcePtr) (((char *) (self)->t_res_top) - (self)->t_res_top->r_prev_size); \
610
if ((char *) (self)->t_res_top < (self)->x.t_res_stack) \
614
#define popr_() do { (self)->t_res_top = (XTResourcePtr) (((char *) (self)->t_res_top) - (self)->t_res_top->r_prev_size); } while (0)
617
#define setr_(r) do { ((XTResourcePtr) (((char *) (self)->t_res_top) - (self)->t_res_top->r_prev_size))->r_data = (r); } while (0)
619
/* Pop and free a resource: */
620
#ifdef DEBUG_RESOURCE_STACK
621
#define freer_() do { \
622
register XTResourcePtr rp; \
623
rp = (XTResourcePtr) (((char *) (self)->t_res_top) - (self)->t_res_top->r_prev_size); \
624
if ((char *) rp < (self)->x.t_res_stack) \
626
(rp->r_free_func)((self), rp->r_data); \
627
(self)->t_res_top = rp; \
630
#define freer_() do { \
631
register XTResourcePtr rp; \
632
rp = (XTResourcePtr) (((char *) (self)->t_res_top) - (self)->t_res_top->r_prev_size); \
633
(rp->r_free_func)((self), rp->r_data); \
634
(self)->t_res_top = rp; \
639
* -----------------------------------------------------------------------
644
#define THR_ARRAY_USE_PTHREAD_RW
646
//#define RR_FLUSH_USE_PTHREAD_RW
647
#define THR_ARRAY_USE_XSMUTEX
650
#if defined(THR_ARRAY_USE_PTHREAD_RW)
651
#define THR_ARRAY_LOCK_TYPE xt_rwlock_type
652
#define THR_ARRAY_INIT_LOCK(s, i) xt_init_rwlock_with_autoname(s, i)
653
#define THR_ARRAY_FREE_LOCK(s, i) xt_free_rwlock(i)
654
#define THR_ARRAY_READ_LOCK(i, o) xt_slock_rwlock_ns(i)
655
#define THR_ARRAY_WRITE_LOCK(i, o) xt_xlock_rwlock_ns(i)
656
#define THR_ARRAY_UNLOCK(i, o) xt_unlock_rwlock_ns(i)
657
#elif defined(THR_ARRAY_USE_XSMUTEX)
658
#define THR_ARRAY_LOCK_TYPE XTMutexXSLockRec
659
#define THR_ARRAY_INIT_LOCK(s, i) xt_xsmutex_init_with_autoname(s, i)
660
#define THR_ARRAY_FREE_LOCK(s, i) xt_xsmutex_free(s, i)
661
#define THR_ARRAY_READ_LOCK(i, o) xt_xsmutex_slock(i, o)
662
#define THR_ARRAY_WRITE_LOCK(i, o) xt_xsmutex_xlock(i, o)
663
#define THR_ARRAY_UNLOCK(i, o) xt_xsmutex_unlock(i, o)
665
#error Please define the lock type
668
extern u_int xt_thr_maximum_threads;
669
extern u_int xt_thr_current_thread_count;
670
extern u_int xt_thr_current_max_threads;
671
extern THR_ARRAY_LOCK_TYPE xt_thr_array_resize_lock;
672
extern XTThreadDataRec *xt_thr_array;
675
* -----------------------------------------------------------------------
676
* Function prototypes
679
/* OpenSolaris has thr_main in /usr/include/thread.h (name conflict)
680
* Thanks for the tip Monty!
682
extern "C" void *xt_thread_main(void *data);
684
void xt_get_now(char *buffer, size_t len);
685
xtBool xt_init_logging(void);
686
void xt_exit_logging(void);
687
void xt_log_flush(XTThreadPtr self);
688
void xt_logf(XTThreadPtr self, c_char *func, c_char *file, u_int line, int level, c_char *fmt, ...);
689
void xt_log(XTThreadPtr self, c_char *func, c_char *file, u_int line, int level, c_char *string);
690
int xt_log_errorf(XTThreadPtr self, c_char *func, c_char *file, u_int line, int level, int xt_err, int sys_err, c_char *fmt, ...);
691
int xt_log_error(XTThreadPtr self, c_char *func, c_char *file, u_int line, int level, int xt_err, int sys_err, c_char *string);
692
void xt_log_exception(XTThreadPtr self, XTExceptionPtr e, int level);
693
void xt_clear_exception(XTThreadPtr self);
694
void xt_log_and_clear_exception(XTThreadPtr self);
695
void xt_log_and_clear_exception_ns(void);
696
void xt_log_and_clear_warning(XTThreadPtr self);
697
void xt_log_and_clear_warning_ns(void);
699
void xt_bug(XTThreadPtr self);
700
void xt_caught(XTThreadPtr self);
701
void xt_throw(XTThreadPtr self);
702
void xt_enter_exception_handler(XTThreadPtr self, XTExceptionPtr e);
703
void xt_exit_exception_handler(XTThreadPtr self, XTExceptionPtr e);
704
void xt_throwf(XTThreadPtr self, c_char *func, c_char *file, u_int line, int xt_err, int sys_err, c_char *format, ...);
705
void xt_throw_error(XTThreadPtr self, c_char *func, c_char *file, u_int line, int xt_err, int sys_err, c_char *message);
706
void xt_throw_i2xterr(XTThreadPtr self, c_char *func, c_char *file, u_int line, int xt_err, c_char *item, c_char *item2);
707
void xt_throw_ixterr(XTThreadPtr self, c_char *func, c_char *file, u_int line, int xt_err, c_char *item);
708
void xt_throw_tabcolerr(XTThreadPtr self, c_char *func, c_char *file, u_int line, int xt_err, XTPathStrPtr tab_item, c_char *item2);
709
void xt_throw_taberr(XTThreadPtr self, c_char *func, c_char *file, u_int line, int xt_err, XTPathStrPtr tab_item);
710
void xt_throw_ulxterr(XTThreadPtr self, c_char *func, c_char *file, u_int line, int xt_err, u_long value);
711
void xt_throw_sulxterr(XTThreadPtr self, c_char *func, c_char *file, u_int line, int xt_err, c_char *item, u_long value);
712
void xt_throw_xterr(XTThreadPtr self, c_char *func, c_char *file, u_int line, int xt_err);
713
void xt_throw_errno(XTThreadPtr self, c_char *func, c_char *file, u_int line, int err_no);
714
void xt_throw_ferrno(XTThreadPtr self, c_char *func, c_char *file, u_int line, int err_no, c_char *path);
715
void xt_throw_assertion(XTThreadPtr self, c_char *func, c_char *file, u_int line, c_char *str);
716
void xt_throw_signal(XTThreadPtr self, c_char *func, c_char *file, u_int line, int sig);
717
xtBool xt_throw_delayed_signal(XTThreadPtr self, c_char *func, c_char *file, u_int line);
719
void xt_registerf(c_char *func, c_char *file, u_int line, int xt_err, int sys_err, c_char *fmt, ...);
720
void xt_register_i2xterr(c_char *func, c_char *file, u_int line, int xt_err, c_char *item, c_char *item2);
721
void xt_register_ixterr(c_char *func, c_char *file, u_int line, int xt_err, c_char *item);
722
void xt_register_tabcolerr(c_char *func, c_char *file, u_int line, int xt_err, XTPathStrPtr tab_item, c_char *item2);
723
void xt_register_taberr(c_char *func, c_char *file, u_int line, int xt_err, XTPathStrPtr tab_item);
724
void xt_register_ulxterr(c_char *func, c_char *file, u_int line, int xt_err, u_long value);
725
xtBool xt_register_ferrno(c_char *func, c_char *file, u_int line, int err, c_char *path);
726
void xt_register_error(c_char *func, c_char *file, u_int line, int xt_err, int sys_err, c_char *msg);
727
xtBool xt_register_errno(c_char *func, c_char *file, u_int line, int err);
728
void xt_register_xterr(c_char *func, c_char *file, u_int line, int xt_err);
730
void xt_exceptionf(XTExceptionPtr e, XTThreadPtr self, c_char *func, c_char *file, u_int line, int xt_err, int sys_err, c_char *fmt, ...);
731
void xt_exception_error(XTExceptionPtr e, XTThreadPtr self, c_char *func, c_char *file, u_int line, int xt_err, int sys_err, c_char *msg);
732
xtBool xt_exception_errno(XTExceptionPtr e, XTThreadPtr self, c_char *func, c_char *file, u_int line, int err);
733
void xt_exception_xterr(XTExceptionPtr e, XTThreadPtr self, c_char *func, c_char *file, u_int line, int xt_err);
735
void xt_log_errno(XTThreadPtr self, c_char *func, c_char *file, u_int line, int err);
737
xtBool xt_assert(XTThreadPtr self, c_char *expr, c_char *func, c_char *file, u_int line);
738
xtBool xt_assume(XTThreadPtr self, c_char *expr, c_char *func, c_char *file, u_int line);
740
XTThreadPtr xt_init_threading();
741
void xt_exit_threading(XTThreadPtr self);
743
XTThreadPtr xt_create_thread(c_char *name, xtBool main_thread, xtBool temp_thread, XTExceptionPtr e);
744
XTThreadPtr xt_create_daemon_ns(c_char *name);
745
XTThreadPtr xt_create_daemon(XTThreadPtr parent, c_char *name);
746
void xt_free_thread(XTThreadPtr self);
747
void xt_set_thread_data(XTThreadPtr self, void *data, XTThreadFreeFunc free_func);
748
xtBool xt_run_thread_ns(XTThreadPtr child, void *(*start_routine)(XTThreadPtr));
749
void xt_run_thread(XTThreadPtr parent, XTThreadPtr child, void *(*start_routine)(XTThreadPtr));
750
void xt_exit_thread(XTThreadPtr self, void *result);
751
void *xt_wait_for_thread_to_exit(xtThreadID tid, xtBool ignore_error);
752
void xt_signal_all_threads(XTThreadPtr self, int sig);
753
void xt_do_to_all_threads(XTThreadPtr self, void (*do_func_ptr)(XTThreadPtr self, XTThreadPtr to_thr, void *thunk), void *thunk);
754
void xt_kill_thread(pthread_t t1);
755
XTThreadPtr xt_get_self(void);
756
void xt_set_self(XTThreadPtr self);
757
void xt_wait_for_all_threads(XTThreadPtr self);
758
void xt_busy_wait(void);
759
void xt_critical_wait(void);
761
void xt_sleep_milli_second(u_int t);
762
xtBool xt_suspend(XTThreadPtr self);
763
xtBool xt_unsuspend(XTThreadPtr target);
764
void xt_lock_thread(XTThreadPtr thread);
765
void xt_unlock_thread(XTThreadPtr thread);
766
xtBool xt_wait_thread(XTThreadPtr thread);
767
xtBool xt_timed_wait_thread(XTThreadPtr thread, u_long milli_sec);
768
void xt_signal_thread(XTThreadPtr target);
769
void xt_terminate_thread(XTThreadPtr self, XTThreadPtr target);
770
xtProcID xt_getpid();
771
xtBool xt_process_exists(xtProcID pid);
773
xtBool xt_add_to_wakeup_list(xtThreadID waiting_id, xtThreadID wait_for_id);
774
void xt_wakeup_waiting_threads(XTThreadPtr thread);
775
void xt_wakeup_thread_list(XTThreadPtr thread);
776
void xt_wakeup_thread(xtThreadID thd_id, XTThreadPtr thread);
778
#ifdef XT_THREAD_LOCK_INFO
779
#define xt_init_rwlock_with_autoname(a,b) xt_init_rwlock(a,b,LOCKLIST_ARG_SUFFIX(b))
781
#define xt_init_rwlock_with_autoname(a,b) xt_init_rwlock(a,b)
784
#ifdef XT_THREAD_LOCK_INFO
785
xtBool xt_init_rwlock(XTThreadPtr self, xt_rwlock_type *rwlock, const char *name);
787
xtBool xt_init_rwlock(XTThreadPtr self, xt_rwlock_type *rwlock);
789
void xt_free_rwlock(xt_rwlock_type *rwlock);
790
xt_rwlock_type *xt_slock_rwlock(XTThreadPtr self, xt_rwlock_type *rwlock);
791
xt_rwlock_type *xt_xlock_rwlock(XTThreadPtr self, xt_rwlock_type *rwlock);
792
void xt_unlock_rwlock(XTThreadPtr self, xt_rwlock_type *rwlock);
794
xt_mutex_type *xt_new_mutex(XTThreadPtr self);
795
void xt_delete_mutex(XTThreadPtr self, xt_mutex_type *mx);
796
#ifdef XT_THREAD_LOCK_INFO
797
#define xt_init_mutex_with_autoname(a,b) xt_init_mutex(a,b,LOCKLIST_ARG_SUFFIX(b))
798
xtBool xt_init_mutex(XTThreadPtr self, xt_mutex_type *mx, const char *name);
800
#define xt_init_mutex_with_autoname(a,b) xt_init_mutex(a,b)
801
xtBool xt_init_mutex(XTThreadPtr self, xt_mutex_type *mx);
803
void xt_free_mutex(xt_mutex_type *mx);
804
xtBool xt_lock_mutex(XTThreadPtr self, xt_mutex_type *mx);
805
void xt_unlock_mutex(XTThreadPtr self, xt_mutex_type *mx);
807
pthread_cond_t *xt_new_cond(XTThreadPtr self);
808
void xt_delete_cond(XTThreadPtr self, pthread_cond_t *cond);
810
xtBool xt_init_cond(XTThreadPtr self, pthread_cond_t *cond);
811
void xt_free_cond(pthread_cond_t *cond);
812
xtBool xt_wait_cond(XTThreadPtr self, pthread_cond_t *cond, xt_mutex_type *mutex);
813
xtBool xt_timed_wait_cond(XTThreadPtr self, pthread_cond_t *cond, xt_mutex_type *mutex, u_long milli_sec);
814
xtBool xt_signal_cond(XTThreadPtr self, pthread_cond_t *cond);
815
void xt_broadcast_cond(XTThreadPtr self, pthread_cond_t *cond);
816
xtBool xt_broadcast_cond_ns(xt_cond_type *cond);
818
xtBool xt_set_key(pthread_key_t key, const void *value, XTExceptionPtr e);
819
void *xt_get_key(pthread_key_t key);
821
void xt_set_low_priority(XTThreadPtr self);
822
void xt_set_normal_priority(XTThreadPtr self);
823
void xt_set_high_priority(XTThreadPtr self);
824
void xt_set_priority(XTThreadPtr self, int priority);
826
void xt_gather_statistics(XTStatisticsPtr stats);
827
u_llong xt_get_statistic(XTStatisticsPtr stats, struct XTDatabase *db, u_int rec_id);
828
int xt_get_index_cache_dirty_perc();
830
#define xt_timed_wait_cond_ns(a, b, c) xt_timed_wait_cond(NULL, a, b, c)