00001 /** 00002 * @ingroup shm 00003 * @file 00004 * 00005 * SCB stand for Shared (memory) Circular Buffer. It is a non blocking 00006 * implementation for just a single writer (producer) and reader 00007 * (consumer) and, under such a constraint, it can be a specific 00008 * substitute for RTAI mailboxes. There are other constraints that 00009 * must be satisfied, so it cannot be a general substitute for the more 00010 * flexible RTAI mailboxes. In fact it provides just functions 00011 * corresponding to RTAI mailboxes non blocking atomic send/receive of 00012 * messages, i.e. the equivalents of rt_mbx_send_if and 00013 * rt_mbx_receive_if. Moreover the circular buffer size must be >= to 00014 * the largest message to be sent/received. At least the double of the 00015 * largest message to be sent/received is strongly recommended. 00016 * Thus sending/receiving a message either succeeds of fails. However 00017 * thanks to the use of shared memory it should be more efficient than 00018 * mailboxes in atomic exchanges of messages from kernel to user space. 00019 * So it is a good candidate for supporting drivers development. 00020 * 00021 * @author Paolo Mantegazza 00022 * 00023 * @note Copyright © 2004-2008 Paolo Mantegazza <mantegazza@aero.polimi.it> 00024 * 00025 * This program is free software; you can redistribute it and/or 00026 * modify it under the terms of the GNU General Public License as 00027 * published by the Free Software Foundation; either version 2 of the 00028 * License, or (at your option) any later version. 00029 * 00030 * This program is distributed in the hope that it will be useful, 00031 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00032 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00033 * GNU General Public License for more details. 00034 * 00035 * You should have received a copy of the GNU General Public License 00036 * along with this program; if not, write to the Free Software 00037 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00038 */ 00039 00040 #ifndef _RTAI_SCB_H 00041 #define _RTAI_SCB_H 00042 00043 #include <rtai_shm.h> 00044 #include <asm/rtai_atomic.h> 00045 00046 #define SCB ((void *)(scb)) 00047 #define SIZE ((volatile int *)scb)[-3] 00048 #define FBYTE ((volatile int *)scb)[-2] 00049 #define LBYTE ((volatile int *)scb)[-1] 00050 #define HDRSIZ (3*sizeof(int)) 00051 00052 struct task_struct; 00053 00054 #ifdef __KERNEL__ 00055 00056 #define RTAI_SCB_PROTO(type, name, arglist) static inline type name arglist 00057 00058 #else 00059 00060 #define RTAI_SCB_PROTO RTAI_PROTO 00061 00062 #endif 00063 00064 /** 00065 * Allocate and initialize a shared memory circular buffer. 00066 * 00067 * @internal 00068 * 00069 * rt_scb_init is used to allocate and/or initialize a shared memory circular 00070 * buffer. 00071 * 00072 * @param name is an unsigned long identifier; 00073 * 00074 * @param size is the size of the circular buffer. 00075 * 00076 * @param suprt is the kernel allocation method to be used, it can be: 00077 * - USE_VMALLOC, use vmalloc; 00078 * - USE_GFP_KERNEL, use kmalloc with GFP_KERNEL; 00079 * - USE_GFP_ATOMIC, use kmalloc with GFP_ATOMIC; 00080 * - USE_GFP_DMA, use kmalloc with GFP_DMA. 00081 * - for use in kernel/(multi-threaded)user space only applications the 00082 * user can use "suprt" to pass the address of any memory area (s)he has 00083 * allocated on her/his own. In such a case the actual buffer should be 00084 * greater than the requested size by the amount HDRSIZ at least. 00085 * 00086 * Since @a an unsigned long can be a clumsy identifier, services are provided 00087 * to convert 6 characters identifiers to unsigned long, and vice versa. 00088 * 00089 * @see nam2num() and num2nam(). 00090 * 00091 * It must be remarked that only the very first call does a real allocation, 00092 * any following call to allocate with the same name, from anywhere, will just 00093 * increase the usage count and map the circular buffer to the user space, or 00094 * return the related pointer to the already allocated buffer in kernel/user 00095 * space. 00096 * In any case the functions return a pointer to the circular buffer, 00097 * appropriately mapped to the memory space in use. So if one is really sure 00098 * that the named circular buffer has been initted already parameters "size" 00099 * and "suprt" are not used and can be assigned any value. 00100 * 00101 * @returns a valid address on succes, you must use it, 0 on failure. 00102 * 00103 */ 00104 00105 RTAI_SCB_PROTO(void *, rt_scb_init, (unsigned long name, int size, unsigned long suprt)) 00106 { 00107 void *scb; 00108 if (suprt > 1000) { 00109 size -= HDRSIZ + 1; 00110 scb = (void *)suprt; 00111 } else { 00112 scb = rt_shm_alloc(name, size + HDRSIZ + 1, suprt); 00113 } 00114 if (scb && !atomic_cmpxchg((atomic_t *)scb, 0, name)) { 00115 ((int *)scb)[1] = ((int *)scb)[2] = 0; 00116 ((int *)scb)[0] = size + 1; 00117 } else { 00118 while (!((int *)scb)[0]); 00119 } 00120 return scb ? scb + HDRSIZ : 0; 00121 } 00122 00123 /** 00124 * Reset a shared memory circular buffer. 00125 * 00126 * @internal 00127 * 00128 * rt_scb_reset reinitializes a shared memory circular buffer. 00129 * 00130 * @param scb is the pointer returned when the buffer was initted. 00131 * 00132 */ 00133 00134 RTAI_SCB_PROTO(void, rt_scb_reset, (void *scb)) 00135 { 00136 LBYTE = FBYTE = 0; 00137 } 00138 00139 /** 00140 * Free a shared memory circular buffer. 00141 * 00142 * @internal 00143 * 00144 * rt_scb_delete is used to release a previously allocated shared memory 00145 * circular buffer. 00146 * 00147 * @param name is the unsigned long identifier used when the buffer was 00148 * allocated; 00149 * 00150 * Analogously to what done by all the named allocation functions the freeing 00151 * calls have just the effect of decrementing a usage count, unmapping any 00152 * user space shared memory being freed, till the last is done, as that is the 00153 * one the really frees any allocated memory. 00154 * 00155 * @returns the size of the succesfully freed buffer, 0 on failure. 00156 * 00157 * No need to call this function if you provided your own memory for the 00158 * circular buffer. 00159 * 00160 */ 00161 00162 RTAI_SCB_PROTO(int, rt_scb_delete, (unsigned long name)) 00163 { 00164 return rt_shm_free(name); 00165 } 00166 00167 /** 00168 * Get the number of bytes avaiable in a shared memory circular buffer. 00169 * 00170 * @internal 00171 * 00172 * rt_scb_avbs is used to get the number of bytes avaiable in a shared 00173 * memory circular buffer. 00174 * 00175 * @param scb is the pointer handle returned when the buffer was initted. 00176 * 00177 * @returns the available number of bytes. 00178 * 00179 */ 00180 00181 RTAI_SCB_PROTO (int, rt_scb_avbs, (void *scb)) 00182 { 00183 int size = SIZE, fbyte = FBYTE, lbyte = LBYTE; 00184 return (lbyte >= fbyte ? lbyte - fbyte : size + lbyte - fbyte); 00185 } 00186 00187 /** 00188 * Get the number of bytes avaiable in a shared memory circular buffer. 00189 * 00190 * @internal 00191 * 00192 * rt_scb_bytes is used to get the number of bytes avaiable in a shared 00193 * memory circular buffer; legacy alias for rt_scb_avbs. 00194 * 00195 * @param scb is the pointer handle returned when the buffer was initted. 00196 * 00197 * @returns the available number of bytes. 00198 * 00199 */ 00200 00201 RTAI_SCB_PROTO (int, rt_scb_bytes, (void *scb)) 00202 { 00203 return rt_scb_avbs(scb); 00204 } 00205 00206 /** 00207 * Get the number of free bytes pace in a shared memory circular buffer. 00208 * 00209 * @internal 00210 * 00211 * rt_scb_frbs is used to get the number of free bytes space avaiable in a 00212 * shared memory circular buffer. 00213 * 00214 * @param scb is the pointer handle returned when the buffer was initted. 00215 * 00216 * @returns the number of free bytes. 00217 * 00218 */ 00219 00220 RTAI_SCB_PROTO (int, rt_scb_frbs, (void *scb)) 00221 { 00222 int size = SIZE, fbyte = FBYTE, lbyte = LBYTE; 00223 return (fbyte <= lbyte ? size + fbyte - lbyte : size - lbyte); 00224 } 00225 00226 /** 00227 * @brief Gets (receives) a message, only if the whole message can be passed 00228 * all at once. 00229 * 00230 * rt_scb_get tries to atomically receive the message @e msg of @e 00231 * msg_size bytes from the shared memory circular buffer @e scb. 00232 * It returns immediately and the caller is never blocked. 00233 * 00234 * @return On success, i.e. message got, it returns 0, msg_size on failure. 00235 * 00236 */ 00237 00238 RTAI_SCB_PROTO(int, rt_scb_get, (void *scb, void *msg, int msg_size)) 00239 { 00240 int size = SIZE, fbyte = FBYTE, lbyte = LBYTE; 00241 if (msg_size > 0 && ((lbyte -= fbyte) >= 0 ? lbyte : size + lbyte) >= msg_size) { 00242 int tocpy; 00243 if ((tocpy = size - fbyte) > msg_size) { 00244 memcpy(msg, SCB + fbyte, msg_size); 00245 FBYTE = fbyte + msg_size; 00246 } else { 00247 memcpy(msg, SCB + fbyte, tocpy); 00248 memcpy(msg + tocpy, SCB, msg_size -= tocpy); 00249 FBYTE = msg_size; 00250 } 00251 return 0; 00252 } 00253 return msg_size; 00254 } 00255 00256 /** 00257 * @brief eavedrops a message. 00258 * 00259 * rt_scb_evdrp atomically spies the message @e msg of @e 00260 * msg_size bytes from the shared memory circular buffer @e scb. 00261 * It returns immediately and the caller is never blocked. It is like 00262 * rt_scb_get but leaves the message in the shared memory circular buffer. 00263 * 00264 * @return On success, i.e. message got, it returns 0, msg_size on failure. 00265 * 00266 */ 00267 00268 RTAI_SCB_PROTO(int, rt_scb_evdrp, (void *scb, void *msg, int msg_size)) 00269 { 00270 int size = SIZE, fbyte = FBYTE, lbyte = LBYTE; 00271 if (msg_size > 0 && ((lbyte -= fbyte) >= 0 ? lbyte : size + lbyte) >= msg_size) { 00272 int tocpy; 00273 if ((tocpy = size - fbyte) > msg_size) { 00274 memcpy(msg, SCB + fbyte, msg_size); 00275 } else { 00276 memcpy(msg, SCB + fbyte, tocpy); 00277 memcpy(msg + tocpy, SCB, msg_size - tocpy); 00278 } 00279 return 0; 00280 } 00281 return msg_size; 00282 } 00283 00284 /** 00285 * @brief Puts (sends) a message, only if the whole message can be passed all 00286 * at once. 00287 * 00288 * rt_scb_put tries to atomically send the message @e msg of @e 00289 * msg_size bytes to the shared memory circular buffer @e scb. 00290 * It returns immediately and the caller is never blocked. 00291 * 00292 * @return On success, i.e. message put, it returns 0, msg_size on failure. 00293 * 00294 */ 00295 00296 RTAI_SCB_PROTO(int, rt_scb_put, (void *scb, void *msg, int msg_size)) 00297 { 00298 int size = SIZE, fbyte = FBYTE, lbyte = LBYTE; 00299 if (msg_size > 0 && ((fbyte -= lbyte) <= 0 ? size + fbyte : fbyte) > msg_size) { 00300 int tocpy; 00301 if ((tocpy = size - lbyte) > msg_size) { 00302 memcpy(SCB + lbyte, msg, msg_size); 00303 LBYTE = lbyte + msg_size; 00304 } else { 00305 memcpy(SCB + lbyte, msg, tocpy); 00306 memcpy(SCB, msg + tocpy, msg_size -= tocpy); 00307 LBYTE = msg_size; 00308 } 00309 return 0; 00310 } 00311 return msg_size; 00312 } 00313 00314 RTAI_SCB_PROTO(int, rt_scb_ovrwr, (void *scb, void *msg, int msg_size)) 00315 { 00316 int size = SIZE, lbyte = LBYTE; 00317 if (msg_size > 0 && msg_size < size) { 00318 int tocpy; 00319 if ((tocpy = size - lbyte) > msg_size) { 00320 memcpy(SCB + lbyte, msg, msg_size); 00321 LBYTE = lbyte + msg_size; 00322 } else { 00323 memcpy(SCB + lbyte, msg, tocpy); 00324 memcpy(SCB, msg + tocpy, msg_size -= tocpy); 00325 LBYTE = msg_size; 00326 } 00327 return 0; 00328 } 00329 return msg_size; 00330 } 00331 00332 #endif /* _RTAI_SCB_H */