Okay, back to the float/memory problem.
I've attached 4 files to this message: one is just a makefile,
one is a common header, one is the rt code, the other is user code.

When the rt module (rt_daq) is inserted, it essentially does nothing until
'random_table' is run.  random_table computes some random numbers, and
passes them (via the shared memory) to the rt process. 
'sh_mem->table_flag' is used to ensure the two processes are
reading/writing to shared_memory at the same time. The number of
random numbers computed = RANDOM_ARRAY_SIZE, and is defined at the top of
rt_daq.h. if
        RANDOM_ARRAY_SIZE = 100   -> Everything works fine
          elseif
        RANDOM_ARRAY_SIZE = 1000  -> System reboot

I recommend not setting RANDOM_ARRAY_SIZE = 1000 unless you enjoy fsck as
much as I do. :) Cheers - Chuck

On Tue, 11 Apr 2000 [EMAIL PROTECTED] wrote:
> 
> Please send me code. I wonder if it is purely a timing issue and 
> has something to do with a case when a RT thread runs out of time 
> while using FP. This would be easy to check. In fact, you could 
> try the following
>            rtl_no_interrupts(x)
>      while(1){
>            do floating point
>            rtl_sched();  /* call the scheduler, don't wait for resched */
>           }
> 
> On Tue, Apr 11, 2000 at 01:53:50PM -0400, [EMAIL PROTECTED] wrote:
> > I'd like to second David Christini's problem.
> > 
> > Like Pavel, I have various RT applications that use doubles. (I never use
> > floats to avoid unnecessary bugs.) I use several math functions, 
> > specifically: exp(), sin(), cos() and sqrt();
> > 
> > Like David however, none of my systems are particularly stable.  As
> > Pavel suggested I think the instability is coming from memory related
> > issues, but not the user/kernel type. 
> > 
> > All of my modules are stable if I use a 'small' number of doubles,
> > and a 'small' number of operations on those doubles (per period in a
> > periodic rt thread.) I observe two possibly related phenomena--
> > 
> > 1) as I increase the number of double operations in a cycle, the cpu will
> >     eventually lock up. This doesn't concern me, perhaps I'm asking
> >     too much of it --
> >             It works with something like 100 double fxns
> >     {ie. exp(),sin(),etc.} & 1000 double operations {ie +-*/}
> >     every 100 microseconds, on a 450MHz PIII.
> > 
> > 2) as I increase the number of doubles I use, the system will eventually
> >     spontaneously reboot itself.  This phenomenon is unpredictable.
> >             ~100  double variables ->  works every time.
> >                     'every time' =  hundreds of trials for up to
> >                                     millions of periods per trial.
> >             ~1000 double variables -> reboots every time.
> >             ~100->1000 double variables -> works/reboots randomly.
> > 
> >     Obviously I observe this when using arrays of doubles, and the
> >     numbers I listed above are highly dependent on the number of
> >     operations I perform in a given period.  But even if I perform
> >     almost no operations in a loop (say, only one typecast), an array
> >     of 2000 doubles in my module will reboot the system upon
> >     insertion. Understand that for a given operation number, the
> >     number of stable double variables is a constant.
> > 
> >     Two examples:
> >     1) 1 array of 100 doubles & 10 other doubles
> >             ~400 operations & 99 functions
> >             -works fine every time
> >        1 array of 105 doubles & 10 other doubles
> >             ~400 operations & 99 functions (extra doubles aren't used)
> >             - reboots every time
> > 
> >     2) 4 arrays of 10 doubles & 30 other doubles
> >             ~150 operations & 78 functions
> >             - works fine every time
> >        4 arrays of 11 doubles & 30 other doubles
> >             ~150 operations & 78 functions (extra doubles aren't used)
> >             - reboots every time
> > 
> > If I use 'int' in place of 'double', (of course I can't use the math
> > fxns), but I find arrays of 100,000 members reliable, without any crash
> > or reboot. (I assume I could go to millions of members before running into
> > a problem.) 
> > 
> > After extreme frustration, I gave up pressing this issue about a month
> > ago, and just restricted myself to small double arrays. But I suspect that
> > my issues are related to David Christini's, so I thought I'd bring it up.
> > 
> > If anyone is interested in examining my problem,
> > let me know and I'll send out the code...
> > 
> > Chuck
> > 
> > On Tue, 11 Apr 2000, Pavel Andris wrote:
> > > David,
> > > I use kernel 2.2.13, RTL 2.0. My RT application uses double variables
> > > and operations heavily including sin(), cos(), sqrt(), atan2(). I also
> > > use shared memory (Tomek Motylewski's mbuff). I don't remember any
> > > crash caused by floating point operations. I'd expect your trouble is
> > > caused by something else (float/double confusion?, kernel/user memory
> > > context trouble?). 
> > > Regards, Pavel Andris
> > 
> > -- [rtl] ---
> > To unsubscribe:
> > echo "unsubscribe rtl" | mail [EMAIL PROTECTED] OR
> > echo "unsubscribe rtl <Your_email>" | mail [EMAIL PROTECTED]
> > ---
> > For more information on Real-Time Linux see:
> > http://www.rtlinux.org/rtlinux/
> 
> -- 
> ---------------------------------------------------------
> Victor Yodaiken 
> FSMLabs:  www.fsmlabs.com  www.rtlinux.com
> FSMLabs is a servicemark and a service of 
> VJY Associates L.L.C, New Mexico.
> 
> -- [rtl] ---
> To unsubscribe:
> echo "unsubscribe rtl" | mail [EMAIL PROTECTED] OR
> echo "unsubscribe rtl <Your_email>" | mail [EMAIL PROTECTED]
> ---
> For more information on Real-Time Linux see:
> http://www.rtlinux.org/rtlinux/
> 
## Makefile Hacked from so many places, it's not
## worth my labeling them all -- ADD2

##### Compiler, Flags, etc. #####

CC  = gcc
GCC = g++
MOC = moc

USR_CFLAGS  = -pipe -Wall -O2 -W -g
RTL_CFLAGS  = -Wall -Wstrict-prototypes -O2 \
        -fomit-frame-pointer -fno-strength-reduce
RTL_DEFS    = -D__RT__ -D__KERNEL__ -DMODULE -c -DMODVERSIONS 

USR_INCLUDE = -I /usr/src/rtlinux/rtl/include \
        -I /usr/src/rtlinux/linux/include \
        -I /usr/src/rtlinux/rtl
RTL_INCLUDE =   -I /usr/src/rtlinux/linux/include \
                -I /usr/src/rtlinux/include/posix \
                -I /usr/src/rtlinux/include

LFLAGS = -L/usr/lib -lqt -L/usr/X11R6/lib -lX11 -lXext -lqwt


##### File Names #####

RTL_HEADER      =       rt_daq.h

RND_SOURCE      =       random_table.cc
RTL_SOURCE      =       rt_daq.c

RND_TARGET      =       random_table
RTL_TEMP        =       rt_daq_temp.o
RTL_TARGET      =       rt_daq.o


##### Build Rules #####

all:    $(RND_TARGET)   $(RTL_TEMP)     $(RTL_TARGET)
daq:    $(RTL_TEMP)     $(RTL_TARGET)


$(RND_TARGET): $(RND_SOURCE) $(RTL_HEADER)
        $(GCC) $(USR_INCLUDE) $(USR_CFLAGS) $(LFLAGS) \
        $(RND_SOURCE) -o $(RND_TARGET)

$(RTL_TEMP): $(RTL_SOURCE) $(RTL_HEADER)
        $(CC) $(RTL_INCLUDE) $(RTL_CFLAGS) $(RTL_DEFS) \
        -c $(RTL_SOURCE) -o $(RTL_TEMP)

$(RTL_TARGET): $(RTL_TEMP)
        $(CC) -nostdlib -static -r $(RTL_TEMP) \
        -o $(RTL_TARGET) -lgcc -lm


// Known Headers
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>

#include <math.h>
#include "rt_daq.h"

#define TWO_PI        6.28318530717958647692  // pi * 2

SHARED_MEM_STRUCT *sh_mem;    // pointer to shared memory
int               fd_shared_mem;

// This is a KEY function!!! Does math!
int main()
{
   int i, j, N;

   j = 0;
   N = RANDOM_ARRAY_SIZE;

   srand(0);

   // Open memory address pointer 
   if ((fd_shared_mem = open("/dev/mem", O_RDWR)) < 0)
     {
      fprintf(stderr, "Error opening /dev/mem \n");
      exit(1);
     }
   sh_mem =(SHARED_MEM_STRUCT *)mmap(0,sizeof(SHARED_MEM_STRUCT),
      PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, 
      fd_shared_mem, SHARED_MEM_ADDRESS);

   // Write Math Table to rt memory via shared memory
   while(sh_mem->table_flag != TABLE_FULL)
     {      
      if(sh_mem->table_flag == TABLE_WRITE)
        {
          for(i=0;i<SHARED_ARRAY_SIZE;i++)
            {
              sh_mem->cos_rand[i] = cos
                ( TWO_PI * (double)rand() / (double)RAND_MAX );
              sh_mem->log_rand[i] = log
                ( (double)rand() / (double)RAND_MAX );
            }

          j+=SHARED_ARRAY_SIZE;
          printf("%d of %d entries complete\n",j,N);

          sh_mem->table_flag = TABLE_READ;
        }
     }

   printf("Random number table created with %d values.\n",
      RANDOM_ARRAY_SIZE);
   munmap((char *)sh_mem, sizeof(SHARED_MEM_STRUCT));
   return(0);
}

#ifndef __RT_DAQ_H 
#define __RT_DAQ_H


// Basics
#ifndef TRUE
#define TRUE   1
#define FALSE  0
#endif

// MAKE THIS NUMBER BIG -> KABOOM!!!!
#define RANDOM_ARRAY_SIZE   100  // max number rands
#define SHARED_ARRAY_SIZE    10

// System/needs dependent
#define HZ_FREQUENCY         10000          //RT Task frequency
#define T_MS                    .1          // 1000/HZ_FREQUENCY
#define SHARED_MEM_ADDRESS   (126*0x100000) //Setup /etc/lilo.conf


// Error Values for the functions listed
#define THREAD_NOT_INITIALIZED  601  // pthread_create
#define THREAD_NOT_FLOAT        602  // pthread_setfp_np
#define THREAD_NOT_PERIODIC     603  // pthread_make_periodic_np
#define THREAD_NOT_DESTROYED    604  // pthread_delete_np
#define ATTR_NOT_INITIALIZED    610  // pthread_attr_init
#define SETSCHED_NOT_MODIFIED   611  // pthread_attr_setschedparam

#define TABLE_FULL              102  // proceed with periodic thread
#define TABLE_READ              103  // rt pthread waiting
#define TABLE_WRITE             104  // usr side waiting

// Shared Memory Sturcture, accessed by user & kernel spaces
typedef struct
{

  // System Error/Debug
  int error_type;
  int error_detail;

  int    table_flag;
  int    data_wait;
  double cos_rand[SHARED_ARRAY_SIZE];
  double log_rand[SHARED_ARRAY_SIZE];
 
} SHARED_MEM_STRUCT;

#endif // __RT_DAQ_H

#include <rtl.h>

#include <time.h>
#include <pthread.h>

#include "rt_daq.h"


// ***** Function Declarations *****/
void  init_shared_mem(void);   // initialize user/kernel memory
void *daq_code(void*);         // CPU Periodic function

// ***** Global Variables ***** //

// RT required 
pthread_t           daq_thread;  // main rtlinux thread
SHARED_MEM_STRUCT  *sh_mem;      // shared memory: user/kernel


// Safety Flags
int error_flag;


// ***** Functions ***** //

// ***** INIT_MODULE, rtLinux standard function
//  before rt_daq.o, board must be configured see comedi docs 
int init_module(void)
{
  pthread_attr_t attr;
  struct sched_param sched_param;

  hrtime_t now, period, soon;

  now    = clock_gethrtime(CLOCK_REALTIME);
  period = HRTICKS_PER_SEC / HZ_FREQUENCY;
  soon   = now + (100 * period);

  // Open shared memory structure, and rt fifos 
  init_shared_mem();

  // initialize pthread attributes
  error_flag = pthread_attr_init(&attr);
  if(error_flag && !(sh_mem->error_type))
    {
      sh_mem->error_type   = ATTR_NOT_INITIALIZED;
      sh_mem->error_detail = error_flag;
    }

  // modify pthread attributes for top priority
  sched_param.sched_priority = 1;
  error_flag = pthread_attr_setschedparam(&attr,&sched_param);
  if(error_flag && !(sh_mem->error_type))
    {
      sh_mem->error_type   = SETSCHED_NOT_MODIFIED;
      sh_mem->error_detail = error_flag;
    }
  
  // initialize the real time cpu thread
  error_flag = 
    pthread_create(&daq_thread, &attr, daq_code,(void *)1);
  if(error_flag && !(sh_mem->error_type))
    {
      sh_mem->error_type   = THREAD_NOT_INITIALIZED;
      sh_mem->error_detail = error_flag;
    }

  // allow use of floating point numbers
  error_flag = pthread_setfp_np(daq_thread,TRUE);
  if(error_flag && !(sh_mem->error_type))
    {
      sh_mem->error_type   = THREAD_NOT_FLOAT;
      sh_mem->error_detail = error_flag;
    }

  // make the thread periodic
  error_flag =
    pthread_make_periodic_np (daq_thread, soon, period ); 
  if(error_flag && !(sh_mem->error_type))
    {
      sh_mem->error_type   = THREAD_NOT_PERIODIC;
      sh_mem->error_detail = error_flag;
    }
 return 0;
}


// Initialize the rt/linux shared memory
void init_shared_mem(void)
{

  //Open Shared Memory structure; '__va' command new in 2.2.x
  sh_mem = (SHARED_MEM_STRUCT *) __va(SHARED_MEM_ADDRESS);


   // Initialize flags & error values
   sh_mem->error_type       = 0;
   sh_mem->error_detail     = 0;
   if(RANDOM_ARRAY_SIZE)
     sh_mem->table_flag = TABLE_WRITE;
   else
     sh_mem->table_flag = TABLE_FULL;    
}



// Task reads/writes data to DAQ board
void *daq_code(void *param)
{
  int   table_index, i;

  double cos_rand[RANDOM_ARRAY_SIZE];
  double log_rand[RANDOM_ARRAY_SIZE];

  table_index = 0;

  while (1)      // periodic task, must loop
    {
      pthread_wait_np();      //wait for next period

      if(sh_mem->table_flag!=TABLE_FULL)
        {
          if(sh_mem->table_flag==TABLE_READ)
            {
              for(i=0;i<SHARED_ARRAY_SIZE;i++)
                {
                  cos_rand[table_index] = sh_mem->cos_rand[i];
                  log_rand[table_index] = sh_mem->log_rand[i];
                  table_index++;
                }
            }
          if(table_index == RANDOM_ARRAY_SIZE)
            sh_mem->table_flag = TABLE_FULL;
          else
            sh_mem->table_flag = TABLE_WRITE;
        }
      else
        {
          // Do Nothing for simplicity
        }
    }
}



void cleanup_module(void)
{

  // destroy periodic thread
  error_flag = pthread_delete_np(daq_thread);
  if(error_flag && !(sh_mem->error_type))
    {
      sh_mem->error_type   = THREAD_NOT_DESTROYED;
      sh_mem->error_detail = error_flag;
    }   
}

Reply via email to