[prev in list] [next in list] [prev in thread] [next in thread] 

List:       linux-rt
Subject:    Re: some questions about c++
From:       Daniele Lugli <danlugli () tin ! it>
Date:       1998-03-23 21:44:39
[Download RAW message or body]

Kay-Ulrich Scholl (Assistent) wrote:
> 
> Hello,
> 
> I read the discussion about C++ with RT-Linux in the mailing list
> archiv.
> Now I have some questions about it:
> 
> 1. I read that I should avoid heap allocation: why ?

I don't know if there is a moral imperative forbidding heap allocation
in rt modules but I can tell you my opinion.
a) I don't think that malloc/free and new/delete are reentrant with
respect to rtlinux. So what happens if a malloc in a non-rt task is
inperrupted by an rt-task doing malloc in turn? I don't know and I don't
want to see.
b) I didn't look into the code of malloc/free and new/delete, but I know
of other implementations using algorithms whose execution time is
largely unpredictable, mainly depending on the fact that these functions
try to allocate an arbitrarily sized piece of heap from an arbitrarily
fragmented heap.

>    I need to allocate some data structure in init_module().
>    How shoud I do this without heap allocation ?

Points (a) and (b) above become invalid if you write your own heap
allocation routines taking fixed size pieces of memory from a local
array (ie not shared with non-rt tasks).

>    What are kalloc and kfree doing?

The initial k reminds of "kernel" so they are probably suitable for use
in kernel code. Anyway I never used them and so I cannot tell you more.

> 2. I read, that there is only a stack of 8 kB. Is that for
>    the whole module or doo I have 8kB per rt-task ? Can I
>    change that ?

I remember that message too. It was from Tomasz Motylewski, saying:

>...the kernel. It has 8 KB stack, as far as I can remember.
> And there were already problems with some SCSI drivers and other
> modules allocating too much.

For rt tasks you can specify the size of the stack as an argument of
rt_task_init. I don't know if it is anyway taken from the kernel stack
but I think not (you can run several rt tasks each with a stack of 3k).

> 3. Has anybody written a small example in C++ and a makefile
>    that I can use? The discussion about that was a little confusing!

Please find it here enclosed. I cut it down from my c++ module and tried
it in a hurry; I hope I haven't pushed any bug in.

> 4. I thought, that it is not possible to use any printf-commands.
>    What does printk do?

The answer is very similar to that for heap allocation.

Best regards, Daniele




// module.c++
#define MODULE

extern "C" {
  /* This scope avoids c++ mangling of system names.
     As an alternative, give ld the option -DNO_IMPLICIT_EXTERN_C
     */
#include <asm/io.h>              /* outb */
#include <asm/rt_time.h>         /* RT_TICKS_PER_SEC */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/errno.h>         
#include <linux/rtf.h>
#include <linux/rt_sched.h>
}

// Parallel port address on my pc
#define LPT 0x378




class DummyObject
{
public:
  DummyObject ();
  DummyObject (RTIME);
  RTIME i;
  static int shouldBeThree;
};

// the following initialization is done, because int is a basic type
// and has no explicit constructor. It is solved at compile time.
int DummyObject::shouldBeThree (3);

DummyObject::DummyObject ()
{
  // Dummy default constructor, to make declaration possible.
  // If this constructor is called, shouldBeThree becomes != 3.
  shouldBeThree = 2;
}

DummyObject::DummyObject (RTIME arg)
{
  // True constructor
  i = arg;
}


/* The following declarations prevent c++ mangling of init_module
   and cleanup_module, which would make the module unloadable.
   As an alternative, it is possible to give g++ the options:
   --defsym init_module=init_module__Fv
   --defsym cleanup_module=cleanup_module__Fv
   */
extern "C" int init_module (void);
extern "C" void cleanup_module (void);

RTIME period;
RT_TASK rtTask;

/* !!! BEWARE OF DOG !!!
   This is a module, and as such has no 'main'.
   Constructors of global objects are called just before 'main'.
   Therefore in the module no constructor will be implicitly called for:
   - global objects,
   - static members of local objects (which ARE in fact global objects).
   The trick of giving ld the option '-e init_module' does not work;
   the constructors for such objects must be called explicitly
somewhere.
   The only global or static members which can be assumed to be
correctly
   initialized without explicitly calling their constructors are those
   without an explicit constructor (e.g. basic types, like 'int').
   */

// The compiler accepts the following declaration because dummyObject
// has a default constructor, but in fact no constructor is called here.
DummyObject globalDummyObject;

RTIME compareIt;

void rtThread (int unusedParameter)
{

  static int toggle = 0;

  // (Note that here, inside the thread, constructors ARE called,
  //  except for static object members).
  DummyObject localDummyObject (1234567890LL);

  for (;;) {

    // If DummyObject's have been correctly initialized, you should see
    // a rectangular wave on your oscilloscope
    if (globalDummyObject.i == compareIt &&
        localDummyObject.i == 1234567890LL &&
        DummyObject::shouldBeThree == 3) outb (toggle, LPT);
    toggle = 1 - toggle;

    rt_task_wait ();
  }
}

int init_module (void)
{

  // Create your RT fifos here if needed

  rt_task_init (
                &rtTask,      // RT_TASK * task
                rtThread,     // void (*rt_thread) (int data)
                0,            // int data (unused)
                3000,         // int stack_size
                2);           // int priority

  period = RT_TICKS_PER_SEC / 1000LL;   // 1 ms

  RTIME start_time = rt_get_time () + period;
  rt_task_make_periodic (
                         &rtTask,      // RT_TASK* task
                         start_time,   // RTIME start_time
                         period);      // RTIME period

  // Explicit constructor call
  globalDummyObject.DummyObject (start_time);

  compareIt = start_time;

  return 0;
}

void cleanup_module (void)
{
  rt_task_delete (&rtTask);
  // Destroy your rtfifos here

}




# Makefile for module.c++
INCLUDE = /usr/src/linux/include
CFLAGS = -O2 -Wall
RTFLAGS= -D__KERNEL__ -D__RT__ -I$(INCLUDE)

all: module.o

# If the module is made up of one single object file you can compile and
# link in one single step:
module.o: module.c++
        g++ $(CFLAGS) $(RTFLAGS) -o module.o -c module.c++

# If the module is made up of more than one object file you should
# compile and link in separate steps:
#module.tmp.o: module.c++
#       g++ $(CFLAGS) $(RTFLAGS) -o module.tmp.o -c module.c++

# Add other objects to the ld command as needed
#module.o: module.tmp.o
#       ld -Ur -static -o module.o module.tmp.o

# If you get complaints about missing __divdi3 or similar, add the
following
# to the ld command
#       -L/usr/lib/gcc-lib/i386-linux/2.7.2.1 -lgcc

insmod:
        insmod /usr/src/linux/modules/rt_prio_sched.o
        insmod module.o

rmmod:
        rmmod module
        rmmod rt_prio_sched

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic