|
|
1.1 root 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_ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.