HPlogo STREAMS/UX for the HP 9000 Reference Manual > Chapter 5 How to Compile and Link STREAMS/UX Drivers, Modules, and Applications

Compiling and Linking TLI/XTI Applications and Threads

» 

Technical documentation

Complete book in PDF

 » Table of Contents

 » Index

As with the STREAMS/UX system calls, compiling and linking a TLI or XTI application requires no special compile or linking options. Choose the appropriate include files from the table below and compile. Link your application with either the TLI library, libnsl_s.a or libnsl_s.sl, or the XTI library, libxti.a or libxti.sl. Both libraries are in /usr/lib.

Table 5-3 TLI/XTI Include Files

Include File

Use

<xti.h> or <sys/xti.h>

Needed by all XTI applications.

<tiuser.h> or <sys/tiuser.h>

Needed by all TLI applications.

<poll.h> or <sys/poll.h>

Needed by programs that use poll.

<stropts.h> or <sys/stropts.h>

Needed by programs that use the STREAMS/UX interface to perform operations such as pushing modules onto a stream.

 

These libraries have been made thread-safe, that is, these libraries may be used with both non-threaded and multi-threaded applications. Please see OSF/DCE documentation for the POSIX threads library calls that may be used.

The following caveats apply to this release of these libraries:

  • When a thread is executing within a TLI/XTI library call, the thread may not be canceled. The library will turn both general and asynchronous cancellation off during execution. This is necessary to avoid corruption of internal mutex structures.

  • The global variable t_errno and the function t_strerror() will return values on a per-thread basis. These values are stored in thread-specific pointers via the pthread_setspecific() and pthread_getspecific() functions.

  • It is possible to deadlock a process should the application attempt to execute in loopback using two threads within the same process' address space. It is recommended that for loopback applications, the sending and receiving threads be in separate processes which will avoid any deadlock situation.

    NOTE: The libraries use two levels of internal locks and it is only during the small time frame between obtaining and releasing the locks that a deadlock can occur.
  • The libcma.a or libcma.sl library must be linked into the application before either the libnsl_s.a or the libxti.a libraries are linked.

  • The include file, pthread.h, must be the first include file defined within an application to have all entry points properly mapped.

  • Independent of the TLI/XTI libraries, if you cancel a thread and it was either waiting on a mutex or a condition variable, it is best to consider either the mutex or the condition variable as corrupted and either re-initialize or destroy and recreate them.

Here are some basic tips on coding TLI/XTI multi-threaded applications.

  • The pthreads library is a user space library. Threads execute using either the default round-robin scheduling mechanism or a scheduling mechanism that the application controls. The default order of execution is not predictable nor should it be relied upon. For instance, if a thread spawns multiple threads, the new threads will not be allowed to execute until either the initiating thread executes a blocking call, executes a pthread_yield(), or its time slice expires. It is recommended that a thread executing a pthread_create() issue a pthread_yield() and possibly a pthread_join() to allow the other threads a chance to execute and finish their tasks before continuing its processing.

    For TLI/XTI, this technique is useful for a responder application which listens for incoming connections and creates a new thread to complete the connection. In this case, the responder could either yield to the new thread or could continue to listen for incoming connect indications until there are no pending indications. At this time it yields or executes a poll call that will block, which allows the other threads to be scheduled for execution. This avoids the potential TLOOK error condition should another indication arrive before the previous one is processed and cleared.

    Another example is if the responder detects a POLLHUP condition exists and creates a thread to handle the disconnect, and then continues to execute. The result could be poll() detecting this condition occurring multiple times when it really only exists once. It is recommended that the thread be coded such that either a pthread_yield() is immediately executed following the pthread_create() or if the responder thread is handling multiple connections, it executes a pthread_join() and waits for the disconnect thread's completion.

  • If using condition variables, a pthread_cond_signal() must be sent for each thread waiting on that condition. Condition variables are useful for synchronizing activity on a single endpoint where multiple threads may be attempting to manipulate that endpoint. Another use is coordinating multiple endpoints that need to arrive at a particular state before proceeding. This contrasts with mutex usage which is better suited for critical data or code section protection.

    An example would be if an application were replicating data at multiple sites, each thread would drive its appropriate endpoint to the state before the final commit is ready. When the controlling thread has detected that all endpoints are currently waiting at the same condition variable, the pthread_cond_signal() could be sent to each thread with the controlling thread waiting until the threads are complete before releasing the shared memory buffer.

  • If the application is utilizing the poll() system call, the application will need to have error handling code in each thread to avoid unnecessary processing. For example, if multiple threads are sending data to a single endpoint and that endpoint becomes flow-controlled, when the flow-control condition is relieved, the poll() system call will return that the endpoint is writable. At this point one or more threads could be scheduled to execute which may result in one thread succeeding with the rest returning TFLOW errors.

  • If a thread is exiting, it is recommended that the thread call pthread_detach() is used to release any memory that has been allocated for that thread's usage. If the detach is not performed, that memory can be lost and the application could experience memory shortage problems. Once the process is terminated, all memory should be returned to the system.

© 1995 Hewlett-Packard Development Company, L.P.