# The Kernel Kit: Threads and Teams

Declared in: be/kernel/OS.h

Library: libroot.so

## Overview

A thread is a synchronous process that executes a series of program instructions. Every application has at least one thread: When you launch an application, an initial thread--the main thread--is automatically created (or spawned) and told to run. The main thread executes the ubiquitous `main()` function, winds through the functions that are called from `main()`, and is automatically deleted (or killed) when `main()` exits.

The Be operating system is multi-threaded: From the main thread you can spawn and run additional threads; from each of these threads you can spawn and run more threads, and so on. All the threads in all applications run concurrently and asynchronously with each other.

Threads are independent of each other. Most notably, a given thread doesn't own the other threads it has spawned. For example, if thread A spawns thread B, and thread A dies (for whatever reason), thread B will continue to run. (But before you get carried away with the idea of leap-frogging threads, you should take note of the caveat in Death and the Main Thread.)

|  | Threads and the POSIX fork() function are not compatible. You can't mix calls to `spawn_thread()` (the function that creates a new thread) and `fork()` in the same application: If you call `spawn_thread()` and then try to call `fork()`, the `fork()` call will fail. And vice versa.

### Teams

Although threads are independent, they do fall into groups called teams. A team consists of a main thread and all other threads that "descend" from it (that are spawned by the main thread directly, or by any thread that was spawned by the main thread, and so on). Viewed from a higher level, a team is the group of threads that are created by a single application. You can't "transfer" threads from one team to another. The team is set when the thread is spawned; it remains the same throughout the thread's life.

All the threads in a particular team share the same address space: Global variables that are declared by one thread will be visible to all other threads in that team.

### Spawning a Thread

You spawn a thread by calling the `spawn_thread()` function. The function assigns and returns a system-wide `thread_id` number that you use to identify the new thread in subsequent function calls. Valid `thread_id` numbers are positive integers; you can check the success of a spawn thus:

       thread_id my_thread = spawn_thread(...);

       if ((my_thread) < B_NO_ERROR)
          /* failure */
       else
          /* success */

The arguments to `spawn_thread()`, which are examined throughout this description, supply information such as what the thread is supposed to do, the urgency of its operation, and so on.

#### Threads and App Images

A conceptual neighbor of spawning a thread is the act of loading an executable (or loading an app image). This is performed by calling the `load_image()` function. Loading an image causes a separate program, identified as a file, to be launched by the system. For more information on the`load_image()` function, see "The Kernel Kit: Threads and Teams."

### Telling a Thread to Run

Spawning a thread isn't enough to make it run. To tell a thread to start running, you must pass its `thread_id` number to either the `resume_thread()` or `wait_for_thread()` function:

- `resume_thread()` starts the new thread running and immediately returns. The new thread runs concurrently and asynchronously with the thread in which `resume_thread()` was called.

- `wait_for_thread()` starts the thread running but doesn't return until the thread has finished. (You can also call `wait_for_thread()` on a thread that's already running.)

Of these two functions, `resume_thread()` is the more common means for starting a thread that was created through`spawn_thread()`. `wait_for_thread()` is typically used to start the thread that was created through `load_image()`.

### The Thread Function

When you call `spawn_thread()`, you must identify the new thread's thread function. This is a global C function (or a static C++ member function) that the new thread will execute when it's told to run. When the thread function exits, the thread is automatically killed.

The `thread_func` type represents a pointer to a thread function:

       typedef int32 (*thread_func)(void *);

- The function accepts a pointer to a buffer of arbitrarily-typed data. What the function does with the data is up to your application. (See The Thread Function's Argument for more information and caveats.)

- The return value is a 32-bit integer value that's typically interpreted as an error code. To whom the value is returned is explored in Thread Function Return Values.

- The function's name isn't prescribed by the protocol; in other words, a thread function doesn't have to be named "thread_func".

You specify a thread function by passing a `thread_func` as the first argument to `spawn_thread()`; the last argument to`spawn_thread()` is forwarded as the thread function's data argument. Since data is delivered as a `void *`, you have to cast the value to the appropriate type within your implementation of the thread function. For example, let's say you define a thread function called `lister()` that takes a pointer to a BList object as an argument:

       int32 lister(void *data)
       {
          /* Cast the argument. */
          BList *listObj = (BList *)data;
          ...
       }

To create and run a thread that would execute the `lister()` function, you call `spawn_thread()` and `resume_thread()` thus (excluding error checks):

       BList *listObj = new BList();
       thread_id my_thread;

       my_thread = spawn_thread(lister, ..., (void *)listObj);
       resume_thread(my_thread);

#### The Thread Function's Argument

The`spawn_thread()` function doesn't copy the data that data points to. It simply passes the pointer through literally. Because of this, you should never pass a pointer that's allocated locally (on the stack).

The reason for this restriction is that there's no guarantee that the thread function will receive any CPU attention before the stack frame from which `spawn_thread()` was called is destroyed. Thus, the thread function won't necessarily have a chance to copy the pointed-to data before the data pointer is freed. There are ways around this restriction--for example, you could use a semaphore to ensure that the thread function has copied the data before the calling frame exits. A better solution is to forego the data argument and use the `send_data()` function (which does copy its data). See Passing Data to a Thread.

#### Using a C++ Thread Function

If you're up in C++ territory, you'll probably want to define a class member function that you can use as a thread function. Unfortunately, you can't pass a normal (non-static) member function directly as the thread function argument to `spawn_thread()`--the system won't know which object it's supposed to invoke the function on (it won't have a `this` pointer). To get from here to there, you have to declare two member functions:

- a static member function that is, literally, the thread function,

- and a non-static member function that the static function can invoke. This non-static function will perform the intended work of the thread function.

To "connect" the two functions, you pass an object of the appropriate class (through the data argument) to the static function, and then allow the static function to invoke the non-static function upon that object. An example is called for:

Here we define a class that contains a static function called `thread_func()`, and a non-static function called `threadFunc()`. By convention, these two are private. In addition, the class declares a public `Go()` function, and a private `thread_id` variable:

       class MyClass {
       public:
          status_t Go(void);

       private:
          static int32 thread_func(void *arg);
          int32 threadFunc(void);
          thread_id my_thread;
       };

`thread_func()` is the literal thread function. It doesn't really do anything--it simply casts its argument as a MyClass object, and then invokes `threadFunc()` on the object:

       int32 MyClass::thread_func(void *arg)
       {
          MyClass *obj = (MyClass *)arg;
          return (obj->threadFunc());
       }

`threadFunc()` performs the actual work:

       int32 MyClass::threadFunc(void)
       {
          /* do something here */
          ...
          return (whatever);
       }

The `Go()` function contains the `spawn_thread()` call that starts the whole thing going:

       status_t MyClass::Go(void)
       {
          my_thread = spawn_thread(thread_func, ..., this);
          return (resume_thread(my_thread));
       }

If you aren't familiar with static member functions, you should consult a qualified C++ textbook. Briefly, the only thing you need to know for the purposes of the technique shown here, is that a static function's implementation can't call (non-static) member functions nor can it refer to member data. Maintain the form demonstrated above and you'll be rewarded in heaven.

#### Thread Function Return Values

The thread function's protocol declares that the function should return a `int32` value when it exits. This value can be captured by sitting in a `wait_for_thread()` call until the thread function exits. `wait_for_thread()` takes two arguments:

- The `thread_id` of the thread that you're waiting for.
- A pointer to an `int32` that captures the thread function's return value.

For example:

       thread_id other_thread;
       status_t result;

       other_thread = spawn_thread(...);
       resume_thread(other_thread);

       ...
       wait_for_thread(other_thread, &result);

If the target thread is already dead, `wait_for_thread()` returns immediately (with an error code as described in the function's full description), and the second argument will be set to an invalid value. If you're late for the train, you'll miss the boat.

|  | You must pass a valid pointer as the second argument to wait_for_thread(). You mustn't pass `NULL` even if you're not interested in the return value.

### Thread Names

A thread can be given a name which you assign through the second argument to `spawn_thread()`. The name can be 32 characters long (as represented by the `B_OS_NAME_LENGTH` constant) and needn't be unique--more than one thread can have the same name.

You can look for a thread based on its name by passing the name to the `find_thread()` function; the function returns the `thread_id` of the so-named thread. If two or more threads bear the same name, the `find_thread()` function returns the first of these threads that it finds.

You can retrieve the `thread_id` of the calling thread by passing `NULL` to`find_thread()`:

       thread_id this_thread = find_thread(NULL);

To retrieve a thread's name, you must look in the thread's `thread_info` structure. This structure is described in the `get_thread_info()` function description.

Dissatisfied with a thread's name? Use the `rename_thread()` function to change it. Fool your friends.

### Thread Priority

In a multi-threaded environment, the CPUs must divide their attention between the candidate threads, executing a few instructions from this thread, then a few from that thread, and so on. But the division of attention isn't always equal: You can assign a higher or lower priority to a thread and so declare it to be more or less important than other threads.

You assign a thread's priority (an integer) as the third argument to `spawn_thread()`. There are two categories of priorities: "time-sharing" and "real-time."

- Time-sharing (values from 1 to 99). A time-sharing thread is executed only if there are no real-time threads in the ready queue. In the absence of real-time threads, a time-sharing thread is elected to run once every "scheduler quantum" (currently, every three milliseconds). The higher the time-sharing thread's priority value, the greater the chance that it will be the next thread to run.

- Real-time (100 and greater). A real-time thread is executed as soon as it's ready. If more than one real-time thread is ready at the same time, the thread with the highest priority is executed first. The thread is allowed to run without being preempted (except by a real-time thread with a higher priority) until it blocks, snoozes, is suspended, or otherwise gives up its plea for attention.

The Kernel Kit defines seven priority constants. Although you can use other, "in-between" value as the priority argument to `spawn_thread()`, it's suggested that you stick with these:

Time-Sharing Priority | Value
`B_LOW_PRIORITY` | `5`
`B_NORMAL_PRIORITY` | `10`
`B_DISPLAY_PRIORITY` | `15`
`B_URGENT_DISPLAY_PRIORITY` | `20`

Real-Time Priority | Value
`B_REAL_TIME_DISPLAY_PRIORITY` | `100`
`B_URGENT_PRIORITY` | `110`
`B_REAL_TIME_PRIORITY` | `120`

### Synchronizing Threads

There are times when you may want a particular thread to pause at a designated point until some other (known) thread finishes some task. Here are three ways to effect this sort of synchronization:

- The most general means for synchronizing threads is to use a semaphore. The semaphore mechanism is described in great detail in "The Kernel Kit: Semaphores."

- Synchronization is sometimes a side-effect of sending data between threads. This is explained in Passing Data to a Thread, and in "The Kernel Kit: Ports."

- Finally, you can tell a thread to wait for some other thread to die by calling `wait_for_thread()`, as described earlier.

### Controlling a Thread

There are four ways to control a thread while it's running:

- You can put a thread to sleep for some number of microseconds through the `snooze()` function. After the thread has been asleep for the requested time, it automatically resumes execution with its next instruction. `snooze()` only works on the calling thread: The function doesn't let you identify an arbitrary thread as the subject of its operation. In other words, whichever thread calls `snooze()` is the thread that's put to sleep.

- You can suspend the execution of any thread through the `suspend_thread()` function. The function takes a single `thread_id` argument that identifies the thread you wish to suspend. The thread remains suspended until you "unsuspend" it through a call to `resume_thread()` or `wait_for_thread()`.

- You can send a POSIX "signal" to a thread through the `send_signal()` function. The `SIGCONT` signal tries to unblock a blocked or sleeping thread without killing it; all other signals kill the thread. To override this behavior, you can install your own signal handlers.

- You can kill the calling thread through `exit_thread()`. The function takes a single (`int32`) argument that's used as the thread's exit status (to make `wait_for_thread()` happy). More generally, you can kill any thread by passing its `thread_id` to the `kill_thread()` function. `kill_thread()` doesn't let you set the exit status.

Feeling itchy? Try killing an entire team of threads: The`kill_team()` function is more than a system call. It's therapy.

#### Death and the Main Thread

As mentioned earlier, the control that's imposed upon a particular thread isn't visited upon the "children" that have been spawned from that thread. However, the death of an application's main thread can affect the other threads:

|  | When a main thread dies, the game is pretty much over. The main thread takes the team's heap, its statically allocated objects, and other team-wide resources--such as access to standard IO--with it. This may seriously cripple any threads that linger beyond the death of the main thread.

It's possible to create an application in which the main thread sets up one or more other threads, gets them running, and then dies. But such applications should be rare. In general, you should try to keep your main thread around until all other threads in the team are dead.

### Passing Data to a Thread

There are three ways to pass data to a thread:

- Through the data argument to the thread function, as described in The Thread Function's Argument.

- By using a port or, at a higher level, by sending a BMessage. Ports are described in the major section "Ports"; BMessages are part of the Application Kit.

- By sending data to the thread's message cache through the `send_data()` and`receive_data()` functions, as described below.

The `send_data()` function sends data from one thread to another. With each `send_data()` call, you can send two packets of information:

- a single four-byte value (this is called the code),
- and an arbitrarily long buffer of arbitrarily-typed data.

The function's protocol is shown below

       status_t send_data(thread_id thread,
                   int32 code,
                   void *buffer,
                   size_t buffer_size)

The arguments are:

- thread is the thread that you want to send the data to,
- code is the four-byte code,
- buffer is a pointer to the buffer of data,
- buffer_size is the size of the data buffer, in bytes.

In the following example, the main thread spawns a thread, sends it some data, and then tells the thread to run:

       main()
       {
          thread_id other_thread;
          int32 code = 63;
          char *buf = "Hello";

          other_thread = spawn_thread(thread_func, ...);
          send_data(other_thread, code, (void *)buf, strlen(buf));
          resume_thread(other_thread);
          ...
       }

The `send_data()` call copies the code and the buffer (the second and third arguments) into the target thread's message cache and then (usually) returns immediately. In some cases, the four-byte code is all you need to send; in such cases, the buffer pointer can be `NULL` and the buffer size set to 0.

To retrieve the data that's been sent to it, the target thread (having been told to run) calls `receive_data()`:

       status_t receive_data(thread_id *sender,
                   void *buffer,
                   size_t buffer_size)

This function returns the four-byte code directly, and copies the data from the message cache into its second argument. It also returns, by reference in its first argument, the`thread_id` of the thread that sent the data:

       int32 thread_func(void *data)
       {
          thread_id sender;
          int32 code;
          char buf[512];

          code = receive_data(&sender, (void *)buf, sizeof(buf));
          ...
       }

Keep in mind that the message data is copied into the second argument; you must allocate adequate storage for the data, and pass, as the final argument to `receive_data()`, the size of the buffer that you allocated. A slightly annoying aspect of this mechanism is...

|  | There isn't any way for the data-receiving thread to determine how much data is in the message cache. It can't tell, before it receives the data, what an "adequate" size for its buffer is. If the buffer isn't big enough to accommodate all the data, the left-over portion is simply thrown away. (But at least you don't get a segmentation fault.)

As shown in the example, `send_data()` is called before the target thread is running. This feature of the system is essential in situations where you want the target thread to receive some data as its first act (as demonstrated above). However, `send_data()` isn't limited to this use--you can also send data to a thread that's already running.

#### Blocking when Sending and Receiving

A thread's message cache isn't a queue; it can only hold one message at a time. If you call `send_data()` twice with the same target thread, the second call will block until the target reads the first transmission through a call to `receive_data().` Analogously, `receive_data()` will block if there isn't (yet) any data to receive.

If you want to make sure that you won't block when receiving data, you should call `has_data()` before calling`receive_data()`. `has_data()` takes a `thread_id` argument, and returns `true` if that thread has a message waiting to be read:

       if (has_data(find_thread(NULL)))
          code = receive_data(...);

You can also use`has_data()` to query the target thread before sending it data. This, you hope, will ensure that the`send_data()` call won't block:

       if (!has_data(target_thread))
          send_data(target_thread, ...);

This usually works, but be aware that there's a race condition between the `has_data()` and `send_data()` calls. If yet another thread sends a message to the same target in that time interval, your `send_data()` (might) block.

## Thread Functions

### exit_thread(), kill_thread(), kill_team()

          void exit_thread(status_t return_value)

          status_t kill_thread(thread_id thread)

          status_t kill_team(team_id team)

These functions command one or more threads to halt execution:

- `exit_thread()` tells the calling thread to exit with a return value as given by the argument. Declaring the return value is only useful if some other thread is sitting in a `wait_for_thread()` call on this thread. `exit_thread()` sends a signal to the thread (after caching the return value in a known place).

- `kill_thread()` kills the thread given by the argument. The value that the thread will return to `wait_for_thread()` is undefined and can't be relied upon. `kill_thread()` is the same as sending a `SIGKILLTHR` signal to the thread.

- `kill_team()` kills all the threads within the given team. Again, the threads' return values are random. `kill_team()` is the same as sending a `SIGKILL` signal to any thread in the team. Each of the threads in the team is then handed a `SIGKILLTHR` signal.

Exiting a thread is a fairly safe thing to do--since a thread can only exit itself, it's assumed that the thread knows what it's doing. Killing some other thread or an entire team is a bit more drastic since the death certificate(s) will be delivered at an indeterminate time. In addition, killing a thread can leak memory since resources that were allocated by the thread may not be freed. Killing an entire team, on the other hand, won't leak since the system reclaims all resources when the team dies.

|  | Keep in mind that threads die automatically (and their resources are reclaimed) if they're allowed to exit naturally. You should only need to kill a thread if something has gone screwy.

RETURN CODES

- `B_NO_ERROR`. The thread or team was successfully killed.
- `B_BAD_THREAD_ID`. Invalid thread value.
- `B_BAD_TEAM_ID`. Invalid team value.

### find_thread()

          thread_id find_thread(const char *name)

Finds and returns the thread with the given name. A name argument of `NULL` returns the calling thread.

A thread's name is assigned when the thread is spawned. The name can be changed thereafter through the `rename_thread()` function. Keep in mind that thread names needn't be unique: If two (or more) threads boast the same name, a `find_thread()` call on that name returns the first so-named thread that it finds. There's no way to iterate through identically-named threads.

RETURN CODES

- `B_NAME_NOT_FOUND`. name doesn't identify a valid thread.

### get_team_info(), get_next_team_info(), team_info

          status_t get_team_info(team_id team, team_info *info)
          status_t get_next_team_info(int32 *cookie, team_info *info)

          typedef struct {} team_info

The functions copy, into the info argument, the `team_info` structure for a particular team. The `get_team_info()` function retrieves information for the team identified by team.

The `get_next_team_info()` version lets you step through the list of all teams. 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 team_info for every team. */
       team_info info;
       int32 cookie = 0;

       while (get_next_team_info(0, &cookie, &info) == B_NO_ERROR)
          ...

The `team_info` structure is defined as:

          typedef struct {
                team_id team;
                int32 thread_count;
                int32 image_count;
                int32 area_count;
                thread_id debugger_nub_thread;
                port_id debugger_nub_port;
                int32 argc;
                char args[64];
                uid_t uid;
                gid_t gid;
             } team_info

The first field is obvious; the next three reasonably so: They give the number of threads that have been spawned, images that have been loaded, and areas that have been created or cloned within this team.

The debugger fields are used by the, uhm, the...debugger?

The `argc` field is the number of command line arguments that were used to launch the team; `args` is a copy of the first 64 characters from the command line invocation. If this team is an application that was launched through the user interface (by double-clicking, or by accepting a dropped icon), then `argc` is 1 and `args` is the name of the application's executable file.

`uid` and `gid` identify the user and group that "owns" the team. You can use these values to play permission games.

RETURN CODES

- `B_NO_ERROR`. The desired team information was found.
- `B_BAD_TEAM_ID`. team doesn't identify an existing team, or there are no more areas to visit.

### get_thread_info(), get_next_thread_info(), thread_info

          status_t get_thread_info(thread_id thread, thread_info *info)
          status_t get_next_thread_info(team_id team,
             int32 *cookie,
             thread_info *info)

          typedef struct {} thread_info

These functions copy, into the info argument, the `thread_info` structure for a particular thread:

The `get_thread_info()` function gets the information for the thread identified by thread.

The `get_next_thread_info()` function lets you step through the list of a team's threads through iterated calls. 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 threads to visit:

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

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

The `thread_info` structure is defined as:

          typedef struct {
                thread_id thread;
                team_id team;
                char name[B_OS_NAME_LENGTH];
                thread_state state;
                int32 priority;
                sem_id sem;
                bigtime_t user_time;
                bigtime_t kernel_time;
                void *stack_base;
                void *stack_end;
             } thread_info

The fields in the structure are:

- `thread`. The `thread_id` number of the thread.
- `team`. The`team_id` of the thread's team.
- `name`. The name assigned to the thread.
- `state`. What the thread is currently doing (see the thread state constants, below).
- `priority`. The level of attention the thread gets (see the priority constants, below).
- `sem`. If the thread is waiting to acquire a semaphore, this is that semaphore.
- `user_time`. The time, in microseconds, the thread has spent executing user code.
- `kernel_time`. The amount of time the kernel has run on the thread's behalf.
- `stack_base`. A pointer to the first byte in the thread's execution stack.
- `stack_end`. A pointer to the last byte in the thread's execution stack.

The last two fields are only meaningful if you understand the execution stack format. Currently, the stack size is fixed at around 256k.

|  | The two stack pointers are currently inverted such that `stack_base` is less than`stack_end`. (In a stack-grows-down world, the base should be greater than the end.)

The value of the `state` field is one of following `thread_state` constants:

Constant | Meaning
`B_THREAD_RUNNING` | The thread is currently receiving attention from a CPU.
`B_THREAD_READY` | The thread is waiting for its turn to receive attention.
`B_THREAD_SUSPENDED` | The thread has been suspended or is freshly-spawned and is waiting to start.
`B_THREAD_WAITING` | The thread is waiting to acquire a semaphore. When in this state, the `sem` field of the `thread_info` structure is set to the `sem_id` number of the semaphore the thread is attempting to acquire. (Note that when a thread is blocked in `wait_for_thread()`, `read_port()`, or `write_port()`, it's actually waiting to acquire a semaphore.)
`B_THREAD_RECEIVING` | The thread is sitting in a `receive_data()` function call.
`B_THREAD_ASLEEP` | The thread is sitting in a `snooze()` call.

The value of the `priority` field describes the thread's "urgency"; the higher the value, the more urgent the thread. The more urgent the thread, the more attention it gets from the CPU. Expected priority values fall between 0 and 120. See "Thread Priority" for the full story.

|  | Thread info is provided primarily as a debugging aid. None of the values that you find in a `thread_info` structure are guaranteed to be valid--the thread's state, for example, will almost certainly have changed by the time `get_thread_info()` returns.

RETURN CODES

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

### has_data()

          bool has_data(thread_id thread)

Returns `true` if the given thread has an unread message in its message cache, otherwise returns `false`. Messages are sent to a thread's message cache through the `send_data()` call. To retrieve a message, you call `receive_data()`.

### kill_team() see exit_thread()

### kill_thread() see exit_thread()

### receive_data()

          int32 receive_data(thread_id *sender,
             void *buffer,
             size_t buffer_size)

Retrieves a message from the thread's message cache. The message will have been placed there through a previous `send_data()` function call. If the cache is empty, `receive_data()` blocks until one shows up--it never returns empty-handed.

The `thread_id` of the thread that called `send_data()` is returned by reference in the sender argument. Note that there's no guarantee that the sender will still be alive by the time you get its ID. Also, the value of sender going into the function is ignored--you can't ask for a message from a particular sender.

The `send_data()` function copies two pieces of data into a thread's message cache:

- A single four-byte code that's delivered as `receive_data()`'s return value,

- and an arbitrarily long data buffer that's copied into `receive_data()`'s buffer argument (you must allocate and free buffer yourself). The buffer_size argument tells the function how many bytes of data to copy. If you don't need the data buffer--if the code value returned directly by the function is sufficient--you set buffer to `NULL` and buffer_size to 0.

Unfortunately, there's no way to tell how much data is in the cache before you call `receive_data()`:

- If there's more data than buffer can accommodate, the unaccommodated portion is discarded--a second `receive_data()` call will not read the rest of the message.

- Conversely, if `receive_data()` asks for more data than was sent, the function returns with the excess portion of buffer unmodified--`receive_data()` doesn't wait for another `send_data()` call to provide more data with which to fill up the buffer.

Each`receive_data()` corresponds to exactly one `send_data()`. Lacking a previous invocation of its mate, `receive_data()` will block until `send_data()` is called. If you don't want to block, you should call `has_data()` before calling `receive_data()` (and proceed to `receive_data()` only if `has_data()` returns `true`).

RETURN CODES

- If successful, the function returns the message's four-byte code.
- `B_INTERRUPTED`. A blocked `receive_data()` call was interrupted by a signal.

### rename_thread()

          status_t rename_thread(thread_id thread, const char *name)

Changes the name of the given thread to name. Keep in mind that the maximum length of a thread name is `B_OS_NAME_LENGTH` (32 characters).

RETURN CODES

- `B_NO_ERROR`. The thread was successfully named.
- `B_BAD_THREAD_ID`. thread argument isn't a valid `thread_id` number.

### resume_thread()

           status_t resume_thread(thread_id thread)

Tells a new or suspended thread to begin executing instructions.

- If the thread has just been spawned, its execution begins with the thread function (keep in mind that a freshly spawned thread doesn't run until told to do so through this function).

- If the thread was previously suspended (through `suspend_thread()`), it continues from where it was suspended.

This function only works on threads that have a status of `B_THREAD_SUSPENDED` (newly spawned threads are born with this state). You can't use this function to wake up a sleeping thread (`B_THREAD_ASLEEP`), or to unblock a thread that's waiting to acquire a semaphore (`B_THREAD_WAITING`) or waiting in a`receive_data()` call (`B_THREAD_RECEIVING`).

However, you can unblock a thread by suspending it and then resuming it. Blocked threads that are resumed return `B_INTERRUPTED`.

`resume_thread()` is the same as sending a `SIGCONT` signal to the thread.

RETURN CODES

- `B_NO_ERROR`. The thread was successfully resumed.
- `B_BAD_THREAD_ID`. thread argument isn't a valid `thread_id` number.
- `B_BAD_THREAD_STATE`. The thread isn't suspended.

### send_data()

          status_t send_data(thread_id thread,
             int32 code,
             void *buffer,
             size_t buffer_size)

Copies data into thread's message cache. The target thread can then retrieve the data from the cache by calling `receive_data()`. There are two parts to the data that you send:

- A single four-byte "code" given by the code argument.

- An arbitrarily long buffer of data that's pointed to by buffer. The length of the buffer, in bytes, is given by buffer_size.

If you only need to send the code, you should set buffer to `NULL` and buffer_size to 0. After `send_data()` returns you can free the buffer argument.

Normally, `send_data()` returns immediately--it doesn't wait for the target to call `receive_data()`. However,`send_data()` will block if the target has an unread message from a previous `send_data()`--keep in mind that a thread's message cache is only one message deep. A thread that's blocked in `send_data()` assumes `B_THREAD_WAITING` status.

RETURN CODES

- `B_NO_ERROR`. The data was successfuly sent.
- `BAD_THREAD_ID`. thread doesn't identify a valid thread.
- `B_NO_MEMORY`. The target couldn't allocate enough memory for its copy of buffer.
- `B_INTERRUPTED`. The function blocked, but a signal unblocked it.

### set_thread_priority()

           status_t set_thread_priority(thread_id thread, int32 new_priority)

Resets the given thread's priority to new_priority.

The value of the new_priority can be any positive integer, but it's recommended that you stick with the following constants (the difference between "time-sharing" priorities and "real-time" priorities is explained in Thread Priority):

Time-Sharing Priority | Value
`B_LOW_PRIORITY` | `5`
`B_NORMAL_PRIORITY` | `10`
`B_DISPLAY_PRIORITY` | `15`
`B_URGENT_DISPLAY_PRIORITY` | `20`

Real-Time Priority | Value
`B_REAL_TIME_DISPLAY_PRIORITY` | `100`
`B_URGENT_PRIORITY` | `110`
`B_REAL_TIME_PRIORITY` | `120`

RETURN CODES

- Positive integers. If the function is successfull, the previous priority is returned.
- `B_BAD_THREAD_ID`. thread doesn't identify a valid thread.

### snooze()

           status_t snooze(bigtime_t microseconds)

Pauses the calling thread for the given number of microseconds (the function blocks until then). The thread's state is set to `B_THREAD_ASLEEP` while it's snoozing.

To wake up a thread prematurely, suspend the thread and then resume it:

       thread_info tinfo;

       get_thread_info(thread, &tinfo);
       if (tinfo.state == B_THREAD_ASLEEP) {
          suspend_thread(thread);
          /* Just to be sure... */
          snooze(1000);
          resume_thread(thread);
       }

|  | The `snooze()` in the "controlling" thread is a precaution; if you're pulling this sort of stunt in your own code, you should also snooze for a bit between the suspend and resume--signals are funny that way.

There is, of course, a race condition in this example--the thread could wake up just after the `get_thread_info()` call. But, as with all signalling operations, the suspend/resume trick is indeterminate and wee bit dangerous. (Actually, the only situation where the race could cause trouble is if the thread wakes up, blocks on a semaphore, is then suspended/resumed AND it doesn't check the`acquire_sem()` return value.)

RETURN CODES

- `B_NO_ERROR`. The thread went to sleep and is now awake.
- `B_ERROR`. Illegal microseconds value (less than 0).
- `B_INTERRUPTED`. The thread received a signal while it was sleeping.

### snooze_until()

          status_t snooze_until(bigtime_t time, int timebase)

Pauses the thread until an absolute time measured in the given timebase. Currently, the only allowed value for timebase is `B_SYSTEM_TIMEBASE`, for which time is equivalent to the system time as returned by `system_time()`.

RETURN CODES

- `B_NO_ERROR`. The thread went to sleep and is now awake.
- `B_ERROR`. Illegal time value (less than 0).
- `B_INTERRUPTED`. The thread received a signal while it was sleeping.

### spawn_thread()

          thread_id spawn_thread(thread_func func,
             const char *name,
             int32 priority,
             void *data)

Creates a new thread and returns its `thread_id` identifier (a positive integer). The arguments are:

- func is a pointer to a thread function. This is the function that the thread will execute when it's told to run.

- name is the name that you wish to give the thread. It can be, at most, `B_OS_NAME_LENGTH` (32) characters long.

- priority is the CPU priority level of the thread. The higher the priority, the more attention the thread gets. The value can be any positive integer, but you should stick with the constants listed about four seconds from now.

- data is forwarded as the argument to the thread function.

Time-Sharing Priority | Value
`B_LOW_PRIORITY` | `5`
`B_NORMAL_PRIORITY` | `10`
`B_DISPLAY_PRIORITY` | `15`
`B_URGENT_DISPLAY_PRIORITY` | `20`

Real-Time Priority | Value
`B_REAL_TIME_DISPLAY_PRIORITY` | `100`
`B_URGENT_PRIORITY` | `110`
`B_REAL_TIME_PRIORITY` | `120`

For a complete explanation of these constants, see Thread Priority.

A newly spawned thread is in a suspended state (`B_THREAD_SUSPENDED`). To tell the thread to run, you pass its `thread_id` to the `resume_thread()` function. The thread will continue to run until the thread function exits, or until the thread is explicitly killed (through a signal or a call to `exit_thread()`, `kill_thread()`, or `kill_team()`).

RETURN CODES

- `B_NO_MORE_THREADS`. all `thread_id` numbers are currently in use.
- `B_NO_MEMORY`. Not enough memory to allocate the resources for another thread.

### suspend_thread()

          status_t suspend_thread(thread_id thread)

Halts the execution of the given thread, but doesn't kill the thread entirely. The thread remains suspended (`suspend_thread()` blocks) until it's told to run through the `resume_thread()` function. Nothing prevents you from suspending your own thread, i.e.:

       suspend_thread(find_thread(NULL));

Of course, this is only smart if you have some other thread that will resume you later.

You can suspend any thread, regardless of its current state. But be careful: If the thread is blocked on a semaphore (for example), the subsequent `resume_thread()` call will "hop over" the semaphore acquisition.

Suspensions don't nest. A single `resume_thread()` unsuspends a thread regardless of the number of `suspend_thread()` calls it has received.

`suspend_thread()` is the same as sending a `SIGSTOP` signal to the thread.

RETURN CODES

- `B_NO_ERROR`. The thread is now suspended.
- `B_BAD_THREAD_ID`. thread isn't a valid `thread_id` number.

### wait_for_thread()

          status_t wait_for_thread(thread_id thread, status_t *exit_value)

This function causes the calling thread to wait until thread (the "target thread") has died. If thread is suspended, the `wait_for_thread()` call will cause it to resume. Thus, you can use `wait_for_thread()` to tell a newly-spawned thread to start running.

When the target thread is dead, the value that was returned by its thread function (or that's imposed by `exit_thread()`, if such was called) is returned by reference in exit_value. If the target thread was killed (by `kill_thread()` or`kill_team()`), or if the thread function doesn't return a value, the value returned in exit_value is unreliable.

RETURN CODES

- `B_NO_ERROR`. The target is now dead.
- `B_BAD_THREAD_ID`. thread isn't a valid `thread_id` number.
- `B_INTERRUPTED`. The target was killed by a signal. This includes `kill_thread()`, `kill_team()`, and `exit_thread()`.

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

Copyright © 1998 Be, Inc. All rights reserved.

Last modified March 26, 1998.