Merge from vendor branch AWK:
[dragonfly.git] / sys / sys / syslink_msg2.h
1 /*
2  * Copyright (c) 2004-2006 The DragonFly Project.  All rights reserved.
3  * 
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@backplane.com>
6  * 
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  * 
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  * $DragonFly: src/sys/sys/syslink_msg2.h,v 1.1 2006/08/08 01:27:14 dillon Exp $
35  */
36 /*
37  * The syslink infrastructure implements an optimized RPC mechanism across a 
38  * communications link.  RPC functions are grouped together into larger
39  * protocols.  Prototypes are typically associated with system structures
40  * but do not have to be.
41  *
42  * syslink      - Implements a communications end-point and protocol.  A
43  *                syslink is typically directly embedded in a related
44  *                structure.
45  *
46  * syslink_proto- Specifies a set of RPC functions.
47  *
48  * syslink_desc - Specifies a single RPC function within a protocol.
49  */
50
51 #ifndef _SYS_SYSLINK2_H_
52 #define _SYS_SYSLINK2_H_
53
54 #ifndef _SYS_SYSLINK_H_
55 #include <sys/syslink.h>
56 #endif
57 #ifndef _MACHINE_CPUFUNC_H_
58 #include <machine/cpufunc.h>
59 #endif
60
61 #ifndef _KERNEL
62 #ifndef _ASSERT_H_
63 #include <assert.h>
64 #endif
65 #define KKASSERT(exp)   assert(exp)
66 #endif
67
68 /*
69  * Basic initialization of a message structure.  Returns a cursor.
70  * 'bytes' represents the amount of reserved space in the message (or the
71  * size of the message buffer) and must already be 8-byte aligned.
72  */
73 static __inline
74 syslink_msg_t
75 syslink_msg_init(void *buf, sl_cid_t cmdid, int bytes, int *cursor)
76 {
77         struct syslink_msg *msg = buf;
78
79         msg->msgid = -1;                /* not yet assigned / placeholder */
80         msg->cid = cmdid;               /* command identifier */
81         msg->reclen = bytes;            /* reserved size, in bytes */
82         *cursor = sizeof(*msg);
83         return (msg);
84 }
85
86 /*
87  * Basic completion of a constructed message buffer.  The cursor is used to
88  * determine the actual size of the message and any remaining space is
89  * converted to PAD.
90  *
91  * NOTE: The original reserved space in the message is required to have been
92  * aligned.  We maintain FIFO atomicy by setting up the PAD before we fixup
93  * the record length.
94  */
95 static __inline
96 void
97 syslink_msg_done(syslink_msg_t msg, int cursor)
98 {
99         syslink_msg_t tmp;
100         int n;
101
102         n = (cursor + SL_ALIGNMASK) & ~SL_ALIGNMASK;
103         if (n != msg->reclen) {
104                 tmp = (syslink_msg_t)((char *)msg + n);
105                 tmp->msgid = 0;
106                 tmp->cid = 0;
107                 tmp->reclen = msg->reclen - n;
108         }
109         cpu_sfence();
110         msg->reclen = cursor;
111 }
112
113 /*
114  * Inline routines to help construct messages.
115  */
116
117 /*
118  * Push a recursive syslink_item.  SLIF_RECURSION must be set in the
119  * passed itemid.  A pointer to the item will be returned and the cursor
120  * will be updated.  The returned item must be used in a future call
121  * to syslink_item_pop().
122  */
123 static __inline
124 syslink_item_t
125 syslink_item_push(syslink_msg_t msg, sl_cid_t itemid, int *cursor)
126 {
127         syslink_item_t item;
128
129         item = (char *)msg + *cursor;
130         item->itemid = itemid;
131         item->auxdata = 0;
132         KKASSERT(itemid & SLIF_RECURSION);
133         *cursor += sizeof(struct syslink_item);
134         KKASSERT(*cursor <= msg->reclen);
135
136         return (item);
137 }
138
139 /*
140  * Pop a previously pushed recursive item.  Use the cursor to figure out
141  * the item's record length.
142  */
143 static __inline
144 void
145 syslink_item_pop(syslink_msg_t msg, syslink_item_t item, int *cursor)
146 {
147         item->reclen = *cursor - ((char *)item - (char *)msg);
148 }
149
150 /*
151  * Construct a leaf node whos total size is 'bytes'.  The recursion bit
152  * must not be set in the itemid.  The cursor will be updated.
153  *
154  * A pointer to the leaf item is returned as a void * so the caller can
155  * assign it to an extended structural pointer.
156  */
157 static __inline
158 void *
159 syslink_item_leaf(syslink_msg_t msg, sl_cid_t itemid, int bytes, int *cursor)
160 {
161         syslink_item_t item;
162
163         item = (char *)msg + *cursor;
164         item->reclen = bytes;
165         item->itemid = itemid;
166         item->auxdata = 0;
167         *cursor += (bytes + SL_ALIGNMASK) & ~SL_ALIGNMASK;
168         KKASSERT(*cursor <= msg->reclen && (itemid & SLIF_RECURSION) == 0);
169         return (item);
170 }
171
172 #endif
173