FreeBSD/Linux Kernel Cross Reference
sys/norma/xmm_split.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1991 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
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 the
24 * rights to redistribute these changes.
25 */
26 /*
27 * HISTORY
28 * $Log: xmm_split.c,v $
29 * Revision 2.4 92/03/10 16:29:47 jsb
30 * Merged in norma branch changes as of NORMA_MK7.
31 * [92/03/09 12:51:54 jsb]
32 *
33 * Revision 2.3.2.2 92/02/21 11:28:13 jsb
34 * Changed reply->mobj to reply->kobj. Discard reply in lock_completed.
35 * [92/02/16 18:24:34 jsb]
36 *
37 * Explicitly provide name parameter to xmm_decl macro.
38 * Changed debugging printf name and declaration.
39 * [92/02/16 14:25:05 jsb]
40 *
41 * Use new xmm_decl, and new memory_object_name and deallocation protocol.
42 * [92/02/09 14:17:57 jsb]
43 *
44 * Revision 2.3.2.1 92/01/21 21:54:54 jsb
45 * De-linted. Supports new (dlb) memory object routines.
46 * Supports arbitrary reply ports to lock_request, etc.
47 * Converted mach_port_t (and port_t) to ipc_port_t.
48 * [92/01/20 17:30:57 jsb]
49 *
50 * Revision 2.3 91/07/01 08:26:34 jsb
51 * Use zone for requests.
52 * [91/06/29 15:34:20 jsb]
53 *
54 * Revision 2.2 91/06/17 15:48:40 jsb
55 * First checkin.
56 * [91/06/17 11:04:50 jsb]
57 *
58 */
59 /*
60 * File: norma/xmm_split.c
61 * Author: Joseph S. Barrera III
62 * Date: 1991
63 *
64 * Xmm layer to split multi-page lock_requests.
65 */
66
67 #ifdef KERNEL
68 #include <norma/xmm_obj.h>
69 #include <mach/vm_param.h>
70 #else KERNEL
71 #include <xmm_obj.h>
72 #endif KERNEL
73
74 #define dprintf xmm_split_dprintf
75
76 typedef struct request *request_t;
77
78 #define REQUEST_NULL ((request_t) 0)
79
80 struct mobj {
81 struct xmm_obj obj;
82 request_t r_head;
83 request_t r_tail;
84 };
85
86 struct request {
87 vm_offset_t r_offset;
88 vm_size_t r_length;
89 vm_offset_t r_start;
90 vm_size_t r_count;
91 vm_size_t r_resid;
92 request_t r_next;
93 };
94
95 #undef KOBJ
96 #define KOBJ ((struct mobj *) kobj)
97
98 #define m_split_init m_interpose_init
99 #define m_split_terminate m_interpose_terminate
100 #define m_split_deallocate m_interpose_deallocate
101 #define m_split_copy m_interpose_copy
102 #define m_split_data_request m_interpose_data_request
103 #define m_split_data_unlock m_interpose_data_unlock
104 #define m_split_data_write m_interpose_data_write
105 #define m_split_supply_completed m_interpose_supply_completed
106 #define m_split_data_return m_interpose_data_return
107 #define m_split_change_completed m_interpose_change_completed
108
109 #define k_split_data_unavailable k_interpose_data_unavailable
110 #define k_split_get_attributes k_interpose_get_attributes
111 #define k_split_data_error k_interpose_data_error
112 #define k_split_set_ready k_interpose_set_ready
113 #define k_split_destroy k_interpose_destroy
114 #define k_split_data_supply k_interpose_data_supply
115
116 xmm_decl(split, "split", sizeof(struct mobj));
117
118 zone_t xmm_split_request_zone;
119
120 xmm_reply_t
121 xmm_reply_allocate_reply(mobj, real_reply)
122 xmm_obj_t mobj;
123 xmm_reply_t real_reply;
124 {
125 kern_return_t kr;
126 xmm_reply_t reply;
127
128 if (real_reply == XMM_REPLY_NULL) {
129 return XMM_REPLY_NULL;
130 }
131 kr = xmm_reply_allocate(mobj, (ipc_port_t) real_reply, XMM_SPLIT_REPLY,
132 &reply);
133 if (kr != KERN_SUCCESS) {
134 panic("xmm_reply_allocate_mobj: xmm_reply_allocate: %d\n", kr);
135 }
136 return reply;
137 }
138
139 kern_return_t
140 xmm_split_create(old_mobj, new_mobj)
141 xmm_obj_t old_mobj;
142 xmm_obj_t *new_mobj;
143 {
144 xmm_obj_t mobj;
145 kern_return_t kr;
146
147 kr = xmm_obj_allocate(&split_class, old_mobj, &mobj);
148 if (kr != KERN_SUCCESS) {
149 return kr;
150 }
151 MOBJ->r_head = REQUEST_NULL;
152 MOBJ->r_tail = REQUEST_NULL;
153 *new_mobj = mobj;
154 return KERN_SUCCESS;
155 }
156
157 k_split_lock_request(kobj, offset, length, should_clean, should_flush,
158 lock_value, reply)
159 xmm_obj_t kobj;
160 vm_offset_t offset;
161 vm_size_t length;
162 boolean_t should_clean;
163 boolean_t should_flush;
164 vm_prot_t lock_value;
165 xmm_reply_t reply;
166 {
167 request_t r;
168
169 #ifdef lint
170 K_LOCK_REQUEST(kobj, offset, length, should_clean, should_flush,
171 lock_value, reply);
172 #endif lint
173 /*
174 * If we don't have to split the request,
175 * then just pass it through.
176 */
177 if (length == 0) {
178 return M_LOCK_COMPLETED(reply, offset, length);
179 }
180 if (length <= PAGE_SIZE) {
181 return K_LOCK_REQUEST(kobj, offset, length, should_clean,
182 should_flush, lock_value, reply);
183 }
184 if (reply != XMM_REPLY_NULL) {
185 r = (request_t) zalloc(xmm_split_request_zone);
186 r->r_offset = offset;
187 r->r_length = length;
188 r->r_start = (offset + PAGE_SIZE - 1) / PAGE_SIZE;
189 r->r_count = (length + PAGE_SIZE - 1) / PAGE_SIZE;
190 r->r_resid = r->r_count;
191 r->r_next = REQUEST_NULL;
192 if (KOBJ->r_head) {
193 KOBJ->r_tail->r_next = r;
194 } else {
195 KOBJ->r_head = r;
196 }
197 KOBJ->r_tail = r;
198 dprintf("@r start=%d count=%d\n", r->r_start, r->r_count);
199 }
200 while (length > PAGE_SIZE) {
201 K_LOCK_REQUEST(kobj, offset, PAGE_SIZE, should_clean,
202 should_flush, lock_value,
203 xmm_reply_allocate_reply(kobj, reply));
204 offset += PAGE_SIZE;
205 length -= PAGE_SIZE;
206 }
207 if (length > 0) {
208 K_LOCK_REQUEST(kobj, offset, length, should_clean,
209 should_flush, lock_value,
210 xmm_reply_allocate_reply(kobj, reply));
211 }
212 /* XXX check return values above??? */
213 return KERN_SUCCESS;
214 }
215
216 m_split_lock_completed(reply, offset, length)
217 xmm_reply_t reply;
218 vm_offset_t offset;
219 vm_size_t length; /* XXX ignored */
220 {
221 vm_offset_t start;
222 request_t r, *rp, r_prev = REQUEST_NULL;
223 xmm_obj_t kobj;
224 xmm_reply_t real_reply;
225
226 #ifdef lint
227 M_LOCK_COMPLETED(reply, offset, length);
228 #endif lint
229 /*
230 * If reply is not a private xmm_split reply, then
231 * just pass it through.
232 */
233 if (reply->reply_to_type != XMM_SPLIT_REPLY) {
234 return M_LOCK_COMPLETED(reply, offset, length);
235 }
236
237 /*
238 * Retrieve kobj and real reply from private reply,
239 * and discard private reply.
240 */
241 kobj = reply->kobj;
242 assert(kobj->class == &split_class);
243 real_reply = (xmm_reply_t) reply->reply_to;
244 xmm_reply_deallocate(reply);
245
246 /*
247 * Look for request structure.
248 * XXX reply->reply_to really should be r, not reply.
249 * XXX that would eliminate this stupid search.
250 * XXX same thing goes for xmm_svm module.
251 */
252 start = (offset + PAGE_SIZE - 1) / PAGE_SIZE;
253 dprintf("#r start=%d\n", start);
254 for (rp = &KOBJ->r_head; r = *rp; rp = &r->r_next) {
255 dprintf(":r start=%d..%d resid=%d\n",
256 r->r_start, r->r_start + r->r_count - 1, r->r_resid);
257 if (start >= r->r_start && start < r->r_start + r->r_count) {
258 break;
259 }
260 r_prev = r;
261 }
262 if (r == REQUEST_NULL) {
263 panic("k_split_lock_completed: lost request\n");
264 }
265 dprintf("#r found\n");
266
267 /*
268 * If this is the reply that we are waiting for, then
269 * send the real unsplit reply. Otherwise, just return.
270 */
271 if (--r->r_resid > 0) {
272 return KERN_SUCCESS;
273 }
274 if (r == KOBJ->r_tail) {
275 KOBJ->r_tail = r_prev;
276 }
277 *rp = r->r_next;
278 M_LOCK_COMPLETED(real_reply, r->r_offset, r->r_length);
279 zfree(xmm_split_request_zone, (vm_offset_t) r);
280 return KERN_SUCCESS;
281 }
282
283 xmm_split_init()
284 {
285 xmm_split_request_zone = zinit(sizeof(struct request), 512*1024,
286 sizeof(struct request), FALSE,
287 "xmm.split.request");
288 }
289
290 #include <sys/varargs.h>
291
292 int xmm_split_debug = 0;
293
294 /* VARARGS */
295 xmm_split_dprintf(fmt, va_alist)
296 char *fmt;
297 va_dcl
298 {
299 va_list listp;
300
301 if (xmm_split_debug) {
302 va_start(listp);
303 printf(fmt, &listp);
304 va_end(listp);
305 }
306 }
Cache object: c7b2679faaed4785dbb0c0b4909b4e2a
|