HELPLIB.HLB  —  POSIX Threads, TIS routines
    The VSI proprietary TIS interface provides routines that you use
    to build thread-safe libraries whose own routines do not create
    threads, but which can safely be called from a multithreaded
    environment. TIS routines are functionally identical to their
    corresponding routines in the PTHREAD interface. See the Guide to
    the POSIX Threads Library documentation for more information.

    In a program that creates threads, TIS routines provide full
    thread synchronization and memory coherence. But, when run in
    a program that does not use threads, the same TIS calls provide
    low-overhead "stub" implementations of PTHREAD features. That
    is, the objects created using the TIS interface are the same as
    PTHREAD objects. When threads are present, the guidelines for
    using PTHREAD routines apply also to the use of the corresponding
    TIS routine.

1  –  tis_cond_broadcast

    Wakes all threads that are waiting on a condition variable.

1.1  –  C Binding

    #include <tis.h>

    int
    tis_cond_broadcast (
                pthread_cond_t   *cond);

1.2  –  Arguments

 cond

    Address of the condition variable (passed by reference) on which
    to broadcast.

1.3  –  Description

    When threads are not present, this routine has no effect.

    When threads are present, this routine unblocks all threads
    waiting on the specified condition variable cond.

    For further information about actions when threads are present,
    refer to the pthread_cond_broadcast() description.

1.4  –  Return Values

    If an error condition occurs, this routine returns an integer
    value indicating the type of error. Possible return values are as
    follows:

    Return      Description

    0           Successful completion.
    [EINVAL]    The value specified by cond is not a valid condition
                variable.

1.5  –  Associated Routines

       tis_cond_destroy()
       tis_cond_init()
       tis_cond_signal()
       tis_cond_wait()

2  –  tis_cond_destroy

    Destroys the specified condition variable.

2.1  –  C Binding

    #include <tis.h>

    int
    tis_cond_destroy (
                pthread_cond_t   *cond);

2.2  –  Arguments

 cond

    Address of the condition variable (passed by reference) to be
    destroyed.

2.3  –  Description

    This routine destroys the condition variable specified by cond.
    After this routine is called, the Threads Library may reclaim
    internal storage used by the condition variable object. Call this
    routine when a condition variable will no longer be referenced.

    The results of this routine are unpredictable if the condition
    variable specified in cond does not exist or is not initialized.

    For more information about actions when threads are present,
    refer to the pthread_cond_destroy() description.

2.4  –  Return Values

    If an error condition occurs, this routine returns an integer
    value indicating the type of error. Possible return values are as
    follows:

    Return      Description

    0           Successful completion.
    [EBUSY]     The object being referenced by cond is being
                referenced by another thread that is currently
                executing a
                tis_cond_wait()  on the condition variable specified
                in cond. (This error can only occur when threads are
                present.)
    [EINVAL]    The value specified by cond is not a valid condition
                variable.

2.5  –  Associated Routines

       tis_cond_broadcast()
       tis_cond_init()
       tis_cond_signal()
       tis_cond_wait()

3  –  tis_cond_init

    Initializes a condition variable.

3.1  –  C Binding

    #include <tis.h>

    int
    tis_cond_init (
                pthread_cond_t   *cond);

3.2  –  Arguments

 cond

    Address of the condition variable (passed by reference) to be
    initialized.

3.3  –  Description

    This routine initializes a condition variable (cond) with the
    Threads Library default condition variable attributes.

    A condition variable is a synchronization object used with a
    mutex. A mutex controls access to shared data. When threads are
    present, a condition variable allows threads to wait for data to
    enter a defined state.

    For more information about actions taken when threads are
    present, refer to the pthread_cond_init() description.

    Your program can use the macro PTHREAD_COND_INITIALIZER to
    initialize statically allocated condition variables to the
    default condition variable attributes. Static initialization
    can be used only for a condition variable with storage class
    "extern" or "static" - "automatic" (stack local) objects must
    be initialized by calling tis_cond_init(). Use this macro as
    follows:

       pthread_cond_t condition = PTHREAD_COND_INITIALIZER;

    When statically initialized, a condition variable should not also
    be initialized using tis_cond_init().

3.4  –  Return Values

    If there is an error condition, the following occurs:

    o  The routine returns an integer value indicating the type of
       error.

    o  The condition variable is not initialized.

    o  The contents of condition variable cond are undefined.

    The possible return values are as follows:

    Return      Description

    0           Successful completion.
    [EAGAIN]    The system lacks the necessary resources to
                initialize another condition variable, or

                The system-imposed limit on the total number of
                condition variables under execution by a single user
                is exceeded.
    [EBUSY]     The implementation has detected an attempt to
                reinitialize the object referenced by cond, a
                previously initialized, but not yet destroyed
                condition variable.
    [EINVAL]    The value specified by cond is not a valid condition
                variable.
    [ENOMEM]    Insufficient memory to initialize the condition
                variable.

3.5  –  Associated Routines

       tis_cond_broadcast()
       tis_cond_destroy()
       tis_cond_signal()
       tis_cond_wait()

4  –  tis_cond_signal

    Wakes at least one thread that is waiting on the specified
    condition variable.

4.1  –  C Binding

    #include <tis.h>

    int
    tis_cond_signal (
                pthread_cond_t   *cond);

4.2  –  Arguments

 cond

    Address of the condition variable (passed by reference) on which
    to signal.

4.3  –  Description

    When threads are present, this routine unblocks at least one
    thread that is waiting on the specified condition variable cond.
    When threads are not present, this routine has no effect.

    For more information about actions taken when threads are
    present, refer to the pthread_cond_signal() description.

4.4  –  Return Values

    If an error condition occurs, this routine returns an integer
    value indicating the type of error. Possible return values are as
    follows:

    Return      Description

    0           Successful completion.
    [EINVAL]    The value specified by cond is not a valid condition
                variable.

4.5  –  Associated Routines

       tis_cond_broadcast()
       tis_cond_destroy()
       tis_cond_init()
       tis_cond_wait()

5  –  tis_cond_timedwait

    Causes a thread to wait for the specified condition variable
    to be signaled or broadcast, such that it will awake after a
    specified period of time.

5.1  –  C Binding

    #include <tis.h>

    int
    tis_cond_timedwait (
             pthread_cond_t   *cond,
             pthread_mutex_t   *mutex,
             const struct timespec   *abstime);

5.2  –  Arguments

 cond

    Condition variable that the calling thread waits on.

 mutex

    Mutex associated with the condition variable specified in cond.

 abstime

    Absolute time at which the wait expires, if the condition has not
    been signaled or broadcast. See the tis_get_expiration() routine,
    which is used to obtain a value for this argument.

    The abstime argument is specified in Universal Coordinated Time
    (UTC). In the UTC-based model, time is represented as seconds
    since the Epoch. The Epoch is defined as the time 0 hours, 0
    minutes, 0 seconds, January 1st, 1970 UTC.

5.3  –  Description

    If threads are not present, this function is equivalent to
    sleep().

    This routine causes a thread to wait until one of the following
    occurs:

    o  The specified condition variable is signaled or broadcast.

    o  The current system clock time is greater than or equal to the
       time specified by the abstime argument.

    This routine is identical to tis_cond_wait(), except that this
    routine can return before a condition variable is signaled or
    broadcast, specifically, when the specified time expires. For
    more information, see the tis_cond_wait() description.

    This routine atomically releases the mutex and causes the calling
    thread to wait on the condition. When the thread regains control
    after calling tis_cond_timedwait(), the mutex is locked and the
    thread is the owner. This is true regardless of why the wait
    ended. If general cancelability is enabled, the thread reacquires
    the mutex (blocking for it if necessary) before the cleanup
    handlers are run (or before the exception is raised).

    If the current time equals or exceeds the expiration time, this
    routine returns immediately, releasing and reacquiring the mutex.
    It might cause the calling thread to yield (see the sched_yield()
    description). Your code should check the return status whenever
    this routine returns and take the appropriate action. Otherwise,
    waiting on the condition variable can become a nonblocking loop.

    Call this routine after you have locked the mutex specified
    in mutex. The results of this routine are unpredictable if
    this routine is called without first locking the mutex. The
    only routines that are supported for use with asynchronous
    cancelability enabled are those that disable asynchronous
    cancelability.

5.4  –  Return Values

    If an error condition occurs, this routine returns an integer
    indicating the type of error. Possible return values are as
    follows:

    Return      Description

    0           Successful completion.
    [EINVAL]    The value specified by cond, mutex, or abstime is
                invalid, or

                Different mutexes are supplied for concurrent
                tis_cond_timedwait()  operations or
                tis_cond_wait()  operations on the same condition
                variable, or

                The mutex was not owned by the calling thread at the
                time of the call.
    [ETIMEDOUT] The time specified by abstime expired.
    [ENOMEM]    The Threads Library cannot acquire memory needed
                to block using a statically initialized condition
                variable.

5.5  –  Associated Routines

       tis_cond_broadcast()
       tis_cond_destroy()
       tis_cond_init()
       tis_cond_signal()
       tis_cond_wait()
       tis_get_expiration()

6  –  tis_cond_wait

    Causes a thread to wait for the specified condition variable to
    be signaled or broadcast.

6.1  –  C Binding

    #include <tis.h>

    int
    tis_cond_wait (
                pthread_cond_t   *cond,
                pthread_mutex_t   *mutex);

6.2  –  Arguments

 cond

    Address of the condition variable (passed by reference) on which
    to wait.

 mutex

    Address of the mutex (passed by reference) that is associated
    with the condition variable specified in cond.

6.3  –  Description

    When threads are present, this routine causes a thread to wait
    for the specified condition variable cond to be signaled or
    broadcast.

    Calling this routine in a single-threaded environment is a coding
    error. Because no other thread exists to issue a call to tis_
    cond_signal() or tis_cond_broadcast(),  using this routine in a
    single-threaded environment forces the program to exit.

    For further information about actions taken when threads are
    present, refer to the pthread_cond_wait() description.

6.4  –  Return Values

    If an error condition occurs, this routine returns an integer
    value indicating the type of error. Possible return values are as
    follows:

    Return      Description

    0           Successful completion.
    [EINVAL]    The value specified by cond is not a valid condition
                variable or the value specified by mutex is not a
                valid mutex, or

                Different mutexes are supplied for concurrent
                tis_cond_wait()  operations on the same condition
                variable, or

                The mutex was not owned by the calling thread at the
                time of the call.

6.5  –  Associated Routines

       tis_cond_broadcast()
       tis_cond_destroy()
       tis_cond_init()
       tis_cond_signal()

7  –  tis_getspecific

    Obtains the data associated with the specified thread-specific
    data key.

7.1  –  C Binding

    #include <tis.h>

    void *
    tis_getspecific (
                pthread_key_t   key);

7.2  –  Arguments

 key

    Identifies a value returned by a call to tis_key_create().
    This routine returns the data value associated with the thread-
    specific data key.

7.3  –  Description

    This routine returns the value currently bound to the specified
    thread-specific data key.

    This routine can be called from a data destructor function.

    When threads are present, the data and keys are thread specific;
    they enable a library to maintain context on a per-thread basis.

7.4  –  Return Values

    No errors are returned. This routine returns the data value
    associated with the specified thread-specific data key key. If
    no data value is associated with key, or if key is not defined,
    then a NULL value is returned.

7.5  –  Associated Routines

       tis_key_create()
       tis_key_delete()
       tis_setspecific()

8  –  tis_get_expiration

    Obtains a value representing a desired expiration time.

8.1  –  C Binding

    #include <tis.h>

    int
    tis_get_expiration (
                const struct timespec   *delta,
                struct timespec   *abstime);

8.2  –  Arguments

 delta

    Number of seconds and nanoseconds to add to the current system
    time. (The result is the time in the future.) This result will be
    placed in abstime.

 abstime

    Value representing the absolute expiration time. The absolute
    expiration time is obtained by adding delta to the current system
    time. The resulting abstime is in Universal Coordinated Time
    (UTC).

8.3  –  Description

    If threads are not present, this routine has no effect.

    This routine adds a specified interval to the current absolute
    system time and returns a new absolute time. This new absolute
    time is used as the expiration time in a call to tis_cond_
    timedwait().

    The timespec structure contains the following two fields:

    o  tv_sec is an integral number of seconds.

    o  tv_nsec is an integral number of nanoseconds.

8.4  –  Return Values

    If an error condition occurs, this routine returns an integer
    value indicating the type of error. Possible return values are as
    follows:

    Return      Description

    0           Successful completion.
    [EINVAL]    The value specified by delta is invalid.

8.5  –  Associated Routines

       tis_cond_timedwait()

9  –  tis_io_complete

    AST completion routine to VMS I/O system services.
    This routine is for OpenVMS systems only.

9.1  –  C Binding

    #include <tis.h>

    int
    tis_io_complete (void);

9.2  –  Description

    When you are performing thread-synchronous "wait-form" system
    service calls on OpenVMS such as $QIOW, $ENQW, $GETJPIW, and
    so on, you should use this routine and tis_sync() with the
    asynchronous form of the service (in other words, without the
    "W"), and specify the address of tis_io_complete() as the
    completion AST routine (the AST argument if any is ignored).
    That must also specify an IOSB (or equivalent, such as an LKSB)
    and if possible a unique event flag (see lib$get_ef). Once the
    library code is ready to wait for the I/O, it simply calls tis_
    sync() (just as if it were calling $SYNC).

9.3  –  Return Values

    None.

9.4  –  Associated Routines

       tis_sync()

10  –  tis_key_create

    Generates a unique thread-specific data key.

10.1  –  C Binding

    #include <tis.h>

    int
    tis_key_create (
       pthread_key_t   *key,
       void   (*destructor)(void *));

10.2  –  Arguments

 key

    Address of a variable that receives the key value. This value
    is used in calls to tis_getspecific() and tis_setspecific()  to
    obtain and set the value associated with this key.

 destructor

    Address of a routine that is called to destroy the context value
    when a thread terminates with a non-NULL value for the key. Note
    that this argument is used only when threads are present.

10.3  –  Description

    This routine generates a unique thread-specific data key. The key
    argument points to an opaque object used to locate data.

    This routine generates and returns a new key value. The key
    reserves a cell. Each call to this routine creates a new cell
    that is unique within an application invocation. Keys must
    be generated from initialization code that is guaranteed to
    be called only once within each process. (See the tis_once()
    description for more information.)

    Your program can associate an optional destructor function with
    each key. At thread exit, if a key has a non-NULL destructor
    function pointer, and the thread has a non-NULL value associated
    with that key, the function pointed to is called with the current
    associated value as its sole argument. The order in which data
    destructors are called at thread termination is undefined.

    When threads are present, keys and any corresponding data are
    thread specific; they enable the context to be maintained on a
    per-thread basis. For more information about the use of tis_key_
    create() in a threaded environment, refer to the pthread_key_
    create() description.

    The Threads Library imposes a maximum number of thread-specific
    data keys, equal to the symbolic constant PTHREAD_KEYS_MAX.

10.4  –  Return Values

    If an error condition occurs, this routine returns an integer
    indicating the type of error. Possible return values are as
    follows:

    Return      Description

    0           Successful completion.
    [EAGAIN]    The system lacked the necessary resources to create
                another thread-specific data key, or the limit on the
                total number of keys per process (PTHREAD_KEYS_MAX)
                has been exceeded.
    [EINVAL]    The value specified by key is invalid.
    [ENOMEM]    Insufficient memory to create the key.

10.5  –  Associated Routines

       tis_getspecific()
       tis_key_delete()
       tis_setspecific()
       tis_once()

11  –  tis_key_delete

    Deletes the specified thread-specific data key.

11.1  –  C Binding

    #include <tis.h>

    int
    tis_key_delete (
                pthread_key_t   key);

11.2  –  Arguments

 key

    Thread-specific data key to be deleted.

11.3  –  Description

    This routine deletes a thread-specific data key key previously
    returned by a call to the tis_key_create() routine. The data
    values associated with key need not be NULL at the time this
    routine is called. The application must free any application
    storage or perform any cleanup actions for data structures
    related to the deleted key or associated data. This cleanup can
    be done before or after this routine is called. If the cleanup
    is done after this routine is called, the application must have a
    private mechanism to access any and all thread-specific values,
    contexts, and so on.

    Attempting to use the thread-specific data key key after calling
    this routine results in unpredictable behavior.

    No destructor functions are invoked by this routine. Any
    destructor functions that may have been associated with key will
    no longer be called upon thread exit.

    This routine can be called from destructor functions.

11.4  –  Return Values

    If an error condition occurs, this routine returns an integer
    indicating the type of error. Possible return values are as
    follows:

    Return      Description

    0           Successful completion.
    [EINVAL]    The value for key is invalid.

11.5  –  Associated Routines

       tis_getspecific()
       tis_key_create()
       tis_setspecific()

12  –  tis_lock_global

    Locks the Threads Library global mutex.

12.1  –  C Binding

    #include <tis.h>

    int
    tis_lock_global (void);

12.2  –  Arguments

    None

12.3  –  Description

    This routine locks the global mutex. The global mutex is
    recursive. For example, if you called tis_lock_global() three
    times, tis_unlock_global() unlocks the global mutex when you call
    it the third time.

    For more information about actions taken when threads are
    present, refer to the pthread_lock_global_np() description.

12.4  –  Return Values

    If an error condition occurs, this routine returns an integer
    value indicating the type of error. Possible return values are as
    follows:

    Return      Description

    0           Successful completion.

12.5  –  Associated Routines

       tis_unlock_global()

13  –  tis_mutex_destroy

    Destroys the specified mutex object.

13.1  –  C Binding

    #include <tis.h>

    int
    tis_mutex_destroy (
                pthread_mutex_t   *mutex);

13.2  –  Arguments

 mutex

    Address of the mutex object (passed by reference) to be
    destroyed.

13.3  –  Description

    This routine destroys a mutex object by uninitializing it, and
    should be called when a mutex object is no longer referenced.
    After this routine is called, the Threads Library can reclaim
    internal storage used by the mutex object.

    It is safe to destroy an initialized mutex object that is
    unlocked. However, it is illegal to destroy a locked mutex
    object.

    The results of this routine are unpredictable if the mutex object
    specified in the mutex argument either does not currently exist
    or is not initialized.

13.4  –  Return Values

    If an error condition occurs, this routine returns an integer
    value indicating the type of error. Possible return values are as
    follows:

    Return      Description

    0           Successful completion.
    [EBUSY]     An attempt was made to destroy the object referenced
                by mutex while it is locked or referenced.
    [EINVAL]    The value specified by mutex is not a valid mutex.
    [EPERM]     The caller does not have privileges to perform the
                operation.

13.5  –  Associated Routines

       tis_mutex_init()
       tis_mutex_lock()
       tis_mutex_trylock()
       tis_mutex_unlock()

14  –  tis_mutex_init

    Initializes the specified mutex object.

14.1  –  C Binding

    #include <tis.h>

    int
    tis_mutex_init (
                pthread_mutex_t   *mutex );

14.2  –  Arguments

 mutex

    Pointer to a mutex object (passed by reference) to be
    initialized.

14.3  –  Description

    This routine initializes a mutex object with the Threads Library
    default mutex attributes. A mutex is a synchronization object
    that allows multiple threads to serialize their access to shared
    data.

    The mutex object is initialized and set to the unlocked state.

    Your program can use the PTHREAD_MUTEX_INITIALIZER macro to
    statically initialize a mutex object without calling this
    routine. Static initialization can be used only for a condition
    variable with storage class "extern" or "static" - "automatic"
    (stack local) objects must be initialized by calling tis_mutex_
    init(). Use this macro as follows:

       pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

14.4  –  Return Values

    If an error condition occurs, this routine returns an integer
    value indicating the type of error. Possible return values are as
    follows:

    Return      Description

    0           Successful completion.
    [EAGAIN]    The system lacks the necessary resources to
                initialize a mutex.
    [EBUSY]     The implementation has detected an attempt to
                reinitialize mutex (a previously initialized, but
                not yet destroyed, mutex).
    [EINVAL]    The value specified by mutex is not a valid mutex.
    [ENOMEM]    Insufficient memory to initialize the mutex.
    [EPERM]     The caller does not have privileges to perform this
                operation.

14.5  –  Associated Routines

       tis_mutex_destroy()
       tis_mutex_lock()
       tis_mutex_trylock()
       tis_mutex_unlock()

15  –  tis_mutex_lock

    Locks an unlocked mutex.

15.1  –  C Binding

    #include <tis.h>

    int
    tis_mutex_lock (
                pthread_mutex_t   *mutex);

15.2  –  Arguments

 mutex

    Address of the mutex (passed by reference) to be locked.

15.3  –  Description

    This routine locks the specified mutex mutex. A deadlock can
    result if the owner of a mutex calls this routine in an attempt
    to lock the same mutex a second time. (The Threads Library may
    not detect or report the deadlock.)

    In a threaded environment, the thread that has locked a mutex
    becomes its current owner and remains the owner until the same
    thread has unlocked it. This routine returns with the mutex
    in the locked state and with the current thread as the mutex's
    current owner.

15.4  –  Return Values

    If an error condition occurs, this routine returns an integer
    value indicating the type of error. Possible return values are as
    follows:

    Return      Description

    0           Successful completion.
    [EDEADLK]   A deadlock condition is detected.
    [EINVAL]    The value specified by mutex is not a valid mutex.

15.5  –  Associated Routines

       tis_mutex_destroy()
       tis_mutex_init()
       tis_mutex_trylock()
       tis_mutex_unlock()

16  –  tis_mutex_trylock

    Attempts to lock the specified mutex.

16.1  –  C Binding

    #include <tis.h>

    int
    tis_mutex_trylock (
                pthread_mutex_t   *mutex);

16.2  –  Arguments

 mutex

    Address of the mutex (passed by reference) to be locked.

16.3  –  Description

    This routine attempts to lock the specified mutex mutex. When
    this routine is called, an attempt is made immediately to lock
    the mutex. If the mutex is successfully locked, zero (0) is
    returned.

    If the specified mutex is already locked when this routine
    is called, the caller does not wait for the mutex to become
    available. [EBUSY] is returned, and the thread does not wait
    to acquire the lock.

16.4  –  Return Values

    If an error condition occurs, this routine returns an integer
    value indicating the type of error. Possible return values are as
    follows:

    Return      Description

    0           Successful completion.
    [EBUSY]     The mutex is already locked; therefore, it was not
                acquired.
    [EINVAL]    The value specified by mutex is not a valid mutex.

16.5  –  Associated Routines

       tis_mutex_destroy()
       tis_mutex_init()
       tis_mutex_lock()
       tis_mutex_unlock()

17  –  tis_mutex_unlock

    Unlocks the specified mutex.

17.1  –  C Binding

    #include <tis.h>

    int
    tis_mutex_unlock (
                pthread_mutex_t   *mutex);

17.2  –  Arguments

 mutex

    Address of the mutex (passed by reference) to be unlocked.

17.3  –  Description

    This routine unlocks the specified mutex mutex.

    For more information about actions taken when threads are
    present, refer to the pthread_mutex_unlock() description.

17.4  –  Return Values

    If an error condition occurs, this routine returns an integer
    value indicating the type of error. Possible return values are as
    follows:

    Return      Description

    0           Successful completion.
    [EINVAL]    The value specified by mutex is not a valid mutex.
    [EPERM]     The caller does not own the mutex.

17.5  –  Associated Routines

       tis_mutex_destroy()
       tis_mutex_init()
       tis_mutex_lock()
       tis_mutex_trylock()

18  –  tis_once

    Calls a one-time initialization routine that can be executed by
    only one thread, once.

18.1  –  C Binding

    #include <tis.h>

    int
    tis_once (
          pthread_once_t   *once_control,
          void   (*init_routine) (void));

18.2  –  Arguments

 once_control

    Address of a record (control block) that defines the one-time
    initialization code. Any one-time initialization routine in
    static storage specified by once_control must have its own unique
    pthread_once_t record.

 init_routine

    Address of a procedure that performs the initialization. This
    routine is called only once, regardless of the number of times it
    and its associated once_control are passed to tis_once().

18.3  –  Description

    The first call to this routine by a process with a given once_
    control calls the init_routine with no arguments. Thereafter,
    subsequent calls to tis_once() with the same once_control do
    not call the init_routine. On return from tis_once(), it is
    guaranteed that the initialization routine has completed.

    For example, a mutex or a thread-specific data key must be
    created exactly once. In a threaded environment, calling tis_
    once() ensures that the initialization is serialized across
    multiple threads.

                                   NOTE

       If you specify an init_routine that directly or indirectly
       results in a recursive call to tis_once() and that specifies
       the same init_block argument, the recursive call results in
       a deadlock.

    The PTHREAD_ONCE_INIT macro, defined in the pthread.h header
    file, must be used to initialize a once_control record. Thus,
    your program must declare a once_control record as follows:

    pthread_once_t  once_control = PTHREAD_ONCE_INIT;

    Note that it is often easier to simply lock a statically
    initialized mutex, check a control flag, and perform necessary
    initialization (in-line) rather than using tis_once(). For
    example, you can code an "init" routine that begins with the
    following basic logic:

      init()
      {
       static pthread_mutex_t    mutex = PTHREAD_MUTEX_INIT;
       static int                flag = FALSE;

       tis_mutex_lock(&mutex);
       if(!flag)
         {
          flag = TRUE;
          /* initialize code */
         }
       tis_mutex_unlock(&mutex);
      }

18.4  –  Return Values

    If an error occurs, this routine returns an integer indicating
    the type of error. Possible return values are as follows:

    Return      Description

    0           Successful completion.
    [EINVAL]    Invalid argument.

19  –  tis_read_lock

    Acquires a read-write lock for read access.

19.1  –  C Binding

    #include <tis.h>

    int
    tis_read_lock (
             tis_rwlock_t   *lock);

19.2  –  Arguments

 lock

    Address of the read-write lock.

19.3  –  Description

    This routine acquires a read-write lock for read access. This
    routine waits for any existing lock holder for write access to
    relinquish its lock before granting the lock for read access.
    This routine returns when the lock is acquired. If the lock is
    already held simply for read access, the lock is granted.

    For each call to tis_read_lock() that successfully acquires the
    lock for read access, a corresponding call to tis_read_unlock()
    must be issued.

19.4  –  Return Values

    If an error condition occurs, this routine returns an integer
    value indicating the type of error. Possible return values are as
    follows:

    Return      Description

    0           Successful completion.
    [EINVAL]    The value specified by lock is not a valid read-write
                lock.

19.5  –  Associated Routines

       tis_read_trylock()
       tis_read_unlock()
       tis_rwlock_destroy()
       tis_rwlock_init()
       tis_write_lock()
       tis_write_trylock()
       tis_write_unlock()

20  –  tis_read_trylock

    Attempts to acquire a read-write lock for read access. Does not
    wait if the lock cannot be immediately granted.

20.1  –  C Binding

    #include <tis.h>

    int
    tis_read_trylock (
             tis_rwlock_t    *lock);

20.2  –  Arguments

 lock

    Address of the read-write lock to be acquired.

20.3  –  Description

    This routine attempts to acquire a read-write lock for read
    access. If the lock cannot be granted, the routine returns
    without waiting.

    When a thread calls this routine, an attempt is made to
    immediately acquire the lock for read access. If the lock is
    acquired, zero (0) is returned. If a holder of the lock for write
    access exists, [EBUSY] is returned.

    If the lock cannot be acquired for read access immediately, the
    calling program does not wait for the lock to be released.

20.4  –  Return Values

    If an error condition occurs, this routine returns an integer
    value indicating the type of error. Possible return values are as
    follows:

    Return      Description

    0           Successful completion; the lock was acquired.
    [EBUSY]     The lock is being held for write access. The lock for
                read access was not acquired.
    [EINVAL]    The value specified by lock is not a valid read-write
                lock.

20.5  –  Associated Routines

       tis_read_lock()
       tis_read_unlock()
       tis_rwlock_destroy()
       tis_rwlock_init()
       tis_write_lock()
       tis_write_trylock()
       tis_write_unlock()

21  –  tis_read_unlock

    Unlocks a read-write lock that was acquired for read access.

21.1  –  C Binding

    #include <tis.h>

    int
    tis_read_unlock (
             tis_rwlock_t   *lock);

21.2  –  Arguments

 lock

    Address of the read-write lock to be unlocked.

21.3  –  Description

    This routine unlocks a read-write lock that was acquired for
    read access. If there are no other holders of the lock for read
    access and another thread is waiting to acquire the lock for
    write access, that lock acquisition is granted.

21.4  –  Return Values

    If an error condition occurs, this routine returns an integer
    value indicating the type of error. Possible return values are as
    follows:

    Return      Description

    0           Successful completion.
    [EINVAL]    The value specified by lock is not a valid read-write
                lock.

21.5  –  Associated Routines

       tis_read_lock()
       tis_read_trylock()
       tis_rwlock_destroy()
       tis_rwlock_init()
       tis_write_lock()
       tis_write_trylock()
       tis_write_unlock()

22  –  tis_rwlock_destroy

    Destroys the specified read-write lock object.

22.1  –  C Binding

    #include <tis.h>

    int
    tis_rwlock_destroy (
             tis_rwlock_t   *lock);

22.2  –  Arguments

 lock

    Address of the read-write lock object to be destroyed.

22.3  –  Description

    This routine destroys the specified read-write lock object. Prior
    to calling this routine, ensure that there are no locks granted
    to the specified read-write lock and that there are no threads
    waiting for pending lock acquisitions on the specified read-write
    lock.

    This routine should be called only after all reader threads (and
    perhaps one writer thread) have finished using the specified
    read-write lock.

22.4  –  Return Values

    If an error condition occurs, this routine returns an integer
    value indicating the type of error. Possible return values are as
    follows:

    Return      Description

    0           Successful completion.
    [EBUSY]     The lock is in use.
    [EINVAL]    The value specified by lock is not a valid read-write
                lock.

22.5  –  Associated Routines

       tis_read_lock()
       tis_read_trylock()
       tis_read_unlock()
       tis_rwlock_init()
       tis_write_lock()
       tis_write_trylock()
       tis_write_unlock()

23  –  tis_rwlock_init

    Initializes a read-write lock object.

23.1  –  C Binding

    #include <tis.h>

    int
    tis_rwlock_init (
             tis_rwlock_t   *lock);

23.2  –  Arguments

 lock

    Address of a read-write lock object.

23.3  –  Description

    This routine initializes a read-write lock object. The routine
    initializes the tis_rwlock_t structure that holds the object's
    lock states.

    To destroy a read-write lock object, call the tis_rwlock_
    destroy() routine.

                                   NOTE

       The tis read-write lock has no relationship to the Single
       UNIX Specification, Version 2 (SUSV2, or UNIX98) read-
       write lock routines (such as pthread_rwlock_init()). The
       tis_rwlock_t type, in particular, cannot be used with the
       pthread read-write lock functions, nor can a pthread_rwlock_
       t type be used with the tis read-write lock functions.

23.4  –  Return Values

    If an error condition occurs, this routine returns an integer
    value indicating the type of error. Possible return values are as
    follows:

    Return      Description

    0           Successful completion.
    [EINVAL]    The value specified by lock is not a valid read-write
                lock.
    [ENOMEM]    Insufficient memory to initialize lock.

23.5  –  Associated Routines

       tis_read_lock()
       tis_read_trylock()
       tis_read_unlock()
       tis_rwlock_destroy()
       tis_write_lock()
       tis_write_trylock()
       tis_write_unlock()

24  –  tis_self

    Returns the identifier of the calling thread.

24.1  –  C Binding

    #include <tis.h>

    pthread_t
    tis_self (void);

24.2  –  Arguments

    None

24.3  –  Description

    This routine allows a thread to obtain its own thread identifier.

    This value becomes meaningless when the thread is destroyed.

    Note that the initial thread in a process can "change identity"
    when thread system initialization completes-that is, when the
    multithreading run-time environment is loaded.

24.4  –  Return Values

    Returns the thread identifier of the calling thread.

24.5  –  Associated Routines

       pthread_create()

25  –  tis_setcancelstate

    Changes the calling thread's cancelability state.

25.1  –  C Binding

    #include <tis.h>

    int
    tis_setcancelstate (
                int   state,
                int   *oldstate );

25.2  –  Arguments

 state

    State of general cancelability to set for the calling thread.
    Valid state values are as follows:

       PTHREAD_CANCEL_ENABLE
       PTHREAD_CANCEL_DISABLE

 oldstate

    Receives the value of the calling thread's previous cancelability
    state.

25.3  –  Description

    This routine sets the calling thread's cancelability state to
    the value specified in the state argument and returns the calling
    thread's previous cancelability state in the location referenced
    by the oldstate argument.

    When a thread's cancelability state is set to PTHREAD_CANCEL_
    DISABLE, a cancelation request cannot be delivered to the
    thread, even if a cancelable routine is called or asynchronous
    cancelability is enabled.

    When a thread is created, its default cancelability state is
    PTHREAD_CANCEL_ENABLE. When this routine is called prior to
    loading threads, the cancelability state propagates to the
    initial thread in the executing program.
    Possible Problems When Disabling Cancelability
    The most important use of a cancelation request is to ensure that
    indefinite wait operations are terminated. For example, a thread
    waiting on some network connection, which might take days to
    respond (or might never respond), should be made cancelable.

    When a thread's cancelability state is disabled, no routine
    called within that thread is cancelable. As a result, the user
    is unable to cancel the operation. When disabling cancelability,
    be sure that no long waits can occur or that it is necessary
    for other reasons to defer cancelation requests around that
    particular region of code.

25.4  –  Return Values

    On successful completion, this routine returns the calling
    thread's previous cancelability state in the oldstate argument.

    If an error condition occurs, this routine returns an integer
    value indicating the type of error. Possible return values are as
    follows:

    Return      Description

    0           Successful completion.
    [EINVAL]    The specified state is not PTHREAD_CANCEL_ENABLE or
                PTHREAD_CANCEL_DISABLE.

25.5  –  Associated Routines

       tis_testcancel()

26  –  tis_setspecific

    Changes the value associated with the specified thread-specific
    data key.

26.1  –  C Binding

    #include <tis.h>

    int
    tis_setspecific (
                pthread_key_t   key,
                const void   *value);

26.2  –  Arguments

 key

    Thread-specific data key that identifies the data to receive
    value. Must be obtained from a call to tis_key_create().

 value

    New value to associate with the specified key. Once set, this
    value can be retrieved using the same key in a call to tis_
    getspecific().

26.3  –  Description

    This routine sets the value associated with the specified thread-
    specific data key. If a value is defined for the key (that is,
    the current value is not NULL), the new value is substituted for
    it. The key is obtained by a previous call to tis_key_create().

    Do not call this routine from a data destructor function. Doing
    so could lead to a memory leak or an infinite loop.

26.4  –  Return Values

    If an error condition occurs, this routine returns an integer
    indicating the type of error. Possible return values are as
    follows:

    Return      Description

    0           Successful completion.
    [EINVAL]    The value specified by key is not a valid key.
    [ENOMEM]    Insufficient memory to associate the value with the
                key.

26.5  –  Associated Routines

       tis_getspecific()
       tis_key_create()
       tis_key_delete()

27  –  tis_sync

    Used as the synchronization point for asynchronous I/O system
    services. This routine is for OpenVMS systems only.

27.1  –  C Binding

    #include <tis.h>

    int
    tis_sync (
          unsigned long   efn,
          void   *iosb);

27.2  –  Arguments

 efn

    The event flag specified with the OpenVMS system service routine.

 iosb

    The IOSB specified with the OpenVMS system service routine.

27.3  –  Description

    When you are performing thread-synchronous "wait-form" system
    service calls on OpenVMS such as $QIOW, $ENQW, $GETJPIW, and so
    on, you should use this routine and tis_io_complete() with the
    asynchronous form of the service (that is, without the "W") and
    specify the address of tis_io_complete() as the completion AST
    routine (the AST argument, if any, is ignored). The call must
    also specify an IOSB (or equivalent, such as an LKSB) and if
    possible a unique event flag (see lib$get_ef). Once the library
    code is ready to wait for the I/O, it simply calls tis_sync()
    (just as if it were calling $SYNC).

27.4  –  Return Values

    This routine has the same return values as the OpenVMS $SYNC()
    routine.

27.5  –  Associated Routines

       tis_io_complete()

28  –  tis_testcancel

    Creates a cancelation point in the calling thread.

28.1  –  C Binding

    #include <tis.h>

    void
    tis_testcancel (void);

28.2  –  Arguments

    None

28.3  –  Description

    This routine requests delivery of a pending cancelation request
    to the calling thread. Thus, this routine creates a cancelation
    point in the calling thread. The cancelation request is delivered
    only if a request is pending for the calling thread and the
    calling thread's cancelability state is enabled. (A thread
    disables delivery of cancelation requests to itself by calling
    tis_setcancelstate().)

    This routine, when called within very long loops, ensures that a
    pending cancelation request is noticed within a reasonable amount
    of time.

28.4  –  Return Values

    None

28.5  –  Associated Routines

       tis_setcancelstate()

29  –  tis_unlock_global

    Unlocks the Threads Library global mutex.

29.1  –  C Binding

    #include <tis.h>

    int
    tis_unlock_global (void);

29.2  –  Arguments

    None

29.3  –  Description

    This routine unlocks the global mutex. Because the global mutex
    is recursive, the unlock occurs when each call to tis_lock_
    global() has been matched by a call to this routine. For example,
    if your program called tis_lock_global() three times, tis_unlock_
    global() unlocks the global mutex when you call it the third
    time.

    For more information about actions taken when threads are
    present, refer to the pthread_unlock_global_np() description.

29.4  –  Return Values

    If an error condition occurs, this routine returns an integer
    value indicating the type of error. Possible return values are as
    follows:

    Return      Description

    0           Successful completion.
    [EPERM]     The global mutex is unlocked or locked by another
                thread.

29.5  –  Associated Routines

       tis_lock_global()

30  –  tis_write_lock

    Acquires a read-write lock for write access.

30.1  –  C Binding

    #include <tis.h>

    int
    tis_write_lock (
             tis_rwlock_t   *lock);

30.2  –  Arguments

 lock

    Address of the read-write lock to be acquired for write access.

30.3  –  Description

    This routine acquires a read-write lock for write access. This
    routine waits for any other active locks (for either read or
    write access) to be unlocked before this acquisition request is
    granted.

    This routine returns when the specified read-write lock is
    acquired for write access.

30.4  –  Return Values

    If an error condition occurs, this routine returns an integer
    value indicating the type of error. Possible return values are as
    follows:

    Return      Description

    0           Successful completion.
    [EINVAL]    The value specified by lock is not a valid read-write
                lock.

30.5  –  Associated Routines

       tis_read_lock()
       tis_read_trylock()
       tis_read_unlock()
       tis_rwlock_destroy()
       tis_rwlock_init()
       tis_write_trylock()
       tis_write_unlock()

31  –  tis_write_trylock

    Attempts to acquire a read-write lock for write access.

31.1  –  C Binding

    #include <tis.h>

    int
    tis_write_trylock (
             tis_rwlock_t   *lock);

31.2  –  Arguments

 lock

    Address of the read-write lock to be acquired for write access.

31.3  –  Description

    This routine attempts to acquire a read-write lock for write
    access. The routine attempts to immediately acquire the lock.
    If the lock is acquired, zero (0) is returned. If the lock is
    held by another thread (for either read or write access), [EBUSY]
    is returned and the calling thread does not wait for the write-
    access lock to be acquired.

    Note that it is a coding error to attempt to acquire the lock
    for write access if the lock is already held by the calling
    thread. (However, this routine returns [EBUSY] anyway, because
    no ownership error-checking takes place.)

31.4  –  Return Values

    If an error condition occurs, this routine returns an integer
    value indicating the type of error. Possible return values are as
    follows:

    Return      Description

    0           Successful completion, the lock is acquired for write
                access.
    [EBUSY]     The lock was not acquired for write access, as it is
                already held by another thread.
    [EINVAL]    The value specified by lock is not a valid read-write
                lock.

31.5  –  Associated Routines

       tis_read_lock()
       tis_read_trylock()
       tis_read_unlock()
       tis_rwlock_destroy()
       tis_rwlock_init()
       tis_write_lock()
       tis_write_unlock()

32  –  tis_write_unlock

    Unlocks a read-write lock that was acquired for write access.

32.1  –  C Binding

    #include <tis.h>

    int
    tis_write_unlock (
             tis_rwlock_t   *lock);

32.2  –  Arguments

 lock

    Address of the read-write lock to be unlocked.

32.3  –  Description

    This routine unlocks a read-write lock that was acquired for
    write access.

    Upon completion of this routine, any thread waiting to acquire
    the lock for read access will have those acquisitions granted. If
    no threads are waiting to acquire the lock for read access, then
    a thread waiting to acquire it for write access will have that
    acquisition granted.

32.4  –  Return Values

    If an error condition occurs, this routine returns an integer
    value indicating the type error. Possible return values are as
    follows:

    Return      Description

    0           Successful completion.
    [EINVAL]    The value specified by lock is not a valid read-write
                lock.

32.5  –  Associated Routines

       tis_read_lock()
       tis_read_trylock()
       tis_read_unlock()
       tis_rwlock_init()
       tis_rwlock_destroy()
       tis_write_lock()
       tis_write_trylock()

33  –  tis_yield

    Notifies the scheduler that the current thread is willing to
    release its processor to other threads of the same or higher
    priority.

    Syntax

      tis_yield();

33.1  –  C Binding

    int
    tis_yield (void);

33.2  –  Arguments

    None

33.3  –  Description

    When threads are not present, this routine has no effect.

    This routine notifies the thread scheduler that the current
    thread is willing to release its processor to other threads of
    equivalent or greater scheduling precedence. (A thread generally
    will release its processor to a thread of a greater scheduling
    precedence without calling this routine.) If no other threads of
    equivalent or greater scheduling precedence are ready to execute,
    the thread continues.

    This routine can allow knowledge of the details of an application
    to be used to improve its performance. If a thread does not call
    tis_yield(), other threads may be given the opportunity to run
    at arbitrary points (possibly even when the interrupted thread
    holds a required resource). By making strategic calls to tis_
    yield(), other threads can be given the opportunity to run when
    the resources are free. This improves performance by reducing
    contention for the resource.

    As a general guideline, consider calling this routine after a
    thread has released a resource (such as a mutex) which is heavily
    contended for by other threads. This can be especially important
    if the program is running on a uniprocessor machine, or if the
    thread acquires and releases the resource inside a tight loop.

    Use this routine carefully and sparingly, because misuse can
    cause unnecessary context switching that will increase overhead
    and actually degrade performance. For example, it is counter-
    productive for a thread to yield while it holds a resource that
    the threads to which it is yielding will need. Likewise, it is
    pointless to yield unless there is likely to be another thread
    that is ready to run.

33.4  –  Return Values

    If an error condition occurs, this routine returns an integer
    value indicating the type of error. Possible return values are as
    follows:

    Return      Description

    0           Successful completion.
    [ENOSYS]    The routine tis_yield()  is not supported by this
                implementation.
Close Help