This file is indexed.

/usr/include/rtai/rtai_scb.h is in librtai-dev 3.9.1-4.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
/**
 * @ingroup shm
 * @file
 *
 * SCB stand for Shared (memory) Circular Buffer. It is a non blocking
 * implementation for just a single writer (producer) and reader
 * (consumer) and, under such a constraint, it can be a specific
 * substitute for RTAI mailboxes. There are other constraints that
 * must be satisfied, so it cannot be a general substitute for the more
 * flexible RTAI mailboxes. In fact it provides just functions
 * corresponding to RTAI mailboxes non blocking atomic send/receive of
 * messages, i.e. the equivalents of rt_mbx_send_if and
 * rt_mbx_receive_if. Moreover the circular buffer size must be >= to
 * the largest message to be sent/received. At least the double of the 
 * largest message to be sent/received is strongly recommended.
 * Thus sending/receiving a message either succeeds of fails. However 
 * thanks to the use of shared memory it should be more efficient than
 * mailboxes in atomic exchanges of messages from kernel to user space.
 * So it is a good candidate for supporting drivers development.
 *
 * @author Paolo Mantegazza
 *
 * @note Copyright &copy; 2004-2008 Paolo Mantegazza <mantegazza@aero.polimi.it>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#ifndef _RTAI_SCB_H
#define _RTAI_SCB_H

#include <rtai_shm.h>
#include <asm/rtai_atomic.h>

#define SCB     ((void *)(scb))
#define SIZE    ((volatile int *)scb)[-3]
#define FBYTE   ((volatile int *)scb)[-2]
#define LBYTE   ((volatile int *)scb)[-1]
#define HDRSIZ  (3*sizeof(int))

struct task_struct;

#ifdef __KERNEL__

#define RTAI_SCB_PROTO(type, name, arglist)  static inline type name arglist

#else

#define RTAI_SCB_PROTO  RTAI_PROTO

#endif

/**
 * Allocate and initialize a shared memory circular buffer.
 *
 * @internal
 *
 * rt_scb_init is used to allocate and/or initialize a shared memory circular
 * buffer.
 *
 * @param name is an unsigned long identifier;
 *
 * @param size is the size of the circular buffer.
 *
 * @param suprt is the kernel allocation method to be used, it can be:
 * - USE_VMALLOC, use vmalloc;
 * - USE_GFP_KERNEL, use kmalloc with GFP_KERNEL;
 * - USE_GFP_ATOMIC, use kmalloc with GFP_ATOMIC;
 * - USE_GFP_DMA, use kmalloc with GFP_DMA.
 * - for use in kernel/(multi-threaded)user space only applications the 
 *   user can use "suprt" to pass the address of any memory area (s)he has
 *   allocated on her/his own. In such a case the actual buffer should be
 *   greater than the requested size by the amount HDRSIZ at least.
 *
 * Since @a an unsigned long can be a clumsy identifier, services are provided
 * to convert 6 characters identifiers to unsigned long, and vice versa.
 *
 * @see nam2num() and num2nam().
 *
 * It must be remarked that only the very first call does a real allocation,
 * any following call to allocate with the same name, from anywhere, will just
 * increase the usage count and map the circular buffer to the user space, or 
 * return the related pointer to the already allocated buffer in kernel/user
 * space.
 * In any case the functions return a pointer to the circular buffer,
 * appropriately mapped to the memory space in use. So if one is really sure
 * that the named circular buffer has been initted already parameters "size"
 * and "suprt" are not used and can be assigned any value.
 *
 * @returns a valid address on succes, you must use it, 0 on failure.
 *
 */

RTAI_SCB_PROTO(void *, rt_scb_init, (unsigned long name, int size, unsigned long suprt))
{	
	void *scb;
	if (suprt > 1000) {
		size -=  HDRSIZ + 1;
		scb = (void *)suprt;
	} else {
		scb = rt_shm_alloc(name, size + HDRSIZ + 1, suprt);
	}
	if (scb && !atomic_cmpxchg((atomic_t *)scb, 0, name)) {
		((int *)scb)[1] = ((int *)scb)[2] = 0;
		((int *)scb)[0] = size + 1;
	} else {
		while (!((int *)scb)[0]);
	}			
	return scb ? scb + HDRSIZ : 0;
}

/**
 * Reset a shared memory circular buffer.
 *
 * @internal
 *
 * rt_scb_reset reinitializes a shared memory circular buffer.
 *
 * @param scb is the pointer returned when the buffer was initted.
 *
 */

RTAI_SCB_PROTO(void, rt_scb_reset, (void *scb))
{ 
	LBYTE = FBYTE = 0;
}

/**
 * Free a shared memory circular buffer.
 *
 * @internal
 *
 * rt_scb_delete is used to release a previously allocated shared memory 
 * circular buffer.
 *
 * @param name is the unsigned long identifier used when the buffer was
 * allocated;
 *
 * Analogously to what done by all the named allocation functions the freeing
 * calls have just the effect of decrementing a usage count, unmapping any
 * user space shared memory being freed, till the last is done, as that is the
 * one the really frees any allocated memory.
 *
 * @returns the size of the succesfully freed buffer, 0 on failure.
 *
 * No need to call this function if you provided your own memory for the
 * circular buffer. 
 *
 */

RTAI_SCB_PROTO(int, rt_scb_delete, (unsigned long name))
{ 
	return rt_shm_free(name);
}

/**
 * Get the number of bytes avaiable in a shared memory circular buffer.
 *
 * @internal
 *
 * rt_scb_avbs is used to get the number of bytes avaiable in a shared 
 * memory circular buffer.
 *
 * @param scb is the pointer handle returned when the buffer was initted.
 *
 * @returns the available number of bytes.
 *
 */

RTAI_SCB_PROTO (int, rt_scb_avbs, (void *scb))
{ 
	int size = SIZE, fbyte = FBYTE, lbyte = LBYTE;
	return (lbyte >= fbyte ? lbyte - fbyte : size + lbyte - fbyte);
}

/**
 * Get the number of bytes avaiable in a shared memory circular buffer.
 *
 * @internal
 *
 * rt_scb_bytes is used to get the number of bytes avaiable in a shared 
 * memory circular buffer; legacy alias for rt_scb_avbs.
 *
 * @param scb is the pointer handle returned when the buffer was initted.
 *
 * @returns the available number of bytes.
 *
 */

RTAI_SCB_PROTO (int, rt_scb_bytes, (void *scb))
{ 
	return rt_scb_avbs(scb);
}

/**
 * Get the number of free bytes pace in a shared memory circular buffer.
 *
 * @internal
 *
 * rt_scb_frbs is used to get the number of free bytes space avaiable in a 
 * shared memory circular buffer.
 *
 * @param scb is the pointer handle returned when the buffer was initted.
 *
 * @returns the number of free bytes.
 *
 */

RTAI_SCB_PROTO (int, rt_scb_frbs, (void *scb))
{ 
	int size = SIZE, fbyte = FBYTE, lbyte = LBYTE;
	return (fbyte <= lbyte ? size + fbyte - lbyte : size - lbyte);
}

/**
 * @brief Gets (receives) a message, only if the whole message can be passed 
 * all at once.
 *
 * rt_scb_get tries to atomically receive the message @e msg of @e
 * msg_size bytes from the shared memory circular buffer @e scb.
 * It returns immediately and the caller is never blocked.
 *
 * @return On success, i.e. message got, it returns 0, msg_size on failure.
 *
 */

RTAI_SCB_PROTO(int, rt_scb_get, (void *scb, void *msg, int msg_size))
{ 
	int size = SIZE, fbyte = FBYTE, lbyte = LBYTE;
	if (msg_size > 0 && ((lbyte -= fbyte) >= 0 ? lbyte : size + lbyte) >= msg_size) {
		int tocpy;
		if ((tocpy = size - fbyte) > msg_size) {
			memcpy(msg, SCB + fbyte, msg_size);
			FBYTE = fbyte + msg_size;
		} else {
			memcpy(msg, SCB + fbyte, tocpy);
			memcpy(msg + tocpy, SCB, msg_size -= tocpy);
			FBYTE = msg_size;
		}
		return 0;
	}
	return msg_size;
}

/**
 * @brief eavedrops a message.
 *
 * rt_scb_evdrp atomically spies the message @e msg of @e
 * msg_size bytes from the shared memory circular buffer @e scb.
 * It returns immediately and the caller is never blocked. It is like 
 * rt_scb_get but leaves the message in the shared memory circular buffer.
 *
 * @return On success, i.e. message got, it returns 0, msg_size on failure.
 *
 */

RTAI_SCB_PROTO(int, rt_scb_evdrp, (void *scb, void *msg, int msg_size))
{ 
	int size = SIZE, fbyte = FBYTE, lbyte = LBYTE;
	if (msg_size > 0 && ((lbyte -= fbyte) >= 0 ? lbyte : size + lbyte) >= msg_size) {
		int tocpy;
		if ((tocpy = size - fbyte) > msg_size) {
			memcpy(msg, SCB + fbyte, msg_size);
		} else {
			memcpy(msg, SCB + fbyte, tocpy);
			memcpy(msg + tocpy, SCB, msg_size - tocpy);
		}
		return 0;
	}
	return msg_size;
}

/**
 * @brief Puts (sends) a message, only if the whole message can be passed all
 * at once.
 *
 * rt_scb_put tries to atomically send the message @e msg of @e
 * msg_size bytes to the shared memory circular buffer @e scb. 
 * It returns immediately and the caller is never blocked.
 *
 * @return On success, i.e. message put, it returns 0, msg_size on failure.
 *
 */

RTAI_SCB_PROTO(int, rt_scb_put, (void *scb, void *msg, int msg_size))
{ 
	int size = SIZE, fbyte = FBYTE, lbyte = LBYTE;
	if (msg_size > 0 && ((fbyte -= lbyte) <= 0 ? size + fbyte : fbyte) > msg_size) {
		int tocpy;
		if ((tocpy = size - lbyte) > msg_size) {
			memcpy(SCB + lbyte, msg, msg_size);
			LBYTE = lbyte + msg_size;
		} else {
			memcpy(SCB + lbyte, msg, tocpy);
			memcpy(SCB, msg + tocpy, msg_size -= tocpy);
			LBYTE = msg_size;
		}
		return 0;
	}
	return msg_size;
}

RTAI_SCB_PROTO(int, rt_scb_ovrwr, (void *scb, void *msg, int msg_size))
{ 
	int size = SIZE, lbyte = LBYTE;
	if (msg_size > 0 && msg_size < size) {
		int tocpy;
		if ((tocpy = size - lbyte) > msg_size) {
			memcpy(SCB + lbyte, msg, msg_size);
			LBYTE = lbyte + msg_size;
		} else {
			memcpy(SCB + lbyte, msg, tocpy);
			memcpy(SCB, msg + tocpy, msg_size -= tocpy);
			LBYTE = msg_size;
		}
		return 0;
	}
	return msg_size;
}

#endif /* _RTAI_SCB_H */