CONTENTS Title Page Copyright Page Preface Part I General Considerations 1 Introduction 2 Program Development 2.1 Compiling, Linking, and Building a VAXELN POSIX Application 2.1.1 Compiling a VAXELN POSIX Program 2.1.2 Linking a VAXELN POSIX Program 2.1.3 Using the System Builder 2.2 Debugging VAXELN POSIX Programs 2.3 Error Codes from VAXELN and Interpretation of errno 2.4 Mixing VAXELN and POSIX Functions 2.5 Permanent Allocation of Two Memory Pages 2.6 Argument Value Limits for Clock, Per-Process Timer, and Sleep Routines 2.7 File Descriptors for Sockets in a Child Process 2.8 Using the Code Examples Part II Program Control 3 Process Primitives 3.1 Controlling Processes 3.1.1 Creating and Executing Processes 3.1.2 Terminating Processes 3.2 Using Signals to Coordinate Processes and Events 3.2.1 Responding to Signals: Default and Specified Action 3.2.2 Using a Signal Mask in Interprocess Communication 3.2.3 Using a Signal to Wake Up a Process That Is Pausing 3.2.4 Using Signal Masks 4 Process Environment 4.1 Retrieving Process IDs 4.2 Getting and Setting User IDs 4.3 Retrieving Process Group IDs 4.4 Retrieving the User's Group IDs 4.5 Retrieving Information About the Current Operating System 5 Directory and File Control 5.1 Directory Control 5.2 File Control 6 Device and Class Specific Functions: Controlling Terminals 6.1 Getting and Setting Terminal Baud Rates 6.2 Controlling the Terminal 7 System Databases 7.1 Creating the POSIX System Databases 7.2 Accessing User Databases 7.3 Accessing the Group Database 7.4 Example Showing Database Access Part III Realtime Functions 8 Processes Synchronization with Binary Semaphores 8.1 Semaphore Persistence 8.2 Posting and Waiting for Binary Semaphores 8.3 A Sample Program That Uses Binary Semaphores 9 Shared Memory 9.1 Creating and Referencing a Shared Memory Object 9.2 Mapping Shared Memory Objects 9.3 Sharing Data 9.4 Cleaning Up a Shared Memory Object 9.5 Passing Data Between Processes Through Shared Memory-an Example 10 Process Memory Locking 11 Priority Scheduling 11.1 Scheduling Policies 11.1.1 First-In/First-Out Scheduling 11.1.2 Round-Robin Scheduling 11.2 Scheduling Functions 11.2.1 Retrieving the Priority and Scheduling Policy 11.2.2 Setting the Priority and the Scheduling Policy 11.2.3 Yielding to Another Process 12 Clocks and Timers 12.1 Using Data Structures and Resolution for Timing Functions 12.1.1 Using the timespec Data Structure 12.1.2 Using the itimerspec Data Structure 12.1.3 Resolution of the System Clock and Timers 12.2 Using the Systemwide Clock 12.2.1 Retrieving System Time 12.2.2 Setting the System Clock 12.2.3 Managing Clock Drift 12.2.4 Converting Time 12.3 Using Timers 12.3.1 Creating Timers 12.3.2 Setting Timer Values 12.3.3 Retrieving Timer Values 12.3.4 Disabling Timers 12.4 Using High-Resolution Sleep Part IV Threads 13 Introduction to Threads 13.1 Objects 13.1.1 Thread Objects 13.1.1.1 Advantages of Using Threads 13.1.1.2 Thread Execution 13.1.2 Mutex Objects 13.1.3 Condition Variable Objects 13.2 Attributes Objects 13.2.1 Thread Attributes Objects 13.2.2 Mutex Attributes Objects 13.2.3 Condition Variable Attributes Objects 13.3 Thread-Specific Data 14 Four Models for Threaded Programming 14.1 Software Models for Multithreaded Programming 14.1.1 Boss/Worker Model 14.1.2 Work Crew Model 14.1.3 Pipelining Model 14.1.4 Combinations of Models 14.2 Potential Problems with Multithreaded Programming 15 Attributes Objects 15.1 Creating an Attributes Object 15.2 Deleting an Attributes Object 15.3 Thread Attributes Objects 15.3.1 Scheduling Policy Attribute 15.3.2 Scheduling Priority Attribute 15.3.3 Inherit Scheduling Attribute 15.3.4 Stacksize Attribute 15.4 Mutex Attributes Objects 15.5 Condition Variable Attributes Objects 16 Programming Threads, Mutexes, and Condition Variables 16.1 Thread Operations 16.1.1 Starting a Thread 16.1.2 Terminating a Thread 16.1.2.1 Normal Termination 16.1.2.2 Error Termination 16.1.2.3 Waiting for a Thread to Terminate 16.1.3 Deleting a Thread 16.1.4 Thread Cancellation 16.1.5 Thread Scheduling 16.1.5.1 Releasing a Thread 16.1.5.2 Delaying a Thread 16.1.6 Thread Identification 16.2 Mutex Operations 16.2.1 Initializing a Mutex 16.2.2 Locking a Mutex 16.2.3 Unlocking a Mutex 16.2.4 Deleting a Mutex 16.3 Condition Variable Operations 16.3.1 Other Synchronization Methods 16.4 General Considerations 16.4.1 One-Time Initialization Routines 16.4.2 Nonthreaded Libraries 16.4.2.1 Working with Nonthreaded Code 16.4.2.2 Changing Nonthreaded Code to be Thread-Reentrant 16.4.3 Nonreentrant Code 16.4.3.1 Global Lock 16.4.3.2 Thread-Specific Data 16.4.4 Shared Variables 16.4.4.1 Static Memory 16.4.4.2 Dynamic Memory 16.4.4.3 Stack Memory 16.4.4.4 Lifetime and Scope of Shared Variables 16.4.5 Stack Management 16.4.5.1 Stack Overflow 16.4.5.2 Sizing the Stack 16.4.6 Priority Inversion 16.4.7 Using Synchronization Objects 16.4.7.1 Mutex or Condition Variable? 16.4.7.2 Race Conditions 16.4.7.3 Deadlocks 16.4.7.4 Signaling a Condition Variable 16.5 Debugging Threads 17 Using the Threads Exception Package 17.1 Overview of Exceptions 17.1.1 Types of Exceptions 17.1.2 Terminating Exception Semantics 17.2 Invoking the pthread Exception-Returning Interface 17.3 Exception Operations 17.3.1 Declaring and Initializing an Exception Object 17.3.2 Raising an Exception 17.3.3 Defining a Region of Code over Which Exceptions Are Caught 17.3.4 Declaring a VMS Condition Handler 17.3.5 Catching a Particular Exception 17.3.6 Catching All Exceptions 17.3.7 Reraising the Current Exception 17.3.8 Defining Epilogue Actions for a Block 17.3.9 Determining the Current Exception 17.3.10 Importing a System-Defined Error Status into the Program as an Exception 17.3.11 Exporting a System-Defined Error Status 17.3.12 Reporting an Exception 17.3.13 Determining Whether Two Exceptions Match 17.4 C Language Syntax for Handling Exceptions 17.5 Rules and Conventions for Modular Use of Exceptions 17.6 Pthread Exceptions and Definitions 18 Threads Examples 18.1 Prime Number Search 18.2 Asynchronous User Interface EXAMPLES 2-1 Building a VAXELN POSIX Application 3-1 Creating a Child Process 3-2 Code for a Child Process 3-3 Sending a Signal to Another Process 3-4 Using the alarm( ) Function 3-5 Using the sigwaitrt( ) and sigqueue( ) Functions 4-1 Retrieving Process IDs 4-2 Getting Real and Effective User IDs 4-3 Retrieving the Process Group ID 4-4 Retrieving the User's Group IDs 4-5 Retrieving Operating System and Hardware Information 5-1 Writing and Reading Files 6-1 Retrieving Terminal Information 6-2 Retrieving the Terminal Input Speed 6-3 Controlling the Terminal 7-1 Database Access 8-1 Binary Semaphores 9-1 Sharing Memory 11-1 Setting Scheduling Policies 12-1 Using the timespec Structure with nanosleep( ) 12-2 Using the time( ) and clock_gettime( ) Functions 12-3 Retrieving the System Time 12-4 Entering the Current Time and Converting It to Coordinated Universal Time 12-5 Setting the System Clock 12-6 Creating and Setting Timers 17-1 Declaring and Initializing an Exception Object 17-2 Raising an Exception 17-3 Defining an Exception-Handling Region 17-4 Catching a Particular Exception 17-5 Catching All Exceptions 17-6 Reraising the Current Exception 17-7 Defining Epilogue Actions for a Block 17-8 Importing a System-Defined Error Status 17-9 Exporting a System-Defined Error Status 17-10 Reporting an Exception 17-11 Determining Whether Two Exceptions Match 17-12 C Language Syntax for Handling Exceptions 18-1 C Program Example (Prime Number Search) 18-2 C Program Example (Asynchronous User Interface) FIGURES 2-1 VAXELN POSIX Application Development 2-2 EBUILD Editing POSIX Characteristics Menu 3-1 Components of a Process 3-2 Creation of a Child Process 3-3 Replacing the Program in the Child Process with a New Program 3-4 Using fork( ) and an exec Function Together 3-5 A Signal Mask That Blocks All Signals But Two 9-1 Two Processes Share a Memory Object 11-1 Lists of Runnable Processes at Various Priority Levels 11-2 Round-Robin Process Scheduling-Using a Quantum 11-3 Round-Robin Process Scheduling-Execution Sequences for a Single Priority 13-1 Single Threaded Process 13-2 Multithreaded Process 13-3 Thread State Transition Diagram 13-4 A Single Thread Locking a Mutex 14-1 Work Crew Model of Thread Operation 14-2 Pipelining Model of Thread Operation 16-1 Flow with FIFO Scheduling 16-2 Flow with RR Scheduling 16-3 Flow with Default Scheduling 16-4 Thread A Waiting on Condition Ready 16-5 Thread B Signaling Condition Ready 16-6 Thread A Waking and Proceeding 16-7 Function Interaction, Case 1 16-8 Function Interaction, Case 2 TABLES 3-1 Process Creation and Execution Functions 3-2 Signals in VAXELN POSIX 3-3 Signal Control Functions 4-1 Functions for Controlling and Monitoring the Process Environment 4-2 Process Environment Configurable System Limits and Options 5-1 Functions for Manipulating Directories and Files 6-1 Functions for Controlling Terminals 7-1 Functions for Accessing the System Databases 7-2 User Database Structure 7-3 Process Group Database Structure 8-1 Binary Semaphore Functions 9-1 Functions Related to Shared Memory 9-2 Symbols for Shared Memory Functions Defined in <mman.h> 10-1 Functions Related to Memory Locking 11-1 Priority Scheduling Functions 12-1 Values Used in Setting Timers 12-2 Timing Resolution Function 12-3 Clock Functions 12-4 Timer Functions 16-1 VAXELN POSIX Threads Debugging Commands and Qualifiers 17-1 Pthread Exceptions