]>
Commit | Line | Data |
---|---|---|
1c79356b A |
1 | /* |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
43866e37 | 6 | * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. |
1c79356b | 7 | * |
43866e37 A |
8 | * This file contains Original Code and/or Modifications of Original Code |
9 | * as defined in and that are subject to the Apple Public Source License | |
10 | * Version 2.0 (the 'License'). You may not use this file except in | |
11 | * compliance with the License. Please obtain a copy of the License at | |
12 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
13 | * file. | |
14 | * | |
15 | * The Original Code and all software distributed under the License are | |
16 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
1c79356b A |
17 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
18 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
43866e37 A |
19 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
20 | * Please see the License for the specific language governing rights and | |
21 | * limitations under the License. | |
1c79356b A |
22 | * |
23 | * @APPLE_LICENSE_HEADER_END@ | |
24 | */ | |
25 | /* | |
26 | * @OSF_COPYRIGHT@ | |
27 | * | |
28 | */ | |
29 | /* | |
30 | * HISTORY | |
31 | * | |
32 | * Revision 1.1.1.1 1998/09/22 21:05:29 wsanchez | |
33 | * Import of Mac OS X kernel (~semeria) | |
34 | * | |
35 | * Revision 1.1.1.1 1998/03/07 02:25:45 wsanchez | |
36 | * Import of OSF Mach kernel (~mburg) | |
37 | * | |
38 | * Revision 1.1.11.1 1996/09/17 16:34:42 bruel | |
39 | * fixed types. | |
40 | * [96/09/17 bruel] | |
41 | * | |
42 | * Revision 1.1.6.1 1995/06/13 18:20:10 sjs | |
43 | * Merged from flipc_shared. | |
44 | * [95/06/07 sjs] | |
45 | * | |
46 | * Revision 1.1.3.14 1995/05/19 00:58:14 sjs | |
47 | * Added send_ready to shared area, used for fast check if there is something | |
48 | * to do (and prevents the cache from getting stirred). | |
49 | * [95/05/18 sjs] | |
50 | * | |
51 | * Revision 1.1.3.13 1995/05/16 20:46:28 randys | |
52 | * Export performance valid information through performance | |
53 | * structure rather than kernel configuration section. | |
54 | * [95/05/16 randys] | |
55 | * | |
56 | * Added performance (FLIPC_PERF) config information to | |
57 | * kernel_configuration section of comm buffer, so that user | |
58 | * programs can find out if this information is being gathered. | |
59 | * [95/05/16 randys] | |
60 | * | |
61 | * Revision 1.1.3.12 1995/05/15 14:26:54 randys | |
62 | * Updated comments on use of acquire pointer (it's completely | |
63 | * ignored if dpb is set) and added macros for testing !dpb and | |
64 | * enabled at the same time. | |
65 | * [95/05/11 randys] | |
66 | * | |
67 | * Change pme_process_ptr ==> sme_process_ptr (since it's being read | |
68 | * by AIL now). | |
69 | * [95/05/11 randys] | |
70 | * | |
71 | * Added private copied of release and process pointers. | |
72 | * [95/05/11 randys] | |
73 | * | |
74 | * Rearrange endpoint structure to separate data with importantly | |
75 | * different access patterns into different cache lines. This | |
76 | * involved duplicating some (effectively constant) entries, and | |
77 | * creating two versions of some macros. | |
78 | * [95/05/11 randys] | |
79 | * | |
80 | * Revision 1.1.3.11 1995/05/08 16:06:33 randys | |
81 | * Added comment explaining that an endpoint bufferlist must always | |
82 | * have valid buffer pointers in all of its entries, to keep | |
83 | * FLIPC_endpoint_buffer_available from going off the deep end. No | |
84 | * code changes. | |
85 | * [95/04/18 randys] | |
86 | * | |
87 | * Revision 1.1.3.10 1995/04/05 21:21:52 randys | |
88 | * Added a field to the buffer control structure holding the | |
89 | * scheduling policy chosen for the allocations lock. | |
90 | * [95/04/05 randys] | |
91 | * | |
92 | * Revision 1.1.3.9 1995/03/23 20:35:19 randys | |
93 | * Added comments indicating duplication of declarations of | |
94 | * flipc_cb_base & flipc_cb_size in this file and in flipc_usermsg.h | |
95 | * Modified declaration of flipc_cb_size to be unsigned long. | |
96 | * [95/03/21 randys] | |
97 | * | |
98 | * Revision 1.1.3.8 1995/02/23 21:32:42 randys | |
99 | * Added space for kernel configuration in communications buffer | |
100 | * control structure. | |
101 | * [95/02/22 randys] | |
102 | * | |
103 | * Revision 1.1.3.7 1995/02/21 17:22:58 randys | |
104 | * Re-indented code to four space indentation | |
105 | * [1995/02/21 16:25:32 randys] | |
106 | * | |
107 | * Revision 1.1.3.6 1995/02/13 22:57:29 randys | |
108 | * Replaced all of NEXT_{ACQUIRE,RELEASE,PROCESS}_PTR macros with a | |
109 | * single NEXT_BUFFERLIST_PTR macro. | |
110 | * [95/02/03 randys] | |
111 | * | |
112 | * Revision 1.1.3.5 1995/01/26 21:01:44 randys | |
113 | * Add performance structure into CB. | |
114 | * [1995/01/24 21:14:31 randys] | |
115 | * | |
116 | * Added flag in epgroup structure to note that epgroup | |
117 | * has a semaphore associated with it. | |
118 | * [1995/01/19 23:02:13 randys] | |
119 | * | |
120 | * Add a space in the comm buffer header for the null_destination | |
121 | * the ME sets up for the AIL. Get rid of | |
122 | * FLIPC_ADDRESS_ENDPOINT_PTR (it isn't used) | |
123 | * [1995/01/19 20:22:30 randys] | |
124 | * | |
125 | * Up the comm buffer size to 1 megabyte | |
126 | * [1995/01/17 22:23:27 randys] | |
127 | * | |
128 | * Revision 1.1.3.4 1995/01/12 21:19:01 randys | |
129 | * Minor commenting changes from dlb | |
130 | * [1995/01/06 18:18:12 randys] | |
131 | * | |
132 | * Revision 1.1.3.3 1994/12/22 16:23:57 randys | |
133 | * Fixed calculation of number of buffers on an endpoint | |
134 | * to take size of buffer pointers into account. | |
135 | * [1994/12/21 16:19:55 randys] | |
136 | * | |
137 | * Revision 1.1.3.2 1994/12/20 19:01:56 randys | |
138 | * Moved definition of flipc_simple_lock to flipc_cb.h | |
139 | * [1994/12/20 17:34:41 randys] | |
140 | * | |
141 | * Added a simple lock in the comm buffer to use for the | |
142 | * allocations lock, along with directions as to how | |
143 | * to use it (not like a normal simple lock). | |
144 | * [1994/12/20 15:27:25 randys] | |
145 | * | |
146 | * Added error log into communications buffer control | |
147 | * structure, and changed FLIPC_ADDRESS_ENDPOINT_PTR to | |
148 | * correctly compute the endpoint pointer based on the | |
149 | * new ctl structure layout. | |
150 | * [1994/12/19 23:47:45 randys] | |
151 | * | |
152 | * Added filename in comment at top of each file | |
153 | * [1994/12/19 20:28:20 randys] | |
154 | * | |
155 | * Add version field to epgroup to check races on buffer acquire | |
156 | * from epgroup. | |
157 | * [1994/12/19 18:05:04 randys] | |
158 | * | |
159 | * Revision 1.1.3.1 1994/12/12 17:46:12 randys | |
160 | * Putting initial flipc implementation under flipc_shared | |
161 | * [1994/12/12 16:27:46 randys] | |
162 | * | |
163 | * Revision 1.1.1.2 1994/12/11 23:11:18 randys | |
164 | * Initial flipc code checkin | |
165 | * | |
166 | * $EndLog$ | |
167 | */ | |
168 | ||
169 | /* | |
170 | * mach/flipc_cb.h | |
171 | * | |
172 | * This file is intended to be the data structure layout for the flipc | |
173 | * communcations buffer, both for the KKT implementation and | |
174 | * for the eventual paragon implementation. This file should include | |
175 | * all of the information necessary for either humans or machines to | |
176 | * understand the data structure layout. | |
177 | * | |
178 | * The communications buffer is the wired section of memory used for | |
179 | * communication between the flipc applications interface layer and | |
180 | * the flipc message engine. No structure in it are visible to the | |
181 | * user; the applications interface layer mediates all user access to | |
182 | * the CB. | |
183 | */ | |
184 | ||
185 | #ifndef _MACH_FLIPC_CB_H_ | |
186 | #define _MACH_FLIPC_CB_H_ | |
187 | ||
188 | #include <mach/flipc_types.h> | |
189 | ||
190 | /* | |
191 | * Flipc naming and argument ordering conventions (this applies mainly to | |
192 | * user-interface.h, but seems inappropriate in a user-visible header file): | |
193 | * | |
194 | * All objects prefixed with "flipc"; uppercase for user-visible | |
195 | * objects, lower case for internal ones. | |
196 | * | |
197 | * Types created with typedef will have _t suffixes. | |
198 | * | |
199 | * Words will be separated by '_'. | |
200 | * | |
201 | * Macro definitions will be all in caps. | |
202 | * | |
203 | * Enum members will have their initial letter (after Flipc) capitalized. | |
204 | * | |
205 | * | |
206 | * For user-visible routines: | |
207 | * | |
208 | * The first word following the "flipc" will be the flipc object type that | |
209 | * that routine operates on (specifically "domain", "epgroup", | |
210 | * "endpoint", or "buffer"). | |
211 | * | |
212 | * The object named by the first word of the call will, if an argument | |
213 | * to the call, be the first argument. | |
214 | * | |
215 | * Output variables passed as pointers in the arglist will come last. | |
216 | */ | |
217 | ||
218 | /* | |
219 | * The kinds of objects that exist in the communications buffer are: | |
220 | * | |
221 | * Endpoints -- Used for sending or receiving. | |
222 | * Buffers -- Composed of a buffer header and buffer data. | |
223 | * Endpoint groups -- Used for collecting multiple numbers of endpoints | |
224 | * together for a select like operation. | |
225 | */ | |
226 | ||
227 | /* | |
228 | * We can't use general pointers inside the communications buffer, | |
229 | * since the address space on either side of the interface is | |
230 | * different. The places where we could use pointers are: | |
231 | * | |
232 | * *) From endpoint sets to endpoints. | |
233 | * *) From endpoints to buffers. | |
234 | * | |
235 | * The kinds of pointers we could use are: | |
236 | * *) Byte offset from the beginning of the comm buffer. This | |
237 | * is simple, but has the disadvantage of allowing the user to | |
238 | * play games with pointing endpoint buffer pointers into data | |
239 | * space, & etc. | |
240 | * *) Rigid arrays of each type of object, with the object | |
241 | * "pointer" being an index into the array. This avoids the | |
242 | * above problem, but complicates memory allocation (forces | |
243 | * allocation to be contiguous, which may force pre-deciding | |
244 | * how much space each of the above types will take). | |
245 | * | |
246 | * Though we appear to be going for the rigid allocation for each type | |
247 | * of data structure, I'm still going to do the "simple offset" | |
248 | * solution to maintain maximum flexibility into the future. | |
249 | * The single exception to this is that FLIPC addresses will be composed of | |
250 | * node number and endpoint number, where the endpoint number will be | |
251 | * the index into the endpoint array. | |
252 | */ | |
253 | ||
254 | typedef unsigned long flipc_cb_ptr; | |
255 | /* Define a null value, which doesn't point anywhere into the CB. */ | |
256 | #define FLIPC_CBPTR_NULL ((flipc_cb_ptr) -1) | |
257 | ||
258 | /* | |
259 | * Synchronization between message engine and application. | |
260 | * | |
261 | * In general, it isn't reasonable to allow locking and unlocking of | |
262 | * data structures between message engine and communications buffer, | |
263 | * as this requires the message engine to trust arbitrary user | |
264 | * threads. The solution is to arrange all data structures so that | |
265 | * they may be accessed by both parties without locking. The way that | |
266 | * this is usually done is that specific variables are considered to | |
267 | * be owned by one of the ME or the AIL, and the other party is | |
268 | * allowed to read the variable but not to modify it. With this | |
269 | * arrangement, implementing things like producer/consumer circular | |
270 | * queues is possible; each agent (ME or AIL) goes around the list | |
271 | * doing its thing, and avoids passing the pointer showing where the | |
272 | * other agent is working. | |
273 | * | |
274 | * Following the above, we may divide structure members into five | |
275 | * classes, and define prefixes for these five classes. | |
276 | * | |
277 | * Description Prefix | |
278 | * ------------------------------- | |
279 | * Private to AIL pail_ | |
280 | * Private to ME pme_ | |
281 | * AIL owned, read by ME sail_ | |
282 | * ME owned, read by AIL sme_ | |
283 | * Shared in other way shrd_ | |
284 | * | |
285 | * Shared variables may change their ownership based on their own | |
286 | * or someone elses value (these variables may be thought of as | |
287 | * being handed back and forth between the two entities) or on a | |
288 | * configuration option of the structure (not handed back and forth, | |
289 | * but still based on another variables value). | |
290 | * | |
291 | * In addition, I am going to put variables that are set at endpoint | |
292 | * allocation and cleared at deallocation (but read by both sides) in | |
293 | * a separate class; they are "AIL owned, read by ME" but are | |
294 | * effectively constant over the synchronization protocols we care | |
295 | * about. | |
296 | * | |
297 | * Constant after allocation const_ | |
298 | * | |
299 | * Note that this ignores memory consistency issues (when the two | |
300 | * agents are actually on two separate processors). These issues need | |
301 | * to be explored in more detail; for now suffice it to say that the | |
302 | * above methods work given a sequentially consistent memory model or | |
303 | * a processor consistent memory model. | |
304 | * | |
305 | * Also note that an optimizing compiler may reorder our memory | |
306 | * accesses, playing merry hell with the inter-node synchronization | |
307 | * protocols (the compiler doesn't know about the other node, after | |
308 | * all). To avoid this, all structure members used for | |
309 | * synchronization will be marked volatile; this will force the | |
310 | * compiler to keep the order and number of accesses intact. This | |
311 | * will also force the compiler *not* to optimize way accesses to | |
312 | * these variables, so it is wise to explicitly load the variable into | |
313 | * a temporary once if you need to do multiple computations with it, | |
314 | * and store it back afterwards when you are done. | |
315 | */ | |
316 | ||
317 | /* | |
318 | * Memory allocation: | |
319 | * | |
320 | * For maximum simplicity in the first implementation, we need to know | |
321 | * at comm buffer allocation time how many endpoints, endpoint_sets, | |
322 | * and buffers we will want total, until the end of time. This | |
323 | * masively simplifies memory allocation; there will be a single array | |
324 | * of each type of data and the communication buffer will be taken up | |
325 | * by the concatenation of these arrays (with some fiddling to make | |
326 | * sure that no data crosses a page boundary). | |
327 | * | |
328 | * For each data type there will be a free list to which pieces of | |
329 | * data will be added to or removed from as needed. Each data type | |
330 | * will have a pointer in it to allow it to be linked onto the free | |
331 | * list. | |
332 | */ | |
333 | ||
334 | /* | |
335 | * Multiple thread access to data structures: | |
336 | * | |
337 | * There are several points in the communications buffer (notably | |
338 | * endpoint accesses) when multiple application threads will be | |
339 | * attempting operations on data structures at the same time. To | |
340 | * multiplex these operations, we need a per-data structure lock. | |
341 | * Lock attributes: | |
342 | * *) This lock will not be kernel based, as such a lock would be | |
343 | * too heavyweight to use for arbitrary sending and receiving | |
344 | * operations). | |
345 | * *) Because it is not kernel based, it may not be used to | |
346 | * multiplex accesses from threads at different kernel | |
347 | * priority levels. Deadlock would result if a low-priority | |
348 | * thread gained the lock and then was prempted by a | |
349 | * high-priority thread that wanted to acquire it. | |
350 | * *) Architecture-dependent interfaces need to be designed to | |
351 | * atomically lock and unlock this data structure. | |
352 | * | |
353 | * These are "simple locks" and are defined in flipc_dep.h. | |
354 | */ | |
355 | ||
356 | /* | |
357 | * Lock type. This placement (in flipc_cb.h) is a little bit of a | |
358 | * hack, as it really should be defined with the machine dependent lock | |
359 | * macros. But then the machine independent lock macros have problems | |
360 | * because they have to include it both before and after the prototypes. | |
361 | * So rather than split the machine dependent stuff into multiple | |
362 | * files, I'll define it here and hope that this definition works for | |
363 | * whatever architectures we're on. | |
364 | */ | |
365 | typedef unsigned long flipc_simple_lock; | |
366 | ||
367 | /* | |
368 | * Ownership of data structures. | |
369 | * | |
370 | * Please note that this is a can of worms, and that I (Randys) | |
371 | * consider this (and it's interactions with endpoint group membership) | |
372 | * the likeliest place for design bugs in FLIPC. Any and all should | |
373 | * take this as an open invitation and challenge to find bugs in what | |
374 | * follows. | |
375 | * | |
376 | * Rules: | |
377 | * | |
378 | * *) If you've disabled a structure and synched with the | |
379 | * appropriate side of the ME, the ME won't touch it. | |
380 | * | |
381 | * *) If you've taken a send endpoint off of the send endpoint | |
382 | * list and sync'd with the ME, the ME won't touch it. | |
383 | * | |
384 | *[The rest of this applies to the AIL only; the above rules are the | |
385 | * only ones the ME respects. ] | |
386 | * | |
387 | * *) Within the AIL, a disabled structure is owned by: | |
388 | * *) The routine that disabled it, before it is put on | |
389 | * the free list. | |
390 | * *) The routine that dequeued it from the free list, | |
391 | * before it is enabled. | |
392 | * Taking of the simple lock is not required for ownership in | |
393 | * these cases. Taking of the simple lock is not required for | |
394 | * the act of *enabling* the structure (you have ownership and | |
395 | * are giving it away), however it is required for the act of | |
396 | * disabling the structure (since it is the only valid way to | |
397 | * take ownership of an enabled structure, and you can't | |
398 | * modify the enabled bit without having ownership). | |
399 | * | |
400 | * *) The simple lock in a structure always needs to be valid, as | |
401 | * simple locks may be taken while the structure is in any | |
402 | * state. Simiarly, the enabled bit must always be valid, | |
403 | * both because it's what the ME checks, and because it may be | |
404 | * checked by the AIL while the structure is free. | |
405 | * | |
406 | * *) Holding the simple lock on an enabled structure imparts | |
407 | * ownership of that structure. You are allowed to take the | |
408 | * simple lock of a disabled structure, but ownership is not | |
409 | * gained by doing so. | |
410 | * | |
411 | * *) You are allowed to read the enabled/disabled bit without | |
412 | * owning the structure (if the structure is disabled, there | |
413 | * may be no way to gain the ownership). | |
414 | * | |
415 | * *) Owning a structure allows you to do what you want with it, | |
416 | * except: | |
417 | * *) As mentioned above, the simple lock and | |
418 | * enabled/disabled bit must always be valid. | |
419 | * *) The ownership of the endpoint group related members | |
420 | * of an endpoint structure is special; see below. | |
421 | * *) The allocations lock must be held to manipulate the | |
422 | * next send endpoint field of any endpoint. | |
423 | * | |
424 | * *) If an endpoint is on an endpoint group, the ownership of | |
425 | * the the endpoint group related members of the structure | |
426 | * (sail_endpoint_group and pail_next_eg_endpoint) go with the | |
427 | * owndership of the endpoint group, not the endpoint. For | |
428 | * this purpose only, membership is defined atomically as the | |
429 | * sail_endpoint_group pointer being set to an endpoint group. | |
430 | * Thus one may remove an endpoint from an endpoint group | |
431 | * without owning the endpoint (change the sail_endpoint_group | |
432 | * pointer last). One requires both locks to add an endpoint | |
433 | * to an endpoint group, however. | |
434 | * | |
435 | * (Part of the motivation for this is that removal and | |
436 | * addition of endpoints to endpoint groups requires | |
437 | * modifications of pointers in other endpoint structures). | |
438 | * | |
439 | * *) No structure may be put on the free list if marked with any | |
440 | * association to any other structure. Specifically, endpoint | |
441 | * groups may have no endpoints belonging to them, and | |
442 | * endpoints may not belong to an endpoint group or have | |
443 | * buffers belonging to them. | |
444 | * | |
445 | * *) One consequence of the above is that endpoint groups may | |
446 | * not be marked as disabled while they have any endpoints on | |
447 | * them, as freeing an endpoint requires it to be removed from | |
448 | * its endpoint group, and if ownership of the endpoint group | |
449 | * cannot be gained, that is impossible. | |
450 | * | |
451 | * *) In theory, endpoints *may* be marked disabled while they | |
452 | * are still on endpoint groups. In practice, they are not. | |
453 | * This is relied on by the code which frees endpoint groups, | |
454 | * in a non-obvious way. Specifically, that code assumes that | |
455 | * there is no way that a call to free endpoint will return | |
456 | * with the endpoint still on the endpoint group. Since the | |
457 | * only way for free endpoint to fail is if the endpoint is | |
458 | * inactive, and since the endpoint is set inactive only after | |
459 | * free endpoint (presumably a different one) confirms that it | |
460 | * isn't on any endpoint group, this assumption is true. | |
461 | * | |
462 | * Got that? Take home lesson: don't allow endpoints to be | |
463 | * marked disabled while still on endpoint groups until you | |
464 | * *do* get that, and are willing to take the responsibility | |
465 | * of changing it so that it works under your new scheme. | |
466 | * | |
467 | * *) Ownership of the freelist(s) are gained by holding the | |
468 | * allocations lock for the buffer, and *only* in that way. | |
469 | * No modification of freelist, send endpoint list, or send | |
470 | * side ME sync bits is valid without holding the allocations | |
471 | * lock. In other words, while you can read things in the | |
472 | * main communications buffer control structure at will, you | |
473 | * may not change them without owning the allocations lock. | |
474 | * | |
475 | * *) The state where a structure is disabled but off of the | |
476 | * freelist may be valid as an intermediate (while an AIL | |
477 | * routine is orchestrating a transition) but is not a valid | |
478 | * static state. This state must not survive the return to | |
479 | * application code of the thread that disabled the structure. | |
480 | */ | |
481 | ||
482 | /* | |
483 | * Flipc data buffer management. | |
484 | * | |
485 | * A buffer (whether being used for sending or receiving) may be in | |
486 | * one of three states: | |
487 | * | |
488 | * READY -- Buffer held by application. | |
489 | * PROCESSING -- Buffer held by endpoint, unprocessed. For receive endpoints, | |
490 | * this means that the buffer is empty, waiting to be filled by | |
491 | * an incoming message. For send endpoints, this means tht the | |
492 | * buffer is full, waiting to be sent out. | |
493 | * COMPLETED -- Buffer held by the endpoint, processed. For receive | |
494 | * endpoints, this means that the buffer is full, with newly | |
495 | * received data in it. For send endpoints, this means that the | |
496 | * buffer is empty (*), with it's data having been sent out. | |
497 | * | |
498 | * (*) In point of fact the data hasn't been touched, though bits | |
499 | * may have been fiddled with in the header data structure. But | |
500 | * it's been sent. | |
501 | * FREE -- The buffer is in the pool of free buffers, and may be | |
502 | * allocated to any newly created endpoint. | |
503 | * | |
504 | * The transition diagram between these states is relatively simple: | |
505 | * | |
506 | * | |
507 | * release | |
508 | * /-----------------\| | |
509 | * +----------+ -+----------+ | |
510 | * | READY | |PROCESSING|<- - - - - - | |
511 | * +----------+_ +----------+ \ | |
512 | * ^ |\ - - - - - - - - / | | \endpoint allocate | |
513 | * | (processed) \endpoint \ | |
514 | * | | \ free | | |
515 | * | acquire / ------\ | |
516 | * | \ | | |
517 | * | / (processed) >+----------+ | |
518 | * +----------+ | FREE | | |
519 | * |COMPLETED |< - - - - - - - - - - +----------+ | |
520 | * +----------+ endpoint allocate / ^ | |
521 | * | ^- - - - - - - - - - - - - - - - - - - - - - - | | |
522 | * | / | |
523 | * \ endpoint free / | |
524 | * ------------------------------------------------------/ | |
525 | * | |
526 | * (If it doesn't look simple, imagine it without the FREE state; that | |
527 | * state doesn't enter into almost any buffer manipulations) | |
528 | * | |
529 | * For send buffers, release==send, acquire==allocate, and | |
530 | * processed==the sending done by the message engine. For receive buffers, | |
531 | * release==release, acquire==receive, and process==the actual | |
532 | * arrival of the message handled by the messaging engine. | |
533 | * | |
534 | * The choice of path from the PROCESSING state is an endpoint | |
535 | * specific configuration option; a particular endpoint may leave a | |
536 | * processed buffer on the endpoint, or it may release it back to the | |
537 | * application by dropping it from the endpoint. | |
538 | * | |
539 | * Buffers are assigned the PROCESSING state on a newly allocated | |
540 | * receive endpoint (to be ready to receive messages) and the | |
541 | * COMPLETED state on a newly allocated send endpoint. | |
542 | * | |
543 | * The state (other than FREE) that a particular buffer is in is | |
544 | * determined by its place on a circular queue of buffer pointers that | |
545 | * is part of the endpoint structure. Buffers owned by the | |
546 | * application (READY) are not pointed to by pointers on this queue. | |
547 | * The buffer is released to the message engine by placement of a | |
548 | * pointer to it on this queue. When the message engine is done | |
549 | * processing the buffer, it sets a flag in the buffer header. If the | |
550 | * endpoint is so configured, it then removes the buffer pointer from | |
551 | * the queue; otherwise the AIL acquires the buffer (and removes the | |
552 | * pointer from the queue) when it chooses. | |
553 | * | |
554 | * . . . . . . | |
555 | * . . | |
556 | * . . | |
557 | * . . AIL releasing | |
558 | * . . ^ | |
559 | * . +-------+--/ | |
560 | * . | | | |
561 | * . |Buffers| | |
562 | * . | to be | | |
563 | * . |Sent or| | |
564 | * . |Receivd| | |
565 | * . | Into | ^ ME processing | |
566 | * . +-------+ --/ | |
567 | * . | | | |
568 | * . AIL | Sent | (These buffers have a flag set to indicate | |
569 | * .Acquiring| or | that they have been processed. This | |
570 | * . |Filled | section is optional; the endpoint may be | |
571 | * . |buffers| configured to drop buffers after processing) | |
572 | * . ^ | | | |
573 | * . \--+-------+ | |
574 | * . . | |
575 | * . . | |
576 | * . . . . . . | |
577 | * | |
578 | * | |
579 | * The AIL will refuse to acquire a buffer that has not yet been | |
580 | * processed by the ME. Acquire will not work at all on endpoints | |
581 | * that have been configured to drop buffers on completion. | |
582 | * | |
583 | * The buffer_available primitive is coded to avoid doing a | |
584 | * (potentially costly) acquiring of the endpoint flipc lock. Since | |
585 | * telling where there is a buffer available requires two operations | |
586 | * (comparison of the acquire and release pointers to see if there are | |
587 | * any buffers on the endpoint, and then indirection of the acquire | |
588 | * pointer to see if that buffer has bee processed yet), there is a | |
589 | * potential race that will admit the possibility of indirecting | |
590 | * through an invalid pointer. For this reason, for the life of an | |
591 | * endpoint, it is a requirement that all buffer pointers on the | |
592 | * bufferlist point *somewhere* (ie. to some existing buffer), so that | |
593 | * this indirection will not cause an access error. The | |
594 | * buffer_available primitive may return the wrong result, but (as | |
595 | * long as the incorrectness is transitory), this is acceptable. | |
596 | */ | |
597 | ||
598 | /* Set up the states so that FLIPC_buffer_processed can just do an | |
599 | & and a test. */ | |
600 | typedef enum { | |
601 | flipc_Free = 0x0, flipc_Processing = 0x1, | |
602 | flipc_Completed = 0x2, flipc_Ready = 0x3 | |
603 | } flipc_buffer_state_t; | |
604 | #define FLIPC_BUFFER_PROCESSED_P(state) ((state) & 0x2) | |
605 | ||
606 | /* | |
607 | * Data header/buffer layout. | |
608 | * | |
609 | * For this implementation, and probably for all time, the header | |
610 | * immediately precedes the data in memory, and the mesaging engine | |
611 | * will send both header and data. Our priority is message dispatch | |
612 | * speed rather than raw bandwidth (this is the small message side of | |
613 | * a transfer mechanism), so we don't mind that we are throwing away | |
614 | * some bandwidth by taking up transferred space with header data. | |
615 | * | |
616 | * The data size will be the maximum size allowed by the underlying | |
617 | * transport, minus the header size (available at run time). The user | |
618 | * will be given a pointer to the data buffer, and will use this both | |
619 | * for copying data in and out, and as an argument to the underlying | |
620 | * flipc routines. The flipc routines will access appropriately. | |
621 | * | |
622 | * The header structure follows; the user data type will be offset and | |
623 | * cast appropriately to access this. | |
624 | */ | |
625 | ||
626 | typedef struct flipc_data_buffer { | |
627 | union { | |
628 | FLIPC_address_t destination; /* For sending. */ | |
629 | flipc_cb_ptr free; /* Link for header free list. */ | |
630 | } u; | |
631 | ||
632 | /* ME owned if flipc_Processing, AIL owned otherwise. May not ever | |
633 | assume the state flipc_Ready in an optimized implementation. */ | |
634 | volatile flipc_buffer_state_t shrd_state; | |
635 | } *flipc_data_buffer_t; | |
636 | ||
637 | /* | |
638 | * Endpoint structure. | |
639 | * | |
640 | * An endpoint is the data structure used for communicating buffers, | |
641 | * either send or receive. Note that all actual circular lists of | |
642 | * buffer pointers on the endpoints are in their own array that gets | |
643 | * partitioned out to the various endpoints. This is because we want | |
644 | * the endpoint structures themselves to be fixed size for easy | |
645 | * indexing upon receit of a message. This large scale array will be | |
646 | * of size (max_buffers_per_endpoint) * (number_of_endpoints). Both | |
647 | * of these values are set during the domain initialization call. | |
648 | * | |
649 | * Note that the pointers contained in the buffer lists are pointers to | |
650 | * buffer *headers*, not to the data. | |
651 | */ | |
652 | ||
653 | /* | |
654 | * This structure is divided into four cache lines, separated by their | |
655 | * usage type: | |
656 | * | |
657 | * *) Private data that the AIL scribbles on. | |
658 | * *) Data the AIL writes (regularly) that the ME reads | |
659 | * (occaisionally). The canonical example is the release pointer. | |
660 | * *) Private data that the ME scribbles on. | |
661 | * *) Data the ME writes (regularly) that the AIL reads (occaisionally). | |
662 | * The canonical example is the process pointer. | |
663 | * | |
664 | * There are a couple of other categories of stuff, that can be shoehorned | |
665 | * into the above: | |
666 | * *) Constant data that both sides read regularly. This can be | |
667 | * duplicated in the two private areas (actually, it can be | |
668 | * duplicated in any two areas that stay in the cache of the | |
669 | * respective processors). | |
670 | * *) Stuff that is not accessed on the critical path; it can go | |
671 | * almost anywhere (probably in one of the two ping-ponging | |
672 | * cache lines). | |
673 | * *) Stuff that is read-only for a single processor goes in that | |
674 | * processors private data section. | |
675 | * | |
676 | * Duplicate entries have a "p" or a "a" suffixed to the name to | |
677 | * indicate that fact. Note that these will usually, but not always, | |
678 | * be "const" variables--they may be "const" variables only from the | |
679 | * critical path viewpoint. | |
680 | * | |
681 | * We take cache line length as being 8 * sizeof(int). | |
682 | */ | |
683 | ||
684 | typedef struct flipc_endpoint { | |
685 | ||
686 | /* ===Private AIL data=== */ | |
687 | /* Type of endpoint (send, recv, etc). Duplicated in private | |
688 | ME section. */ | |
689 | FLIPC_endpoint_type_t constda_type; | |
690 | ||
691 | /* This next value is two variables squeezed into a single word to | |
692 | * save on memory accesses (since they are almost always read at | |
693 | * the same time. The two variables are: | |
694 | * | |
695 | * const_drop_processed_buffers -- Should the message engine drop | |
696 | * buffers after processing them (as opposed to leaving them on | |
697 | * the endpoint)? | |
698 | * | |
699 | * sail_enabled (volatile) -- Is the endpoint enabled? This isn't | |
700 | * marked constant because it is used for synchronization on | |
701 | * endpoint deallocation. | |
702 | * | |
703 | * Note that to reduce test and branches, we these two variables | |
704 | * are represented by two bits in the word (bit 0 and bit 16). It | |
705 | * is illegal to have bits other than 0 and 16 set in this word. | |
706 | * This assumption is used in ENABLED_AND_NOT_DPB_P, and is enforced | |
707 | * in DOE_CONSTRUCT (assumed to not be performance critical) below. | |
708 | * | |
709 | * Duplicated in private ME section. | |
710 | */ | |
711 | ||
712 | volatile unsigned long sailda_dpb_or_enabled; | |
713 | ||
714 | #define EXTRACT_DPB(dpb_or_enabled) ((dpb_or_enabled) >> 16) | |
715 | #define EXTRACT_ENABLED(dpb_or_enabled) ((dpb_or_enabled) & 0xffff) | |
716 | #define DISABLED_OR_DPB_P(dpb_or_enabled) ((dpb_or_enabled) ^ 0x1) | |
717 | #define DOE_CONSTRUCT(dpb, enabled) \ | |
718 | (((dpb) ? 0x10000 : 0) | ((enabled) ? 0x1 : 0)) | |
719 | ||
720 | flipc_simple_lock pail_lock; /* Simple lock for serializing | |
721 | multiple thread access to | |
722 | structure. AIL owned. */ | |
723 | /* First element in buffer list array that is ours. Constant | |
724 | from communications buffer initialization. */ | |
725 | flipc_cb_ptr constda_my_buffer_list; | |
726 | /* First element after my_buffer_list that is *not* in my buffer | |
727 | list. Constant from communications buffer initialization. */ | |
728 | flipc_cb_ptr constda_next_buffer_list; | |
729 | ||
730 | /* First location that has a valid buffer pointer in it. This may | |
731 | contain a pointer to a buffer available for acquisition, or it | |
732 | may contain a pointer to a buffer that is still being | |
733 | processed; the buffer header or process_ptr needs to be checked | |
734 | to be sure. This location is AIL owned. It is ignored by all | |
735 | (including the ME and initialization code) if | |
736 | drop_processed_buffers, above, is set. */ | |
737 | volatile flipc_cb_ptr shrd_acquire_ptr; | |
738 | ||
739 | /* AIL private copy of process pointer. This hopefully means that | |
740 | the AIL won't need to read the real process pointer (and fault | |
741 | in a cache line) very often. */ | |
742 | flipc_cb_ptr pail_process_ptr; | |
743 | ||
744 | unsigned int pad_pail_7; | |
745 | ||
746 | /* ===End of cache line===*/ | |
747 | /* ===AIL writes, ME occaisionally reads=== */ | |
748 | ||
749 | /* Next location at which the AIL may insert a buffer pointer. */ | |
750 | volatile flipc_cb_ptr sail_release_ptr; | |
751 | unsigned int pad_sail_1; | |
752 | unsigned int pad_sail_2; | |
753 | unsigned int pad_sail_3; | |
754 | unsigned int pad_sail_4; | |
755 | unsigned int pad_sail_5; | |
756 | unsigned int pad_sail_6; | |
757 | unsigned int pad_sail_7; | |
758 | ||
759 | /* ===End of cache line===*/ | |
760 | /* ===Private ME data=== */ | |
761 | /* See above comments (in private ail section). */ | |
762 | ||
763 | FLIPC_endpoint_type_t constdm_type; | |
764 | volatile unsigned long saildm_dpb_or_enabled; | |
765 | ||
766 | volatile unsigned long sme_overruns; /* For a receive endpoint, counter for | |
767 | the number of messages that have | |
768 | arrived when there hasn't been | |
769 | space. ME owned. */ | |
770 | unsigned long pail_overruns_seen; /* A count of the number of overruns | |
771 | that the AIL has noted and doesn't | |
772 | want to be bothered with again. | |
773 | The user only sees the difference | |
774 | between the previous count and this. */ | |
775 | ||
776 | /* | |
777 | * For send endpoints; linked into a list that is used by the ME | |
778 | * to find stuff to do. Also used for endpoint free list. | |
779 | * Null if at end of list. Not "const" because it's used as a | |
780 | * synchronization variable during setup and teardown | |
781 | * of send endpoints. | |
782 | */ | |
783 | volatile flipc_cb_ptr sail_next_send_endpoint; | |
784 | ||
785 | /* Constant buffer lsit pointers for ME. See private ail comments. */ | |
786 | flipc_cb_ptr constdm_my_buffer_list; | |
787 | flipc_cb_ptr constdm_next_buffer_list; | |
788 | ||
789 | /* Private ME copy of release pointer. This hopefully means that | |
790 | the ME won't have to read (and fault in a cache line) the | |
791 | release pointer very often. */ | |
792 | ||
793 | flipc_cb_ptr pme_release_ptr; | |
794 | /* ===End of cache line===*/ | |
795 | ||
796 | /* ===ME writes, AIL occaisionally reads=== */ | |
797 | /* | |
798 | * For endpoint group membership. | |
799 | */ | |
800 | flipc_cb_ptr pail_next_eg_endpoint; /* Next endpoint in endpoint group. | |
801 | AIL owned. */ | |
802 | flipc_cb_ptr sail_epgroup; /* Direct pointer to endpoint group that | |
803 | we are part of. FLIPC_CBPTR_NULL | |
804 | if none. AIL owned. */ | |
805 | ||
806 | /* First location that has a buffer pointer available for | |
807 | processing. If this value is equal to the release_ptr there are no | |
808 | buffers available for processing. */ | |
809 | volatile flipc_cb_ptr sme_process_ptr; | |
810 | unsigned int pad_sme_3; | |
811 | unsigned int pad_sme_4; | |
812 | unsigned int pad_sme_5; | |
813 | unsigned int pad_sme_6; | |
814 | unsigned int pad_sme_7; | |
815 | ||
816 | /* ===End of cache line===*/ | |
817 | /* ===END=== */ | |
818 | ||
819 | /* The following macros may have possible performance loss in | |
820 | multiple accesses (or indirection, but a good compiler will get | |
821 | around that). We need to have versions for each processor so | |
822 | that the constant reads are done from the right copy. */ | |
823 | ||
824 | /* General bufferlist pointer increment macro, with versions | |
825 | for ME and AIL. */ | |
826 | ||
827 | #define NEXT_BUFFERLIST_PTR(bufferlist_ptr, endpoint, suf) \ | |
828 | (((bufferlist_ptr) + sizeof(flipc_data_buffer_t) \ | |
829 | == ((endpoint)->const ## suf ## _next_buffer_list)) ? \ | |
830 | ((endpoint)->const ## suf ## _my_buffer_list) : \ | |
831 | (bufferlist_ptr) + sizeof(flipc_data_buffer_t)) | |
832 | #define NEXT_BUFFERLIST_PTR_ME(bufferlist_ptr, endpoint) \ | |
833 | NEXT_BUFFERLIST_PTR(bufferlist_ptr, endpoint, dm) | |
834 | #define NEXT_BUFFERLIST_PTR_AIL(bufferlist_ptr, endpoint) \ | |
835 | NEXT_BUFFERLIST_PTR(bufferlist_ptr, endpoint, da) | |
836 | ||
837 | /* Macros for each of "can I release onto this buffer?" "Can I | |
838 | acquire from this buffer?" and "Can I process an element on | |
839 | this buffer?" The first two presume they are being executed on | |
840 | the main procesor, the third on the co-processor. | |
841 | All have three arguments: | |
842 | *) A variable which will be set to the release, acquire, or | |
843 | process pointer after the macro *if* the operation is ok. | |
844 | *) A temporary variable used inside the function. | |
845 | *) The endpoint. | |
846 | ||
847 | We presume the acquire macro won't be called if drop processed | |
848 | buffers is enabled; the process and release macros deal | |
849 | appropriately with that issue. */ | |
850 | ||
851 | /* In general these macros will: | |
852 | *) Not read a volatile structure member more than once. | |
853 | *) If a variables owner is the other processor, these macros | |
854 | will check a local copy of the variable first before checking | |
855 | the other processors. | |
856 | *) Will only update the local copy if the remote copy really is | |
857 | different from the local one. | |
858 | */ | |
859 | ||
860 | /* This macro implements the synchronization check; local cbptr is | |
861 | the pointer owned by the local processor which we want to compare | |
862 | with a pointer on the remote processor which we have a copy | |
863 | of locally. Reads the remote pointer zero or one times; other | |
864 | reads are as necessary. | |
865 | ||
866 | The algorithm is: | |
867 | *) If the local copy says our pointer and the remote value aren't equal, | |
868 | we're done. | |
869 | *) Otherwise, check the remote copy. If it says the values aren't | |
870 | equal, update the local copy. */ | |
871 | ||
872 | #define ENDPOINT_SYNCNE_CHECK(local_cbptr, copy_rmt_cbptr, \ | |
873 | rmt_cbptr, tmp_cbptr) \ | |
874 | ((local_cbptr) != (copy_rmt_cbptr) \ | |
875 | || ((((tmp_cbptr) = (rmt_cbptr)) != (local_cbptr)) \ | |
876 | && (((copy_rmt_cbptr) = (tmp_cbptr)), 1))) | |
877 | ||
878 | #define ENDPOINT_ACQUIRE_OK(acquire_cbptr, tmp_cbptr, endpoint) \ | |
879 | ((acquire_cbptr) = (endpoint)->shrd_acquire_ptr, \ | |
880 | ENDPOINT_SYNCNE_CHECK(acquire_cbptr, (endpoint)->pail_process_ptr, \ | |
881 | (endpoint)->sme_process_ptr, tmp_cbptr)) | |
882 | ||
883 | #define ENDPOINT_PROCESS_OK(process_cbptr, tmp_cbptr, endpoint) \ | |
884 | ((process_cbptr) = (endpoint)->sme_process_ptr, \ | |
885 | ENDPOINT_SYNCNE_CHECK(process_cbptr, (endpoint)->pme_release_ptr, \ | |
886 | (endpoint)->sail_release_ptr, tmp_cbptr)) | |
887 | ||
888 | #define NODPB_ENDPOINT_RELEASE_OK(release_cbptr, tmp_cbptr, endpoint) \ | |
889 | ((release_cbptr) = (endpoint)->sail_release_ptr, \ | |
890 | (tmp_cbptr) = (endpoint)->shrd_acquire_ptr, \ | |
891 | (NEXT_BUFFERLIST_PTR_AIL(release_cbptr, endpoint) \ | |
892 | != (tmp_cbptr))) | |
893 | ||
894 | /* Don't use NEXT_BUFFERLIST_PTR here to save a temporary variable. */ | |
895 | #define DPB_ENDPOINT_RELEASE_OK(release_cbptr, tmp_cbptr, endpoint) \ | |
896 | (release_cbptr = (endpoint)->sail_release_ptr, \ | |
897 | ((release_cbptr + sizeof(flipc_data_buffer_t) == \ | |
898 | (endpoint)->constda_next_buffer_list) \ | |
899 | ? ENDPOINT_SYNCNE_CHECK((endpoint)->constda_my_buffer_list, \ | |
900 | (endpoint)->pail_process_ptr, \ | |
901 | (endpoint)->sme_process_ptr, \ | |
902 | tmp_cbptr) \ | |
903 | : ENDPOINT_SYNCNE_CHECK(release_cbptr + sizeof(flipc_data_buffer_t), \ | |
904 | (endpoint)->pail_process_ptr, \ | |
905 | (endpoint)->sme_process_ptr, \ | |
906 | tmp_cbptr))) | |
907 | ||
908 | /* This next is tricky; remember that acquire_ptr points | |
909 | to an actual bufferptr on the list, whereas release_ptr does | |
910 | not. This macro is only used in FLIPC_endpoint_query, and so | |
911 | doesn't need to have an ME version. */ | |
912 | ||
913 | #define BUFFERS_ON_ENDPOINT_AIL(acquire_ptr, release_ptr, endpoint) \ | |
914 | ((release_ptr) > (acquire_ptr) \ | |
915 | ? ((release_ptr) - (acquire_ptr)) / sizeof(flipc_cb_ptr) \ | |
916 | : ((((release_ptr) - (endpoint)->constda_my_buffer_list) \ | |
917 | + ((endpoint)->constda_next_buffer_list - acquire_ptr)) \ | |
918 | / sizeof(flipc_cb_ptr))) | |
919 | } *flipc_endpoint_t; | |
920 | ||
921 | ||
922 | /* | |
923 | * Endpoint groups. | |
924 | * | |
925 | * Used to represent a group of endpoints, for linking sending/receiving | |
926 | * with semaphores & etc. Note that there needs to be a private data | |
927 | * structure kept by the kernel that associates with each epgroup | |
928 | * a semaphore to be used for wakeups on that endpoint set. | |
929 | */ | |
930 | ||
931 | typedef struct flipc_epgroup { | |
932 | flipc_simple_lock pail_lock; /* Lock to synchronize threads (at the | |
933 | same priority level) accessing this | |
934 | structure. */ | |
935 | volatile unsigned long sail_enabled; /* Set if structure is active. */ | |
936 | unsigned long const_semaphore_associated; /* Flag to indicate whether or not | |
937 | there is a semaphore associated | |
938 | with this endpoint group in the | |
939 | kernel flipc routines. */ | |
940 | volatile unsigned long sail_wakeup_req; /* Incremented when a thread wants to | |
941 | be woken. */ | |
942 | volatile unsigned long pme_wakeup_del; /* Incremented when the ME delivers a | |
943 | wakeup. */ | |
944 | unsigned long pail_version; /* Incremented when epgroup membership | |
945 | is changed; checked when retrieving | |
946 | a buffer from an epgroup. */ | |
947 | unsigned long sail_msgs_per_wakeup; /* How many messages need to arrive | |
948 | before the ME delivers a wakeup. */ | |
949 | unsigned long pme_msgs_since_wakeup; /* How many messages have arrived | |
950 | since the last wakeup. ME | |
951 | owned. */ | |
952 | ||
953 | flipc_cb_ptr pail_first_endpoint; /* First endpoint in the group. The | |
954 | other endpoints are linked along | |
955 | behind him. AIL owned. */ | |
956 | flipc_cb_ptr pail_free; /* Used to link this endpoint onto | |
957 | the freelist. */ | |
958 | } *flipc_epgroup_t; | |
959 | ||
960 | /* | |
961 | * Communication buffer control structure. | |
962 | * | |
963 | * This is in the communications buffer itself. Note that any changes | |
964 | * in this structure require it to be locked with the allocation lock, | |
965 | * as access to this structure is shared by all threads using the CB. | |
966 | */ | |
967 | ||
968 | /* | |
969 | * Individual data type layout. | |
970 | * | |
971 | * All we need here is a pointer to the start of each type of data | |
972 | * struct, the number of those data structures in the communications | |
973 | * buffer, and a pointer to the beginning of the freelist for that data | |
974 | * structure. | |
975 | * | |
976 | * Note that the composite buffer list doesn't have a freelist associated | |
977 | * with it, since each section of the buffer list is tightly bound to an | |
978 | * endpoint, and is allocated and freed with that endpoint. We still | |
979 | * need the start and number information, though. | |
980 | */ | |
981 | struct flipc_cb_type_ctl { | |
982 | flipc_cb_ptr start; /* Where there array of this type of | |
983 | data structure starts. */ | |
984 | unsigned long number; /* How many of them we've got. */ | |
985 | flipc_cb_ptr free; /* Where the beginning of the freelist | |
986 | is. */ | |
987 | }; | |
988 | ||
989 | /* | |
990 | * Synchronization with message engine. | |
991 | * | |
992 | * At certain times (specifically during structure allocation/free or | |
993 | * additions to the send list) you want to know that the messaging | |
994 | * engine has picked up your changes. However, the message engine has | |
995 | * (effectively) two threads, one for each of the send and receive | |
996 | * sides. The mechanisms used for synchronizations with the two sides | |
997 | * differ. In an eventual co-processor implementation (with a single | |
998 | * thread), only the send side mechanism will be used. | |
999 | * | |
1000 | * To request a cached state flush by the send side of the mesasging | |
1001 | * engine, you flip the request_sync bit and it responds by flipping | |
1002 | * the response_sync bit. The send ME checks this bit once every trip | |
1003 | * through the send endpoints. | |
1004 | * | |
1005 | * On the receive side, since receives take very little time and do | |
1006 | * not block (unlike sends) when we want to make sure the ME is | |
1007 | * holding no cached receive side state, we simply spin until we see | |
1008 | * that the ME receive side is no longer operating. It sets a | |
1009 | * variable whenever it is in the process of receiving a message. | |
1010 | */ | |
1011 | ||
1012 | /* | |
1013 | * Proper manipulation of the send endpoint list. | |
1014 | * | |
1015 | * Note that synchronizing with the message engine over access to the | |
1016 | * send endpoint list is especially tricky. There is no problem with | |
1017 | * writing new values in all of the locations required to take a send | |
1018 | * endpoint off of the list. However, we must be very sure before | |
1019 | * modifying the pointer *in* the send endpoint that the ME isn't | |
1020 | * currently working in that send endpoint (else it could be sent off | |
1021 | * into the void). Two options here: | |
1022 | * | |
1023 | * *) Synchronize (using the below variables) for each send | |
1024 | * endpoint removed, after the removal but before the | |
1025 | * modification of the data in the internal structure. | |
1026 | * *) If we can always be sure that the send endpoint link in the | |
1027 | * endpoint structure has a valid value, we can simply let the | |
1028 | * chips fall where they may. It will be null while free, and | |
1029 | * have a value that points back into the send buffer list | |
1030 | * when reallocated. I'm not going to do this; it's sleezy | |
1031 | * and will partially mess up fairness based on ME send | |
1032 | * endpoint round-robinning. | |
1033 | */ | |
1034 | ||
1035 | /* | |
1036 | * This entire structure is protected by an kernel level lock so there | |
1037 | * is no conflict between threads accessing it. See flipc_kfr.c for | |
1038 | * details on this lock; how it is implemented and used depends on what | |
1039 | * kernel base we are on. | |
1040 | */ | |
1041 | ||
1042 | /* | |
1043 | * Note that the last element of this structure is variable sized, so this | |
1044 | * structure itself is also variable sized. | |
1045 | */ | |
1046 | typedef struct flipc_comm_buffer_ctl { | |
1047 | /* Kernel flipc configuration that the user must match in order to | |
1048 | work with this kernel. Checked as soon as the comm buffer is | |
1049 | mapped. */ | |
1050 | struct { | |
1051 | unsigned int real_time_primitives:1; | |
1052 | unsigned int message_engine_in_kernel:1; | |
1053 | unsigned int no_bus_locking:1; /* One way check -- if the kernel doesn't | |
1054 | have this and the user does, that's | |
1055 | an error. */ | |
1056 | } kernel_configuration; | |
1057 | volatile unsigned long send_ready; /* A send(s) is ready to go */ | |
1058 | ||
1059 | /* These first three structures are constant after communications buffer | |
1060 | initialization. */ | |
1061 | unsigned long data_buffer_size; /* Size of the data buffers. */ | |
1062 | unsigned long local_node_address; /* Local node number. */ | |
1063 | FLIPC_address_t null_destination; /* Local null destination value. */ | |
1064 | ||
1065 | #if REAL_TIME_PRIMITIVES | |
1066 | /* The scheduling policy used by the task initializing flipc for | |
1067 | the allocations lock. */ | |
1068 | int allocations_lock_policy; | |
1069 | #else | |
1070 | /* A poor substitute for a kernel level allocations lock. | |
1071 | Note that this *cannot* be used as a regular simple lock; | |
1072 | instead, try to acquire it, call sleep(1), try again, etc. | |
1073 | Spinning on this lock will probably waste lots of cycles. */ | |
1074 | flipc_simple_lock pail_alloc_lock; | |
1075 | #endif | |
1076 | ||
1077 | /* All of the members of these structures except for the free pointer | |
1078 | are constant after initialization. The free pointer is ail owned | |
1079 | and private. */ | |
1080 | struct flipc_cb_type_ctl endpoint; | |
1081 | struct flipc_cb_type_ctl epgroup; | |
1082 | struct flipc_cb_type_ctl bufferlist; | |
1083 | struct flipc_cb_type_ctl data_buffer; | |
1084 | ||
1085 | /* Global synchronization with the message engine. On the KKT | |
1086 | implementation we need one synchronizer for each thread. */ | |
1087 | ||
1088 | /* Send side: */ | |
1089 | volatile unsigned long sail_request_sync; /* request_sync = !request_sync when the | |
1090 | AIL wants to synchronize with the | |
1091 | CB. */ | |
1092 | volatile unsigned long sme_respond_sync; /* respond_sync = !respond_sync when | |
1093 | the ME has noticed the sync | |
1094 | request. By responding to the | |
1095 | sync, the ME is stating that it has | |
1096 | no communications buffer state that | |
1097 | was cached previous to it noticing | |
1098 | the sync. */ | |
1099 | ||
1100 | /* Receive side. */ | |
1101 | volatile unsigned long sme_receive_in_progress; /* Set by the ME before it looks at | |
1102 | any data structures; cleared | |
1103 | afterwards. A simple spin in | |
1104 | the user space on this | |
1105 | variable will suffice, as the | |
1106 | time that the message | |
1107 | engine could be receiving | |
1108 | is low. */ | |
1109 | ||
1110 | /* Send endpoint list starts here. */ | |
1111 | volatile flipc_cb_ptr sail_send_endpoint_list; /* Null if no send endpoints. | |
1112 | */ | |
1113 | ||
1114 | /* Keep track of whatever performance information we choose. */ | |
1115 | struct FLIPC_domain_performance_info performance; | |
1116 | ||
1117 | /* Keep track of various kinds of error information here. */ | |
1118 | struct FLIPC_domain_errors sme_error_log; | |
1119 | ||
1120 | } *flipc_comm_buffer_ctl_t; | |
1121 | ||
1122 | ||
1123 | /* | |
1124 | * The communications buffer. | |
1125 | * | |
1126 | * The only restriction on the layout of the communications buffer is | |
1127 | * that the buffers themselves may not cross page boundaries. So we | |
1128 | * will place the data buffers at the end of the communications | |
1129 | * buffer, and the other objects at the beginning, and there may be a | |
1130 | * little bit of extra space in the middle. | |
1131 | * | |
1132 | * Note that this layout may change in future versions of FLIPC. | |
1133 | * | |
1134 | * +---------------------------+ | |
1135 | * | flipc_comm_buffer_ctl | | |
1136 | * +---------------------------+ | |
1137 | * | | | |
1138 | * | Endpoints | | |
1139 | * | | | |
1140 | * +---------------------------+ | |
1141 | * | | | |
1142 | * | Endpoint Groups | | |
1143 | * | | | |
1144 | * +---------------------------+ | |
1145 | * | | | |
1146 | * | Combined Buffer Lists | | |
1147 | * | | | |
1148 | * +---------------------------+ | |
1149 | * | | | |
1150 | * | (Possible empty space) | | |
1151 | * | | | |
1152 | * +---------------------------+ | |
1153 | * | | | |
1154 | * | Data Buffers | | |
1155 | * | | | |
1156 | * +---------------------------+ | |
1157 | */ | |
1158 | ||
1159 | /* The number of pages that the kernel will reserve for the comm | |
1160 | buffer. The AIL needs to know this to know how much to map. */ | |
1161 | #define COMM_BUFFER_SIZE 0x100000 | |
1162 | ||
1163 | /* | |
1164 | * These variables are set, in a per-address space context, to the base | |
1165 | * and length of the communications buffer. The ME needs to do bounds | |
1166 | * checking to make sure it isn't overrunning anything. Note that the | |
1167 | * existence of these variables implies that an application will only | |
1168 | * open a single domain. | |
1169 | * | |
1170 | * These declarations are duplicated in flipc/flipc_usermsg.h, and | |
1171 | * should be kept in sync with that file. | |
1172 | */ | |
1173 | unsigned char *flipc_cb_base; | |
1174 | unsigned long flipc_cb_length; /* In bytes. */ | |
1175 | ||
1176 | /* | |
1177 | * Following is a set of macros to convert back and forth between | |
1178 | * real address pointers and flipc_cb_ptr's for each data type. They | |
1179 | * rely on the flipc_cb_base being set correctly. | |
1180 | * | |
1181 | * A possible future improvement might be to have bounds checking occur | |
1182 | * inside these macros, but I'm not sure what I'd do if it failed. | |
1183 | */ | |
1184 | ||
1185 | /* Easy going one way. */ | |
1186 | #define FLIPC_CBPTR(ptr) \ | |
1187 | (((unsigned char *) (ptr)) - flipc_cb_base) | |
1188 | ||
1189 | /* Need to get the right types going the other way. */ | |
1190 | #define FLIPC_ENDPOINT_PTR(cb_ptr) \ | |
1191 | ((flipc_endpoint_t) ((cb_ptr) + flipc_cb_base)) | |
1192 | #define FLIPC_EPGROUP_PTR(cb_ptr) \ | |
1193 | ((flipc_epgroup_t) ((cb_ptr) + flipc_cb_base)) | |
1194 | #define FLIPC_DATA_BUFFER_PTR(cb_ptr) \ | |
1195 | ((flipc_data_buffer_t) ((cb_ptr) + flipc_cb_base)) | |
1196 | #define FLIPC_BUFFERLIST_PTR(cb_ptr) \ | |
1197 | ((flipc_cb_ptr *) ((cb_ptr) + flipc_cb_base)) | |
1198 | ||
1199 | ||
1200 | /* | |
1201 | * Flipc addresses. | |
1202 | * | |
1203 | * The addresses used by flipc for communication are defined in the | |
1204 | * user visible header file as unsigned longs. These macros pull that | |
1205 | * information apart for use of the FLIPC internal routines. | |
1206 | * | |
1207 | * I assume in the following that endpoints immediately follow the | |
1208 | * comm buffer control structure, because that makes indexing into | |
1209 | * them much easier. | |
1210 | */ | |
1211 | ||
1212 | #define FLIPC_CREATE_ADDRESS(node, endpoint_idx) \ | |
1213 | ((node << 16) | (endpoint_idx)) | |
1214 | #define FLIPC_ADDRESS_NODE(addr) (((unsigned long) (addr)) >> 16) | |
1215 | #define FLIPC_ADDRESS_ENDPOINT(addr) (((unsigned long) (addr)) & 0xffff) | |
1216 | ||
1217 | #endif /* _MACH_FLIPC_CB_H_ */ |