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