~clint-fewbar/drizzle/regex-policy-cache-limiter

« back to all changes in this revision

Viewing changes to plugin/pbxt/src/lock_xt.h

  • Committer: Clint Byrum
  • Date: 2012-03-15 18:05:43 UTC
  • mfrom: (2224.1.302 workspace)
  • Revision ID: clint@ubuntu.com-20120315180543-9jxxm4q10k3np2ws
merging with latest trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2005 PrimeBase Technologies GmbH
2
 
 *
3
 
 * PrimeBase XT
4
 
 *
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.
9
 
 *
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.
14
 
 *
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
 
 *
19
 
 * 2008-01-24   Paul McCullagh
20
 
 *
21
 
 * Row lock functions.
22
 
 *
23
 
 * H&G2JCtL
24
 
 */
25
 
#ifndef __xt_lock_h__
26
 
#define __xt_lock_h__
27
 
 
28
 
#include "xt_defs.h"
29
 
#include "util_xt.h"
30
 
#include "locklist_xt.h"
31
 
#include "pthread_xt.h"
32
 
 
33
 
struct XTThread;
34
 
struct XTDatabase;
35
 
struct XTOpenTable;
36
 
struct XTXactData;
37
 
struct XTTable;
38
 
 
39
 
#ifdef XT_ATOMIC_SOLARIS_LIB
40
 
#include <atomic.h>
41
 
#endif
42
 
 
43
 
void xt_log_atomic_error_and_abort(c_char *func, c_char *file, u_int line);
44
 
 
45
 
/*
46
 
 * -----------------------------------------------------------------------
47
 
 * ATOMIC OPERATIONS
48
 
 */
49
 
 
50
 
/*
51
 
 * This macro is to remind me where it was safe
52
 
 * to use a read lock!
53
 
 */
54
 
#define xt_lck_slock            xt_spinlock_lock
55
 
 
56
 
/* I call these operations flushed because the result
57
 
 * is written atomically.
58
 
 * But the operations themselves are not atomic!
59
 
 */
60
 
inline void xt_atomic_inc1(volatile xtWord1 *mptr)
61
 
{
62
 
#ifdef XT_ATOMIC_WIN32_X86
63
 
        __asm MOV  ECX, mptr
64
 
        __asm MOV  DL, BYTE PTR [ECX]
65
 
        __asm INC  DL
66
 
        __asm XCHG DL, BYTE PTR [ECX]
67
 
#elif defined(XT_ATOMIC_GNUC_X86)
68
 
        xtWord1 val;
69
 
 
70
 
        asm volatile ("movb %1,%0" : "=r" (val) : "m" (*mptr) : "memory");
71
 
        val++;
72
 
        asm volatile ("xchgb %1,%0" : "=r" (val) : "m" (*mptr), "0" (val) : "memory");
73
 
#elif defined(XT_ATOMIC_SOLARIS_LIB)
74
 
        atomic_inc_8(mptr);
75
 
#else
76
 
        *mptr++;
77
 
        xt_log_atomic_error_and_abort(__FUNC__, __FILE__, __LINE__);
78
 
#endif
79
 
}
80
 
 
81
 
inline xtWord1 xt_atomic_dec1(volatile xtWord1 *mptr)
82
 
{
83
 
        xtWord1 val;
84
 
 
85
 
#ifdef XT_ATOMIC_WIN32_X86
86
 
        __asm MOV  ECX, mptr
87
 
        __asm MOV  DL, BYTE PTR [ECX]
88
 
        __asm DEC  DL
89
 
        __asm MOV  val, DL
90
 
        __asm XCHG DL, BYTE PTR [ECX]
91
 
#elif defined(XT_ATOMIC_GNUC_X86)
92
 
        xtWord1 val2;
93
 
 
94
 
        asm volatile ("movb %1, %0" : "=r" (val) : "m" (*mptr) : "memory");
95
 
        val--;
96
 
        asm volatile ("xchgb %1,%0" : "=r" (val2) : "m" (*mptr), "0" (val) : "memory");
97
 
        /* Should work, but compiler makes a mistake?
98
 
         * asm volatile ("xchgb %1, %0" : : "r" (val), "m" (*mptr) : "memory");
99
 
         */
100
 
#elif defined(XT_ATOMIC_SOLARIS_LIB)
101
 
        val = atomic_dec_8_nv(mptr);
102
 
#else
103
 
        val = --(*mptr);
104
 
        xt_log_atomic_error_and_abort(__FUNC__, __FILE__, __LINE__);
105
 
#endif
106
 
        return val;
107
 
}
108
 
 
109
 
inline void xt_atomic_inc2(volatile xtWord2 *mptr)
110
 
{
111
 
#ifdef XT_ATOMIC_WIN32_X86
112
 
        __asm MOV  ECX, mptr
113
 
        __asm LOCK INC  WORD PTR [ECX]
114
 
#elif defined(XT_ATOMIC_GNUC_X86)
115
 
        asm volatile ("lock; incw %0" : : "m" (*mptr) : "memory");
116
 
#elif defined(XT_ATOMIC_GCC_OPS)
117
 
        __sync_fetch_and_add(mptr, 1);
118
 
#elif defined(XT_ATOMIC_SOLARIS_LIB)
119
 
        atomic_inc_16_nv(mptr);
120
 
#else
121
 
        (*mptr)++;
122
 
        xt_log_atomic_error_and_abort(__FUNC__, __FILE__, __LINE__);
123
 
#endif
124
 
}
125
 
 
126
 
inline void xt_atomic_dec2(volatile xtWord2 *mptr)
127
 
{
128
 
#ifdef XT_ATOMIC_WIN32_X86
129
 
        __asm MOV  ECX, mptr
130
 
        __asm LOCK DEC  WORD PTR [ECX]
131
 
#elif defined(XT_ATOMIC_GNUC_X86)
132
 
        asm volatile ("lock; decw %0" : : "m" (*mptr) : "memory");
133
 
#elif defined(XT_ATOMIC_GCC_OPS)
134
 
        __sync_fetch_and_sub(mptr, 1);
135
 
#elif defined(XT_ATOMIC_SOLARIS_LIB)
136
 
        atomic_dec_16_nv(mptr);
137
 
#else
138
 
        --(*mptr);
139
 
        xt_log_atomic_error_and_abort(__FUNC__, __FILE__, __LINE__);
140
 
#endif
141
 
}
142
 
 
143
 
/* Atomic test and set 2 byte word! */
144
 
inline xtWord2 xt_atomic_tas2(volatile xtWord2 *mptr, xtWord2 val)
145
 
{
146
 
#ifdef XT_ATOMIC_WIN32_X86
147
 
        __asm MOV  ECX, mptr
148
 
        __asm MOV  DX, val
149
 
        __asm XCHG DX, WORD PTR [ECX]
150
 
        __asm MOV  val, DX
151
 
#elif defined(XT_ATOMIC_GNUC_X86)
152
 
        asm volatile ("xchgw %1,%0" : "=r" (val) : "m" (*mptr), "0" (val) : "memory");
153
 
#elif defined(XT_ATOMIC_SOLARIS_LIB)
154
 
        val = atomic_swap_16(mptr, val);
155
 
#else
156
 
        /* Yikes! */
157
 
        xtWord2 nval = val;
158
 
 
159
 
        val = *mptr;
160
 
        *mptr = nval;
161
 
        xt_log_atomic_error_and_abort(__FUNC__, __FILE__, __LINE__);
162
 
#endif
163
 
        return val;
164
 
}
165
 
 
166
 
inline void xt_atomic_set4(volatile xtWord4 *mptr, xtWord4 val)
167
 
{
168
 
#ifdef XT_ATOMIC_WIN32_X86
169
 
        __asm MOV  ECX, mptr
170
 
        __asm MOV  EDX, val
171
 
        __asm XCHG EDX, DWORD PTR [ECX]
172
 
        //__asm MOV  DWORD PTR [ECX], EDX
173
 
#elif defined(XT_ATOMIC_GNUC_X86)
174
 
        asm volatile ("xchgl %1,%0" : "=r" (val) : "m" (*mptr), "0" (val) : "memory");
175
 
        //asm volatile ("movl %0,%1" : "=r" (val) : "m" (*mptr) : "memory");
176
 
#elif defined(XT_ATOMIC_SOLARIS_LIB)
177
 
        atomic_swap_32(mptr, val);
178
 
#else
179
 
        *mptr = val;
180
 
        xt_log_atomic_error_and_abort(__FUNC__, __FILE__, __LINE__);
181
 
#endif
182
 
}
183
 
 
184
 
inline xtWord4 xt_atomic_tas4(volatile xtWord4 *mptr, xtWord4 val)
185
 
{                               
186
 
#ifdef XT_ATOMIC_WIN32_X86
187
 
        __asm MOV  ECX, mptr
188
 
        __asm MOV  EDX, val
189
 
        __asm XCHG EDX, DWORD PTR [ECX]
190
 
        __asm MOV  val, EDX
191
 
#elif defined(XT_ATOMIC_GNUC_X86)
192
 
        val = val;
193
 
        asm volatile ("xchgl %1,%0" : "=r" (val) : "m" (*mptr), "0" (val) : "memory");
194
 
#elif defined(XT_ATOMIC_SOLARIS_LIB)
195
 
        val = atomic_swap_32(mptr, val);
196
 
#else
197
 
        *mptr = val;
198
 
        xt_log_atomic_error_and_abort(__FUNC__, __FILE__, __LINE__);
199
 
#endif
200
 
        return val;
201
 
}
202
 
 
203
 
/*
204
 
 * -----------------------------------------------------------------------
205
 
 * DIFFERENT TYPES OF LOCKS
206
 
 */
207
 
 
208
 
typedef struct XTSpinLock {
209
 
        volatile xtWord4                        spl_lock;
210
 
#ifdef XT_NO_ATOMICS
211
 
        xt_mutex_type                           spl_mutex;
212
 
#endif
213
 
#ifdef DEBUG
214
 
        struct XTThread                         *spl_locker;
215
 
#endif
216
 
#ifdef XT_THREAD_LOCK_INFO
217
 
        XTThreadLockInfoRec                     spl_lock_info;
218
 
        const char                                  *spl_name;
219
 
#endif
220
 
} XTSpinLockRec, *XTSpinLockPtr;
221
 
 
222
 
#ifdef XT_THREAD_LOCK_INFO
223
 
#define xt_spinlock_init_with_autoname(a,b) xt_spinlock_init(a,b,LOCKLIST_ARG_SUFFIX(b))
224
 
void    xt_spinlock_init(struct XTThread *self, XTSpinLockPtr sp, const char *name);
225
 
#else
226
 
#define xt_spinlock_init_with_autoname(a,b) xt_spinlock_init(a,b)
227
 
void    xt_spinlock_init(struct XTThread *self, XTSpinLockPtr sp);
228
 
#endif
229
 
void    xt_spinlock_free(struct XTThread *self, XTSpinLockPtr sp);
230
 
xtBool  xt_spinlock_spin(XTSpinLockPtr spl);
231
 
#ifdef DEBUG
232
 
void    xt_spinlock_set_thread(XTSpinLockPtr spl);
233
 
#endif
234
 
 
235
 
/* Code for test and set is derived from code by Larry Zhou and
236
 
 * Google: http://code.google.com/p/google-perftools
237
 
 */
238
 
inline xtWord4 xt_spinlock_set(XTSpinLockPtr spl)
239
 
{
240
 
        xtWord4                         prv;
241
 
        volatile xtWord4        *lck;
242
 
                                
243
 
        lck = &spl->spl_lock;
244
 
#ifdef XT_ATOMIC_WIN32_X86
245
 
        __asm MOV  ECX, lck
246
 
        __asm MOV  EDX, 1
247
 
        __asm XCHG EDX, DWORD PTR [ECX]
248
 
        __asm MOV  prv, EDX
249
 
#elif defined(XT_ATOMIC_GNUC_X86)
250
 
        prv = 1;
251
 
        asm volatile ("xchgl %1,%0" : "=r" (prv) : "m" (*lck), "0" (prv) : "memory");
252
 
#elif defined(XT_ATOMIC_SOLARIS_LIB)
253
 
        prv = atomic_swap_32(lck, 1);
254
 
#else
255
 
        /* The default implementation just uses a mutex, and
256
 
         * does not spin! */
257
 
        xt_lock_mutex_ns(&spl->spl_mutex);
258
 
        /* We have the lock */
259
 
        *lck = 1;
260
 
        prv = 0;
261
 
#endif
262
 
#ifdef DEBUG
263
 
        if (!prv)
264
 
                xt_spinlock_set_thread(spl);
265
 
#endif
266
 
        return prv;
267
 
}
268
 
 
269
 
inline xtWord4 xt_spinlock_reset(XTSpinLockPtr spl)
270
 
{
271
 
        xtWord4                         prv;
272
 
        volatile xtWord4        *lck;
273
 
                                
274
 
#ifdef DEBUG
275
 
        spl->spl_locker = NULL;
276
 
#endif
277
 
        lck = &spl->spl_lock;
278
 
#ifdef XT_ATOMIC_WIN32_X86
279
 
        __asm MOV  ECX, lck
280
 
        __asm MOV  EDX, 0
281
 
        __asm XCHG EDX, DWORD PTR [ECX]
282
 
        __asm MOV  prv, EDX
283
 
#elif defined(XT_ATOMIC_GNUC_X86)
284
 
        prv = 0;
285
 
        asm volatile ("xchgl %1,%0" : "=r" (prv) : "m" (*lck), "0" (prv) : "memory");
286
 
#elif defined(XT_ATOMIC_SOLARIS_LIB)
287
 
        prv = atomic_swap_32(lck, 0);
288
 
#else
289
 
        *lck = 0;
290
 
        xt_unlock_mutex_ns(&spl->spl_mutex);
291
 
        prv = 1;
292
 
#endif
293
 
        return prv;
294
 
}
295
 
 
296
 
/*
297
 
 * Return FALSE, and register an error on failure.
298
 
 */
299
 
inline xtBool xt_spinlock_lock(XTSpinLockPtr spl)
300
 
{
301
 
        if (!xt_spinlock_set(spl)) {
302
 
#ifdef XT_THREAD_LOCK_INFO
303
 
                xt_thread_lock_info_add_owner(&spl->spl_lock_info);
304
 
#endif
305
 
                return OK;
306
 
        }
307
 
#ifdef XT_THREAD_LOCK_INFO
308
 
        xtBool spin_result = xt_spinlock_spin(spl);
309
 
        if (spin_result)
310
 
                xt_thread_lock_info_add_owner(&spl->spl_lock_info);
311
 
        return spin_result;
312
 
#else
313
 
        return xt_spinlock_spin(spl);
314
 
#endif
315
 
}
316
 
 
317
 
inline void xt_spinlock_unlock(XTSpinLockPtr spl)
318
 
{
319
 
        xt_spinlock_reset(spl);
320
 
#ifdef XT_THREAD_LOCK_INFO
321
 
        xt_thread_lock_info_release_owner(&spl->spl_lock_info);
322
 
#endif
323
 
}
324
 
 
325
 
#define XT_SXS_SLOCK_COUNT              2
326
 
 
327
 
typedef struct XTSpinXSLock {
328
 
        volatile xtWord2                        sxs_xlocked;
329
 
        volatile xtWord2                        sxs_xwaiter;
330
 
        volatile xtWord2                        sxs_rlock_count;
331
 
        volatile xtWord2                        sxs_wait_count;                 /* The number of readers waiting for the xlocker. */
332
 
#ifdef DEBUG
333
 
        xtThreadID                                      sxs_locker;
334
 
#endif
335
 
#ifdef XT_THREAD_LOCK_INFO
336
 
        XTThreadLockInfoRec                     sxs_lock_info;
337
 
        const char                                  *sxs_name;
338
 
#endif
339
 
} XTSpinXSLockRec, *XTSpinXSLockPtr;
340
 
 
341
 
#ifdef XT_THREAD_LOCK_INFO
342
 
#define xt_spinxslock_init_with_autoname(a,b) xt_spinxslock_init(a,b,LOCKLIST_ARG_SUFFIX(b))
343
 
void xt_spinxslock_init(struct XTThread *self, XTSpinXSLockPtr sxs, const char *name);
344
 
#else
345
 
#define xt_spinxslock_init_with_autoname(a,b) xt_spinxslock_init(a,b)
346
 
void xt_spinxslock_init(struct XTThread *self, XTSpinXSLockPtr sxs);
347
 
#endif
348
 
void xt_spinxslock_free(struct XTThread *self, XTSpinXSLockPtr sxs);
349
 
xtBool xt_spinxslock_xlock(XTSpinXSLockPtr sxs, xtBool try_lock, xtThreadID thd_id);
350
 
xtBool xt_spinxslock_slock(XTSpinXSLockPtr sxs);
351
 
xtBool xt_spinxslock_unlock(XTSpinXSLockPtr sxs, xtBool xlocked);
352
 
 
353
 
typedef struct XTMutexXSLock {
354
 
        xt_mutex_type                           xsm_lock;
355
 
        xt_cond_type                            xsm_xcond;
356
 
        xt_cond_type                            xsm_rcond;
357
 
        volatile xtThreadID                     xsm_xlocker;
358
 
        volatile xtWord2                        xsm_xwait_count;
359
 
        volatile xtWord2                        xsm_rlock_count;
360
 
        volatile xtWord2                        xsm_rwait_count;                        /* The number of readers waiting for the xlocker. */
361
 
#ifdef DEBUG
362
 
        xtThreadID                                      xsm_locker;
363
 
#endif
364
 
#ifdef XT_THREAD_LOCK_INFO
365
 
        XTThreadLockInfoRec                     xsm_lock_info;
366
 
        const char                                  *xsm_name;
367
 
#endif
368
 
} XTMutexXSLockRec, *XTMutexXSLockPtr;
369
 
 
370
 
#ifdef XT_THREAD_LOCK_INFO
371
 
#define xt_xsmutex_init_with_autoname(a,b) xt_xsmutex_init(a,b,LOCKLIST_ARG_SUFFIX(b))
372
 
void xt_xsmutex_init(struct XTThread *self, XTMutexXSLockPtr xsm, const char *name);
373
 
#else
374
 
#define xt_xsmutex_init_with_autoname(a,b) xt_xsmutex_init(a,b)
375
 
void xt_xsmutex_init(struct XTThread *self, XTMutexXSLockPtr xsm);
376
 
#endif
377
 
 
378
 
void xt_xsmutex_free(struct XTThread *self, XTMutexXSLockPtr xsm);
379
 
xtBool xt_xsmutex_xlock(XTMutexXSLockPtr xsm, xtThreadID thd_id);
380
 
xtBool xt_xsmutex_slock(XTMutexXSLockPtr xsm, xtThreadID thd_id);
381
 
xtBool xt_xsmutex_unlock(XTMutexXSLockPtr xsm, xtThreadID thd_id);
382
 
 
383
 
void xt_unit_test_read_write_locks(struct XTThread *self);
384
 
void xt_unit_test_mutex_locks(struct XTThread *self);
385
 
void xt_unit_test_create_threads(struct XTThread *self);
386
 
 
387
 
/*
388
 
 * -----------------------------------------------------------------------
389
 
 * ROW LOCKS
390
 
 */
391
 
 
392
 
/*
393
 
 * [(9)]
394
 
 *
395
 
 * These are perminent row locks. They are set on rows for 2 reasons:
396
 
 *
397
 
 * 1. To lock a row that is being updated. The row is locked
398
 
 *    when it is read, until the point that it is updated. If the row
399
 
 *    is not updated, the lock is removed.
400
 
 *    This prevents an update coming between which will cause an error
401
 
 *    on the first thread.
402
 
 *
403
 
 * 2. The locks are used to implement SELECT FOR UPDATE.
404
 
 */
405
 
 
406
 
/*
407
 
 * A lock that is set in order to perform an update is a temporary lock.
408
 
 * This lock will be removed once the update of the record is done.
409
 
 * The objective is to prevent some other thread from changine the
410
 
 * record between the time the record is read and updated. This is to
411
 
 * prevent unncessary "Record was updated" errors.
412
 
 *
413
 
 * A permanent lock is set by a SELECT FOR UPDATE. These locks are
414
 
 * held until the end of the transaction.
415
 
 *
416
 
 * However, a SELECT FOR UPDATE will pop its lock stack before
417
 
 * waiting for a transaction that has updated a record.
418
 
 * This is to prevent the deadlock that can occur because a
419
 
 * SELECT FOR UPDATE locks groups of records (I mean in general the
420
 
 * locks used are group locks).
421
 
 *
422
 
 * This means a SELECT FOR UPDATE can get ahead of an UPDATE as far as
423
 
 * locking is concerned. Example:
424
 
 *
425
 
 * Record 1,2 and 3 are in group A.
426
 
 *
427
 
 * T1: UPDATES record 2.
428
 
 * T2: SELECT FOR UPDATE record 1, which locks group A.
429
 
 * T2: SELECT FOR UPDATE record 2, which must wait for T1.
430
 
 * T1: UPDATES record 3, which musts wait because of group lock A.
431
 
 *
432
 
 * To avoid deadlock, T2 releases its group lock A before waiting for
433
 
 * record 2. It then regains the lock after waiting for record 2.
434
 
 *
435
 
 * (NOTE: Locks are no longer released. Please check this comment:
436
 
 * {RELEASING-LOCKS} in lock_xt.cc. )
437
 
 *
438
 
 * However, release group A lock mean first releasing all locks gained
439
 
 * after group a lock.
440
 
 *
441
 
 * For example: a thread locks groups: A, B and C. To release group B
442
 
 * lock the thread must release C as well. Afterwards, it must gain
443
 
 * B and C again, in that order. This is to ensure that the lock
444
 
 * order is NOT changed!
445
 
 *
446
 
 */
447
 
#define XT_LOCK_ERR                                     -1
448
 
#define XT_NO_LOCK                                      0
449
 
#define XT_TEMP_LOCK                            1                                                               /* A temporary lock */
450
 
#define XT_PERM_LOCK                            2                                                               /* A permanent lock */
451
 
 
452
 
typedef struct XTRowLockList : public XTBasicList {
453
 
        void    xt_remove_all_locks(struct XTDatabase *db, struct XTThread *thread);
454
 
} XTRowLockListRec, *XTRowLockListPtr;
455
 
 
456
 
#define XT_USE_LIST_BASED_ROW_LOCKS
457
 
 
458
 
#ifdef XT_USE_LIST_BASED_ROW_LOCKS
459
 
/*
460
 
 * This method stores each lock, and avoids conflicts.
461
 
 * But it is a bit more expensive in time.
462
 
 */
463
 
 
464
 
#ifdef DEBUG
465
 
#define XT_TEMP_LOCK_BYTES                              10
466
 
#define XT_ROW_LOCK_GROUP_COUNT                 5
467
 
#else
468
 
#define XT_TEMP_LOCK_BYTES                              0xFFFF
469
 
#define XT_ROW_LOCK_GROUP_COUNT                 23
470
 
#endif
471
 
 
472
 
typedef struct XTLockWait {
473
 
        /* Information about the lock to be aquired: */
474
 
        struct XTThread                 *lw_thread;
475
 
        struct XTOpenTable              *lw_ot;
476
 
        xtRowID                                 lw_row_id;
477
 
 
478
 
        /* This is the lock currently held, and the transaction ID: */
479
 
        int                                             lw_curr_lock;
480
 
        xtXactID                                lw_xn_id;
481
 
 
482
 
        /* This is information about the updating transaction: */
483
 
        xtBool                                  lw_row_updated;
484
 
        xtXactID                                lw_updating_xn_id;
485
 
 
486
 
        /* Pointers for the lock list: */
487
 
        struct XTLockWait               *lw_next;
488
 
        struct XTLockWait               *lw_prev;
489
 
} XTLockWaitRec, *XTLockWaitPtr;
490
 
 
491
 
typedef struct XTLockItem {
492
 
        xtRowID                                 li_row_id;                              /* The row list is sorted in this value. */
493
 
        xtWord2                                 li_count;                               /* The number of consecutive rows locked. FFFF means a temporary lock. */
494
 
        xtWord2                                 li_thread_id;                   /* The thread that holds this lock. */
495
 
} XTLockItemRec, *XTLockItemPtr;
496
 
 
497
 
typedef struct XTLockGroup {
498
 
        XTSpinLockRec                   lg_lock;                                /* A lock for the list. */
499
 
        XTLockWaitPtr                   lg_wait_queue;                  /* A queue of threads waiting for a lock in this group. */
500
 
        XTLockWaitPtr                   lg_wait_queue_end;              /* The end of the thread queue. */
501
 
        size_t                                  lg_list_size;                   /* The size of the list. */
502
 
        size_t                                  lg_list_in_use;                 /* Number of slots on the list in use. */
503
 
        XTLockItemPtr                   lg_list;                                /* List of locks. */
504
 
} XTLockGroupRec, *XTLockGroupPtr;
505
 
 
506
 
struct XTLockWait;
507
 
 
508
 
typedef struct XTRowLocks {
509
 
        XTLockGroupRec                  rl_groups[XT_ROW_LOCK_GROUP_COUNT];
510
 
 
511
 
        void    xt_cancel_temp_lock(XTLockWaitPtr lw);
512
 
        xtBool  xt_set_temp_lock(struct XTOpenTable *ot, XTLockWaitPtr lw, XTRowLockListPtr lock_list);
513
 
        void    xt_remove_temp_lock(struct XTOpenTable *ot, xtBool updated);
514
 
        xtBool  xt_make_lock_permanent(struct XTOpenTable *ot, XTRowLockListPtr lock_list);
515
 
 
516
 
        xtBool  rl_lock_row(XTLockGroupPtr group, XTLockWaitPtr lw, XTRowLockListPtr lock_list, int *result, struct XTThread *thread);
517
 
        void    rl_grant_locks(XTLockGroupPtr group, struct XTThread *thread);
518
 
#ifdef DEBUG_LOCK_QUEUE
519
 
        void    rl_check(XTLockWaitPtr lw);
520
 
#endif
521
 
} XTRowLocksRec, *XTRowLocksPtr;
522
 
 
523
 
#define XT_USE_TABLE_REF
524
 
 
525
 
typedef struct XTPermRowLock {
526
 
#ifdef XT_USE_TABLE_REF
527
 
        struct XTTable                  *pr_table;
528
 
#else
529
 
        xtTableID                               pr_tab_id;
530
 
#endif
531
 
        xtWord1                                 pr_group[XT_ROW_LOCK_GROUP_COUNT];
532
 
} XTPermRowLockRec, *XTPermRowLockPtr;
533
 
 
534
 
#else // XT_ROW_LOCK_GROUP_COUNT
535
 
 
536
 
/* Hash based row locking. This method allows conflics, even
537
 
 * when there is none.
538
 
 */
539
 
typedef struct XTRowLocks {
540
 
        xtWord1                                 tab_lock_perm[XT_ROW_LOCK_COUNT];               /* Byte set to 1 for permanent locks. */
541
 
        struct XTXactData               *tab_row_locks[XT_ROW_LOCK_COUNT];              /* The transactions that have locked the specific rows. */
542
 
 
543
 
        int             xt_set_temp_lock(struct XTOpenTable *ot, xtRowID row, xtXactID *xn_id, XTRowLockListPtr lock_list);
544
 
        void    xt_remove_temp_lock(struct XTOpenTable *ot);
545
 
        xtBool  xt_make_lock_permanent(struct XTOpenTable *ot, XTRowLockListPtr lock_list);
546
 
        int             xt_is_locked(struct XTOpenTable *ot, xtRowID row, xtXactID *xn_id);
547
 
} XTRowLocksRec, *XTRowLocksPtr;
548
 
 
549
 
typedef struct XTPermRowLock {
550
 
        xtTableID                               pr_tab_id;
551
 
        xtWord4                                 pr_group;
552
 
} XTPermRowLockRec, *XTPermRowLockPtr;
553
 
 
554
 
#endif // XT_ROW_LOCK_GROUP_COUNT
555
 
 
556
 
xtBool                  xt_init_row_locks(XTRowLocksPtr rl);
557
 
void                    xt_exit_row_locks(XTRowLocksPtr rl);
558
 
 
559
 
xtBool                  xt_init_row_lock_list(XTRowLockListPtr rl);
560
 
void                    xt_exit_row_lock_list(XTRowLockListPtr rl);
561
 
 
562
 
#define XT_NO_LOCK                              0
563
 
#define XT_WANT_LOCK                    1
564
 
#define XT_HAVE_LOCK                    2
565
 
#define XT_WAITING                              3
566
 
 
567
 
/*
568
 
 * -----------------------------------------------------------------------
569
 
 * RECURSIVE MUTEX (allows lockers to lock again)
570
 
 */
571
 
 
572
 
typedef struct XTRecursiveMutex {
573
 
        struct XTThread                         *rm_locker;
574
 
        u_int                                           rm_lock_count;
575
 
        xt_mutex_type                           rm_mutex;
576
 
 
577
 
#ifdef XT_THREAD_LOCK_INFO
578
 
        XTThreadLockInfoRec                     rm_lock_info;
579
 
        const char                                  *rm_name;
580
 
#endif
581
 
} XTRecursiveMutexRec, *XTRecursiveMutexPtr;
582
 
 
583
 
#ifdef XT_THREAD_LOCK_INFO
584
 
#define xt_recursivemutex_init_with_autoname(a,b) xt_recursivemutex_init(a,b,LOCKLIST_ARG_SUFFIX(b))
585
 
void xt_recursivemutex_init(struct XTThread *self, XTRecursiveMutexPtr rm, const char *name);
586
 
#else
587
 
#define xt_recursivemutex_init_with_autoname(a,b) xt_recursivemutex_init(a,b)
588
 
void xt_recursivemutex_init(struct XTThread *self, XTRecursiveMutexPtr rm);
589
 
#endif
590
 
void xt_recursivemutex_free(XTRecursiveMutexPtr rm);
591
 
void xt_recursivemutex_lock(struct XTThread *self, XTRecursiveMutexPtr rm);
592
 
void xt_recursivemutex_unlock(struct XTThread *self, XTRecursiveMutexPtr rm);
593
 
 
594
 
typedef struct XTRecurRWLock {
595
 
        struct XTThread                         *rrw_locker;
596
 
        u_int                                           rrw_lock_count;
597
 
        xt_rwlock_type                          rrw_lock;
598
 
 
599
 
#ifdef XT_THREAD_LOCK_INFO
600
 
        XTThreadLockInfoRec                     rrw_lock_info;
601
 
        const char                                  *rrw_name;
602
 
#endif
603
 
} XTRecurRWLockRec, *XTRecurRWLockPtr;
604
 
 
605
 
#ifdef XT_THREAD_LOCK_INFO
606
 
#define xt_recurrwlock_init_with_autoname(a,b) xt_recurrwlock_init(a,b,LOCKLIST_ARG_SUFFIX(b))
607
 
void xt_recurrwlock_init(struct XTThread *self, XTRecurRWLockPtr rrw, const char *name);
608
 
#else
609
 
#define xt_recurrwlock_init_with_autoname(a,b) xt_recurrwlock_init(a,b)
610
 
void xt_recurrwlock_init(struct XTThread *self, XTRecurRWLockPtr rrw);
611
 
#endif
612
 
void xt_recurrwlock_free(XTRecurRWLockPtr rrw);
613
 
void xt_recurrwlock_xlock(struct XTThread *self, XTRecurRWLockPtr rrw);
614
 
void xt_recurrwlock_slock(struct XTThread *self, XTRecurRWLockPtr rrw);
615
 
void xt_recurrwlock_slock_ns(XTRecurRWLockPtr rrw);
616
 
void xt_recurrwlock_unxlock(struct XTThread *self, XTRecurRWLockPtr rrw);
617
 
void xt_recurrwlock_unslock(struct XTThread *self, XTRecurRWLockPtr rrw);
618
 
void xt_recurrwlock_unslock_ns(XTRecurRWLockPtr rrw);
619
 
 
620
 
#endif