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;
}
}