Simultaneous access synchronization

The following example shows how the mailbox works during the parallel data retrieval by multiple tasks. The two tasks waits for incoming data that is sent by three other task.

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

TIME StartTime;


static ERROR SenderTask(PVOID Arg)
{
  HANDLE MailboxHandle;
  int Message;

  /* Sleep for specified amount of time */
  osSleep(100 * ((TIME) Arg));

  /* Open the mailbox */
  MailboxHandle = osOpenMailbox("Mbox1");

  /* Send messages continuously */
  while(MailboxHandle)
  {
    /* Send first message after one second */
    osSleep(1000);

    /* Send message */
    Message = (int) Arg;
    osMailboxPost(MailboxHandle, &Message, sizeof(Message));
  }

  /* Return with success */
  return ERR_NO_ERROR;
}


static ERROR ReceiverTask(PVOID Arg)
{
  HANDLE MailboxHandle;
  BOOL PrevLockState;
  int Message;

  /* Open the mailbox */
  MailboxHandle = osOpenMailbox("Mbox1");

  /* Receive all sent messages */
  while(MailboxHandle)
  {
    osMailboxPend(MailboxHandle, &Message, sizeof(Message));

    /* Enter critical section */
    PrevLockState = arLock();

    /* Print the message */
    printf("%8i: Task%i receives message from task%i\n",
      (int) (arGetTickCount() - StartTime),
      (int) Arg,
      Message);

    /* Leave critical section */
    arRestore(PrevLockState);
  }

  /* Return with success */
  return ERR_NO_ERROR;
}


int main(void)
{
  /* Initialization */
  arInit();
  stInit();
  osInit();

  /* Startup time */
  StartTime = arGetTickCount();

  /* Create mailbox */
  osCreateMailbox("Mbox1", OS_IPC_PROTECT_MUTEX |
    OS_IPC_WAIT_IF_EMPTY | OS_IPC_DIRECT_READ_WRITE);

  /* Create sender tasks */
  osCreateTask(SenderTask, (PVOID) 1, 0, 0, FALSE);
  osCreateTask(SenderTask, (PVOID) 2, 0, 0, FALSE);
  osCreateTask(SenderTask, (PVOID) 3, 0, 0, FALSE);

  /* Create receiver tasks */
  osCreateTask(ReceiverTask, (PVOID) 4, 0, 0, FALSE);
  osCreateTask(ReceiverTask, (PVOID) 5, 0, 0, FALSE);

  /* Start the operating system */
  osStart();

  /* Deinitialization */
  osDeinit();
  arDeinit();
  return 0;
}

When both tasks are waiting for incoming message, the first of waiting tasks will read a message. When it again starts waiting for incoming message, it will be queued, and a second task will read message as first. The result on the console should look as follows:

    1100: Task4 receives message from task1
    1200: Task5 receives message from task2
    1300: Task4 receives message from task3
    2100: Task5 receives message from task1
    2200: Task4 receives message from task2
    2300: Task5 receives message from task3
    3100: Task4 receives message from task1
    3200: Task5 receives message from task2
    3300: Task4 receives message from task3
    4100: Task5 receives message from task1
    4200: Task4 receives message from task2
    4300: Task5 receives message from task3
SpaceShadow documentation