function pointer fifo

Discussion to talk about software related topics only.
Post Reply
sulliwk06
Posts: 118
Joined: Tue Sep 17, 2013 7:14 am

function pointer fifo

Post by sulliwk06 »

So I'm trying to set up a system where i can queue up functions to be executed from with a specific task. At first I thought of using a complicated system of flags and an array of functions to execute, but then it occurred to me that a fifo is probably the correct way to do it.

I've never used a fifo before but I think I have a problem in the casting the function to an OS_FIFO_EL and back. What happens is when I make the call to myFunction(), I start trapping repeatedly. I know I'm at least passing the function correctly, but when i cast it to put in the queue and pull it out, something breaks. Anyone notice what I'm doing wrong?

Code: Select all

OS_FIFO functionQueue;
void main()
{
	OS_FIFO_EL *func;
	void ( *myFunction )();
	while(1)
	{
		func = OSFifoPend(&functionQueue,0);
		myFunction = (void (*)()) func;
		myFunction();
	}
}
void QueueFunction(void ( *function )())
{
	OSFifoPost(&functionQueue,(OS_FIFO_EL *) function);
}

void InitFunctionFifo()
{
	OSFifoInit(&functionQueue);
}
User avatar
dciliske
Posts: 624
Joined: Mon Feb 06, 2012 9:37 am
Location: San Diego, CA
Contact:

Re: function pointer fifo

Post by dciliske »

I'm 90% certain that you're either not passing a structure containing the function pointer or you're allocating the structure on the stack in the posting context. Either of these will cause you to get a corrupted memory address for the resulting function pointer.

Take a look at the OSFifo example in the RTOS examples for how to do this correctly.

-Dan
Dan Ciliske
Project Engineer
Netburner, Inc
sulliwk06
Posts: 118
Joined: Tue Sep 17, 2013 7:14 am

Re: function pointer fifo

Post by sulliwk06 »

dciliske wrote:I'm 90% certain that you're either not passing a structure containing the function pointer or you're allocating the structure on the stack in the posting context. Either of these will cause you to get a corrupted memory address for the resulting function pointer.

Take a look at the OSFifo example in the RTOS examples for how to do this correctly.

-Dan
It seems you are right, but I can't seem to figure out how to pass the function pointer without it being allocated on the stack. I've tried passing it with QueueFunction(&Function) and that had no effect. I also tried casting it to an OS_FIFO_EL before passing it and that didn't work either. Maybe I'm misunderstanding something fundamental about passing function pointers. Any ideas?

Code: Select all

void Function()
{
	iprintf("print me");
}

void main()
{
	QueueFunction(Function);
}

int QueueFunction(void ( *function )())
{
//	function(); //function can be called from here successfully
	if(!taskInitialized)
	{
		return NOT_INITIALIZED;
	}

	OSFifoPost(&functionQueue,(OS_FIFO_EL *) function);

//	function(); //function cannot be called from here

	return NO_ERROR;
}

I also tried to copy everything exactly from the OSFifo example and it didn't work with functions. Maybe what I'm trying to do isn't possible?

Code: Select all

OSFifoPost(&functionQueue,(OS_FIFO_EL *) &Function);
void ( *myFunction )() = (void (*)()) OSFifoPend(&functionQueue,0);
myFunction();//failed


Update:
I've figured out that the call to OSFifoPost is causing some kind of change in the function pointer. Is this what you would expect to happen? I would have thought that it shouldn't change anything.

Code: Select all

int QueueFunction(void ( *function )())
{
	if(!taskInitialized)
	{
		return NOT_INITIALIZED;
	}

//	OSFifoPost(&functionQueue,(OS_FIFO_EL *) function);
	OSFifoPost(&functionQueue,(OS_FIFO_EL *) &taskInitialized);  //post something other than the function pointer

	function(); //executes properly now that it isn't being posted to the queue, previously it would fail here

	return NO_ERROR;
}
dpursell
Posts: 20
Joined: Thu Aug 05, 2010 3:15 pm

Re: function pointer fifo

Post by dpursell »

sulliwk06 wrote: Update:
I've figured out that the call to OSFifoPost is causing some kind of change in the function pointer. Is this what you would expect to happen? I would have thought that it shouldn't change anything.

Code: Select all

int QueueFunction(void ( *function )())
{
	if(!taskInitialized)
	{
		return NOT_INITIALIZED;
	}

//	OSFifoPost(&functionQueue,(OS_FIFO_EL *) function);
	OSFifoPost(&functionQueue,(OS_FIFO_EL *) &taskInitialized);  //post something other than the function pointer

	function(); //executes properly now that it isn't being posted to the queue, previously it would fail here

	return NO_ERROR;
}

According to the docs and example, the OS_FIFO objects expect a struct where the first element if a void*, and the structs use that pointer for internal bookkeeping. So yes, I think it's expected that the value changes. You need to provide a struct with a void* and then your function pointer.

Try something like this:

Code: Select all

typedef struct
{
  void* internalBookkeeping;  // don't use this yourself at all
  void (*function)(); // here's your function pointer
} MyQueueStruct;

int QueueFunction(void (*function)())
{
  MyQueueStruct* item;

  if (!taskInitialized)
  {
    return NOT_INITIALIZED;
  }

  // I use C++ so forgive me if my malloc call is wrong
  // If you don't want to use dynamic memory allocation you can use global variables instead,
  // but if I'm reading the docs correctly you *cannot* just create a MyQueueStruct on the stack here
  // because the memory would be lost as soon as this function exits. If you use malloc, make sure to
  // call free after you pull it out of the FIFO or you will have a memory leak
  item = (MyQueueStruct*)malloc(sizeof(MyQueueStruct));
  item->function = function;

  OSFifoPost(&functionQueue, (OS_FIFO_EL*) item);

  return NO_ERROR;
}
Ridgeglider
Posts: 513
Joined: Sat Apr 26, 2008 7:14 am

Re: function pointer fifo

Post by Ridgeglider »

In addition to dciliske's advice, take a look at the C:\nburn\docs\NetworkProgrammersGuide\NNDK Netburner Programmer's Manual.PDF FIFO example, in my docs, section 5.1.4. It passes a trivial struct on a fifo of statically allocated maximum size. It includes a simple way to check whether space is left in the fifo and if so, adds to the fifo, and if not, produce an error message. Modify the example struct to meet your needs, but keep the first element as the examples define it if you want to use their approach to ensuring empty space. On a somewhat unrelated note, you may want to modify the struct using something like:
struct __attribute__ ((__packed__)) MyStruct_t {
// your elements here
}

if you care about the offsets into your struct(s) being the same in various instances.
sulliwk06
Posts: 118
Joined: Tue Sep 17, 2013 7:14 am

Re: function pointer fifo

Post by sulliwk06 »

Thank you all for your help, I didn't realize that a FIFO needed a persistent struct to reference with a void pointer in it. I've got it working properly now.
User avatar
pbreed
Posts: 1088
Joined: Thu Apr 24, 2008 3:58 pm

Re: function pointer fifo

Post by pbreed »

I'd use the queue rather than the fifo....

Exact same functionality, but the queu holds the storage, vs counting on having an element in the structure for the fifo.
The Fifo is really a rather special class for managing network and other variable length buffer blocks.


Paul
Post Reply