base/include/rtai_scb.h

Go to the documentation of this file.
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. Thus sending/receiving a 00015 * message either succeeds of fails. However thanks to the use of 00016 * shared memory it should be more efficient than mailboxes in atomic 00017 * exchanges of messages from kernel to user space. So it is a good 00018 * candidate for supporting drivers development. 00019 * 00020 * @author Paolo Mantegazza 00021 * 00022 * @note Copyright &copy; 2004 Paolo Mantegazza <mantegazza@aero.polimi.it> 00023 * 00024 * This program is free software; you can redistribute it and/or 00025 * modify it under the terms of the GNU General Public License as 00026 * published by the Free Software Foundation; either version 2 of the 00027 * License, or (at your option) any later version. 00028 * 00029 * This program is distributed in the hope that it will be useful, 00030 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00031 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00032 * GNU General Public License for more details. 00033 * 00034 * You should have received a copy of the GNU General Public License 00035 * along with this program; if not, write to the Free Software 00036 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00037 */ 00038 00039 #ifndef _RTAI_SCB_H 00040 #define _RTAI_SCB_H 00041 00042 #include <rtai_shm.h> 00043 #include <asm/rtai_atomic.h> 00044 00045 #define SCB ((void *)(scb)) 00046 #define SIZE ((volatile int *)scb)[-3] 00047 #define FBYTE ((volatile int *)scb)[-2] 00048 #define LBYTE ((volatile int *)scb)[-1] 00049 #define HDRSIZ (3*sizeof(int)) 00050 00051 struct task_struct; 00052 00053 /** 00054 * Allocate and initialize a shared memory circular buffer. 00055 * 00056 * @internal 00057 * 00058 * rt_scb_init is used to allocate and initialize a shared memory circular buffer. 00059 * 00060 * @param name is an unsigned long identifier; 00061 * 00062 * @param size is the size of the circular buffer. 00063 * 00064 * @param suprt is the kernel allocation method to be used, it can be: 00065 * - USE_VMALLOC, use vmalloc; 00066 * - USE_GFP_KERNEL, use kmalloc with GFP_KERNEL; 00067 * - USE_GFP_ATOMIC, use kmalloc with GFP_ATOMIC; 00068 * - USE_GFP_DMA, use kmalloc with GFP_DMA. 00069 * - for use in kernel only applications the user can use "suprt" to pass 00070 * the address of any memory area (s)he has allocated on her/his own. 00071 * 00072 * Since @a name can be a clumsy identifier, services are provided to 00073 * convert 6 characters identifiers to unsigned long, and vice versa. 00074 * 00075 * @see nam2num() and num2nam(). 00076 * 00077 * It must be remarked that only the very first call does a real allocation, 00078 * any following call to allocate with the same name from anywhere will just 00079 * increase the usage count and maps the circular buffer to the user space, or 00080 * return the related pointer to the already allocated buffer in kernel space. 00081 * In any case the functions return a pointer to the circular buffer, 00082 * appropriately mapped to the memory space in use. So if one is really sure 00083 * that the named circular buffer has been initted already parameters size 00084 * and suprt are not used and can be assigned any value. 00085 * 00086 * @returns a valid address on succes, 0 on failure. 00087 * 00088 */ 00089 00090 RTAI_PROTO(void *, rt_scb_init, (unsigned long name, int size, unsigned long suprt)) 00091 { 00092 void *scb; 00093 scb = suprt > 1000 ? (void *)suprt : rt_shm_alloc(name, size + HDRSIZ + 1, suprt); 00094 if (scb && !atomic_cmpxchg((int *)scb, 0, name)) { 00095 ((int *)scb)[1] = ((int *)scb)[2] = 0; 00096 ((int *)scb)[0] = size + 1; 00097 } else { 00098 while (!((int *)scb)[0]); 00099 } 00100 return scb ? scb + HDRSIZ : 0; 00101 } 00102 00103 /** 00104 * Free a shared memory circular buffer. 00105 * 00106 * @internal 00107 * 00108 * rt_scb_delete is used to release a previously allocated shared memory 00109 * circular buffer. 00110 * 00111 * @param name is the unsigned long identifier used when the buffer was 00112 * allocated; 00113 * 00114 * Analogously to what done by all the named allocation functions the freeing 00115 * calls have just the effect of decrementing a usage count, unmapping any 00116 * user space shared memory being freed, till the last is done, as that is the 00117 * one the really frees any allocated memory. 00118 * 00119 * @returns the size of the succesfully freed buffer, 0 on failure. 00120 * 00121 * Do not call this function if you provided your own memory to the circular 00122 * buffer. 00123 * 00124 */ 00125 00126 RTAI_PROTO(int, rt_scb_delete, (unsigned long name)) 00127 { 00128 return rt_shm_free(name); 00129 } 00130 00131 /** 00132 * Get the number of bytes avaiable in a shared memory circular buffer. 00133 * 00134 * @internal 00135 * 00136 * rt_scb_bytes is used to get the number of bytes avaiable in a shared 00137 * memory circular buffer. 00138 * 00139 * @param scb is the pointer handle returned when the buffer was initted. 00140 * 00141 * @returns the available number of bytes. 00142 * 00143 */ 00144 00145 RTAI_PROTO (int, rt_scb_bytes, (void *scb)) 00146 { 00147 int size = SIZE, fbyte = FBYTE, lbyte = LBYTE; 00148 return (lbyte >= fbyte ? lbyte - fbyte : size + lbyte - fbyte); 00149 } 00150 00151 /** 00152 * @brief Gets (receives) a message, only if the whole message can be passed 00153 * all at once. 00154 * 00155 * rt_scb_get tries to atomically receive the message @e msg of @e 00156 * msg_size bytes from the shared memory circular buffer @e scb. 00157 * It returns immediately and the caller is never blocked. 00158 * 00159 * @return On success, i.e. message got, it returns 0, msg_size on failure. 00160 * 00161 */ 00162 00163 RTAI_PROTO(int, rt_scb_get, (void *scb, void *msg, int msg_size)) 00164 { 00165 int size = SIZE, fbyte = FBYTE, lbyte = LBYTE; 00166 if (msg_size > 0 && (lbyte >= fbyte ? lbyte - fbyte : size + lbyte - fbyte) >= msg_size) { 00167 int tocpy; 00168 if ((tocpy = size - fbyte) > msg_size) { 00169 memcpy(msg, SCB + fbyte, msg_size); 00170 FBYTE = fbyte + msg_size; 00171 } else { 00172 memcpy(msg, SCB + fbyte, tocpy); 00173 if ((msg_size -= tocpy)) { 00174 memcpy(msg + tocpy, SCB, msg_size); 00175 } 00176 FBYTE = msg_size; 00177 } 00178 return 0; 00179 } 00180 return msg_size; 00181 } 00182 00183 /** 00184 * @brief eavedrops a message. 00185 * 00186 * rt_scb_evdrp atomically spies the message @e msg of @e 00187 * msg_size bytes from the shared memory circular buffer @e scb. 00188 * It returns immediately and the caller is never blocked. It is like 00189 * rt_scb_get but leaves the message in the shared memory circular buffer. 00190 * 00191 * @return On success, i.e. message got, it returns 0, msg_size on failure. 00192 * 00193 */ 00194 00195 RTAI_PROTO(int, rt_scb_evdrp, (void *scb, void *msg, int msg_size)) 00196 { 00197 int size = SIZE, fbyte = FBYTE, lbyte = LBYTE; 00198 if (msg_size > 0 && (lbyte >= fbyte ? lbyte - fbyte : size + lbyte - fbyte) >= msg_size) { 00199 int tocpy; 00200 if ((tocpy = size - fbyte) > msg_size) { 00201 memcpy(msg, SCB + fbyte, msg_size); 00202 } else { 00203 memcpy(msg, SCB + fbyte, tocpy); 00204 if ((msg_size -= tocpy)) { 00205 memcpy(msg + tocpy, SCB, msg_size); 00206 } 00207 } 00208 return 0; 00209 } 00210 return msg_size; 00211 } 00212 00213 /** 00214 * @brief Puts (sends) a message, only if the whole message can be passed all 00215 * at once. 00216 * 00217 * rt_scb_put tries to atomically send the message @e msg of @e 00218 * msg_size bytes to the shared memory circular buffer @e scb. 00219 * It returns immediately and the caller is never blocked. 00220 * 00221 * @return On success, i.e. message put, it returns 0, msg_size on failure. 00222 * 00223 */ 00224 00225 RTAI_PROTO(int, rt_scb_put, (void *scb, void *msg, int msg_size)) 00226 { 00227 int size = SIZE, fbyte = FBYTE, lbyte = LBYTE; 00228 if (msg_size > 0 && (lbyte >= fbyte ? size - (lbyte - fbyte) : fbyte - lbyte) > msg_size) { 00229 int tocpy; 00230 if ((tocpy = size - lbyte) > msg_size) { 00231 memcpy(SCB + lbyte, msg, msg_size); 00232 LBYTE = lbyte + msg_size; 00233 } else { 00234 memcpy(SCB + lbyte, msg, tocpy); 00235 if ((msg_size -= tocpy)) { 00236 memcpy(SCB, msg + tocpy, msg_size); 00237 } 00238 LBYTE = msg_size; 00239 } 00240 return 0; 00241 } 00242 return msg_size; 00243 } 00244 00245 #endif /* _RTAI_SCB_H */

Generated on Thu Nov 20 11:49:50 2008 for RTAI API by doxygen 1.3.8