HP 3000 Manuals

Writing Threaded Applications [ DCE for the HP 3000 ] MPE/iX 5.0 Express III Documentation


DCE for the HP 3000

Writing Threaded Applications 

The following are hints on writing multithreaded DCE applications:

   *   All DCE applications are multithreaded - When writing DCE
       applications, keep in mind, that the DCE runtime software is
       multithreaded and all DCE applications are multithreaded; even if
       the application code itself does not explicitly create threads.

   *   Using non-thread-safe libraries - When making calls to libraries
       you do not specifically know to be thread-safe, you must provide
       your own locking scheme to prevent multiple threads from executing
       the same library calls concurently.  While a given call may appear
       to be innocuous with respect to threads, it is very difficult to
       know exactly what interactions can occur within the library, or
       with other libraries.  For example, suppose non-thread-safe
       routines 1 and 2 make a call to routine A (also non-thread-safe),
       if routines 1 and 2 use different mutexes to lock their calls to
       routine A, then routines 1 and 2 can both get into routine A at
       the same time (violating the programmer's attempt to make the
       calls thread-safe).

   *   Using fork() in a threaded application - fork() is not allowed
       from a threaded task.

   *   environ is a process-wide resource - Programmers must coordinate
       threads that use the putenv() and getenv() interfaces to change
       and read environ.

   *   Signal mask:  a thread-specific resource - The signal mask is a
       thread-specific resource; therefore, if one thread manipulates the
       signal mask, it only affects signals that specific threads might
       be interested in (Posix 1003.4a Draft 3 behavior).

   *   Handling synchronous terminating signals - The default behavior of
       OSF DCE 1.0.2 is to translate synchronous terminating signals into
       exceptions.  If the exception is not caught, the thread that
       caused the exception is terminated.  Any thread that goes through
       the terminate code causes the entire task to be terminated.

   *   Establish synchronous signal handlers using sigaction() - The
       MPE/iX POSIX C Library supports the following routines for setting
       up signal handlers:

            signal()
            sigaction()

       Of these routines, only sigaction() is supported in a DCE
       application.  It is used to establish handlers for synchronous
       signals on an individual thread basis only.

   *   Asynchronous signals - There is no supported mechanism for
       establishing signal handlers for asynchronous signals on MPE/iX.

   *   Cancelling threads blocked on a system call - The HP 3000 Kernel
       Threads Service provides a cancellation facility that enables one
       thread to terminate another.  The cancelled thread normally
       terminates at a well-defined point.  Terminating a thread that is
       blocked while executing system code is not possible on MPE/iX;
       only threads executing non-system code may be cancelled.

   *   Using waitpid() - The waitpid() routine allows the parent thread
       to specify which child it cares about by specifying its PID. This
       call only works for the initial thread; because children created
       by any thread within the task are considered children of the whole
       task.

   *   Using setjmp and longjmp - Do not use calls to setjmp and longjmp,
       these routines save and restore the signal mask and could
       inadvertently cause a signal that another thread is waiting on to
       be masked.  Instead, use _setjmp and _longjmp; these routines do
       not manipulate the signal mask.

       When executing _longjmp be aware of the following:

          *   Ensure you are returning to a state saved within the
              context of the same thread.

          *   If you _longjmp over a TRY clause, an exception could try
              to _longjmp to a stack frame that no longer exists; and
              vice versa.

          *   Do not _longjmp out of a signal handler.

   *   Use pthread_yield to allow other threads processor time - If your
       application is running on a single-processor machine, and you want
       to permit other threads access to the processor, you can use
       pthread_yield to notify the scheduler that the current thread is
       willing to release the processor to other threads of the same or
       higher priority.  If no threads of the same or higher priority are
       ready to execute, the thread continues.

       An example of the use of pthread_yield is to avoid spinning in a
       tight loop, such as:

            while (!flag);

       by using pthread_yield as:

            while (!flag) pthread_yield();

       Use pthread_yield with caution; misuse can cause unnecessary
       context switching and increasing overhead with no increase in
       "fairness." For example, it is counterproductive for a thread to
       yield while it has a needed resource locked.



MPE/iX 5.0 Express III Documentation