|
|
1.1 root 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 [email protected]
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:
34: #ifndef _IPC_IPC_KMSG_H_
35: #define _IPC_IPC_KMSG_H_
36:
37: #include <cpus.h>
38: #include <mach_ipc_compat.h>
39: #include <norma_ipc.h>
40:
41: #include <mach/machine/vm_types.h>
42: #include <mach/message.h>
43: #include <kern/assert.h>
44: #include "cpu_number.h"
45: #include <kern/macro_help.h>
46: #include <kern/kalloc.h>
47: #include <ipc/ipc_marequest.h>
48: #if NORMA_IPC
49: #include <vm/vm_page.h>
50: #include <vm/vm_map.h>
51: #endif /* NORMA_IPC */
52:
53: /*
54: * This structure is only the header for a kmsg buffer;
55: * the actual buffer is normally larger. The rest of the buffer
56: * holds the body of the message.
57: *
58: * In a kmsg, the port fields hold pointers to ports instead
59: * of port names. These pointers hold references.
60: *
61: * The ikm_header.msgh_remote_port field is the destination
62: * of the message.
63: */
64:
65: typedef struct ipc_kmsg {
66: struct ipc_kmsg *ikm_next, *ikm_prev;
67: vm_size_t ikm_size;
68: ipc_marequest_t ikm_marequest;
69: #if NORMA_IPC
70: vm_page_t ikm_page;
71: vm_map_copy_t ikm_copy;
72: unsigned long ikm_source_node;
73: #endif /* NORMA_IPC */
74: mach_msg_header_t ikm_header;
75: } *ipc_kmsg_t;
76:
77: #define IKM_NULL ((ipc_kmsg_t) 0)
78:
79: #define IKM_OVERHEAD \
80: (sizeof(struct ipc_kmsg) - sizeof(mach_msg_header_t))
81:
82: #define ikm_plus_overhead(size) ((vm_size_t)((size) + IKM_OVERHEAD))
83: #define ikm_less_overhead(size) ((mach_msg_size_t)((size) - IKM_OVERHEAD))
84:
85: /*
86: * XXX For debugging.
87: */
88: #define IKM_BOGUS ((ipc_kmsg_t) 0xffffff10)
89:
90: /*
91: * We keep a per-processor cache of kernel message buffers.
92: * The cache saves the overhead/locking of using kalloc/kfree.
93: * The per-processor cache seems to miss less than a per-thread cache,
94: * and it also uses less memory. Access to the cache doesn't
95: * require locking.
96: */
97:
98: extern ipc_kmsg_t ipc_kmsg_cache[NCPUS];
99:
100: #define ikm_cache() ipc_kmsg_cache[cpu_number()]
101:
102: /*
103: * The size of the kernel message buffers that will be cached.
104: * IKM_SAVED_KMSG_SIZE includes overhead; IKM_SAVED_MSG_SIZE doesn't.
105: */
106:
107: #define IKM_SAVED_KMSG_SIZE ((vm_size_t) 256)
108: #define IKM_SAVED_MSG_SIZE ikm_less_overhead(IKM_SAVED_KMSG_SIZE)
109:
110: #define ikm_alloc(size) \
111: ((ipc_kmsg_t) kalloc(ikm_plus_overhead(size)))
112:
113: #define ikm_init(kmsg, size) \
114: MACRO_BEGIN \
115: ikm_init_special((kmsg), ikm_plus_overhead(size)); \
116: MACRO_END
117:
118: #define ikm_init_special(kmsg, size) \
119: MACRO_BEGIN \
120: (kmsg)->ikm_size = (size); \
121: (kmsg)->ikm_marequest = IMAR_NULL; \
122: MACRO_END
123:
124: #define ikm_check_initialized(kmsg, size) \
125: MACRO_BEGIN \
126: assert((kmsg)->ikm_size == (size)); \
127: assert((kmsg)->ikm_marequest == IMAR_NULL); \
128: MACRO_END
129:
130: /*
131: * Non-positive message sizes are special. They indicate that
132: * the message buffer doesn't come from ikm_alloc and
133: * requires some special handling to free.
134: *
135: * ipc_kmsg_free is the non-macro form of ikm_free.
136: * It frees kmsgs of all varieties.
137: */
138:
139: #define IKM_SIZE_NORMA 0
140: #define IKM_SIZE_NETWORK -1
141:
142: #define ikm_free(kmsg) \
143: MACRO_BEGIN \
144: register vm_size_t _size = (kmsg)->ikm_size; \
145: \
146: if ((integer_t)_size > 0) \
147: kfree((vm_offset_t) (kmsg), _size); \
148: else \
149: ipc_kmsg_free(kmsg); \
150: MACRO_END
151:
152: /*
153: * struct ipc_kmsg_queue is defined in kern/thread.h instead of here,
154: * so that kern/thread.h doesn't have to include ipc/ipc_kmsg.h.
155: */
156:
157: #include <ipc/ipc_kmsg_queue.h>
158:
159: typedef struct ipc_kmsg_queue *ipc_kmsg_queue_t;
160:
161: #define IKMQ_NULL ((ipc_kmsg_queue_t) 0)
162:
163:
164: #define ipc_kmsg_queue_init(queue) \
165: MACRO_BEGIN \
166: (queue)->ikmq_base = IKM_NULL; \
167: MACRO_END
168:
169: #define ipc_kmsg_queue_empty(queue) ((queue)->ikmq_base == IKM_NULL)
170:
171: /* Enqueue a kmsg */
172: extern void ipc_kmsg_enqueue(
173: ipc_kmsg_queue_t queue,
174: ipc_kmsg_t kmsg);
175:
176: /* Dequeue and return a kmsg */
177: extern ipc_kmsg_t ipc_kmsg_dequeue(
178: ipc_kmsg_queue_t queue);
179:
180: /* Pull a kmsg out of a queue */
181: extern void ipc_kmsg_rmqueue(
182: ipc_kmsg_queue_t queue,
183: ipc_kmsg_t kmsg);
184:
185: #define ipc_kmsg_queue_first(queue) ((queue)->ikmq_base)
186:
187: /* Return the kmsg following the given kmsg */
188: extern ipc_kmsg_t ipc_kmsg_queue_next(
189: ipc_kmsg_queue_t queue,
190: ipc_kmsg_t kmsg);
191:
192: #define ipc_kmsg_rmqueue_first_macro(queue, kmsg) \
193: MACRO_BEGIN \
194: register ipc_kmsg_t _next; \
195: \
196: assert((queue)->ikmq_base == (kmsg)); \
197: \
198: _next = (kmsg)->ikm_next; \
199: if (_next == (kmsg)) { \
200: assert((kmsg)->ikm_prev == (kmsg)); \
201: (queue)->ikmq_base = IKM_NULL; \
202: } else { \
203: register ipc_kmsg_t _prev = (kmsg)->ikm_prev; \
204: \
205: (queue)->ikmq_base = _next; \
206: _next->ikm_prev = _prev; \
207: _prev->ikm_next = _next; \
208: } \
209: /* XXX Debug paranoia */ \
210: kmsg->ikm_next = IKM_BOGUS; \
211: kmsg->ikm_prev = IKM_BOGUS; \
212: MACRO_END
213:
214: #define ipc_kmsg_enqueue_macro(queue, kmsg) \
215: MACRO_BEGIN \
216: register ipc_kmsg_t _first = (queue)->ikmq_base; \
217: \
218: if (_first == IKM_NULL) { \
219: (queue)->ikmq_base = (kmsg); \
220: (kmsg)->ikm_next = (kmsg); \
221: (kmsg)->ikm_prev = (kmsg); \
222: } else { \
223: register ipc_kmsg_t _last = _first->ikm_prev; \
224: \
225: (kmsg)->ikm_next = _first; \
226: (kmsg)->ikm_prev = _last; \
227: _first->ikm_prev = (kmsg); \
228: _last->ikm_next = (kmsg); \
229: } \
230: MACRO_END
231:
232: extern void
233: ipc_kmsg_destroy(/* ipc_kmsg_t */);
234:
235: extern void
236: ipc_kmsg_clean(/* ipc_kmsg_t */);
237:
238: extern void
239: ipc_kmsg_free(/* ipc_kmsg_t */);
240:
241: extern mach_msg_return_t
242: ipc_kmsg_get(/* mach_msg_header_t *, mach_msg_size_t, ipc_kmsg_t * */);
243:
244: extern mach_msg_return_t
245: ipc_kmsg_get_from_kernel(/* mach_msg_header_t *, mach_msg_size_t,
246: ipc_kmsg_t * */);
247:
248: extern mach_msg_return_t
249: ipc_kmsg_put(/* mach_msg_header_t *, ipc_kmsg_t, mach_msg_size_t */);
250:
251: extern void
252: ipc_kmsg_put_to_kernel(/* mach_msg_header_t *, ipc_kmsg_t, mach_msg_size_t */);
253:
254: extern mach_msg_return_t
255: ipc_kmsg_copyin_header(/* mach_msg_header_t *, ipc_space_t, mach_port_t */);
256:
257: extern mach_msg_return_t
258: ipc_kmsg_copyin(/* ipc_kmsg_t, ipc_space_t, vm_map_t, mach_port_t */);
259:
260: extern void
261: ipc_kmsg_copyin_from_kernel(/* ipc_kmsg_t */);
262:
263: extern mach_msg_return_t
264: ipc_kmsg_copyout_header(/* mach_msg_header_t *, ipc_space_t, mach_port_t */);
265:
266: extern mach_msg_return_t
267: ipc_kmsg_copyout_object(/* ipc_space_t, ipc_object_t,
268: mach_msg_type_name_t, mach_port_t * */);
269:
270: extern mach_msg_return_t
271: ipc_kmsg_copyout_body(/* vm_offset_t, vm_offset_t, ipc_space_t, vm_map_t */);
272:
273: extern mach_msg_return_t
274: ipc_kmsg_copyout(/* ipc_kmsg_t, ipc_space_t, vm_map_t, mach_port_t */);
275:
276: extern mach_msg_return_t
277: ipc_kmsg_copyout_pseudo(/* ipc_kmsg_t, ipc_space_t, vm_map_t */);
278:
279: extern void
280: ipc_kmsg_copyout_dest(/* ipc_kmsg_t, ipc_space_t */);
281:
282: #if MACH_IPC_COMPAT
283:
284: extern mach_msg_return_t
285: ipc_kmsg_copyin_compat(/* ipc_kmsg_t, ipc_space_t, vm_map_t */);
286:
287: extern mach_msg_return_t
288: ipc_kmsg_copyout_compat(/* ipc_kmsg_t, ipc_space_t, vm_map_t */);
289:
290: #endif /* MACH_IPC_COMPAT */
291: #endif /* _IPC_IPC_KMSG_H_ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.