# The Kernel Kit: Areas

Declared in: be/kernel/OS.h

Library: libroot.so

## Overview

An area is a chunk of virtual memory. As such, it has all the expected properties of virtual memory: It has a starting address, a size, the addresses it comprises are contiguous, and it maps to (possibly non-contiguous) physical memory. The features that an area provides that you don't get with "standard" memory are these:

- Areas can be shared. Different areas can refer to the same physical memory. Put another way, different virtual memory addresses can map to the same physical locations. Furthermore, the different areas needn't belong to the same application. By creating and "cloning" areas, applications can easily share the same data.

- Areas can be locked into RAM. You can specify that the area's physical memory be locked into RAM when it's created, locked on a page-by-page basis as pages are swapped in, or that it be swapped in and out as needed.

- Areas can be read- and write-protected.

- Areas are page-aligned. Areas always start on a page boundary, and are allocated in integer multiples of the size of a page. (A page is 4096 bytes, as represented by the `B_PAGE_SIZE` constant.)

- You can specify the starting address of the area's virtual memory. The specification can require that the area start precisely at a certain address, anywhere above a certain address, or anywhere at all.

Because areas are large--one page, minimum--you don't create them arbitrarily. The two most compelling reasons to create an area are the two first points listed above: To share data among different applications, and to lock memory into RAM.

In all particulars (but one) you treat the memory that an area gives you exactly as you would treat any allocated memory: You can read and write it through pointer manipulation, or through standard functions such as `memcpy()` and `strcpy()`. The one difference is between areas and malloc'd memory is...

- You never `free()` the memory that an area allocates for you. If you want to get rid of an area, use the `delete_area()` function, instead.

### Area IDs and Area Names

Each area that you create is tagged with an `area_id` number:

- An `area_id` number is a positive integer that's global and unique within the scope of the computer. They're not unique across the network, nor are they persistent across boots.

- The `area_id` numbers are generated and assigned automatically by the `create_area()` and `clone_area()` functions. The other area functions operate on these `area_id` numbers (they're required as arguments).

- Although they are global, `area_id` numbers have little meaning outside of the address space (application) in which they were created.

- Once assigned, the `area_id` number doesn't change; the number is invalidated when `delete_area()` is called or when the application (team) that created it dies.

- Don't worry about recycled `area_id` numbers. When an area is deleted, it's `area_id` goes with it. (`area_id` values are recycled, but the turnover is at 2^31.)

Areas can also be (loosely) identified by name:

- When you create an area (through `create_area()` or `clone_area()`), you get to name it.

- Area names are not unique--any number of areas can be assigned the same name.

- To look up an area by name, use the `FindArea()` function.

### Sharing an Area Between Applications

For multiple applications to share a common area, one of the applications has to create the area, and the other applications clone the area. You clone an area by calling `clone_area()`. The function takes, as its last argument, the `area_id` of the source area and returns a new (unique) `area_id` number. All further references to the cloned area (in the cloning application) must be based on the area_id that's returned by `clone_area()`.

So how does a cloner find a source `area_id` in the first place?

- The source application can pass the "original" `area_id` number to the cloners.
- The cloners can find the area by name, by calling `find_area()`.

Keep in mind that area names are not forced to be unique, so the `find_area()` method has some amount of uncertainty. But this can be minimized through clever name creation.

#### Cloned Memory

The physical memory that lies beneath an area is never implicitly copied--for example, the area mechanism doesn't perform a "copy-on-write." If two areas refer to the same memory because of cloning, a data modification that's affected through one area will be seen by the other area.

### Locking an Area

When you're working with moderately large amounts of data, it's often the case that you would prefer that the data remain in RAM, even if the rest of your application needs to be swapped out. An argument to `create_area()` lets you declare, through the use of one of the following constants, the locking scheme that you wish to apply to your area:

Constant | Meaning
`B_FULL_LOCK` | The area's memory is locked into RAM when the area is created, and won't be swapped out.
`B_CONTIGUOUS` | Not only is the area's memory locked into RAM, it's also guaranteed to be contiguous. This is particularly--and perhaps exclusively--useful to designers of certain types of device drivers.
`B_LAZY_LOCK` | Allows individual pages of memory to be brought into RAM through the natural order of things and then locks them.
`B_NO_LOCK` | Pages are never locked, they're swapped in and out as needed.
`B_LOMEM` | This is a special constant that's used for for areas that need to be locked, contiguous, and that fit within the first 16MB of physical memory. The folks that need this constant know who they are.

Keep in mind that locking an area essentially reduces the amount of RAM that can be used by other applications, and so increases the likelihood of swapping. So you shouldn't lock simply because you're greedy. But if the area that you're locking is going to be shared among some number of other applications, or if you're writing a real-time application that processes large chunks of data, then locking can be a justifiable excess.

The locking scheme is set by the `create_area()` function and is thereafter immutable. You can't re-declare the lock when you clone an area.

### Area Info

Ultimately, you use an area for the virtual memory that it represents: You create an area because you want some memory to which you can write and from which you can read data. These acts are performed in the usual manner, through references to specific addresses. Setting a pointer to a location within the area, and checking that you haven't exceeded the area's memory bounds as you increment the pointer (while reading or writing) are your own responsibility. To do this properly, you need to know the area's starting address and its extent:

- An area's starting address is maintained as the `address` field in its `area_info` structure; you retrieve the `area_info` for a particular area through the `get_area_info()` function.

- The size of the area (in bytes) is given as the `size` field of its `area_info` structure.

An important point, with regard to `area_info`, is that the `address` field is only valid for the application that created or cloned the area (in other words, the application that created the `area_id` that was passed to `get_area_info()`). Although the memory that underlies an area is global, the address that you get from an `area_info` structure refers to a specific address space.

If there's any question about whether a particular `area_id` is "local" or "foreign," you can compare the `area_info.team` field to your thread's team.

### Deleting an Area

When your application quits, the areas (the `area_id` numbers) that it created through `create_area()` or `clone_area()` are automatically rendered invalid. The memory underlying these areas, however, isn't necessarily freed. An area's memory is freed only when (and as soon as) there are no more areas that refer to it.

You can force the invalidation of an `area_id` by passing it to the `delete_area()` function. Again, the underlying memory is only freed if yours is the last area to refer to the memory.

Deleting an area, whether explicitly through `delete_area()`, or because your application quit, never affects the status of other areas that were cloned from it.

## Example 1: Creating and Writing into an Area

As a simple example of area creation and usage, here we create a ten page area and fill half of it (with nonsense) by bumping a pointer:

       area_id my_area;
       char *area_addr, *ptr;

       /* Create an area. */
       my_area = create_area("my area", /* name you give to the area */
             (void *)&area_addr,   /* returns the starting addr */
             B_ANY_ADDRESS,        /* area can start anywhere */
             B_PAGE_SIZE*10,       /* size in bytes */
             B_NO_LOCK,            /* Lock in RAM?  No. */
             B_READ_AREA | B_WRITE_AREA); /* permissions */

       /* All the errors you're likely to see. */
       switch(my_area) {
          case B_NO_ERROR:
             break;
          case B_NO_MEMORY:
             printf("Not enough swap space (or RAM if locked).\\n");
             return;
          case B_BAD_VALUE:
             printf("Argument to create_area() was invalid.\\n");
             return;
          case B_ERROR:
          default:
             printf("Something bad happened\\n");
             return;
       }

       /* Set ptr to the beginning of the area. */
       ptr = area_addr;

       /* Fill half the area (with random-ish data). */
       for (int i; i < B_PAGE_SIZE*5; i++)
          *ptr++ = system_time()%256;

You can also `memcpy()` and `strcpy()` into the area:

       /* Copy the first half of the area into the second half. */
       memcpy(ptr, area_addr, B_PAGE_SIZE*5);

       /* Overwrite the beginning of the area. */
       strcpy(area_addr, "Hey, look where I am.");

When we're all done, we delete the area:

       delete_area(my_area);

## Example 2: Reading a File into an Area

Here's a function that finds a file, opens it (implicit in the BFile constructor), and copies its contents into RAM:

       #include <File.h>

       area_id file_area;

       status_t file_reader(const char *pathname)
       {
          status_t err;
          char *area_addr;

          BFile file(pathname, B_READ_ONLY);
          if ((err=file.InitCheck()) != B_NO_ERROR) {
             printf("%s: Can't find or open.\\n", pathname);
             return err;
          }

          err = file.GetSize(&file_size);
          if (err != B_NO_ERROR || file_size == 0) {
             printf("%s:  Disappeared?  Empty?\\n", pathname);
             return err;
          }

          /* Round the size up to the nearest page. */
          file_size = (((file_size-1)%B_PAGE_SIZE)+1)*B_PAGE_SIZE;

          /* Make sure the size won't overflow a size_t spec. */
          if (file_size >= ((1<<32)-1) ) {
             printf("%s: What'd you do?  Read Montana?\\n");
             return B_NO_MEMORY;
          }
          file_area = create_area("File area", (void *)&area_addr,
             B_ANY_ADDRESS, file_size, B_FULL_LOCK,
             B_READ_AREA | B_WRITE_AREA);

          /* Check create_area() errors, as in the last example. */
          ...

          /* Read the file; delete the area if there's an error. */
          if ((err=file.Read(area_addr, file_size)) < B_NO_ERROR) {
             printf("%s: File read error.\\n");
             delete_area(file_area);
             return err;
          }

          /* The file is automatically closed when the stack-based
           * BFile is destroyed.
           */
          return B_NO_ERROR;
       }

## Example 3: Accessing a Designated Area

In the previous example, a local variable (`area_addr`) was used to capture the starting address of the newly-created area. If some other function wants to access the area, it must "re-find" the starting address (and the length of the area, for boundary checking). To do this, you call `get_area_info()`.

In the following example, an area is passed in by name; the function, which will write its argument buffer to the area, calls `get_area_info()` to determine the start and extent of the area, and also to make sure that the area is part of this team. If the area was created by some other team, the function could still write to it, but it would have to clone the area first (cloning is demonstrated in the next example).

       status_t write_to_area(const char *area_name,
                      const void *buf,
                      size_t len)
       {
          area_id area;
          area_info ai;
          thread_id thread;
          thread_info ti;
          status_t err;

          if (!area_name)
             return B_BAD_VALUE;

          area = find_area(area_name);

          /* Did we find it? */
          if (area < B_NO_ERROR) {
             printf("Couldn't find area %s.\\n", area_name);
             return err;
          }

          /* Get the info. */
          err = get_area_info(area, &ai);

          if (err < B_NO_ERROR) {
             printf("Couldn't get area info.\\n");
             return err;
          }

          /* Get the team of the calling thread; to do this, we have
           * to look in the thread_info structure.
           */
          err = get_thread_info(find_thread(NULL), &ti);

          if (err < B_NO_ERROR) {
             printf("Couldn't get thread info.\\n");
             return err;
          }

          /* Compare this team to the area's team. */
          if (ai.team != ti.team)
             printf("Foreign area.\\n");
             return B_NOT_ALLOWED;
          }
          /* Make sure we're not going to overflow the area,
           * and make sure this area can be written to.
           */
          if (len > ai.size) {
             printf("Buffer bigger than area.\\n");
             return B_BAD_VALUE;
          }
          if (!(ai.protection & B_WRITE_AREA)) {
             printf("Can't write to this area.\\n");
             return B_NOT_ALLOWED;
          }

          /* Now we can write. */
          memcpy(ai.address, buf, len);
          return B_NO_ERROR;
       }

It's important that you only write to areas that were created or cloned within the calling team. The starting address of a "foreign" area is usually meaningless within your own address space.

You don't have to check the area's protectection before writing to it (or reading from it). The memory-accessing fucntions (`memcpy()`, in this example) will simply fail if an invalid read or write is requested.

However, you do have to do your own boundary checking. None of the memory-accessing functions know anything about area boundaries: `memcpy()` will gladly write beyond the end of the area (and possibly seg fault) if you that's what you ask for.

## Example 4: Cloning and Sharing an Area

In the following example, a server and a client are set up to share a common area. Here's the server:

       /* Server side */
       class AServer
       {
          status_t make_shared_area(size_t size);
          area_id the_area;
          char *area_addr;
       };

       status_t AServer::make_shared_area(size_t size)
       {
          /* The size must be rounded to a page. */
          size = ((size % B_PAGE_SIZE)+1) * B_PAGE_SIZE;
          the_area = create_area("server area", (void *)&area_addr
                   B_ANY_ADDRESS, size, B_NO_LOCK,
                    B_READ_AREA|B_WRITE_AREA);

          if (the_area < B_NO_ERROR) {
             printf("Couldn't create server area\\n");
             return the_area;

          return B_NO_ERROR;
       }

And here's the client:

       /* Client side */
       class AClient
       {
          status_t make_shared_clone();
          area_id the_area;
          char *area_addr;
       };

       status_t AClient::make_shared_clone()
       {
          area_id src_area;

          src_area = find_area("server area");
          if (src_area < B_ERROR) {
             printf("Couldn't find server area.\\n");
             return src_area;
          }
          the_area = clone_area("client area",
                      (void *)&area_addr,
                         B_ANY_ADDRESS,
                      B_READ_AREA | B_WRITE_AREA,
                      src_area);

          if (the_area < B_NO_ERROR)
             printf("Couldn't create clone area\\n");
             return the_area;
          }
          return B_NO_ERROR;
       }

Notice that the area creator (the server in the example) doesn't have to designate the created area as sharable. All areas are candidates for cloning.

After it creates the cloned area, the client's `area_id` value (`AClient::the_area`) will be different from the server's (`AServer::the_area`). Even though `area_id` numbers are global, the client should only refer to the server's `area_id` number in order to clone it. After the clone, the client talks to the area through its own `area_id` (the value passed backed by `clone_area()`).

## Example 5: Cloning Addresses

It's sometimes useful for shared areas (in other words, a "source" and a clone) to begin at the same starting address. For example, if a client's clone area starts at the same address as the server's original area, then the client and server can pass area-accessing pointers back and forth without having to translate the addresses. Here we modify the previous example to do this:

       status_t AClient::make_shared_clone()
       {
          area_id src_area;

          src_area = find_area("server area");

          if (src_area < B_ERROR) {
             printf("Couldn't find server area.\\n");
             return B_BAD_VALUE;
          }

          /* This time, we specify the address that we want the
           * clone to start at.  The B_CLONE_ADDRESS constant
           * does this for us.
           */
          area_addr = src_info.address;
          the_area = clone_area("client area",
                      (void *)&area_addr,
                         B_CLONE_ADDRESS,
                      B_READ_AREA | B_WRITE_AREA,
                      src_area);

          if (the_area < B_NO_ERROR)
             printf("Couldn't create clone area\\n");
             return the_area;
          }
          return B_NO_ERROR;
       }

Of course, demanding that an area begin at a specific address can be too restrictive; if any of the memory within [area_addr, area_addr + src_info.size] is already allocated, the clone will fail.

## Area Functions

### area_for()

          area_id area_for(void *addr)

Returns the area that contains the given address (within your own team's address space). The argument needn't be the starting address of an area, nor must it start on a page boundary: If the address lies anywhere within one of your application's areas, the ID of that area is returned.

Since the address is taken to be in the local address space, the area that's returned will also be local--it will have been created or cloned by your application.

RETURN CODES

- `B_ERROR`. The address doesn't lie within an area.

See also: `find_area()`

### clone_area()

          area_id clone_area(const char *clone_name,
             void **clone_addr,
             uint32 clone_addr_spec,
             uint32 clone_protection,
             area_id source_area)

Creates a new area (the clone area) that maps to the same physical memory as an existing area (the source area).

- clone_name is the name that you wish to assign to the clone area. Area names are, at most, `B_OS_NAME_LENGTH` characters long.

- clone_addr points to a value that gives the address at which you want the clone area to start; the pointed-to value must be a multiple of `B_PAGE_SIZE` (4096). The function sets the value pointed to by clone_addr to the area's actual starting address--it may be different from the one you requested. The constancy of *clone_addr depends on the value of clone_addr_spec, as explained next.

- clone_addr_spec is one of four constants that describes how clone_addr is to be interpreted. The first three constants,`B_EXACT_ADDRESS`, `B_BASE_ADDRESS`, and `B_ANY_ADDRESS`, have meanings as explained under `create_area()`.

  The fourth constant, `B_CLONE_ADDRESS`, specifies that the address of the cloned area should be the same as the address of the source area. Cloning the address is convenient if you have two (or more) applications that want to pass pointers to each other--by using cloned addresses, the applications won't have to offset the pointers that they receive. For both the `B_ANY_ADDRESS` and `B_CLONE_ADDRESS` specifications, the value that's pointed to by the clone_addr argument is ignored.

- clone_protection is one or both of `B_READ_AREA` and `B_WRITE_AREA`. These have the same meaning as in `create_area()`; keep in mind, as described there, that a cloned area can have a protection that's different from that of its source.

- source_area is the `area_id` of the area that you wish to clone. You usually supply this value by passing an area name to the `find_area()` function.

The cloned area inherits the source area's locking scheme.

Usually, the source area and clone area are in two different applications. It's possible to clone an area from a source that's in the same application, but there's not much reason to do so unless you want the areas to have different protections.

If `clone_area()` clone is successful, the clone's `area_id` is returned. Otherwise, it returns a descriptive error code, listed below.

RETURN CODES

- `B_BAD_VALUE`. Bad argument value; you passed an unrecognized constant for addr_spec or lock, the addr value isn't a multiple of `B_PAGE_SIZE`, you set addr_spec to `B_EXACT_ADDRESS` or `B_CLONE_ADDRESS` but the address request couldn't be fulfilled, or source_area doesn't identify an existing area.

- `B_NO_MEMORY`. Not enough memory to allocate the system structures that support this area (unlikely).

- `B_ERROR`. Some other system error prevented the area from being created.

See also: `create_area()`

### create_area()

          area_id create_area(const char *name,
             void **addr,
             uint32 addr_spec,
             uint32 size,
             uint32 lock,
             uint32 protection)

Creates a new area and returns its `area_id.`

- name is the name that you wish to assign to the area. It needn't be unique. Area names are, at most, `B_OS_NAME_LENGTH` (32) characters long.

- addr points to the address at which you want the area to start. The value of *addr must signify a page boundary; in other words, it must be an integer multiple of `B_PAGE_SIZE` (4096). Note that this is a pointer to a pointer: *addr--not addr--should be set to the desired address; you then pass the address of addr as the argument, as shown below:

          /* Set the address to a page boundary. */
          char *addr = (char *)(B_PAGE_SIZE * 100);

          /* Pass the address of addr as the second argument. */
          create_area( "my area", &addr, ...);

The function sets the value of *addr to the area's actual starting address--it may be different from the one you requested. The constancy of *addr depends on the value of addr_spec, as explained next.

- addr_spec is a constant that tells the function how the *addr value should be applied. There are three useful address specification constants, and one that doesn't apply here:

Constant | Meaning
`B_EXACT_ADDRESS` | You want the value of *addr to be taken literally and strictly. If the area can't be allocated at that location, the function fails.
`B_BASE_ADDRESS` | The area can start at a location equal to or greater than *addr.
`B_ANY_ADDRESS` | The starting address is determined by the system. In this case, the value that's pointed to by addr is ignored (going into the function).
`B_CLONE_ADDRESS` | This is only meaningful to the `clone_area()` function.

- size is the size, in bytes, of the area. The size must be an integer multiple of `B_PAGE_SIZE` (4096). The upper limit of size depends on the available swap space (or RAM, if the area is to be locked).

- lock describes how the physical memory should be treated with regard to swapping. There are four locking constants:

Constant | Meaning
`B_FULL_LOCK` | The area's memory is locked into RAM when the area is created, and won't be swapped out.
`B_CONTIGUOUS` | Not only is the area's memory locked into RAM, it's also guaranteed to be contiguous. This is particularly--and perhaps exclusively--useful to designers of certain types of device drivers.
`B_LAZY_LOCK` | Allows individual pages of memory to be brought into RAM through the natural order of things and then locks them.
`B_NO_LOCK` | Pages are never locked, they're swapped in and out as needed.
`B_LOMEM` | This is a special constant that's used for for areas that need to be locked, contiguous, and that fit within the first 16MB of physical memory. The folks that need this constant know who they are.

- protection is a mask that describes whether the memory can be written and read. You form the mask by adding the constants `B_READ_AREA` (the area can be read) and `B_WRITE_AREA` (it can be written). The protection you describe applies only to this area. If your area is cloned, the clone can specify a different protection.

If `create_area()` is successful, the new`area_id` number is returned. If it's unsuccessful, one of the following error constants is returned.

RETURN CODES

- `B_BAD_VALUE`. Bad argument value. You passed an unrecognized constant for addr_spec or lock, the addr or size value isn't a multiple of `B_PAGE_SIZE`, or you set addr_spec to `B_EXACT_ADDRESS` but the address request couldn't be fulfilled.

- `B_NO_MEMORY`. Not enough memory to allocate the system structures that support this area (unlikely), not enough physical memory to support a locked area, or not enough swap space to allocate virtual memory (in other words, size is too big.)

- `B_ERROR`. Some other system error prevented the area from being created.

See also: `clone_area()`

### delete_area()

          status_t delete_area(area_id area)

Deletes the designated area. If no one other area maps to the physical memory that this area represents, the memory is freed. After being deleted, the area value is invalid as an area identifier.

|  | Currently, anybody can delete any area--the act isn't denied if, for example, the `area_id` argument was created by another application. This freedom will be rescinded in a later release. Until then, try to avoid deleting other application's areas.

RETURN CODES

- `B_NO_ERROR`. The area was deleted; area is now invalid.
- `B_ERROR`. area doesn't designate an actual area.

### find_area()

          area_id find_area(const char *name)

Returns an area that has a name that matches the argument. Area names needn't be unique--successive calls to this function with the same argument value may not return the same `area_id`.

What you do with the area you've found depends on where it came from:

- If you're finding an area that your own application created or cloned, you can use the returned ID directly.

- If the area was created or cloned by some other application, you should immediately clone the area (unless you're doing something truly innocuous, such as simply examining the area's info structure).

RETURN CODES

- `B_NAME_NOT_FOUND`. The argument doesn't identify an existing area.

See also: `area_for()`

### get_area_info(), get_next_area_info(), area_info

          status_t get_area_info(area_id area, area_info *info)
          status_t get_next_area_info(team_id team, uint32 *cookie, area_info *info)

          struct {} area_info

Copies information about a particular area into the `area_info` structure designated by info. The first version of the function designates the area directly, by `area_id`.

The `get_next_area_info()` version lets you step through the list of a team's areas through iterated calls on the function. The team argument identifies the team you want to look at; a team value of 0 means the team of the calling thread. The cookie argument is a placemark; you set it to 0 on your first call, and let the function do the rest. The function returns `B_BAD_VALUE` when there are no more areas to visit:

       /* Get the area_info for every area in this team. */
       area_info info;
       int32 cookie = 0;

       while (get_next_area_info(0, &cookie, &info) == B_OK)
          ...

The `area_info` structure is:

          typedef struct area_info {
                area_id  area;
                char  name[B_OS_NAME_LENGTH];
                size_t  size;
                uint32  lock;
                uint32  protection;
                team_id  team;
                size_t  ram_size;
                uint32  copy_count;
                uint32  in_count;
                uint32  out_count;
                void  *address;
             } area_info;

The fields are:

- `area` is the `area_id` that identifies the area.

- `name` is the name that was assigned to the area when it was created or cloned.

- `size` is the (virtual) size of the area, in bytes.

- `lock` is a constant that represents the area's locking scheme. This will be one of `B_FULL_LOCK`, `B_CONTIGUOUS, B_LAZY_LOCK`, `B_NO_LOCK`, or `B_LOMEM`.

- `protection` specifies whether the area's memory can be read or written. It's a combination of `B_READ_AREA` and `B_WRITE_AREA.

  `
- `team` is the `team_id` of the team that created or cloned this area.

- `address` is a pointer to the area's starting address. Keep in mind that this address is only meaningful to the team that created (or cloned) the area.

The final four fields give information about the area that's useful in diagnosing system use. The fields are particularly valuable if you're hunting for memory leaks:

- `ram_size` gives the amount of the area, in bytes, that's currently swapped in.

- `copy_count` is a "copy-on-write" count that can be ignored--it doesn't apply to the areas that you create. The system can create copy-on-write areas (it does so when it loads the data section of an executable, for example), but you can't.

- `in_count` is a count of the total number of times any of the pages in the area have been swapped in.

- `out_count` is a count of the total number of times any of the pages in the area have been swapped out.

RETURN CODES

- `B_NO_ERROR`. The area was found; info contains valid information.
- `B_BAD_VALUE`. area doesn't identify an existing area, team doesn't identify an existing team, or there are no more areas to visit.

### resize_area()

          status_t resize_area(area_id area, size_t new_size)

Sets the size of the designated area to new_size, measured in bytes. The new_size argument must be a multiple of `B_PAGE_SIZE` (4096).

Size modifications affect the end of the area's existing memory allocation: If you're increasing the size of the area, the new memory is added to the end of area; if you're shrinking the area, end pages are released and freed. In neither case does the area's starting address change, nor is existing data modified (except, of course, for data that's lost due to shrinkage).

Resizing affects all areas that refer to this areas physical memory. For example, if B is a clone of A, and you resize A, B will be automatically resized (if possible).

RETURN CODES

- `B_NO_ERROR`. The area was successfully resized.

- `B_BAD_VALUE`. area doesn't signify a valid area, or new_size isn't a multiple of `B_PAGE_SIZE`.

- `B_NO_MEMORY`. Not enough memory to support the new portion of the area. This should only happen if you're increasing the size of the area.

- `B_ERROR`. Some other system error prevented the area from being created.

### set_area_protection()

          status_t set_area_protection(area_id area, uint32 new_protection)

Sets the given area's read and write protection. The new_protection argument is a mask that specifies one or both of the values `B_READ_AREA` and `B_WRITE_AREA`. The former means that the area can be read; the latter, that it can be written to. An area's protection only applies to access to the underlying memory through that specific area. Different area clones that refer to the same memory may have different protections.

RETURN CODES

- `B_NO_ERROR`. The protection was changed.
- `B_BAD_VALUE`. area doesn't identify a valid area.

The Be Book, in lovely HTML, for BeOS Release 3.

Copyright © 1998 Be, Inc. All rights reserved.

Last modified March 26, 1998.