Dynamic Memory Allocation

The example below presents a simple FIFO queue implementation which uses the memory management module to allocate and free memory blocks within a specified memory buffer.

#include <stdio.h>
#include "ST_API.h"

/* Data structure */
struct TQueueData
{
  /* Any type of data */
  int Index;
};

/* Queue item */
struct TQueueItem
{
  PVOID Next;
  struct TQueueData Data;
};


/* Queue buffer (16 KB) */
UINT8 QueueBuffer[16 * 1024];

/* Queue head and tail pointers */
struct TQueueItem *FirstMessage;
struct TQueueItem *LastMessage;


/* Initialize queue */
BOOL InitQueue(void)
{
  /* Initialize memory buffer */
  if(!stMemoryInit(QueueBuffer, sizeof(QueueBuffer)))
    return FALSE;

  /* Initialize queue head and tail pointers */
  FirstMessage = NULL;
  LastMessage = NULL;

  /* Return success */
  return TRUE;
}


/* Store message in the queue */
BOOL Push(struct TQueueData FAR *Message)
{
  struct TQueueItem FAR *NewItem;

  /* Allocate buffer for new data */
  NewItem = (struct TQueueItem FAR *) stMemoryAlloc(QueueBuffer,
    sizeof(*NewItem));

  /* Not enough memory in the buffer (queue is full) */
  if(!NewItem)
    return FALSE;

  /* Copy item data */
  stMemCpy(&NewItem->Data, Message, sizeof(*Message));

  /* Update pointers (this section should be protected by a critical section
     in a multitasking system) */
  NewItem->Next = NULL;

  if(!FirstMessage)
    FirstMessage = NewItem;
  else
    LastMessage->Next = NewItem;

  LastMessage = NewItem;

  /* Return success */
  return TRUE;
}


/* Read and remove message from the queue */
BOOL Pop(struct TQueueData FAR *Message)
{
  struct TQueueItem FAR *Item;

  /* Return failure if queue is empty */
  if(!FirstMessage)
    return FALSE;

  Item = FirstMessage;

  /* Update pointers. LastMessage pointer can be ignored. (this section
     should be protected by a critical section in a multitasking
     system) */
  FirstMessage = FirstMessage->Next;

  /* Copy item data */
  stMemCpy(Message, &Item->Data, sizeof(*Message));

  /* Release memory block */
  stMemoryFree(QueueBuffer, Item);

  /* Return success */
  return TRUE;
}


int main(void)
{
  int i;
  struct TQueueData Message;

  /* Initialization */
  arInit();
  stInit();


  /* Initialize queue */
  if(!InitQueue())
  {
    printf("Failure during InitQueue() function call.\n");
    return 0;
  }

  /* Store 10 messages in the queue */
  for(i = 0; i < 10; i++)
  {
    /* Prepare message (may be a local variable because it will be copied) */
    Message.Index = i;

    /* Store message */
    if(Push(&Message))
      printf("Message %i stored in the queue.\n", i);

    /* Stop on failure (queue is full) */
    else
    {
      printf("Failed to store new message.\n");
      break;
    }
  }

  /* Read all messages from the queue */
  while(1)
  {
    /* Read next message */
    if(Pop(&Message))
      printf("Message %i has been read.\n", Message.Index);

    /* Stop on failure (queue is empty) */
    else
    {
      printf("All messages have been read.\n");
      break;
    }
  }


  /* Deinitialization */
  arDeinit();

  return 0;
}
Would you like me to proceed with the sections on "Using multiple memory regions" or "Defining reserved memory areas"?
SpaceShadow documentation