Programmer's Guide
About This Book
Note to Windows users
Recommended reading
Compiling and Debugging
Conforming to standards
Header files in include
Self-hosted or cross-development
A simple example
Self-hosted
Cross-development with network filesystem
Cross-development with debugger
Download/upload facility
Cross-development, deeply embedded
Step 1: Build a QNX system image.
Step 2: Transfer the system image to the target.
Step 3: Boot the target.
Using libraries
Static linking
Dynamic linking
Runtime loading
Static and dynamic libraries
Static libraries
Dynamic libraries
dlopen
Platform-specific library locations
Linking your modules
Creating shared objects
Specifying an internal name
Debugging
Debugging in a self-hosted environment
Debugging in a cross-development environment
The GNU debugger (gdb)
Starting gdb
The process-level debug agent
Serial connection
TCP/IP connection
TCP/IP static port connection
TCP/IP dynamic port connection
Sample boot script for dynamic port sessions
A simple debug session
Configure the target
Compile for debugging
Start the debug session
Get help
Sample boot image
Programming Overview
Process model
An application as a set of processes
Processes and threads
Some definitions
Priorities and scheduling
Priority range
BLOCKED and READY states
The ready queue
Suspending a running thread
When the thread is blocked
When the thread is preempted
When the thread yields
Scheduling algorithms
FIFO scheduling
Round-robin scheduling
Why threads?
Summary
Processes
Starting processes --- two methods
Process creation
Concurrency
Using fork and forkpty
Inheriting file descriptors
Process termination
Normal process termination
Abnormal process termination
Affect of parent termination
Detecting process termination
Detecting termination from a starter process
Sample parent process using wait
Sample parent process using sigwaitinfo
Detecting dumped processes
Detecting the termination of daemons
Detecting client termination
Writing a Resource Manager
What is a Resource Manager?
A few examples...
Why write a Resource Manager?
Under the covers
Under the client's covers
Under the resource manager's covers
The types of resource managers
Device resource managers
Filesystem resource managers
Components of a Resource Manager
iofunc layer
resmgr layer
dispatch layer
thread pool layer
Simple device Resource Manager examples
Single-threaded device resource manager example
Initialize the dispatch interface
Initialize the resource manager attributes
Initialize functions used to handle messages
Initialize the attribute structure used by the device
Put a name into the namespace
Allocate the context structure
Start the resource manager message loop
Multi-threaded device resource manager example
Define THREAD_POOL_PARAM_T
Initialize thread pool attributes
Allocate a thread pool handle
Start the threads
Data carrying structures
The open control block (ocb) structure
The attribute structure
The mount structure
Handling the _IO_READ message
Sample code for handling _IO_READ messages
Ways of adding functionality to the resource manager
Using the default functions
Using the helper functions
Writing the entire function yourself
Handling the _IO_WRITE message
Sample code for handling _IO_WRITE messages
Methods of returning and replying
Returning with an error
Returning using an IOV array that points to your data
Returning with a single buffer containing data
Returning success but with no data
Getting the resource manager library to do the reply
Performing the reply in the server
Leaving the client blocked, replying later
Returning and telling the library to do the default action
Handling other read/write details
Handling the xtype member
If you're not expecting extended types (xtype)
Handling pread* and pwrite*
Sample code for handling _IO_READ messages in pread*
Sample code for handling _IO_WRITE messages in pwrite
Handling readcond
Attribute handling
Updating the time for reads and writes
Combine messages
Where combine messages are used
Atomic operations
Using a mutex
Per-thread files
The readblock function
Bandwidth considerations
The library's combine-message handling
Component responses
Component data access
Locking and unlocking the attribute structure
Connect message types
_IO_CONNECT_COMBINE_CLOSE
_IO_CONNECT_COMBINE
Extending Data Control Structures (DCS)
Extending the ocb and attribute structures
Extending the mount structure
Handling devctl messages
Sample code for handling _IO_DEVCTL messages
Handling ionotify and select
Sample code for handling _IO_NOTIFY messages
Handling private messages and pulses
Handling open, dup, and close messages
Handling client unblocking due to signals or timeouts
Handling interrupts
Sample code for handling interrupts
Multi-threaded Resource Managers
Multi-threaded Resource Manager example
Thread pool attributes
Thread pool functions
Filesystem Resource Managers
Considerations for Filesystem Resource Managers
Taking over more than one device
Handling directories
Matching at or below a mountpoint
The _IO_OPEN message for filesystems
Returning directory entries from _IO_READ
Returning information associated with a directory structure
Message types
Connect messages
I/O messages
Resource Manager data structures
_resmgr_attr_t control structure
_resmgr_connect_funcs_t connect table
resmgr_io_funcs_t I/O table
Qnet Networking
Where the programmer lives
Node descriptors aren't nids!
How do I pass node descriptors around?
The sys/netmgr.h header file
netmgr_strtond
netmgr_ndtostr
netmgr_remote_nd
When node descriptors are valid for a node other than its own
Writing an Interrupt Handler
Overview
Attaching and detaching interrupts
The Interrupt Service Routine (ISR)
Determining the source of the interrupt
Edge-triggered IRQ
Level-sensitive IRQ
Servicing the hardware
Safe functions
Updating common data structures
Signalling the application code
Using InterruptAttach
Using InterruptAttachEvent
Advanced topics
Interrupt environment
Ordering of shared interrupts
Interrupt latency
Atomic Operations
Heap Analysis - Making Memory Errors a Thing of the Past
Abstract
Dynamic Memory Management
Problems with Heap Corruption
Common Errors
Overrun/Underrun
Requests to free
Using Uninitialized/Stale Pointers
Detecting and Reporting Errors
Using the malloc_g Library
What's Checked?
Memory Allocation
Reallocating Memory
Releasing Memory
Controlling Level of Checking
mallopt
MALLOC_CKACCESS
MALLOC_FILLAREA
MALLOC_CKCHAIN
Forcing verification
Controlling Error Handling
Manual Checking (Bounds Checking)
Getting pointer information
find_malloc_ptr
_mptr
Getting the heap buffer size
_msize
_musize
DH_ULEN
Memory Leaks
Tracing
Causing a Trace and Giving Results
malloc_dump_unreferenced
Analyzing Dumps
Compiler Support
C++ Issues
Clean C
C++ Example
Bounds Checking GCC
Summary
Freedom from Hardware and Platform Dependencies
Common problems
I/O space vs memory-mapped
Big-endian vs little-endian
Typecast mangling
Hardware access
Network transparency
Alignment and structure packing
Atomic operations
Solutions
Determining endianness
Swapping data if required
ENDIAN_LE16
ENDIAN_LE32
ENDIAN_LE64
ENDIAN_BE16
ENDIAN_BE32
ENDIAN_BE64
Accessing unaligned data
UNALIGNED_RET16
UNALIGNED_RET32
UNALIGNED_RET64
UNALIGNED_PUT16
UNALIGNED_PUT32
UNALIGNED_PUT64
Examples
Mixed-endian accesses
Accessing hardware with dual-ported memory
Accessing I/O ports
Conventions for Makefiles and Directories
Structure
Makefile structure
The recurse.mk file
Macros
The EARLY_DIRS and LATE_DIRS macros
The LIST macro
Directory structure
The project level
The section level (optional)
The OS level
The CPU level
The variant level
Specifying options
The common.mk file
The variant-level makefile
Recognized variant names
Using the standard macros and include files
The qconfig.mk include file
The preset macros
The post-set macros
qconfig.mk macros
The qrules.mk include file
The qtargets.mk include file
Advanced topics
Collapsing unnecessary directory levels
Performing partial builds
More uses for LIST
Developing SMP Systems
Introduction
Building an SMP image
The impact of SMP
To SMP or not to SMP
Processor affinity
SMP and synchronization primitives
SMP and FIFO scheduling
SMP and interrupts
SMP and atomic operations
Designing with SMP in mind
Use the SMP primitives
Assume that threads really do run concurrently
Break the problem down
Using GDB
GDB commands
Command syntax
Command completion
Getting help
Running programs under GDB
Compiling for debugging
Setting the target
Starting your program
Your program's arguments
Your program's environment
Your program's input and output
Debugging an already-running process
Killing the child process
Debugging programs with multiple threads
Debugging programs with multiple processes
Stopping and continuing
Breakpoints, watchpoints, and exceptions
Setting breakpoints
Setting watchpoints
Breakpoints and exceptions
Deleting breakpoints
Disabling breakpoints
Break conditions
Breakpoint command lists
Breakpoint menus
Continuing and stepping
Signals
Stopping and starting multithreaded programs
Examining the stack
Stack frames
Backtraces
Selecting a frame
Information about a frame
MIPS machines and the function stack
Examining source files
Printing source lines
Searching source files
Specifying source directories
Source and machine code
Shared libraries
Examining data
Expressions
Program variables
Artificial arrays
Output formats
Examining memory
Automatic display
Print settings
Value history
Convenience variables
Registers
Floating point hardware
Examining the symbol table
Altering execution
Assignment to variables
Continuing at a different address
Giving your program a signal
Returning from a function
Calling program functions
Patching programs
Glossary