spinlock.h 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /*
  2. * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
  3. * The President and Fellows of Harvard College.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the University nor the names of its contributors
  14. * may be used to endorse or promote products derived from this software
  15. * without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
  18. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
  21. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. * SUCH DAMAGE.
  28. */
  29. #ifndef _MIPS_SPINLOCK_H_
  30. #define _MIPS_SPINLOCK_H_
  31. #include <cdefs.h>
  32. /* Type of value needed to actually spin on */
  33. typedef unsigned spinlock_data_t;
  34. /* Initializer for use by SPINLOCK_INITIALIZER */
  35. #define SPINLOCK_DATA_INITIALIZER 0
  36. /* Atomic operations on spinlock_data_t */
  37. void spinlock_data_set(volatile spinlock_data_t *sd, unsigned val);
  38. spinlock_data_t spinlock_data_get(volatile spinlock_data_t *sd);
  39. spinlock_data_t spinlock_data_testandset(volatile spinlock_data_t *sd);
  40. ////////////////////////////////////////////////////////////
  41. SPINLOCK_INLINE
  42. void
  43. spinlock_data_set(volatile spinlock_data_t *sd, unsigned val)
  44. {
  45. *sd = val;
  46. }
  47. SPINLOCK_INLINE
  48. spinlock_data_t
  49. spinlock_data_get(volatile spinlock_data_t *sd)
  50. {
  51. return *sd;
  52. }
  53. SPINLOCK_INLINE
  54. spinlock_data_t
  55. spinlock_data_testandset(volatile spinlock_data_t *sd)
  56. {
  57. spinlock_data_t x;
  58. spinlock_data_t y;
  59. /*
  60. * Test-and-set using LL/SC.
  61. *
  62. * Load the existing value into X, and use Y to store 1.
  63. * After the SC, Y contains 1 if the store succeeded,
  64. * 0 if it failed.
  65. *
  66. * On failure, return 1 to pretend that the spinlock
  67. * was already held.
  68. */
  69. y = 1;
  70. __asm volatile(
  71. ".set push;" /* save assembler mode */
  72. ".set mips32;" /* allow MIPS32 instructions */
  73. ".set volatile;" /* avoid unwanted optimization */
  74. "ll %0, 0(%2);" /* x = *sd */
  75. "sc %1, 0(%2);" /* *sd = y; y = success? */
  76. ".set pop" /* restore assembler mode */
  77. : "=r" (x), "+r" (y) : "r" (sd));
  78. if (y == 0) {
  79. return 1;
  80. }
  81. return x;
  82. }
  83. #endif /* _MIPS_SPINLOCK_H_ */