spinlock.h 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /* Linuxthreads - a simple clone()-based implementation of Posix */
  2. /* threads for Linux. */
  3. /* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr) */
  4. /* */
  5. /* This program is free software; you can redistribute it and/or */
  6. /* modify it under the terms of the GNU Library General Public License */
  7. /* as published by the Free Software Foundation; either version 2 */
  8. /* of the License, or (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 Library General Public License for more details. */
  14. #if defined(TEST_FOR_COMPARE_AND_SWAP)
  15. extern int __pthread_has_cas;
  16. extern int __pthread_compare_and_swap(long * ptr, long oldval, long newval,
  17. int * spinlock);
  18. static inline int compare_and_swap(long * ptr, long oldval, long newval,
  19. int * spinlock)
  20. {
  21. if (__builtin_expect (__pthread_has_cas, 1))
  22. return __compare_and_swap(ptr, oldval, newval);
  23. else
  24. return __pthread_compare_and_swap(ptr, oldval, newval, spinlock);
  25. }
  26. #elif defined(HAS_COMPARE_AND_SWAP)
  27. static inline int compare_and_swap(long * ptr, long oldval, long newval,
  28. int * spinlock)
  29. {
  30. return __compare_and_swap(ptr, oldval, newval);
  31. }
  32. #else
  33. extern int __pthread_compare_and_swap(long * ptr, long oldval, long newval,
  34. int * spinlock);
  35. static inline int compare_and_swap(long * ptr, long oldval, long newval,
  36. int * spinlock)
  37. {
  38. return __pthread_compare_and_swap(ptr, oldval, newval, spinlock);
  39. }
  40. #endif
  41. /* Internal locks */
  42. extern void internal_function __pthread_lock(struct _pthread_fastlock * lock,
  43. pthread_descr self);
  44. extern void internal_function __pthread_unlock(struct _pthread_fastlock *lock);
  45. static inline void __pthread_init_lock(struct _pthread_fastlock * lock)
  46. {
  47. lock->__status = 0;
  48. lock->__spinlock = 0;
  49. }
  50. static inline int __pthread_trylock (struct _pthread_fastlock * lock)
  51. {
  52. long oldstatus;
  53. do {
  54. oldstatus = lock->__status;
  55. if (oldstatus != 0) return EBUSY;
  56. } while(! compare_and_swap(&lock->__status, 0, 1, &lock->__spinlock));
  57. return 0;
  58. }
  59. #define LOCK_INITIALIZER {0, 0}
  60. /* Operations on pthread_atomic, which is defined in internals.h */
  61. static inline long atomic_increment(struct pthread_atomic *pa)
  62. {
  63. long oldval;
  64. do {
  65. oldval = pa->p_count;
  66. } while (!compare_and_swap(&pa->p_count, oldval, oldval + 1, &pa->p_spinlock));
  67. return oldval;
  68. }
  69. static inline long atomic_decrement(struct pthread_atomic *pa)
  70. {
  71. long oldval;
  72. do {
  73. oldval = pa->p_count;
  74. } while (!compare_and_swap(&pa->p_count, oldval, oldval - 1, &pa->p_spinlock));
  75. return oldval;
  76. }
  77. #define ATOMIC_INITIALIZER { 0, 0 }