ia64/xen-unstable

view xen/include/public/io/ring.h @ 5755:be1153585cb0

Fix hgignore regexps some more.
author kaf24@firebug.cl.cam.ac.uk
date Tue Jul 12 16:19:59 2005 +0000 (2005-07-12)
parents 445b12a7221a
children 122779b57b40 9af349b055e5
line source
1 /*
2 * Shared producer-consumer ring macros.
3 * Tim Deegan and Andrew Warfield November 2004.
4 */
6 #ifndef __XEN_PUBLIC_IO_RING_H__
7 #define __XEN_PUBLIC_IO_RING_H__
9 typedef unsigned int RING_IDX;
11 /* Round a 32-bit unsigned constant down to the nearest power of two. */
12 #define __RD2(_x) (((_x) & 0x00000002) ? 0x2 : ((_x) & 0x1))
13 #define __RD4(_x) (((_x) & 0x0000000c) ? __RD2((_x)>>2)<<2 : __RD2(_x))
14 #define __RD8(_x) (((_x) & 0x000000f0) ? __RD4((_x)>>4)<<4 : __RD4(_x))
15 #define __RD16(_x) (((_x) & 0x0000ff00) ? __RD8((_x)>>8)<<8 : __RD8(_x))
16 #define __RD32(_x) (((_x) & 0xffff0000) ? __RD16((_x)>>16)<<16 : __RD16(_x))
18 /*
19 * Calculate size of a shared ring, given the total available space for the
20 * ring and indexes (_sz), and the name tag of the request/response structure.
21 * A ring contains as many entries as will fit, rounded down to the nearest
22 * power of two (so we can mask with (size-1) to loop around).
23 */
24 #define __RING_SIZE(_s, _sz) \
25 (__RD32(((_sz) - 2*sizeof(RING_IDX)) / sizeof((_s)->ring[0])))
27 /*
28 * Macros to make the correct C datatypes for a new kind of ring.
29 *
30 * To make a new ring datatype, you need to have two message structures,
31 * let's say request_t, and response_t already defined.
32 *
33 * In a header where you want the ring datatype declared, you then do:
34 *
35 * DEFINE_RING_TYPES(mytag, request_t, response_t);
36 *
37 * These expand out to give you a set of types, as you can see below.
38 * The most important of these are:
39 *
40 * mytag_sring_t - The shared ring.
41 * mytag_front_ring_t - The 'front' half of the ring.
42 * mytag_back_ring_t - The 'back' half of the ring.
43 *
44 * To initialize a ring in your code you need to know the location and size
45 * of the shared memory area (PAGE_SIZE, for instance). To initialise
46 * the front half:
47 *
48 * mytag_front_ring_t front_ring;
49 *
50 * SHARED_RING_INIT((mytag_sring_t *)shared_page);
51 * FRONT_RING_INIT(&front_ring, (mytag_sring_t *)shared_page, PAGE_SIZE);
52 *
53 * Initializing the back follows similarly...
54 */
56 #define DEFINE_RING_TYPES(__name, __req_t, __rsp_t) \
57 \
58 /* Shared ring entry */ \
59 union __name##_sring_entry { \
60 __req_t req; \
61 __rsp_t rsp; \
62 }; \
63 \
64 /* Shared ring page */ \
65 struct __name##_sring { \
66 RING_IDX req_prod; \
67 RING_IDX rsp_prod; \
68 union __name##_sring_entry ring[1]; /* variable-length */ \
69 }; \
70 \
71 /* "Front" end's private variables */ \
72 struct __name##_front_ring { \
73 RING_IDX req_prod_pvt; \
74 RING_IDX rsp_cons; \
75 unsigned int nr_ents; \
76 struct __name##_sring *sring; \
77 }; \
78 \
79 /* "Back" end's private variables */ \
80 struct __name##_back_ring { \
81 RING_IDX rsp_prod_pvt; \
82 RING_IDX req_cons; \
83 unsigned int nr_ents; \
84 struct __name##_sring *sring; \
85 }; \
86 \
87 /* Syntactic sugar */ \
88 typedef struct __name##_sring __name##_sring_t; \
89 typedef struct __name##_front_ring __name##_front_ring_t; \
90 typedef struct __name##_back_ring __name##_back_ring_t;
92 /*
93 * Macros for manipulating rings.
94 *
95 * FRONT_RING_whatever works on the "front end" of a ring: here
96 * requests are pushed on to the ring and responses taken off it.
97 *
98 * BACK_RING_whatever works on the "back end" of a ring: here
99 * requests are taken off the ring and responses put on.
100 *
101 * N.B. these macros do NO INTERLOCKS OR FLOW CONTROL.
102 * This is OK in 1-for-1 request-response situations where the
103 * requestor (front end) never has more than RING_SIZE()-1
104 * outstanding requests.
105 */
107 /* Initialising empty rings */
108 #define SHARED_RING_INIT(_s) do { \
109 (_s)->req_prod = 0; \
110 (_s)->rsp_prod = 0; \
111 } while(0)
113 #define FRONT_RING_INIT(_r, _s, __size) do { \
114 (_r)->req_prod_pvt = 0; \
115 (_r)->rsp_cons = 0; \
116 (_r)->nr_ents = __RING_SIZE(_s, __size); \
117 (_r)->sring = (_s); \
118 } while (0)
120 #define BACK_RING_INIT(_r, _s, __size) do { \
121 (_r)->rsp_prod_pvt = 0; \
122 (_r)->req_cons = 0; \
123 (_r)->nr_ents = __RING_SIZE(_s, __size); \
124 (_r)->sring = (_s); \
125 } while (0)
127 /* Initialize to existing shared indexes -- for recovery */
128 #define FRONT_RING_ATTACH(_r, _s, __size) do { \
129 (_r)->sring = (_s); \
130 (_r)->req_prod_pvt = (_s)->req_prod; \
131 (_r)->rsp_cons = (_s)->rsp_prod; \
132 (_r)->nr_ents = __RING_SIZE(_s, __size); \
133 } while (0)
135 #define BACK_RING_ATTACH(_r, _s, __size) do { \
136 (_r)->sring = (_s); \
137 (_r)->rsp_prod_pvt = (_s)->rsp_prod; \
138 (_r)->req_cons = (_s)->req_prod; \
139 (_r)->nr_ents = __RING_SIZE(_s, __size); \
140 } while (0)
142 /* How big is this ring? */
143 #define RING_SIZE(_r) \
144 ((_r)->nr_ents)
146 /* How many empty slots are on a ring? */
147 #define RING_PENDING_REQUESTS(_r) \
148 ( ((_r)->req_prod_pvt - (_r)->rsp_cons) )
150 /* Test if there is an empty slot available on the front ring.
151 * (This is only meaningful from the front. )
152 */
153 #define RING_FULL(_r) \
154 (((_r)->req_prod_pvt - (_r)->rsp_cons) == RING_SIZE(_r))
156 /* Test if there are outstanding messages to be processed on a ring. */
157 #define RING_HAS_UNCONSUMED_RESPONSES(_r) \
158 ( (_r)->rsp_cons != (_r)->sring->rsp_prod )
160 #define RING_HAS_UNCONSUMED_REQUESTS(_r) \
161 ( ((_r)->req_cons != (_r)->sring->req_prod ) && \
162 (((_r)->req_cons - (_r)->rsp_prod_pvt) != \
163 RING_SIZE(_r)) )
165 /* Test if there are messages waiting to be pushed. */
166 #define RING_HAS_UNPUSHED_REQUESTS(_r) \
167 ( (_r)->req_prod_pvt != (_r)->sring->req_prod )
169 #define RING_HAS_UNPUSHED_RESPONSES(_r) \
170 ( (_r)->rsp_prod_pvt != (_r)->sring->rsp_prod )
172 /* Copy the private producer pointer into the shared ring so the other end
173 * can see the updates we've made. */
174 #define RING_PUSH_REQUESTS(_r) do { \
175 wmb(); \
176 (_r)->sring->req_prod = (_r)->req_prod_pvt; \
177 } while (0)
179 #define RING_PUSH_RESPONSES(_r) do { \
180 wmb(); \
181 (_r)->sring->rsp_prod = (_r)->rsp_prod_pvt; \
182 } while (0)
184 /* Direct access to individual ring elements, by index. */
185 #define RING_GET_REQUEST(_r, _idx) \
186 (&((_r)->sring->ring[ \
187 ((_idx) & (RING_SIZE(_r) - 1)) \
188 ].req))
190 #define RING_GET_RESPONSE(_r, _idx) \
191 (&((_r)->sring->ring[ \
192 ((_idx) & (RING_SIZE(_r) - 1)) \
193 ].rsp))
195 /* Loop termination condition: Would the specified index overflow the ring? */
196 #define RING_REQUEST_CONS_OVERFLOW(_r, _cons) \
197 (((_cons) - (_r)->rsp_prod_pvt) >= RING_SIZE(_r))
199 #endif /* __XEN_PUBLIC_IO_RING_H__ */