Main Page   Class Hierarchy   Alphabetical List   Data Structures   File List   Data Fields   Globals  

rtlnml.c

Go to the documentation of this file.
00001 
00002 
00003 struct RTLNML_HEADER
00004 {
00005   long message_type;
00006   unsigned long message_size;
00007   long first_message_count;
00008   long second_message_count;
00009 };
00010 
00011 struct RTLNML
00012 {
00013   struct RTLNML_HEADER *header;
00014   void *mbuff_address;
00015   void *direct_data_pointer;
00016   void *local_pointer;
00017   int rtlnml_allocated_local_pointer;
00018   unsigned long max_message_size;
00019   int last_id_read;
00020 #if defined(rtai) || defined(linux_rtai)
00021   int key;
00022 #endif
00023 };
00024 
00025 typedef struct RTLNML *rtlnml_t;
00026 
00027 #if defined(rtai) || defined(linux_rtai)
00028 typedef rtlnml_t rtainml_t;
00029 
00030 #ifdef rtai
00031 #include <linux/module.h>
00032 #else
00033 #include <stdlib.h>
00034 #include <unistd.h>
00035 #include <signal.h>
00036 #include <sys/types.h>
00037 #include <sys/stat.h>
00038 #include <fcntl.h>
00039 #include <sys/mman.h>
00040 #include <errno.h>
00041 #include <unistd.h>
00042 #endif
00043 
00044 #include "rtai_shm.h"
00045 #endif
00046 
00047 #define RTLNML_TYPEDEFED
00048 #ifdef MODULE
00049 #undef MODULE
00050 #endif
00051 
00052 
00053 #include "rtlnml.h"
00054 
00055 #if !defined(rtlinux) && !defined(rtai)
00056 #include <stdlib.h>
00057 #endif
00058 
00059 // On a Debian 2.2/ glibc 2.1.3, linux kernel 2.4.1, rtl 3.0 
00060 // insane compile errors occur if linux/string.h is included after string.h
00061 #ifdef  NEED_LINUX_STRING_H
00062 #include <linux/string.h>
00063 /* But then again, two fatal parsing errors crop up if linux/string.h is
00064    included on a RH7.1 2.4.9-rtai system.
00065    Also causes multiple defines of strnlen on BDI 2.10 for nonrealtime compile.)
00066    (aproximately RedHat 6.x, glibc 2.1.1, rtlinux 3.0)
00067 */
00068 #endif
00069 
00070 #include <string.h>
00071 
00072 #if defined(rtlinux) || defined(rtai)
00073 extern void *kmalloc (unsigned long, int);
00074 extern void kfree (const void *);
00075 #endif
00076 
00077 
00078 //
00079 // This insanity is here because mbuff.h puts C functions in the header file.
00080 // We need the function but if we end up exporting it it will cause multiple
00081 // definition linker errors. Therefore we use this nonsense plus some extra
00082 // gcc flags to get rid of those functions.
00083 //
00084 // added by terrylr on 15 october 2000.
00085 // changed the ifdef to an if defined conditional.
00086 // if either rtlinux_2_0 or rtlinux_2_3 is defined
00087 // inline will be redefined to be static.
00088 // this is only necessary for version rtlinux-2.0 & rtlinux-2.3.
00089 // version rtlinux-2.2 defines certain functions declared in
00090 // mbuff.h to be static inline.
00091 //
00092 #if defined(rtlinux) || defined(HAVE_RTL)
00093 #include <linux/types.h>
00094 #include <linux/fs.h>
00095 #include <unistd.h>
00096 #include <fcntl.h>
00097 #include <string.h>
00098 #include <sys/mman.h>
00099 #include <sys/types.h>
00100 #include <sys/stat.h>
00101 #ifndef rtlinux_2_2
00102 #define inline static inline
00103 #endif
00104 #include "mbuff.h"
00105 #ifndef rtlinux_2_2
00106 #undef inline
00107 #endif
00108 #endif
00109 
00110 /* All applications should call this before any other rtlnml functions. */
00111 /* In rtlinux, call this only from init_module, never from an RT task
00112    function. */
00113 void
00114 rtlnml_init (void)
00115 {
00116 }
00117 
00118 static inline void *
00119 rtlnml_malloc (unsigned long sz)
00120 {
00121 #if defined(rtlinux) || defined(rtai)
00122   return ((void *) kmalloc (sz, 1));
00123 #else
00124   return malloc (sz);
00125 #endif
00126 }
00127 
00128 static inline void
00129 rtlnml_free (void *p)
00130 {
00131 #if defined(rtlinux) || defined(rtai)
00132   kfree (p);
00133 #else
00134   free (p);
00135 #endif
00136 }
00137 
00138 
00139 
00140 /* This fuction is used to create each channel. */
00141 /* In rtlinux, call this only from init_module, never from an RT task
00142    function. */
00143 #if !defined(rtai) && !defined(linux_rtai)
00144 rtlnml_t
00145 rtlnml_open (const char *name,  /* buffer name */
00146              const char *processname,   /* process name (not used) */
00147              const char *filename,      /* configuration file (not used) */
00148              unsigned long size,        /* Maximum size of message for buffer, (actual buffer is slightly larger). */
00149              int master)
00150 #else
00151 rtainml_t
00152 rtainml_open (const char *name, /* buffer name */
00153               const char *processname,  /* process name (not used) */
00154               const char *filename,     /* configuration file (not used) */
00155               unsigned long size,       /* Maximum size of message for buffer, (actual buffer is slightly larger). */
00156               int master, int key)
00157 #endif
00158 {
00159   int i;
00160   struct RTLNML *r = NULL;
00161 
00162   r = (struct RTLNML *) rtlnml_malloc (sizeof (struct RTLNML));
00163   if (NULL == r)
00164     {
00165       return NULL;
00166     }
00167   r->header = NULL;
00168   r->mbuff_address = NULL;
00169   r->direct_data_pointer = NULL;
00170   r->local_pointer = NULL;
00171   r->rtlnml_allocated_local_pointer = 0;
00172   r->max_message_size = 0;
00173   r->last_id_read = 0;
00174 
00175 #ifdef rtai
00176   r->mbuff_address = rtai_kmalloc (key, size + 16);
00177   r->key = key;
00178 #else
00179 #ifdef linux_rtai
00180   r->mbuff_address = rtai_malloc (key, size + 16);
00181   r->key = key;
00182 #else
00183   r->mbuff_address = mbuff_alloc (name, size + 16);
00184 #endif
00185 #endif
00186   if (NULL == r->mbuff_address)
00187     {
00188       rtlnml_free (r);
00189       return NULL;
00190     }
00191 
00192   if (master)
00193     {
00194       for (i = 0; i < size + 16; i++)
00195         {
00196           ((char *) (r->mbuff_address))[i] = 0;
00197         }
00198     }
00199   r->local_pointer = rtlnml_malloc (size);
00200   r->rtlnml_allocated_local_pointer = 1;
00201   r->direct_data_pointer = (void *) (((char *) r->mbuff_address) + 16);
00202   r->header = (struct RTLNML_HEADER *) r->mbuff_address;
00203   r->max_message_size = size;
00204   return r;
00205 }
00206 
00207 
00208 /* These functions get and release
00209    a direct pointer to the shared memory area.
00210    If a read occurs while the
00211    writer has direct access to the shared memory a split-buffer error will
00212    occur when either  rtlnml_get_direct_pointer_for_read,
00213    rtlnml_release_direct_pointer_for_read or rtlnml_read will return
00214    RTLNML_SPLIT_READ
00215    So the pointer should be released as soon as possible.*/
00216 int
00217 rtlnml_get_direct_pointer_for_read (rtlnml_t r, void **p)
00218 {
00219   if (r->last_id_read == r->header->first_message_count)
00220     {
00221       return RTLNML_READ_OLD;
00222     }
00223   if (r->header->first_message_count != r->header->second_message_count)
00224     {
00225       return RTLNML_SPLIT_READ_ERROR;
00226     }
00227   r->last_id_read = r->header->first_message_count;
00228   *p = r->direct_data_pointer;
00229   return r->header->message_type;
00230 }
00231 
00232 int
00233 rtlnml_release_direct_pointer_for_read (rtlnml_t r, void **p)
00234 {
00235   *p = NULL;
00236   if (r->header->second_message_count != r->last_id_read)
00237     {
00238       return RTLNML_SPLIT_READ_ERROR;
00239     }
00240   return r->header->message_type;
00241 }
00242 
00243 int
00244 rtlnml_get_direct_pointer_for_write (rtlnml_t r, void **p)
00245 {
00246   r->header->first_message_count++;
00247   *p = r->direct_data_pointer;
00248   return (0);
00249 }
00250 
00251 int
00252 rtlnml_release_direct_pointer_for_write (rtlnml_t r, void **p, long msg_type,
00253                                          unsigned long msg_size)
00254 {
00255   *p = NULL;
00256   r->header->message_type = msg_type;
00257   r->header->message_size = msg_size;
00258   r->header->second_message_count = r->header->first_message_count;
00259   if (msg_size <= r->max_message_size && msg_size > 0)
00260     {
00261       return (-1);
00262     }
00263   return (0);
00264 }
00265 
00266   /* Reads from the buffer, possibly copying the contents to the location
00267      that can be obtained with rtlnml_get_local_pointer. This is
00268      safer and more flexible than using direct pointers but possibly
00269      slower. */
00270 long
00271 rtlnml_read (rtlnml_t r)
00272 {
00273   long orig_last_id_read = r->last_id_read;
00274   long msg_type;
00275   if (r->last_id_read == r->header->first_message_count)
00276     {
00277       return RTLNML_READ_OLD;
00278     }
00279   if (r->header->first_message_count != r->header->second_message_count)
00280     {
00281       return RTLNML_SPLIT_READ_ERROR;
00282     }
00283   if (r->header->message_size <= 0
00284       || r->header->message_size > r->max_message_size)
00285     {
00286       return RTLNML_READ_ERROR;
00287     }
00288   r->last_id_read = r->header->first_message_count;
00289   msg_type = r->header->message_type;
00290 #ifdef USE_BCOPY
00291   bcopy (r->direct_data_pointer, r->local_pointer, r->header->message_size);
00292 #else
00293   memcpy (r->local_pointer, r->direct_data_pointer, r->header->message_size);
00294 #endif /* ] */
00295   if (r->last_id_read != r->header->second_message_count)
00296     {
00297       r->last_id_read = orig_last_id_read;
00298       return RTLNML_SPLIT_READ_ERROR;
00299     }
00300   return msg_type;
00301 }
00302 
00303   /* Writes to the buffer. This may be
00304      safer and more flexible than using direct pointers but possibly
00305      slower. */
00306 long
00307 rtlnml_write (rtlnml_t r, void *data,   /* address of data to be copied into nml buffer. */
00308               long msg_type,    /* NML message type. */
00309               unsigned long msg_size)   /* size of message */
00310 {
00311   if (msg_size <= 0 || msg_size > r->max_message_size)
00312     {
00313       return RTLNML_WRITE_ERROR;
00314     }
00315   r->header->first_message_count++;
00316 #ifdef USE_BCOPY
00317   bcopy (data, r->direct_data_pointer, msg_size);
00318 #else
00319   memcpy (r->direct_data_pointer, data, msg_size);
00320 #endif
00321   r->header->message_size = msg_size;
00322   r->header->message_type = msg_type;
00323   r->header->second_message_count = r->header->first_message_count;
00324   return (RTLNML_WRITE_OK);
00325 }
00326 
00327   /* This function should be called after a successful rtlnml_read to
00328      get a pointer to a local copy of the message. */
00329 void *
00330 rtlnml_get_local_pointer (rtlnml_t r)
00331 {
00332   return r->local_pointer;
00333 }
00334 
00335 /* Use only if you want rtlnml_read to copy data to a special location.*/
00336 extern void
00337 rtlnml_set_local_pointer (rtlnml_t r, void *p)
00338 {
00339   if (NULL != r->local_pointer && r->rtlnml_allocated_local_pointer)
00340     {
00341       rtlnml_free (r->local_pointer);
00342     }
00343   r->rtlnml_allocated_local_pointer = 0;
00344   r->local_pointer = p;
00345 }
00346 
00347   /* Close each channel. */
00348 void
00349 rtlnml_close (rtlnml_t r, const char *bufname)
00350 {
00351   if (NULL != r)
00352     {
00353       if (NULL != r->mbuff_address)
00354         {
00355 #ifdef rtai
00356           rtai_kfree (r->key);
00357 #else
00358 #ifdef linux_rtai
00359           rtai_free (r->key, r->mbuff_address);
00360 #else
00361           mbuff_free (bufname, r->mbuff_address);
00362 #endif
00363 #endif
00364           r->mbuff_address = NULL;
00365         }
00366       if (NULL != r->local_pointer && r->rtlnml_allocated_local_pointer)
00367         {
00368           rtlnml_free (r->local_pointer);
00369           r->local_pointer = NULL;
00370         }
00371       rtlnml_free (r);
00372     }
00373 }
00374 
00375 /* This function should be called after all other rtlnml functions. */
00376 /* In rtlinux call this only from cleanup_module, never from an RT task function. */
00377 void
00378 rtlnml_exit ()
00379 {
00380 }

Generated on Sun Dec 2 15:56:52 2001 for rcslib by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001