ChorusOS 4.0 Introduction

Sharing Memory Between Two Actors

The ChorusOS operating system offers the possibility of sharing an area of memory between two or more actors, regardless of whether these actors are user or supervisor actors. The memory area does not need to be located at the same address within the address space of each actor.

This mechanism is based on the following service:

#include <chorus.h>

int rgnMapFromActor(KnCap*    targetActor,
                    KnRgnDesc*targetRgnDesc,
                    KnCap*    sourceActor,
                    KnRgnDesc*sourceRgnDesc);

This call allows mapping of a memory area as defined by sourceActor and sourceRgnDesc in the address space of the actor defined by the targetActor parameter. The source memory area is explicitly defined by the startAddr and size fields of the sourceRgnDesc parameter. The region created within the address space of the target actor is defined by the targetRgnDesc parameter: the address may be fixed or undefined if the K_ANYWHERE flag is set. After the mapping has been established, both actors may freely use the shared memory area.

Figure 7-2 shows two actors before they share memory and after sharing has been established. Usually some synchronization mechanism is required in order to get a consistent view of the memory: semaphores may be used in shared memory areas to synchronize threads from the various actors.

Figure 7-2 Actors Sharing Memory

Graphic

Example 7-2 does the following:

This example uses a call which enables an actor to get its own capability in order to pass it to another actor.

#include <chorus.h>

int actorSelf(KnCap* myCap);

Refer to the rgnMapFromActor(2K) man page.


Example 7-2 Sharing a Memory Region

(file: progov/rgnMapFromActor.c)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <chorus.h>
#include <am/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
         */
    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);							      
    }								      

    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;
}