AGT_CREATE(3L)

NAME
agt_create, agt_enumerate, agt_trap - map LWP events into messages

SYNOPSIS
#include <lwp/lwp.h>

thread_t agt_create(agt, event, memory)
thread_t *agt;
int event;
caddr_t memory;

int agt_enumerate(vec, maxsize)
thread_t vec[];
int maxsize;

int agt_trap(event)
int event;

DESCRIPTION

Agents are entities that act like threads sending messages when an asynchronous event occurs. agt_create() creates an object called an agent which maps the asynchronous event event into messages that can be received with msg_recv() (see msg_send(3L)). agt stores the handle on this object. event is a UNIX signal number.

agt_trap() causes the event, event, to generate an exception (see exc_handle(3L)). Once initialized using agt_create() or agt_trap(), an event can not be remapped to a different style of handling. If traps are enabled, an event will cause the termination of the thread running at the time of the trap if the trap exception is not handled. If an exception handler is in place, an exception will be raised. If an agent exists for the event, the event is mapped into a message for the agent. If neither agent nor trap mapping is enabled, the default signal action (SIG_DFL) is applied to the pod. Use of standard UNIX signal handling facilities will defeat the event mapping mechanism.

The message sent by the agent (in the argument buffer) will look like any other message with the sender being the agent. The receive buffer is NULL. A message is always sent by an agent to the thread which created the agent.

All messages sent by an agent contain an eventinfo_t. This structure indicates the thread running at the time the interrupt happened, and the particular event that occurred. Some agent messages contain more information if the particular event warrants it. In this case, a struct containing an eventinfo_t as its first element is passed as the argument buffer. Definitions of these structures are contained in <lwp/lwp.h>.

An agent appears to the owning thread just like another thread. It must therefore have some memory for holding its message, as the sender and receiver must belong to the same address space. memory is the space an agent will use to store its message. Typically, this is on the stack of the thread that created the agent. It must be of the correct size for the kind of event being created (most events need something to store an eventinfo_t. SIGCHLD events need room for a sigchldev_t.)

You should reply to an agent (using msg_reply() (see msg_send(3L)) as you would reply to a thread. Although agents do not ordinarily lose events, the next agent message will not be delivered until a reply is sent to the agent. Thus, an agent appears to the client as an ordinary thread sending messages. An agent will only lose events if the total number of unreplied-to events in a pod exceeds AGENTMEMORY.

lwp_destroy() is used to destroy an agent. All agents created by a thread automatically disappear when that thread dies. agt_enumerate() fills in a list with the ID's of all existing agents and returns the total number of agents. This primitive uses maxsize to avoid exceeding the capacity of the list. If the number of agents is greater than maxsize, only maxsize agents ID's are filled in vec. If maxsize is zero, agt_enumerate() returns the total number of agents.

The special event LASTRITES is caused by the termination of a thread. An agent for LASTRITES will be informed about every thread that terminates, regardless of cause. The eventinfo_code element of this agent will contain the stack argument that the dead thread was created with. Note: by allocating adjacent space above the thread stack, this argument can be used to point to private information about a thread. The eventinfo_victimid element will contain the id of the dead thread.

RETURN VALUES

agt_create() and agt_trap() return:

0   on success.

-1  on failure.

agt_enumerate() returns the total number of agents.

ERRORS

agt_trap() will fail if one or more of the following are true:

LE_INUSE
    Agent in use for this event.

LE_INVALIDARG
    Event specified does not exist.

agt_create() will fail if one or more of the following are true:

LE_INUSE
    Trap mapping in use for this event.

LE_INVALIDARG
    Attempt to create agent for non-existent event.

SEE ALSO
exc_handle(3L), msg_send(3L)

BUGS

Signal handlers always take the SIG_DFL action when no agent manages the event.

If a descriptor used by a parent of the pod (such as its standard input) is marked non-blocking by a thread, it should be reset when the pod terminates to prevent the parent from receiving EWOULDBLOCK errors on the descriptor. There is no way to prevent this from happening if a pod is terminated with extreme prejudice (for instance, using SIGKILL).

If an agent reports that a descriptor has I/O available, there may be more than one occurrence of I/O available from that descriptor. Thus, being informed that SIGIO has occurred on socket s may mean that there are several messages waiting to be received from s. Clients should be careful to clean out all I/O from a descriptor before going back to sleep.

All system calls should be protected with loops testing for EINTR (and monitors if multiple threads can try to use system calls concurrently). An lwp_sleep() could result in a hidden clock interrupt for example.

WARNINGS

agt_trap() should not be used for asynchronous events. If an unsuspecting thread which has no exception handler is running at the time of a trapped event, it will be terminated.

Clients should not normally handle signals themselves since the agent mechanism assumes it is the only entity handling signals.