ChorusOS 5.0 Application Developer's Guide

Sharing Memory Between Applications

The following code example shows how to share memory between applications.


Example 8-2 Sharing Memory Between Actors

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <chorus.h>
#include <cx/afexec.h>

AcParam param;

#define RGN_SIZE  (3 * vmPageSize())
#define SHARED_RGN_SIZE (1 * vmPageSize())

typedef struct sampleSharedArea {
  KnSem    sem;
  char     data[1];
} sharea_t;

char capString[80];
char sharedAddr[20];

int main(int argc, char** argv, char**envp)
{
  KnRgnDesc    rgnDesc;
  sharea_t*    ptr;
  KnCap        spawningCap;
  KnCap        spawnedCap;
  int          res;
  VmFlags      rgnOpt = 0;
  KnActorPrivilege actorP;

  res = actorPrivilege(K_MYACTOR, &actorP, NULL);
  if (res != K_OK) {                                                  
    printf("Cannot get privilege, error %d\n", res);                  
    exit(1);                                                          
  }                                                                   
                                                                      
  if (actorP == K_SUPACTOR) {
    rgnOpt = K_SUPERVISOR;
  }

  if (argc == 1) {
        /*
         * This is the first actor (or spawning actor):
         *   Allocate a memory region
         *   Initialize a semaphore within the region
         *   Spawn the second actor
         *   Wait on the semaphore
         *   Get data written in shared mem by spawned actor
         *   Terminate
         */
    rgnDesc.size = RGN_SIZE;
    rgnDesc.options = rgnOpt | K_ANYWHERE | K_WRITABLE | K_FILLZERO;
    rgnDesc.opaque1 = NULL;
    rgnDesc.opaque2 = NULL;

    res = rgnAllocate(K_MYACTOR, &rgnDesc);
    if (res != K_OK) {                                                
      printf("Cannot allocate memory, error %d\n", res);              
      exit(1);                                                        
    }                                                                 

    ptr = (sharea_t*) rgnDesc.startAddr;

    strcpy(&ptr->data[0], "First actor initializing the shared mem\n");

    res = semInit(&ptr->sem, 0);

        /*
         * Get my own capability and pass it as a string argument
         * to spawned actor, so that it may use it to share memory
         */
    (void) actorSelf(&spawningCap);
    sprintf(capString, "0x%x 0x%x 0x%x 0x%x", spawningCap.ui.uiHead,
            spawningCap.ui.uiTail, spawningCap.key.keyHead,
            spawningCap.key.keyTail);

        /*
         * Pass address of memory to be shared as a string argument
         * to spawned actor.
         */
    sprintf(sharedAddr, "0x%x", ptr);

    param.acFlags = (actorP == K_SUPACTOR)? AFX_SUPERVISOR_SPACE : 
                                            AFX_USER_SPACE;
    res = afexeclp(argv[0], &spawnedCap, &param , argv[0], capString,
                   sharedAddr, NULL);
    if (res == -1) {                                                  
      printf("cannot spawn second actor, error %d\n", errno);         
      exit(1);                                                        
    }                                                                 

    (void) semP(&ptr->sem, K_NOTIMEOUT);

    printf("%s", &ptr->data[0]);

  } else {
    
    KnRgnDesc srcRgn;
    KnRgnDesc tgtRgn;
    unsigned long uHead, uTail, kHead, kTail;
        /*
         * This is the spawned actor:
         *   Get arguments
         *   Set up the memory sharing 
         *   Write some string in shared memory
         *   Wake up spawning actor
         *   Terminate
         */
    sscanf(argv[1], "0x%x 0x%x 0x%x 0x%x", &uHead, &uTail, &kHead, &kTail);
    spawningCap.ui.uiHead = uHead;
    spawningCap.ui.uiTail = uTail;
    spawningCap.key.keyHead = kHead;
    spawningCap.key.keyTail = kTail;

    sscanf(argv[2], "0x%x", &srcRgn.startAddr);

    if (actorP != K_SUPACTOR) {

      srcRgn.size      = SHARED_RGN_SIZE;
      tgtRgn.startAddr = srcRgn.startAddr;
      tgtRgn.size      = SHARED_RGN_SIZE; 
      tgtRgn.options   = rgnOpt | K_WRITABLE;
      tgtRgn.opaque1   = NULL;
      tgtRgn.opaque2   = NULL;

      res = rgnMapFromActor(K_MYACTOR, &tgtRgn, &spawningCap, &srcRgn);

      if (res != K_OK) {
        printf("Cannot share memory, error %d\n", res);
        exit(1);
      }
      ptr = (sharea_t*) tgtRgn.startAddr;

    } else {
          /*
           * Both actors are running in supervisor space,
           * There is no need to perform the rgnMapFromActor.
           * One may use the received shared address.
           */
      ptr = (sharea_t*) srcRgn.startAddr;
    }

        /* Get data from spawning actor */
    printf("Spawning actor sent: %s", &ptr->data[0]);

        /* Modify contents of shared memory */
    sprintf(&ptr->data[0], "Spawned actor mapped shared memory at 0x%x\n",
            ptr);

    res = semV(&ptr->sem);
    if (res != K_OK) {                                                
      printf("Spawned actor failed on semV, error %d\n", res);        
      exit(1);                                                        
    }                                                                 
  }
  return 0;
}