lock.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /*
  2. * Mach Operating System
  3. * Copyright (c) 1993-1987 Carnegie Mellon University
  4. * All Rights Reserved.
  5. *
  6. * Permission to use, copy, modify and distribute this software and its
  7. * documentation is hereby granted, provided that both the copyright
  8. * notice and this permission notice appear in all copies of the
  9. * software, derivative works or modified versions, and any portions
  10. * thereof, and that both notices appear in supporting documentation.
  11. *
  12. * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
  13. * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
  14. * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  15. *
  16. * Carnegie Mellon requests users of this software to return to
  17. *
  18. * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
  19. * School of Computer Science
  20. * Carnegie Mellon University
  21. * Pittsburgh PA 15213-3890
  22. *
  23. * any improvements or extensions that they make and grant Carnegie Mellon
  24. * the rights to redistribute these changes.
  25. */
  26. /*
  27. * File: kern/lock.h
  28. * Author: Avadis Tevanian, Jr., Michael Wayne Young
  29. * Date: 1985
  30. *
  31. * Locking primitives definitions
  32. */
  33. #ifndef _KERN_LOCK_H_
  34. #define _KERN_LOCK_H_
  35. #include <mach/boolean.h>
  36. #include <mach/machine/vm_types.h>
  37. #if NCPUS > 1
  38. #include <machine/lock.h>/*XXX*/
  39. #endif
  40. #define MACH_SLOCKS ((NCPUS > 1) || MACH_LDEBUG)
  41. /*
  42. * A simple spin lock.
  43. */
  44. struct slock {
  45. volatile natural_t lock_data; /* in general 1 bit is sufficient */
  46. struct {} is_a_simple_lock;
  47. };
  48. /*
  49. * Used by macros to assert that the given argument is a simple
  50. * lock.
  51. */
  52. #define simple_lock_assert(l) (void) &(l)->is_a_simple_lock
  53. typedef struct slock simple_lock_data_t;
  54. typedef struct slock *simple_lock_t;
  55. #if MACH_SLOCKS
  56. /*
  57. * Use the locks.
  58. */
  59. #define decl_simple_lock_data(class,name) \
  60. class simple_lock_data_t name;
  61. #define simple_lock_addr(lock) (simple_lock_assert(&(lock)), \
  62. &(lock))
  63. #if (NCPUS > 1)
  64. /*
  65. * The single-CPU debugging routines are not valid
  66. * on a multiprocessor.
  67. */
  68. #define simple_lock_taken(lock) (simple_lock_assert(lock), \
  69. 1) /* always succeeds */
  70. #define check_simple_locks()
  71. #define check_simple_locks_enable()
  72. #define check_simple_locks_disable()
  73. #else /* NCPUS > 1 */
  74. /*
  75. * Use our single-CPU locking test routines.
  76. */
  77. extern void simple_lock_init(simple_lock_t);
  78. extern void _simple_lock(simple_lock_t,
  79. const char *, const char *);
  80. extern void simple_unlock(simple_lock_t);
  81. extern boolean_t _simple_lock_try(simple_lock_t,
  82. const char *, const char *);
  83. /* We provide simple_lock and simple_lock_try so that we can save the
  84. location. */
  85. #define XSTR(x) #x
  86. #define STR(x) XSTR(x)
  87. #define LOCATION __FILE__ ":" STR(__LINE__)
  88. #define simple_lock(lock) _simple_lock((lock), #lock, LOCATION)
  89. #define simple_lock_try(lock) _simple_lock_try((lock), #lock, LOCATION)
  90. #define simple_lock_pause()
  91. #define simple_lock_taken(lock) (simple_lock_assert(lock), \
  92. (lock)->lock_data)
  93. extern void check_simple_locks(void);
  94. extern void check_simple_locks_enable(void);
  95. extern void check_simple_locks_disable(void);
  96. #endif /* NCPUS > 1 */
  97. #else /* MACH_SLOCKS */
  98. /*
  99. * Do not allocate storage for locks if not needed.
  100. */
  101. struct simple_lock_data_empty { struct {} is_a_simple_lock; };
  102. #define decl_simple_lock_data(class,name) \
  103. class struct simple_lock_data_empty name;
  104. #define simple_lock_addr(lock) (simple_lock_assert(&(lock)), \
  105. (simple_lock_t)0)
  106. /*
  107. * No multiprocessor locking is necessary.
  108. */
  109. #define simple_lock_init(l) simple_lock_assert(l)
  110. #define simple_lock(l) simple_lock_assert(l)
  111. #define simple_unlock(l) simple_lock_assert(l)
  112. #define simple_lock_try(l) (simple_lock_assert(l), \
  113. TRUE) /* always succeeds */
  114. #define simple_lock_taken(l) (simple_lock_assert(l), \
  115. 1) /* always succeeds */
  116. #define check_simple_locks()
  117. #define check_simple_locks_enable()
  118. #define check_simple_locks_disable()
  119. #define simple_lock_pause()
  120. #endif /* MACH_SLOCKS */
  121. #define decl_mutex_data(class,name) decl_simple_lock_data(class,name)
  122. #define mutex_try(l) simple_lock_try(l)
  123. #define mutex_lock(l) simple_lock(l)
  124. #define mutex_unlock(l) simple_unlock(l)
  125. #define mutex_init(l) simple_lock_init(l)
  126. /*
  127. * The general lock structure. Provides for multiple readers,
  128. * upgrading from read to write, and sleeping until the lock
  129. * can be gained.
  130. *
  131. * On some architectures, assembly language code in the 'inline'
  132. * program fiddles the lock structures. It must be changed in
  133. * concert with the structure layout.
  134. *
  135. * Only the "interlock" field is used for hardware exclusion;
  136. * other fields are modified with normal instructions after
  137. * acquiring the interlock bit.
  138. */
  139. struct lock {
  140. struct thread *thread; /* Thread that has lock, if
  141. recursive locking allowed */
  142. unsigned int read_count:16, /* Number of accepted readers */
  143. /* boolean_t */ want_upgrade:1, /* Read-to-write upgrade waiting */
  144. /* boolean_t */ want_write:1, /* Writer is waiting, or
  145. locked for write */
  146. /* boolean_t */ waiting:1, /* Someone is sleeping on lock */
  147. /* boolean_t */ can_sleep:1, /* Can attempts to lock go to sleep? */
  148. recursion_depth:12, /* Depth of recursion */
  149. :0;
  150. #if MACH_LDEBUG
  151. struct thread *writer;
  152. #endif /* MACH_LDEBUG */
  153. decl_simple_lock_data(,interlock)
  154. /* Hardware interlock field.
  155. Last in the structure so that
  156. field offsets are the same whether
  157. or not it is present. */
  158. };
  159. typedef struct lock lock_data_t;
  160. typedef struct lock *lock_t;
  161. /* Sleep locks must work even if no multiprocessing */
  162. extern void lock_init(lock_t, boolean_t);
  163. extern void lock_sleepable(lock_t, boolean_t);
  164. extern void lock_write(lock_t);
  165. extern void lock_read(lock_t);
  166. extern void lock_done(lock_t);
  167. extern boolean_t lock_read_to_write(lock_t);
  168. extern void lock_write_to_read(lock_t);
  169. extern boolean_t lock_try_write(lock_t);
  170. extern boolean_t lock_try_read(lock_t);
  171. extern boolean_t lock_try_read_to_write(lock_t);
  172. #define lock_read_done(l) lock_done(l)
  173. #define lock_write_done(l) lock_done(l)
  174. extern void lock_set_recursive(lock_t);
  175. extern void lock_clear_recursive(lock_t);
  176. /* Lock debugging support. */
  177. #if ! MACH_LDEBUG
  178. #define have_read_lock(l) 1
  179. #define have_write_lock(l) 1
  180. #else /* MACH_LDEBUG */
  181. /* XXX: We don't keep track of readers, so this is an approximation. */
  182. #define have_read_lock(l) ((l)->read_count > 0)
  183. #define have_write_lock(l) ((l)->writer == current_thread())
  184. #endif /* MACH_LDEBUG */
  185. #define have_lock(l) (have_read_lock(l) || have_write_lock(l))
  186. void db_show_all_slocks(void);
  187. #endif /* _KERN_LOCK_H_ */