ChorusOS 5.0 Application Developer's Guide

Allocating and Freeing Memory Regions

A memory region is allocated through the following call:

#include <chorus.h>
int rgnAllocate(KnCap*				actorCap,
                KnRgnDesc*			rgnDesc);		

This call frees a memory region within the address space of an actor. The memory region is described by the rgnDesc parameter and the actor is defined by the actorCap parameter.

Figure 8-1 Allocating and Freeing Memory Regions

Graphic

The following example includes these steps:

The illustration in Figure 8-1 shows only the main steps of the example. For more information, refer to the rgnAllocate(2K) and rgnFree(2K) man pages.


Example 8-1 Allocating a Memory Region

(file: progov/rgnAlloc.c)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <chorus.h>
#define RGN_SIZE_1 (6 * vmPageSize())
#define RGN_SIZE_2 (3 * vmPageSize())
#define FREE_START (2 * vmPageSize())
#define FREE_SIZE  (4 * vmPageSize())
#define STILL_ALLOC_START (FREE_SIZE - (RGN_SIZE_2 - FREE_START))
int main(int argc, char** argv, char**envp)
{
  KnRgnDesc           rgnDesc;
  KnActorPrivilege    actorP;
  int                 res;
  VmFlags             rgnOpt = 0;
  char*               ptr1 = NULL; /* Avoids "unexpected" warning */
  char*               ptr2 = NULL; /* Avoids "unexpected" warning */
  printf("Starting rgnAllocate example\n");         
  res = actorPrivilege(K_MYACTOR, &actorP, NULL);
  if (res != K_OK) {            
    printf("Cannot get actor privilege, error %d\n", res);       
    exit(1);             
  }              
  if (actorP == K_SUPACTOR) {
    rgnOpt = K_SUPERVISOR;
  }
  rgnDesc.size = RGN_SIZE_1;
  rgnDesc.options = rgnOpt | K_WRITABLE | K_FILLZERO | K_ANYWHERE;
  rgnDesc.opaque1 = NULL;
  rgnDesc.opaque2 = NULL;
      /*
       * No need to set rgnDesc.startAddr
       * since we set the K_ANYWHERE flag
       */
  res = rgnAllocate(K_MYACTOR, &rgnDesc);
  if (res == K_OK) {
    printf("Successfully allocated memory starting at 0x%x\n", 
    rgnDesc.startAddr);
    ptr1 = (char*) rgnDesc.startAddr;
  } else {
    printf("First rgnAllocate failed with error %d\n", res);
    exit(1);
  }
  strcpy(ptr1, "Fill the allocated memory with this string\n");
      /* 
       * Second allocate has a fixed address, such that
       * both memory areas will be contiguous. Hence
       * we do not want the K_ANYWHERE flag any more.
       */
  rgnDesc.size       = RGN_SIZE_2;
  rgnDesc.options   &= ~K_ANYWHERE;
  rgnDesc.startAddr -= RGN_SIZE_2;
  res = rgnAllocate(K_MYACTOR, &rgnDesc);
  if (res == K_OK) {
    printf("Successfully allocated memory starting at 0x%x)\n", 
    rgnDesc.startAddr);
    ptr2 = (char*) rgnDesc.startAddr;
  } else {
    printf("Second rgnAllocate failed with error %d\n", res);
    exit(1);
  }
      /* Copy from first allocated area to second one */
  strcpy(ptr2, ptr1);
      /* 
       * Free a memory area spanning both areas 
       * previously created
       */
  rgnDesc.options = NULL;
  rgnDesc.startAddr = (VmAddr) (ptr2 + FREE_START);
  rgnDesc.size      = FREE_SIZE;
  res = rgnFree(K_MYACTOR, &rgnDesc);
  if (res != K_OK) {            
    printf("Cannot free memory, error %d\n", res);        
    exit(1);             
  }              
      /* 
       * Access to ptr2: beginning of secondly allocated area
       * is still valid.
       * Access to ptr1 is now invalid: memory has been freed.
       */
  printf("%s", ptr2); 
      /*
       * Access to "end" of first allocated area
       * is still valid
       */
  ptr1 += STILL_ALLOC_START;
  strcpy(ptr1, ptr2);
      /*
       * Remaining memory areas not yet freed will 
       * effectively be freed at actor termination time.
       */
  return 0;
}

Region descriptors are only used to describe a creation or deletion operation on the system. They are not kept by the system because of the way in which they are given to the rgnAllocate(2K) call. For example, an allocation of two contiguous areas with the same attributes (writable, fill zero) and the same opaque fields results in the system recognizing a single region, the size of which is the sum of the sizes passed as part of the two region descriptors.

You cannot allocate a region in a range of addresses that are not free. No implicit deallocation of the address space is undertaken by the system. Instead an error code K_EOVERLAP is returned to the caller.

A call to rgnFree(2K) does not reuse a region descriptor that was previously used to allocate a memory area. A free operation can freely span several regions that were allocated by separate operations. Also, a free operation can only free a chunk of memory in the center of a large memory area that was allocated in a single operation.

Only the precise region described by the region descriptor can be freed. The free operation is not extended to match the address range which was allocated at rgnAllocate(2K) time.

The options field of the region descriptor must be set to 0 to use the free operation. If the options field is set to K_FREEALL, all memory regions of the actor will be freed (the code, the data, and the stacks). The K_FREEALL option should therefore be used with care.

All memory areas that have been dynamically allocated are freed when an actor terminates.