[ECOS] cyg_thread_create(), CYG_USER_START COMPLETION

Fernando Herrera fherrera@teisa.unican.es
Thu Jan 17 09:30:00 GMT 2002


Lots of Thanks, Bart,  for your quick and right response....!
...sorry I answer late but I have been testing that solution  and
It seems to be a very common problem when somebody try
to write C++ objects based code reusing a kernel or library
based on functions that need function pointers, like interruprion
handlers, etc... sorry if the question very sample. But I have
another doubt now.

Using that solution I get to include functionality in some class or
struct that emulates a module.

But now I have a problem when I try to communicate two tasks
in some specific manner.

I tested 3 ways of communication:

(a) defining and instacing a channel class,
     global to the module classes that contain the
    processes. This function without problems.

(b) Using a shared data, but, using a pointer variable
      as data member of the module instance, instead of
     doing a direct access to the shared data.

(c) Using a pointer to a channel base class, where the
      pointer to the channel derived class was  previously
     assigned.

(b) and (c) cases doesn't function  the next code. They are
interesting for me because their are aproaches to the concept
of a module port, that allows us to restrict the type (b)
and/or the methods (c), that a module can use to access
other channels (the only way to communicate modules)..

I provide this  representative code, ...

class if_read {
public:
  virtual int read()=0;
};

class if_write {
public:
  virtual void write(int dat)=0;
};

class channel: public if_read,
                  public if_write
{
public:
  canal () { data=0;}
  int read() {
    return data;
  }
  void write(int dat) {
    data=dat;
  }

private:
  int data;
};

channel mychannel;

int global;

struct modulo1 {
public:
//  uc_simple_read_if<bool>      *count_done;
  int *p;
  if_escritura *w;

  void modulo1_func1(void) {
    int a;
    a=2;

(a)    mychannel.write(3);
(b)   *p=5;
(c)    w->write(3);

  }

  // caller (static member function)
  static void module1_func1_caller(cyg_addrword_t objptr) {
    //    pdv_naf *obj = static_cast<pdv_naf*> (objptr);  // didn't function
    module1 *obj;
    obj= (module1 *)objptr;
    obj -> module1_func1();
  }

  module1() {
     cyg_thread_create(4, module1_func1_caller, (cyg_addrword_t) this,
             "Thread A", (void *) stack_A, 4096,
             &simple_threadA, &thread_s_A);
  }

};

struct module2 {
public:
  int *p;
  if_lectura *r;

  void module2_func2(void) {
    int counter;
    int sum;
(a)    sum = mychannel.read();
(b)   sum = *p;
(c)    sum = r->read();
    for (counterr=0;counter<4;counter++) {
      sum=sum+counterr;
    }
  };

  static void module2_func2_caller(cyg_addrword_t objptr) {
    //    pdv_naf *obj = static_cast<pdv_naf*> (objptr); // This didn't function
    module2 *obj;
    obj= (module2 *)objptr;
    obj -> module2_func2();
  }

  module2() {
    cyg_thread_create(4, module2_func2_caller, (cyg_addrword_t) this,
            "Thread B", (void *) stack_B, 4096,
            &simple_threadB, &thread_s_B);
  }

};

extern "C" void cyg_user_start(void)
{
  module1 mymod1;
  module2 mymod2;

(b)  mymod1.p = &global;
(b)  mymod2.p = &global;

(c)  mimod1.w = &mychannel;
(c)  mimod2.r = &mychannel;

  cyg_thread_resume(simple_threadA);
  cyg_thread_resume(simple_threadB);
}

The only clue that I got is that in (b), once...

(b)  mymod1.p = &global;
(b)  mymod2.p = &global;

...are executed (this goes right and the inner pointer get the correct value),
it turned out that when the code of one of the processes is going to be
executed THE p POINTER HAVE CHANGED ITS VALUE.

I think something similar happened with (c) case, because, It seemed that
write() and read() function were not found and the debugger blocked there
without entering the methods.

This made me think that cyg_user_start(void) had ended before
module1 and module2 process executions had finished, so mimod1 and
mimod2 objects were distroyed, so p or r pointers "loose" somehow their
value!! and global object or mychannel object can't be accesed (by
the same reason this need objects to be placed as global).

I tried placing mimod1 and mimod2 instances as global (in the same
way as 'global' and 'mychannel') and the the example functions.

As a conclusion, it seems that cyg_user_start() reach its completion
(or whatever the name of the state that means that execution  of
top function is completed and all the objects of its ambit destroyed).
If this is the case....

How can is posible that the processes, created inside module instances,
which contain the functionality to execute, are able to go on execution?
and Why they lost pointer values, has their context changed somehow?

If this is true, I think would be interesting to avoid cyg_user_start()
completion until the rest of the concurrent tasks of the system has
finished. Is there some simple way to do this (for example, avoiding to
have to launch some kind of sinchronization signal from every process
of the system to unblock the cyg_user_start)?

Thanks in advance!

nando.


Bart Veer wrote:

> >>>>> "Fernando" == Fernando Herrera <fherrera@teisa.unican.es> writes:
>
>     Fernando> Hi!
>     Fernando>    I'd wanted to call cyg_thread_create() funcion passing to it
>     Fernando> a function member (that is, a method) of a determined class
>     Fernando> object, as the 2nd argument. For instance, something like this:
>
>     Fernando> (class declaration)
>
>     Fernando> class myclass {
>     Fernando> public:
>     Fernando>    int i;
>     Fernando>    int func();
>     Fernando> }
>
>     Fernando> (object declaration)
>     Fernando> myclass myobject;
>
>     Fernando> (... and this is what I want to do:)
>     Fernando> cyg_thread_create(..., myobject.func,...)
>
>     Fernando> BUT I FOUND A COMPILING TIME ERROR, because it seems
>     Fernando> that cyg_thread_create() necessarily asks a function
>     Fernando> pointer, instead of a function member pointer.
>
>     Fernando> I have tried also making and explicit conversion but it
>     Fernando> doesn't functions, I'm not very sure, but it seems it's
>     Fernando> not posible to convert a method pointer to a function
>     Fernando> pointer, at least with the compiler I'm using (g++
>     Fernando> 2.95.2).
>
>     Fernando>   So it seems that all the process functionalities must
>     Fernando> be defined as functions in eCos. Is this true or there
>     Fernando> is another alternative? Can't be this solved somehow?
>
>     Fernando> (I'm new in the forum, so I don't now if this is a
>     Fernando> trivial question or is simply a C++ question, (sorry in
>     Fernando> advance in that case)), anyway you can tell me about.
>
> What you see is the expected behaviour.
>
> An C++ normal member function is different from an ordinary function
> or a static member function: there is an implicit "this" argument.
> Hence for any part of the system such as the thread code to invoke a
> member function it needs to know two values, the function pointer and
> the "this" pointer. The function argument to cyg_thread_create()
> can only hold the first of these. The compiler is warning you that
> what you are attempting is impossible.
>
> One way around this is to have a utility static member function and
> pass the "this" pointer as the entry_data argument to
> cyg_thread_create, something along the following lines (untested):
>
>     class myclass {
>         ...
>         int member_func(void);
>         static void call_member(cyg_addrword_t);
>     }
>
>    myclass myobject;
>
>    void
>    myclass::call_member(cyg_addrword_t objptr)
>    {
>        myclass* obj = static_cast<myclass*>(objptr);
>        obj->member_func();
>    }
>
>    int
>    main(int argc, char** argv)
>    {
>        cyg_thread_create( ..., &myclass::call_member, (cyg_addrword_t) &myobject, ...)
>    }
>
> The kernel cannot do anything like this for you automatically because
> when it is compiled it has no knowledge of myclass or how to invoke
> its member functions.
>
> Bart

--
---------------------------------------------
Fernando Herrera Casanueva
fherrera@teisa.unican.es
Phone +34 942 20 08 78

    University of Cantabria.
  Av. Castros sn. E.T.S.I.I.T.
       TEISA Department
       Santander  39009
       Spain
---------------------------------------------




More information about the Ecos-discuss mailing list