ipc_kmsg.h 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. /*
  2. * Mach Operating System
  3. * Copyright (c) 1991,1990,1989 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: ipc/ipc_kmsg.h
  28. * Author: Rich Draves
  29. * Date: 1989
  30. *
  31. * Definitions for kernel messages.
  32. */
  33. #ifndef _IPC_IPC_KMSG_H_
  34. #define _IPC_IPC_KMSG_H_
  35. #include <mach/machine/vm_types.h>
  36. #include <mach/message.h>
  37. #include <kern/assert.h>
  38. #include <kern/cpu_number.h>
  39. #include <kern/macros.h>
  40. #include <kern/kalloc.h>
  41. #include <ipc/ipc_marequest.h>
  42. #include <ipc/ipc_object.h>
  43. #include <ipc/ipc_types.h>
  44. #include <vm/vm_map.h>
  45. /*
  46. * This structure is only the header for a kmsg buffer;
  47. * the actual buffer is normally larger. The rest of the buffer
  48. * holds the body of the message.
  49. *
  50. * In a kmsg, the port fields hold pointers to ports instead
  51. * of port names. These pointers hold references.
  52. *
  53. * The ikm_header.msgh_remote_port field is the destination
  54. * of the message.
  55. */
  56. typedef struct ipc_kmsg {
  57. struct ipc_kmsg *ikm_next, *ikm_prev;
  58. vm_size_t ikm_size;
  59. ipc_marequest_t ikm_marequest;
  60. mach_msg_header_t ikm_header;
  61. } *ipc_kmsg_t;
  62. #define IKM_NULL ((ipc_kmsg_t) 0)
  63. #define IKM_OVERHEAD \
  64. (sizeof(struct ipc_kmsg) - sizeof(mach_msg_header_t))
  65. #define ikm_plus_overhead(size) ((vm_size_t)((size) + IKM_OVERHEAD))
  66. #define ikm_less_overhead(size) ((mach_msg_size_t)((size) - IKM_OVERHEAD))
  67. #if MACH_IPC_TEST
  68. /*
  69. * For debugging.
  70. */
  71. #define IKM_BOGUS ((ipc_kmsg_t) 0xffffff10)
  72. #define ikm_mark_bogus(kmsg) \
  73. MACRO_BEGIN \
  74. (kmsg)->ikm_next = IKM_BOGUS; \
  75. (kmsg)->ikm_prev = IKM_BOGUS; \
  76. MACRO_END
  77. #else /* MACH_IPC_TEST */
  78. #define ikm_mark_bogus(kmsg) ;
  79. #endif /* MACH_IPC_TEST */
  80. /*
  81. * We keep a per-processor cache of kernel message buffers.
  82. * The cache saves the overhead/locking of using kalloc/kfree.
  83. * The per-processor cache seems to miss less than a per-thread cache,
  84. * and it also uses less memory. Access to the cache doesn't
  85. * require locking.
  86. */
  87. extern ipc_kmsg_t ipc_kmsg_cache[NCPUS];
  88. #define ikm_cache() ipc_kmsg_cache[cpu_number()]
  89. /*
  90. * The size of the kernel message buffers that will be cached.
  91. * IKM_SAVED_KMSG_SIZE includes overhead; IKM_SAVED_MSG_SIZE doesn't.
  92. *
  93. * We use the page size for IKM_SAVED_KMSG_SIZE to make sure the
  94. * page is pinned to a single processor.
  95. */
  96. #define IKM_SAVED_KMSG_SIZE PAGE_SIZE
  97. #define IKM_SAVED_MSG_SIZE ikm_less_overhead(IKM_SAVED_KMSG_SIZE)
  98. #define ikm_alloc(size) \
  99. ((ipc_kmsg_t) kalloc(ikm_plus_overhead(size)))
  100. #define ikm_init(kmsg, size) \
  101. MACRO_BEGIN \
  102. ikm_init_special((kmsg), ikm_plus_overhead(size)); \
  103. MACRO_END
  104. #define ikm_init_special(kmsg, size) \
  105. MACRO_BEGIN \
  106. (kmsg)->ikm_size = (size); \
  107. (kmsg)->ikm_marequest = IMAR_NULL; \
  108. MACRO_END
  109. #define ikm_check_initialized(kmsg, size) \
  110. MACRO_BEGIN \
  111. assert((kmsg)->ikm_size == (size)); \
  112. assert((kmsg)->ikm_marequest == IMAR_NULL); \
  113. MACRO_END
  114. /*
  115. * Non-positive message sizes are special. They indicate that
  116. * the message buffer doesn't come from ikm_alloc and
  117. * requires some special handling to free.
  118. *
  119. * ipc_kmsg_free is the non-macro form of ikm_free.
  120. * It frees kmsgs of all varieties.
  121. */
  122. #define IKM_SIZE_NORMA 0
  123. #define IKM_SIZE_NETWORK -1
  124. #define ikm_free(kmsg) \
  125. MACRO_BEGIN \
  126. vm_size_t _size = (kmsg)->ikm_size; \
  127. \
  128. if ((integer_t)_size > 0) \
  129. kfree((vm_offset_t) (kmsg), _size); \
  130. else \
  131. ipc_kmsg_free(kmsg); \
  132. MACRO_END
  133. /*
  134. * struct ipc_kmsg_queue is defined in ipc/ipc_kmsg_queue.h
  135. */
  136. #include <ipc/ipc_kmsg_queue.h>
  137. typedef struct ipc_kmsg_queue *ipc_kmsg_queue_t;
  138. #define IKMQ_NULL ((ipc_kmsg_queue_t) 0)
  139. #define ipc_kmsg_queue_init(queue) \
  140. MACRO_BEGIN \
  141. (queue)->ikmq_base = IKM_NULL; \
  142. MACRO_END
  143. #define ipc_kmsg_queue_empty(queue) ((queue)->ikmq_base == IKM_NULL)
  144. /* Enqueue a kmsg */
  145. extern void ipc_kmsg_enqueue(
  146. ipc_kmsg_queue_t queue,
  147. ipc_kmsg_t kmsg);
  148. /* Dequeue and return a kmsg */
  149. extern ipc_kmsg_t ipc_kmsg_dequeue(
  150. ipc_kmsg_queue_t queue);
  151. /* Pull a kmsg out of a queue */
  152. extern void ipc_kmsg_rmqueue(
  153. ipc_kmsg_queue_t queue,
  154. ipc_kmsg_t kmsg);
  155. #define ipc_kmsg_queue_first(queue) ((queue)->ikmq_base)
  156. /* Return the kmsg following the given kmsg */
  157. extern ipc_kmsg_t ipc_kmsg_queue_next(
  158. ipc_kmsg_queue_t queue,
  159. ipc_kmsg_t kmsg);
  160. #define ipc_kmsg_rmqueue_first_macro(queue, kmsg) \
  161. MACRO_BEGIN \
  162. ipc_kmsg_t _next; \
  163. \
  164. assert((queue)->ikmq_base == (kmsg)); \
  165. \
  166. _next = (kmsg)->ikm_next; \
  167. if (_next == (kmsg)) { \
  168. assert((kmsg)->ikm_prev == (kmsg)); \
  169. (queue)->ikmq_base = IKM_NULL; \
  170. } else { \
  171. ipc_kmsg_t _prev = (kmsg)->ikm_prev; \
  172. \
  173. (queue)->ikmq_base = _next; \
  174. _next->ikm_prev = _prev; \
  175. _prev->ikm_next = _next; \
  176. } \
  177. ikm_mark_bogus (kmsg); \
  178. MACRO_END
  179. #define ipc_kmsg_enqueue_macro(queue, kmsg) \
  180. MACRO_BEGIN \
  181. ipc_kmsg_t _first = (queue)->ikmq_base; \
  182. \
  183. if (_first == IKM_NULL) { \
  184. (queue)->ikmq_base = (kmsg); \
  185. (kmsg)->ikm_next = (kmsg); \
  186. (kmsg)->ikm_prev = (kmsg); \
  187. } else { \
  188. ipc_kmsg_t _last = _first->ikm_prev; \
  189. \
  190. (kmsg)->ikm_next = _first; \
  191. (kmsg)->ikm_prev = _last; \
  192. _first->ikm_prev = (kmsg); \
  193. _last->ikm_next = (kmsg); \
  194. } \
  195. MACRO_END
  196. extern void
  197. ipc_kmsg_destroy(ipc_kmsg_t);
  198. extern void
  199. ipc_kmsg_clean(ipc_kmsg_t);
  200. extern void
  201. ipc_kmsg_free(ipc_kmsg_t);
  202. extern mach_msg_return_t
  203. ipc_kmsg_get(mach_msg_header_t *, mach_msg_size_t, ipc_kmsg_t *);
  204. extern mach_msg_return_t
  205. ipc_kmsg_get_from_kernel(mach_msg_header_t *, mach_msg_size_t, ipc_kmsg_t *);
  206. extern mach_msg_return_t
  207. ipc_kmsg_put(mach_msg_header_t *, ipc_kmsg_t, mach_msg_size_t);
  208. extern void
  209. ipc_kmsg_put_to_kernel(mach_msg_header_t *, ipc_kmsg_t, mach_msg_size_t);
  210. extern mach_msg_return_t
  211. ipc_kmsg_copyin_header(mach_msg_header_t *, ipc_space_t, mach_port_t);
  212. extern mach_msg_return_t
  213. ipc_kmsg_copyin(ipc_kmsg_t, ipc_space_t, vm_map_t, mach_port_t);
  214. extern void
  215. ipc_kmsg_copyin_from_kernel(ipc_kmsg_t);
  216. extern mach_msg_return_t
  217. ipc_kmsg_copyout_header(mach_msg_header_t *, ipc_space_t, mach_port_t);
  218. extern mach_msg_return_t
  219. ipc_kmsg_copyout_object(ipc_space_t, ipc_object_t,
  220. mach_msg_type_name_t, mach_port_t *);
  221. extern mach_msg_return_t
  222. ipc_kmsg_copyout_body(vm_offset_t, vm_offset_t, ipc_space_t, vm_map_t);
  223. extern mach_msg_return_t
  224. ipc_kmsg_copyout(ipc_kmsg_t, ipc_space_t, vm_map_t, mach_port_t);
  225. extern mach_msg_return_t
  226. ipc_kmsg_copyout_pseudo(ipc_kmsg_t, ipc_space_t, vm_map_t);
  227. extern void
  228. ipc_kmsg_copyout_dest(ipc_kmsg_t, ipc_space_t);
  229. #endif /* _IPC_IPC_KMSG_H_ */