00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 #ifndef S_LOCK_H
00095 #define S_LOCK_H
00096
00097 #include "storage/pg_sema.h"
00098
00099 #ifdef HAVE_SPINLOCKS
00100
00101
00102 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 #ifdef __i386__
00133 #define HAS_TEST_AND_SET
00134
00135 typedef unsigned char slock_t;
00136
00137 #define TAS(lock) tas(lock)
00138
00139 static __inline__ int
00140 tas(volatile slock_t *lock)
00141 {
00142 register slock_t _res = 1;
00143
00144
00145
00146
00147
00148
00149 __asm__ __volatile__(
00150 " cmpb $0,%1 \n"
00151 " jne 1f \n"
00152 " lock \n"
00153 " xchgb %0,%1 \n"
00154 "1: \n"
00155 : "+q"(_res), "+m"(*lock)
00156 :
00157 : "memory", "cc");
00158 return (int) _res;
00159 }
00160
00161 #define SPIN_DELAY() spin_delay()
00162
00163 static __inline__ void
00164 spin_delay(void)
00165 {
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189 __asm__ __volatile__(
00190 " rep; nop \n");
00191 }
00192
00193 #endif
00194
00195
00196 #ifdef __x86_64__
00197 #define HAS_TEST_AND_SET
00198
00199 typedef unsigned char slock_t;
00200
00201 #define TAS(lock) tas(lock)
00202
00203 static __inline__ int
00204 tas(volatile slock_t *lock)
00205 {
00206 register slock_t _res = 1;
00207
00208
00209
00210
00211
00212
00213 __asm__ __volatile__(
00214 " lock \n"
00215 " xchgb %0,%1 \n"
00216 : "+q"(_res), "+m"(*lock)
00217 :
00218 : "memory", "cc");
00219 return (int) _res;
00220 }
00221
00222 #define SPIN_DELAY() spin_delay()
00223
00224 static __inline__ void
00225 spin_delay(void)
00226 {
00227
00228
00229
00230
00231 __asm__ __volatile__(
00232 " rep; nop \n");
00233 }
00234
00235 #endif
00236
00237
00238 #if defined(__ia64__) || defined(__ia64)
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 #define HAS_TEST_AND_SET
00256
00257 typedef unsigned int slock_t;
00258
00259 #define TAS(lock) tas(lock)
00260
00261
00262 #define TAS_SPIN(lock) (*(lock) ? 1 : TAS(lock))
00263
00264 #ifndef __INTEL_COMPILER
00265
00266 static __inline__ int
00267 tas(volatile slock_t *lock)
00268 {
00269 long int ret;
00270
00271 __asm__ __volatile__(
00272 " xchg4 %0=%1,%2 \n"
00273 : "=r"(ret), "+m"(*lock)
00274 : "r"(1)
00275 : "memory");
00276 return (int) ret;
00277 }
00278
00279 #else
00280
00281 static __inline__ int
00282 tas(volatile slock_t *lock)
00283 {
00284 int ret;
00285
00286 ret = _InterlockedExchange(lock,1);
00287
00288 return ret;
00289 }
00290
00291 #endif
00292 #endif
00293
00294
00295
00296
00297
00298
00299
00300
00301 #if defined(__arm__) || defined(__arm)
00302 #define HAS_TEST_AND_SET
00303
00304 #define TAS(lock) tas(lock)
00305
00306 #ifdef HAVE_GCC_INT_ATOMICS
00307
00308 typedef int slock_t;
00309
00310 static __inline__ int
00311 tas(volatile slock_t *lock)
00312 {
00313 return __sync_lock_test_and_set(lock, 1);
00314 }
00315
00316 #define S_UNLOCK(lock) __sync_lock_release(lock)
00317
00318 #else
00319
00320 typedef unsigned char slock_t;
00321
00322 static __inline__ int
00323 tas(volatile slock_t *lock)
00324 {
00325 register slock_t _res = 1;
00326
00327 __asm__ __volatile__(
00328 " swpb %0, %0, [%2] \n"
00329 : "+r"(_res), "+m"(*lock)
00330 : "r"(lock)
00331 : "memory");
00332 return (int) _res;
00333 }
00334
00335 #endif
00336 #endif
00337
00338
00339
00340 #if defined(__s390__) || defined(__s390x__)
00341 #define HAS_TEST_AND_SET
00342
00343 typedef unsigned int slock_t;
00344
00345 #define TAS(lock) tas(lock)
00346
00347 static __inline__ int
00348 tas(volatile slock_t *lock)
00349 {
00350 int _res = 0;
00351
00352 __asm__ __volatile__(
00353 " cs %0,%3,0(%2) \n"
00354 : "+d"(_res), "+m"(*lock)
00355 : "a"(lock), "d"(1)
00356 : "memory", "cc");
00357 return _res;
00358 }
00359
00360 #endif
00361
00362
00363 #if defined(__sparc__)
00364 #define HAS_TEST_AND_SET
00365
00366 typedef unsigned char slock_t;
00367
00368 #define TAS(lock) tas(lock)
00369
00370 static __inline__ int
00371 tas(volatile slock_t *lock)
00372 {
00373 register slock_t _res;
00374
00375
00376
00377
00378
00379
00380 __asm__ __volatile__(
00381 " ldstub [%2], %0 \n"
00382 : "=r"(_res), "+m"(*lock)
00383 : "r"(lock)
00384 : "memory");
00385 return (int) _res;
00386 }
00387
00388 #endif
00389
00390
00391
00392 #if defined(__ppc__) || defined(__powerpc__) || defined(__ppc64__) || defined(__powerpc64__)
00393 #define HAS_TEST_AND_SET
00394
00395 typedef unsigned int slock_t;
00396
00397 #define TAS(lock) tas(lock)
00398
00399
00400 #define TAS_SPIN(lock) (*(lock) ? 1 : TAS(lock))
00401
00402
00403
00404
00405
00406
00407 static __inline__ int
00408 tas(volatile slock_t *lock)
00409 {
00410 slock_t _t;
00411 int _res;
00412
00413 __asm__ __volatile__(
00414 #ifdef USE_PPC_LWARX_MUTEX_HINT
00415 " lwarx %0,0,%3,1 \n"
00416 #else
00417 " lwarx %0,0,%3 \n"
00418 #endif
00419 " cmpwi %0,0 \n"
00420 " bne 1f \n"
00421 " addi %0,%0,1 \n"
00422 " stwcx. %0,0,%3 \n"
00423 " beq 2f \n"
00424 "1: li %1,1 \n"
00425 " b 3f \n"
00426 "2: \n"
00427 #ifdef USE_PPC_LWSYNC
00428 " lwsync \n"
00429 #else
00430 " isync \n"
00431 #endif
00432 " li %1,0 \n"
00433 "3: \n"
00434
00435 : "=&r"(_t), "=r"(_res), "+m"(*lock)
00436 : "r"(lock)
00437 : "memory", "cc");
00438 return _res;
00439 }
00440
00441
00442
00443
00444
00445 #ifdef USE_PPC_LWSYNC
00446 #define S_UNLOCK(lock) \
00447 do \
00448 { \
00449 __asm__ __volatile__ (" lwsync \n"); \
00450 *((volatile slock_t *) (lock)) = 0; \
00451 } while (0)
00452 #else
00453 #define S_UNLOCK(lock) \
00454 do \
00455 { \
00456 __asm__ __volatile__ (" sync \n"); \
00457 *((volatile slock_t *) (lock)) = 0; \
00458 } while (0)
00459 #endif
00460
00461 #endif
00462
00463
00464
00465 #if (defined(__mc68000__) || defined(__m68k__)) && defined(__linux__)
00466 #define HAS_TEST_AND_SET
00467
00468 typedef unsigned char slock_t;
00469
00470 #define TAS(lock) tas(lock)
00471
00472 static __inline__ int
00473 tas(volatile slock_t *lock)
00474 {
00475 register int rv;
00476
00477 __asm__ __volatile__(
00478 " clrl %0 \n"
00479 " tas %1 \n"
00480 " sne %0 \n"
00481 : "=d"(rv), "+m"(*lock)
00482 :
00483 : "memory", "cc");
00484 return rv;
00485 }
00486
00487 #endif
00488
00489
00490
00491
00492
00493
00494 #if defined(__vax__)
00495 #define HAS_TEST_AND_SET
00496
00497 typedef unsigned char slock_t;
00498
00499 #define TAS(lock) tas(lock)
00500
00501 static __inline__ int
00502 tas(volatile slock_t *lock)
00503 {
00504 register int _res;
00505
00506 __asm__ __volatile__(
00507 " movl $1, %0 \n"
00508 " bbssi $0, (%2), 1f \n"
00509 " clrl %0 \n"
00510 "1: \n"
00511 : "=&r"(_res), "+m"(*lock)
00512 : "r"(lock)
00513 : "memory");
00514 return _res;
00515 }
00516
00517 #endif
00518
00519
00520 #if defined(__ns32k__)
00521 #define HAS_TEST_AND_SET
00522
00523 typedef unsigned char slock_t;
00524
00525 #define TAS(lock) tas(lock)
00526
00527 static __inline__ int
00528 tas(volatile slock_t *lock)
00529 {
00530 register int _res;
00531
00532 __asm__ __volatile__(
00533 " sbitb 0, %1 \n"
00534 " sfsd %0 \n"
00535 : "=r"(_res), "+m"(*lock)
00536 :
00537 : "memory");
00538 return _res;
00539 }
00540
00541 #endif
00542
00543
00544 #if defined(__alpha) || defined(__alpha__)
00545
00546
00547
00548
00549
00550
00551 #define HAS_TEST_AND_SET
00552
00553 typedef unsigned long slock_t;
00554
00555 #define TAS(lock) tas(lock)
00556
00557 static __inline__ int
00558 tas(volatile slock_t *lock)
00559 {
00560 register slock_t _res;
00561
00562 __asm__ __volatile__(
00563 " ldq $0, %1 \n"
00564 " bne $0, 2f \n"
00565 " ldq_l %0, %1 \n"
00566 " bne %0, 2f \n"
00567 " mov 1, $0 \n"
00568 " stq_c $0, %1 \n"
00569 " beq $0, 2f \n"
00570 " mb \n"
00571 " br 3f \n"
00572 "2: mov 1, %0 \n"
00573 "3: \n"
00574 : "=&r"(_res), "+m"(*lock)
00575 :
00576 : "memory", "0");
00577 return (int) _res;
00578 }
00579
00580 #define S_UNLOCK(lock) \
00581 do \
00582 {\
00583 __asm__ __volatile__ (" mb \n"); \
00584 *((volatile slock_t *) (lock)) = 0; \
00585 } while (0)
00586
00587 #endif
00588
00589
00590 #if defined(__mips__) && !defined(__sgi)
00591
00592
00593 #define HAS_TEST_AND_SET
00594
00595 typedef unsigned int slock_t;
00596
00597 #define TAS(lock) tas(lock)
00598
00599 static __inline__ int
00600 tas(volatile slock_t *lock)
00601 {
00602 register volatile slock_t *_l = lock;
00603 register int _res;
00604 register int _tmp;
00605
00606 __asm__ __volatile__(
00607 " .set push \n"
00608 " .set mips2 \n"
00609 " .set noreorder \n"
00610 " .set nomacro \n"
00611 " ll %0, %2 \n"
00612 " or %1, %0, 1 \n"
00613 " sc %1, %2 \n"
00614 " xori %1, 1 \n"
00615 " or %0, %0, %1 \n"
00616 " sync \n"
00617 " .set pop "
00618 : "=&r" (_res), "=&r" (_tmp), "+R" (*_l)
00619 :
00620 : "memory");
00621 return _res;
00622 }
00623
00624
00625 #define S_UNLOCK(lock) \
00626 do \
00627 { \
00628 __asm__ __volatile__( \
00629 " .set push \n" \
00630 " .set mips2 \n" \
00631 " .set noreorder \n" \
00632 " .set nomacro \n" \
00633 " sync \n" \
00634 " .set pop "); \
00635 *((volatile slock_t *) (lock)) = 0; \
00636 } while (0)
00637
00638 #endif
00639
00640
00641 #if defined(__m32r__) && defined(HAVE_SYS_TAS_H)
00642 #define HAS_TEST_AND_SET
00643
00644 #include <sys/tas.h>
00645
00646 typedef int slock_t;
00647
00648 #define TAS(lock) tas(lock)
00649
00650 #endif
00651
00652
00653 #if defined(__sh__)
00654 #define HAS_TEST_AND_SET
00655
00656 typedef unsigned char slock_t;
00657
00658 #define TAS(lock) tas(lock)
00659
00660 static __inline__ int
00661 tas(volatile slock_t *lock)
00662 {
00663 register int _res;
00664
00665
00666
00667
00668
00669
00670 __asm__ __volatile__(
00671 " tas.b @%2 \n"
00672 " movt %0 \n"
00673 " xor #1,%0 \n"
00674 : "=z"(_res), "+m"(*lock)
00675 : "r"(lock)
00676 : "memory", "t");
00677 return _res;
00678 }
00679
00680 #endif
00681
00682
00683
00684
00685
00686 #if defined(__m68k__) && !defined(__linux__)
00687 #define HAS_TEST_AND_SET
00688
00689 typedef unsigned char slock_t;
00690 #endif
00691
00692
00693 #endif
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703 #if !defined(HAS_TEST_AND_SET)
00704
00705
00706 #if defined(USE_UNIVEL_CC)
00707 #define HAS_TEST_AND_SET
00708
00709 typedef unsigned char slock_t;
00710
00711 #define TAS(lock) tas(lock)
00712
00713 asm int
00714 tas(volatile slock_t *s_lock)
00715 {
00716
00717 %mem s_lock
00718 pushl %ebx
00719 movl s_lock, %ebx
00720 movl $255, %eax
00721 lock
00722 xchgb %al, (%ebx)
00723 popl %ebx
00724 }
00725
00726 #endif
00727
00728
00729 #if defined(__alpha) || defined(__alpha__)
00730
00731
00732
00733
00734
00735
00736
00737
00738 #define HAS_TEST_AND_SET
00739
00740 typedef unsigned long slock_t;
00741
00742 #include <alpha/builtins.h>
00743 #define S_INIT_LOCK(lock) (*(lock) = 0)
00744 #define TAS(lock) (__LOCK_LONG_RETRY((lock), 1) == 0)
00745 #define S_UNLOCK(lock) __UNLOCK_LONG(lock)
00746
00747 #endif
00748
00749
00750 #if defined(__hppa) || defined(__hppa__)
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761 #define HAS_TEST_AND_SET
00762
00763 typedef struct
00764 {
00765 int sema[4];
00766 } slock_t;
00767
00768 #define TAS_ACTIVE_WORD(lock) ((volatile int *) (((uintptr_t) (lock) + 15) & ~15))
00769
00770 #if defined(__GNUC__)
00771
00772 static __inline__ int
00773 tas(volatile slock_t *lock)
00774 {
00775 volatile int *lockword = TAS_ACTIVE_WORD(lock);
00776 register int lockval;
00777
00778 __asm__ __volatile__(
00779 " ldcwx 0(0,%2),%0 \n"
00780 : "=r"(lockval), "+m"(*lockword)
00781 : "r"(lockword)
00782 : "memory");
00783 return (lockval == 0);
00784 }
00785
00786 #endif
00787
00788 #define S_UNLOCK(lock) (*TAS_ACTIVE_WORD(lock) = -1)
00789
00790 #define S_INIT_LOCK(lock) \
00791 do { \
00792 volatile slock_t *lock_ = (lock); \
00793 lock_->sema[0] = -1; \
00794 lock_->sema[1] = -1; \
00795 lock_->sema[2] = -1; \
00796 lock_->sema[3] = -1; \
00797 } while (0)
00798
00799 #define S_LOCK_FREE(lock) (*TAS_ACTIVE_WORD(lock) != 0)
00800
00801 #endif
00802
00803
00804 #if defined(__hpux) && defined(__ia64) && !defined(__GNUC__)
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818 #define HAS_TEST_AND_SET
00819
00820 typedef unsigned int slock_t;
00821
00822 #include <ia64/sys/inline.h>
00823 #define TAS(lock) _Asm_xchg(_SZ_W, lock, 1, _LDHINT_NONE)
00824
00825 #define TAS_SPIN(lock) (*(lock) ? 1 : TAS(lock))
00826
00827 #endif
00828
00829
00830 #if defined(__sgi)
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843 #define HAS_TEST_AND_SET
00844
00845 typedef unsigned long slock_t;
00846
00847 #include "mutex.h"
00848 #define TAS(lock) (test_and_set(lock,1))
00849 #define S_UNLOCK(lock) (test_then_and(lock,0))
00850 #define S_INIT_LOCK(lock) (test_then_and(lock,0))
00851 #define S_LOCK_FREE(lock) (test_then_add(lock,0) == 0)
00852 #endif
00853
00854
00855 #if defined(sinix)
00856
00857
00858
00859
00860
00861 #define HAS_TEST_AND_SET
00862
00863 #include "abi_mutex.h"
00864 typedef abilock_t slock_t;
00865
00866 #define TAS(lock) (!acquire_lock(lock))
00867 #define S_UNLOCK(lock) release_lock(lock)
00868 #define S_INIT_LOCK(lock) init_lock(lock)
00869 #define S_LOCK_FREE(lock) (stat_lock(lock) == UNLOCKED)
00870 #endif
00871
00872
00873 #if defined(_AIX)
00874
00875
00876
00877 #define HAS_TEST_AND_SET
00878
00879 #include <sys/atomic_op.h>
00880
00881 typedef int slock_t;
00882
00883 #define TAS(lock) _check_lock((slock_t *) (lock), 0, 1)
00884 #define S_UNLOCK(lock) _clear_lock((slock_t *) (lock), 0)
00885 #endif
00886
00887
00888
00889
00890
00891 #if defined(sun3)
00892 #define HAS_TEST_AND_SET
00893
00894 typedef unsigned char slock_t;
00895 #endif
00896
00897
00898 #if defined(__SUNPRO_C) && (defined(__i386) || defined(__x86_64__) || defined(__sparc__) || defined(__sparc))
00899 #define HAS_TEST_AND_SET
00900
00901 #if defined(__i386) || defined(__x86_64__) || defined(__sparcv9) || defined(__sparcv8plus)
00902 typedef unsigned int slock_t;
00903 #else
00904 typedef unsigned char slock_t;
00905 #endif
00906
00907 extern slock_t pg_atomic_cas(volatile slock_t *lock, slock_t with,
00908 slock_t cmp);
00909
00910 #define TAS(a) (pg_atomic_cas((a), 1, 0) != 0)
00911 #endif
00912
00913
00914 #ifdef WIN32_ONLY_COMPILER
00915 typedef LONG slock_t;
00916
00917 #define HAS_TEST_AND_SET
00918 #define TAS(lock) (InterlockedCompareExchange(lock, 1, 0))
00919
00920 #define SPIN_DELAY() spin_delay()
00921
00922
00923
00924
00925 #if defined(_WIN64)
00926 static __forceinline void
00927 spin_delay(void)
00928 {
00929 _mm_pause();
00930 }
00931 #else
00932 static __forceinline void
00933 spin_delay(void)
00934 {
00935
00936 __asm rep nop;
00937 }
00938 #endif
00939
00940 #endif
00941
00942
00943 #endif
00944
00945
00946
00947 #ifndef HAS_TEST_AND_SET
00948 #error PostgreSQL does not have native spinlock support on this platform. To continue the compilation, rerun configure using --disable-spinlocks. However, performance will be poor. Please report this to [email protected].
00949 #endif
00950
00951
00952 #else
00953
00954
00955
00956
00957
00958
00959
00960 typedef PGSemaphoreData slock_t;
00961
00962 extern bool s_lock_free_sema(volatile slock_t *lock);
00963 extern void s_unlock_sema(volatile slock_t *lock);
00964 extern void s_init_lock_sema(volatile slock_t *lock);
00965 extern int tas_sema(volatile slock_t *lock);
00966
00967 #define S_LOCK_FREE(lock) s_lock_free_sema(lock)
00968 #define S_UNLOCK(lock) s_unlock_sema(lock)
00969 #define S_INIT_LOCK(lock) s_init_lock_sema(lock)
00970 #define TAS(lock) tas_sema(lock)
00971
00972
00973 #endif
00974
00975
00976
00977
00978
00979
00980 #if !defined(S_LOCK)
00981 #define S_LOCK(lock) \
00982 (TAS(lock) ? s_lock((lock), __FILE__, __LINE__) : 0)
00983 #endif
00984
00985 #if !defined(S_LOCK_FREE)
00986 #define S_LOCK_FREE(lock) (*(lock) == 0)
00987 #endif
00988
00989 #if !defined(S_UNLOCK)
00990 #define S_UNLOCK(lock) (*((volatile slock_t *) (lock)) = 0)
00991 #endif
00992
00993 #if !defined(S_INIT_LOCK)
00994 #define S_INIT_LOCK(lock) S_UNLOCK(lock)
00995 #endif
00996
00997 #if !defined(SPIN_DELAY)
00998 #define SPIN_DELAY() ((void) 0)
00999 #endif
01000
01001 #if !defined(TAS)
01002 extern int tas(volatile slock_t *lock);
01003
01004
01005 #define TAS(lock) tas(lock)
01006 #endif
01007
01008 #if !defined(TAS_SPIN)
01009 #define TAS_SPIN(lock) TAS(lock)
01010 #endif
01011
01012
01013
01014
01015
01016 extern int s_lock(volatile slock_t *lock, const char *file, int line);
01017
01018
01019 #define DEFAULT_SPINS_PER_DELAY 100
01020
01021 extern void set_spins_per_delay(int shared_spins_per_delay);
01022 extern int update_spins_per_delay(int shared_spins_per_delay);
01023
01024 #endif