home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
contrinf.zip
/
CP3.INF
(
.txt
)
< prev
Wrap
OS/2 Help File
|
2001-03-21
|
279KB
|
9,907 lines
ΓòÉΓòÉΓòÉ 1. Memory Management ΓòÉΓòÉΓòÉ
This chapter describes the memory management features and functions of OS/2.
The key features of OS/2 memory management are paged virtual memory and a
32-bit linear (flat) address space that is mapped through page tables to
physical memory. An OS/2 application can allocate memory for its own use or to
be shared with other applications.
The following topics are related to the information in this chapter:
Exception handling
Program execution and control
Semaphores
Queues
ΓòÉΓòÉΓòÉ 1.1. About Memory Management ΓòÉΓòÉΓòÉ
OS/2 offers developers a 32-bit, linear (flat) memory address space. OS/2 uses
a paged memory structure. OS/2 allocates, protects, and manipulates memory in
terms of pages.
ΓòÉΓòÉΓòÉ 1.1.1. Process Address Space ΓòÉΓòÉΓòÉ
The OS/2 memory allocation functions return a 32-bit pointer to the allocated
memory object. While a 32-bit pointer is sufficient to address the entire 4
gigabyte global address space, applications can access only the first 512MB of
linear memory, called the process address space. Of this 512MB process address
space, a minimum of 64MB is reserved for shared memory regions, leaving 448MB.
Of this 448MB, some will be used by the application itself and a small amount
will be taken by operating system overhead. The remainder is available for
allocation. The amount of memory that can actually be committed and used is, of
course, determined by the physical memory and hard disk space available on the
machine.
Keep in mind that the amount of memory that can be committed for actual use is
limited by the amount of physical memory and free hard disk space that is
available on the computer on which the application is executing.
ΓòÉΓòÉΓòÉ 1.1.2. Memory Objects ΓòÉΓòÉΓòÉ
Applications allocate and manipulate memory in terms of memory objects. A
memory object consists of one or more pages of memory. An OS/2 application can
allocate any number of memory objects, within the following limits:
the physical memory in the system
the free hard disk space on the hard disk containing the swap file
the 512MB process address space limit (see Process Address Space).
When requesting memory, the size of the memory object is rounded up to the
next higher multiple of 4KB. An application can suballocate a memory object
into memory blocks whose size can range from 1 byte to the size of the memory
object.
Memory objects have the following characteristics:
They are not relocatable.
They are allocated in units of 4KB. One 4KB unit is called a page.
They can be larger than 64KB in size.
ΓòÉΓòÉΓòÉ 1.1.3. Memory Pages ΓòÉΓòÉΓòÉ
OS/2 allocates and commits memory objects in pages. A memory page is a 4KB
(4096 bytes) piece of memory. Memory access protection is also done on a
page-basis, rather than the segment-based protection used in previous versions
of OS/2.
A page range is a linearly contiguous group of pages within a memory object. A
page range can be any of the following:
The entire memory object
Part of the memory object
A single page within a memory object
If an application requests 512 bytes of memory, it will receive a 32-bit
pointer to a 4KB page. All 4096 bytes are available to the application, even
though the request specified only 512 bytes. If an application requests 62000
bytes, it will receive a pointer to a 65536-byte (64KB, 16-page) object.
Again, all 65536 bytes are available for use.
Each page in the virtual address space of the process is either free
(unallocated), private (available only to the process that allocated it), or
shared (memory that is shared between processes).
Each page within a memory object can be in one of two states, either
uncommitted (that is, the linear address range has been reserved, but is not
yet backed by physical storage) or committed (physical storage has been
allotted for the logical address range).
Access to a committed page is controlled by the page's access protection
attribute. These protection attributes are read access, write access, execute
access (on the 80386, this is the same as read access), and guard page access.
An uncommitted page is not accessible.
ΓòÉΓòÉΓòÉ 1.1.4. Memory Overcommitment and Swapping ΓòÉΓòÉΓòÉ
Memory overcommitment occurs when applications allocate and commit more memory
than is actually available in the computer. OS/2 handles memory overcommitment
by copying memory to the system swap file, SWAPPER.DAT, on the hard disk then
reusing the memory for another allocation. OS/2 copies as many pages of memory
as are necessary to make room for the new allocation. The swapped memory can be
retrieved the next time it is accessed; at that time, some other memory might
be written to the swap file.
OS/2 selects the memory to swap based on when it was last used. The page that
is least-recently-used, that is, the page that has gone the longest since its
last access, is the page chosen to swap to disk.
Swapping is transparent to an application, although excessive swapping can
cause an application to run slowly.
Through swapping, OS/2 enables applications to allocate more memory than
actually exists in the computer, bounded only by the amount of free space on
the hard disk that contains the swap file.
ΓòÉΓòÉΓòÉ 1.1.5. User Configuration of Memory Swapping ΓòÉΓòÉΓòÉ
Although an application cannot control swapping, the user can specify whether
the system can swap memory by including the MEMMAN command in the CONFIG.SYS
file.
If the MEMMAN command specifies SWAP, OS/2 writes selected memory pages to the
SWAPPER.DAT file whenever insufficient physical memory exists to satisfy an
allocation request. This is the default choice. If the MEMMAN command specifies
NOSWAP, OS/2 does not swap memory.
Note: Be aware that disabling swapping will severely limit the number of
applications that the user will be able to run concurrently; if there is
not enough physical memory present, OS/2 might not even boot.
The exact amount of memory available to an application depends on the amount
of physical memory in the machine and the amount of free disk space on the
partition that contains the SWAPPER.DAT file. The location of the SWAPPER.DAT
file can be specified by including the SWAPPATH command in the CONFIG.SYS
file. With the SWAPPATH command, one can specify the location of the
SWAPPER.DAT file, the amount of free disk space to reserve in the partition
which will contain SWAPPER.DAT, and the initial size of SWAPPER.DAT. OS/2
adjusts the size of SWAPPER.DAT as necessary, leaving other files on the drive
and the requested free space untouched.
ΓòÉΓòÉΓòÉ 1.1.6. Memory Allocation and Commitment ΓòÉΓòÉΓòÉ
When an application asks OS/2 to allocate memory, a linear address range is
reserved. The range is not backed by physical memory until the memory is
committed. Commitment assigns physical memory to the linear address range.
A memory object that is allocated, but not committed is called a sparse memory
object. A sparse memory object must be committed before it can be used. An
attempt to read from or write to uncommitted memory will cause an access
violation.
An application can ask OS/2 to commit the memory at the same time it is
allocated, thus making it immediately usable, or the memory can be committed at
a later time. If the application commits the memory at the same time the memory
is allocated, the entire memory object is committed. If the application commits
the memory at a later time, it can commit the entire sparse memory object or
only commit a portion of it.
When multiple pages are committed at the same time (a page range), the pages
will have sequential linear addresses.
Managing Memory Allocation and Commitment
The recommended way to manage memory is to make a large memory allocation early
in program execution, then to commit or suballocate memory as the need occurs.
The initial allocation should be for as much space as you expect to use during
program execution. Allocation without commitment does not actually use any
physical memory, so there is no waste involved in allocating several megabytes.
After the memory object is allocated, the application uses one of two ways to
manage the memory object:
Commit and decommit the memory as it is required
Set up the memory object as a heap and suballocate memory from the heap.
Committing and decommitting memory gives the application more control over the
process, but the application will have to keep track of which pages are
committed and which pages are not. When suballocating memory from a heap, the
application can have OS/2 track commitment and decommitment of physical memory
pages, so the application does not have to. If you want DosSubAllocMem to
manage the commitment of the pages spanned by the heap, all of the pages
spanned by the memory object must be uncommitted initially.
Remember, no matter how much memory is originally allocated, the amount that
an application will ultimately be able to commit and use is limited by the
amount of physical memory and free disk space available on the machine.
Applications are not limited to a single large allocation of memory-other
memory allocations can be made as necessary during execution-but large
allocations and small commitments or suballocations are the most efficient way
to manage memory.
ΓòÉΓòÉΓòÉ 1.1.7. Memory Resizing and Reallocation ΓòÉΓòÉΓòÉ
In earlier versions of OS/2, an application could increase or decrease the size
of an allocated memory segment by reallocating the segment.
Memory objects cannot be resized. Instead, an application should allocate a
sparse memory object of whatever size might be necessary, then commit or
decommit portions of the object.
If the amount of memory required cannot be determined at the time the memory is
allocated, the application should allocate a sparse memory object large enough
to meet the largest memory requirement. The application can then change the
amount of committed memory as necessary.
For example, if you anticipate your application will use around 512KB of memory
for most purposes, but might use 5MB under certain circumstances, you might
take the following steps:
During program initialization, use DosAllocMem to allocate 5MB.
Commit the first 512KB (or some part of it) using DosSetMem.
Proceed with normal processing.
If extra memory is required occasionally, commit it and decommit it using
DosSetMem.
When the situation arises that the application requires the full 5MB,
commit it at that time, using DosSetMem, then decommit it after you are
finished with it, also using DosSetMem.
When the application is finished with the memory, use DosFreeMem to
release the memory back to the system.
ΓòÉΓòÉΓòÉ 1.1.8. Memory Protection ΓòÉΓòÉΓòÉ
When an application allocates a memory object, it can specify the type of
access to allow to the object. Memory access protection provides a program with
control over the type of access that its threads have to a page of memory.
Access protection can only be defined for committed pages of memory and is
initially set at the time the memory is committed. Different pages within the
same memory object can have different access attributes and access attributes
can be changed on a page-by-page basis at any time.
An application can request any combination of the following access protection
attributes:
Memory Access Protection Attributes
ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
ΓöéAccess ΓöéDefined Constant ΓöéDescription Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéRead Access ΓöéPAG_READ ΓöéThe object can be Γöé
Γöé Γöé Γöéread from, but not Γöé
Γöé Γöé Γöéwritten to. Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéWrite Access ΓöéPAG_WRITE ΓöéThe object can be Γöé
Γöé Γöé Γöéwritten to. On the Γöé
Γöé Γöé Γöé80386 Γöé
Γöé Γöé Γöémicroprocessor, Γöé
Γöé Γöé Γöéwrite access impliesΓöé
Γöé Γöé Γöéboth read and Γöé
Γöé Γöé Γöéexecute access. Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéExecute Access ΓöéPAG_EXECUTE ΓöéThis is equivalent Γöé
Γöé Γöé Γöéto read access on Γöé
Γöé Γöé Γöéthe 80386. Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéGuard Page Access ΓöéPAG_GUARD ΓöéCauses a Γöé
Γöé Γöé Γöéguard-page-entered Γöé
Γöé Γöé Γöéexception to be Γöé
Γöé Γöé Γöéraised in a process Γöé
Γöé Γöé Γöéthat attempts to Γöé
Γöé Γöé Γöéaccess the memory. Γöé
Γöé Γöé ΓöéThis exception can Γöé
Γöé Γöé Γöébe ignored or Γöé
Γöé Γöé Γöéhandled by the Γöé
Γöé Γöé Γöéapplication's Γöé
Γöé Γöé Γöéexception handler, Γöé
Γöé Γöé Γöéif one is Γöé
Γöé Γöé Γöéregistered. Γöé
ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
The guard page attribute is intended to provide automatic stack growth and
stack limit checking. An application can also use it in other data structures,
such as arrays. For example, if an application is using an array of 4096 bytes
(one page), the application can allocate and commit two pages, one with read
and write access and one designated as a guard page. If the application tries
to write past the end of the array a page guard exception will be generated.
Any reference-read, write, or execute-to a guard page causes an access
violation (page fault) to be generated. This fault causes a Guard Page Entered
exception to occur for the thread that referred to the guard page. The
exception can be handled by the exception handler of the process, if one is
registered. If the process does not have an exception handler registered,
OS/2's default exception handler will handle the exception. The default action
by the system exception handler is to convert the page from a guard page to a
committed page, then try to mark the next page in memory as a guard page. If
the system is not successful in marking the next page as a guard page, an
Unable-To-Grow-Stack exception occurs. The thread is allowed to continue
execution, but must be aware that it has at most 4KB of stack remaining.
ΓòÉΓòÉΓòÉ 1.1.9. Obtaining Information about a Page Range ΓòÉΓòÉΓòÉ
DosQueryMem is used to obtain information about a range of pages within the
virtual address space of the current process.
Each page in the virtual address space of a process is either free, private, or
shared.
Each page within a memory object can be in one of two states, either committed
or uncommitted.
A committed page has its access controlled by an access protection attribute.
These protection attributes are read protection (PAG_READ), write protection
(PAG_WRITE), execute protection (PAG_EXECUTE), and guard page protection
(PAG_GUARD).
ΓòÉΓòÉΓòÉ 1.1.10. Protection Violations ΓòÉΓòÉΓòÉ
OS/2 fully utilizes the memory protection capabilities of the 80386
microprocessor. OS/2 grants an application access to a memory object only if
the object has been explicitly allocated by the application or made available
for use by the application.
If an application attempts to access memory that it is not assigned, the system
interrupts the application and executes the exception handling routine for
protection violations. Protection violations can be handled by the application
(in its own exception handling routines) or by OS/2. If the protection
violation is handled by the operating system, the system exception handling
routine determines the cause of the exception, displays an error message, and
then terminates the application.
It is usually not possible for an application to recover from a protection
violation. Therefore, programmers should ensure that all pointers are valid.
Because protection violations commonly occur during application debugging, each
message displayed for a protection violation includes the contents of the
registers when the violation occurred. If the violation occurred as a result of
passing an invalid pointer to a memory function, an error code is returned by
the memory function.
In earlier versions of OS/2, protection violations could be used to find bugs
when an application accessed memory that was not allocated to the application.
This approach will no longer work because memory objects can be larger than the
size requested by the application because the memory objects are allocated on
4KB page boundaries. For example, a pointer to the 513th byte of a 512 byte
memory object is valid and does not cause a protection violation. This means
that programmers cannot always rely on protection violations to spot memory
addressing errors.
ΓòÉΓòÉΓòÉ 1.1.11. Memory Suballocation and Using Heaps ΓòÉΓòÉΓòÉ
There are times when a process requires only small amounts of memory rather
than an entire memory object. It would be wasteful to allocate an entire page
of memory when only a few bytes are necessary, so a mechanism is provided for
applications to allocate a large block of memory and then suballocate portions
of the memory as necessary to fulfill small requests from an application. This
is done by creating a heap.
A heap is a region of storage within a memory object from which an application
can allocate blocks of memory. A memory block is a piece of memory within a
heap. The size of the memory block is rounded up to the next higher multiple of
8 bytes.
Because OS/2 allocates a 4KB page for each memory allocation, using a heap to
suballocate amounts of memory smaller than 4KB is more efficient than using
DosAllocMem.
When an application creates a heap, it can have OS/2 track the committing and
decommitting of memory within the heap. When the application commits and
decommits memory itself, it has to keep track of the access state of each page
as they are accessed.
Applications use DosSubSetMem to initialize a memory object for suballocation,
then use DosSubAllocMem and DosSubFreeMem to allocate and free the memory.
Memory is still committed in pages when an application uses suballocation. If
the application suballocates 512 bytes, 4096 bytes will be committed. Accessing
the 513th byte will not cause a protection violation, but you could be
accessing memory that was suballocated by another thread in the process.
ΓòÉΓòÉΓòÉ 1.1.12. Shared Memory ΓòÉΓòÉΓòÉ
Shared memory is memory that two or more applications can read from and write
to. Shared memory is prepared in such a way that any application can receive a
pointer to the memory and access the data. Applications must explicitly request
access to shared memory; the shared memory is protected from applications that
are not granted access.
There are two kinds of shared memory: named and unnamed. For named shared
memory, any application that knows the name of the shared memory can access it.
For unnamed shared memory, a pointer to the shared memory must be passed from
the process that created the shared memory to the process being given access.
Access can be granted to any application; it is not necessary that the process
being granted access be related (parent-child) to the application that created
the shared memory.
Since memory sharing is done by sharing linear addresses, the linear address
range of the shared memory object is reserved in all process address spaces.
There are two basic methods of managing shared memory:
In one method, two or more applications share the same memory at the same
time. These applications read from and write to the memory object,
usually controlling access to the memory by using a semaphore.
In the other method of managing shared memory, one application prepares
data in memory, then passes that memory to another application for
further processing. The first application releases the memory after
passing it along, so that only one application accesses the memory at a
time.
ΓòÉΓòÉΓòÉ 1.1.13. Thread Local Memory ΓòÉΓòÉΓòÉ
Thread local memory is a 128-byte region of thread-specific memory that OS/2
assigns to a thread when the thread is created. Thread local memory for each
thread is always at the same virtual address, but each thread's local memory
region is backed by different physical memory, so the memory is specific to
each thread. This memory region is divided into 32 DWORDS (4 bytes per DWORD),
and is normally used to store a small number of pointers.
A thread can allocate thread local memory by calling DosAllocThreadLocalMemory.
Thread local memory is freed by calling DosFreeThreadLocalMemory.
Note that thread local memory should be used sparingly. You should not use the
entire 128 byte region.
ΓòÉΓòÉΓòÉ 1.2. Using Memory Management ΓòÉΓòÉΓòÉ
This section describes how to use the OS/2 memory management functions and
configuration commands to control the use of memory for OS/2 applications.
Note: In the example code fragments that follow, error checking was left out
to conserve space. Applications should always check the return code that
the functions return. Control Program functions return an APIRET value.
A return code of 0 indicates success. If a non-zero value is returned,
an error occurred.
ΓòÉΓòÉΓòÉ 1.2.1. Allocating Private Memory ΓòÉΓòÉΓòÉ
An application can allocate regions of storage within the virtual address space
of the process. Such an allocated region is called a memory object.
DosAllocMem is used to allocate a memory object. You specify a variable to
receive the pointer that will address the new object, the amount of memory
needed, and the allocation attributes and access protection attributes of the
new memory object. When choosing the size of the memory object to allocate,
remember that the maximum size of the memory object is defined when it is
allocated, and memory objects cannot be resized.
When applications call DosAllocMem, the operating system reserves a range of
private pages large enough to fulfill the specified allocation request from the
private virtual address space of the subject process.
DosAllocMem will reserve this linear space and return zero if the allocation
was successful. If it was unsuccessful, DosAllocMem will return an error code.
An application should always test the return value before attempting to use the
memory.
The following code fragment requests an allocation of 512 bytes. Remember that
4096 bytes will actually be allocated for this request:
#define INCL_DOSMEMMGR /* Memory Manager values */
#include <os2.h>
PBYTE pb;
APIRET ulrc;
ulrc = DosAllocMem((PVOID *) &pb,
512,
fALLOC); /* pb receives the base address of the */
/* 4KB memory object */
if (!ulrc) { /* If the allocation was successful, ulrc == 0 */
*pb = 3000; /* Use the allocated memory */
}
In this example, DosAllocMem returns a 32-bit pointer to a 4096 byte committed
memory object and allows the application to write to and read from the memory.
This pointer is valid only for the 4096 bytes allocated by the system. An
attempt to use the pointer outside the allocated memory will cause a protection
violation.
ΓòÉΓòÉΓòÉ 1.2.2. Committing and Decommitting Page Ranges ΓòÉΓòÉΓòÉ
If an application allocates a sparse memory object, no physical memory location
is committed for the object. Memory in a sparse object must be committed before
it can be used. DosSetMem is used to commit or decommit a range of previously
allocated pages in a private or shared memory object. Applications can make
specific address ranges within a memory object valid or invalid. Commitment and
decommitment always take place in multiples of one or more pages.
Applications can also use DosSetMem to change the access protection attributes
of a range of pages within a memory object.
The following code fragment requests allocation of 2MB of uncommitted memory
and then commits 4096 bytes of the memory:
#define INCL_DOSMEMMGR /* Memory Manager values */
#include <os2.h>
APIRET ulrc;
PBYTE pb;
/* Allocate 16KB object */
ulrc = DosAllocMem((PVOID *) &pb,
2097152,
PAG_READ |
PAG_WRITE);
/* Commit 4KB */
ulrc = DosSetMem(pb,
4096,
PAG_COMMIT |
PAG_DEFAULT);
An application can also allocate a large committed object and then decommit
portions of it as they are no longer needed. Decommitment, like commitment, is
done on page boundaries; an application can decommit no less than a 4096 byte
page.
The following code fragment allocates 16384 bytes of committed memory and then
decommits the first 4096 bytes of the memory:
#define INCL_DOSMEMMGR /* Memory Manager values */
#include <os2.h>
APIRET ulrc;
PBYTE pb;
ulrc = DosAllocMem((PVOID *) &pb,
16384,
fALLOC); /* Allocate 16 K object */
ulrc = DosSetMem(pb,
4096,
PAG_DECOMMIT); /* Decommit 4KB */
After memory is decommitted, an attempt to access the decommitted memory will
cause a protection violation.
You cannot pass an argument that crosses multiple memory objects. The function
will return an error.
ΓòÉΓòÉΓòÉ 1.2.3. Establishing Access Protection ΓòÉΓòÉΓòÉ
When an OS/2 application commits a memory object, it specifies the types of
access permitted for the memory object. This can be done at the same time the
memory object is allocated, with DosAllocMem, or at a later time, using
DosSetMem.
Any combination of read, write, execute, or guard-page access can be set, but
at least read or write access must be specified when the memory object is
committed; it is not possible to commit an object with no access protection
attributes.
The application can also use DosSetMem to change the access permission of pages
within a previously committed memory object. An application can permit read
access to one page of the memory object and write access to the rest.
When using DosSetMem, all the pages in the range being changed must be either
committed or decommitted.
The following code fragment commits a region of two pages within a previously
allocated memory object, and sets read-only access rights for the region.
#define INCL_DOSMEMMGR /* Memory Manager values */
#include <os2.h>
#include <stdio.h>
PVOID pBaseAddress; /* Pointer to the range of pages to be changed */
ULONG ulRegionSize; /* Size, in bytes, of the region to be changed */
ULONG ulAttributeFlags; /* Flag describing the page range */
APIRET ulrc; /* Return code */
ulRegionSize = 8192; /* Specify a two-page region */
/* Obtain the base address */
ulrc = DosAllocMem((PVOID *) &pBaseAddress,
ulRegionSize,
PAG_WRITE);
ulAttributeFlags = PAG_COMMIT |
PAG_READ;
ulrc = DosSetMem(pBaseAddress,
ulRegionSize,
ulAttributeFlags);
if (ulrc != 0) {
printf("DosSetMem error: return code = %ld", ulrc);
return;
}
ΓòÉΓòÉΓòÉ 1.2.4. Querying Memory Object Information ΓòÉΓòÉΓòÉ
DosQueryMem is used to determine the allocation state and access protection for
a specified memory object. The application can query an entire memory object or
a range of pages within an object.
The following code fragment uses DosQueryMem to ensure that memory is committed
before the application attempts to use the memory:
#define INCL_DOSMEMMGR /* Memory Manager values */
#include <os2.h>
#define HF_STDOUT 1 /* Standard output handle */
PBYTE pb; /* Base address of an allocated object */
ULONG ulSize,
ulFlags,
ulWritten;
APIRET ulrc; /* Return Code */
ulSize = 4096;
ulrc = DosAllocMem((PVOID *)&pb,
16384,
PAG_COMMIT |
PAG_WRITE);
ulrc = DosQueryMem(pb,
&ulSize,
&ulFlags); /* Queries first 4096 bytes */
if (ulFlags & PAG_COMMIT) { /* If memory is committed, use it */
ulrc = DosWrite(HF_STDOUT,
"\r\n 4KB is committed.\r\n",
21,
&ulWritten);
}
ΓòÉΓòÉΓòÉ 1.2.5. Freeing Memory ΓòÉΓòÉΓòÉ
When memory object is no longer needed, the application uses the DosFreeMem
function to release the memory.
If applications do not release memory, the operating system either swaps the
memory to the hard disk (if swapping is enabled) or uses memory that could be
used by other applications. If OS/2 swaps the memory to the hard disk, the
SWAPPER.DAT swap file could become very large. Therefore, applications should
release memory as soon as it is no longer needed. Any memory that is still
allocated when the application ends is released by OS/2.
DosFreeMem frees a private or shared memory object from the virtual address
space of the process. The released pages are returned to the system.
The following code fragment allocates 8192 bytes of committed memory and then
releases the memory:
#define INCL_DOSMEMMGR /* Memory Manager values */
#include <os2.h>
PBYTE pb;
APIRET ulrc;
ulrc = DosAllocMem((PVOID *) &pb,
8192,
fALLOC); /* Allocate 8KB object */
.
.
.
ulrc = DosFreeMem(pb); /* Free the object */
ΓòÉΓòÉΓòÉ 1.3. Using Suballocation and Heaps ΓòÉΓòÉΓòÉ
This section describes how you can use DosAllocMem, DosSubSetMem,
DosSubAllocMem, DosSubFreeMem, and DosSubUnsetMem to manage a memory heap.
ΓòÉΓòÉΓòÉ 1.3.1. Suballocating Memory ΓòÉΓòÉΓòÉ
DosAllocMem can be used to create a memory heap.
Before an application can allocate small portions of the heap, it must use the
DosSubSetMem function to set up the memory for suballocation. The size of the
heap is rounded up to the next higher multiple of 8 bytes.
Then, the application uses DosSubAllocMem to allocate sections of the heap and
the DosSubFreeMem function to release the memory.
DosSubAllocMem returns a 32-bit pointer to a block of memory. The pointer can
be used to access the memory without further modification.
The following code fragment sets up 8192 bytes for suballocation and then
allocates two small blocks of memory:
#define INCL_DOSMEMMGR /* Memory Manager values */
#include <os2.h>
APIRET ulrc;
PBYTE pbBase,
pb1,
pb2;
ulrc = DosAllocMem((PVOID *) &pbBase,
8192,
fALLOC); /* Allocate 8K object */
ulrc = DosSubSetMem(pbBase,
DOSSUB_INIT,
8192); /* Set up object */
/* for suballocation */
ulrc = DosSubAllocMem(pbBase,
(PVOID *) &pb1,
100); /* Suballocate 100 bytes */
ulrc = DosSubAllocMem(pbBase,
(PVOID *) &pb2,
500); /* Suballocate 500 bytes */
ulrc = DosSubFreeMem(pbBase,
pb1,
100); /* Free 1st suballocation*/
ulrc = DosSubAllocMem(pbBase,
(PVOID *) &pb1,
50); /* Suballocate 50 bytes */
ΓòÉΓòÉΓòÉ 1.3.2. Increasing the Size of a Heap ΓòÉΓòÉΓòÉ
DosSubSetMem can also be used to increase the size of a previously initialized
heap. The heap size can be increased up to the size of the memory object that
contains it.
The size of the heap is rounded up to the next higher multiple of 8 bytes.
The following code fragment increases the size of a heap. Assume that the
Offset variable was previously loaded with the virtual address of the memory
object.
#define INCL_DOSMEMMGR /* Memory Manager values */
#include <os2.h>
#include <stdio.h>
PVOID pOffset; /* Address of the heap to be used for suballocation */
ULONG ulFlags; /* Flags describing the memory object being resized */
ULONG ulSize; /* Size in bytes to increase the size of the heap */
APIRET ulrc; /* Return code */
ulSize = 20000; /* Indicate a heap size increase of 20000 bytes */
/* DOSSUB_INIT set to initialize memory for suballocation */
ulFlags = DOSSUB_INIT |
DOSSUB_SPARSE_OBJ;
ulrc = DosSubSetMem(pOffset,
ulFlags,
ulSize);
if (ulrc != 0) {
printf("DosSubSetMem error: return code = %ld", ulrc);
return;
}
In this example, the heap is incremented, and that memory commitment is managed
internally within subsequent DosSubAllocMem calls.
When using DosSubSetMem to increase the size of the heap, the Flags parameter
must have the same setting as when the heap was initialized.
Note: Do not call DosSetMem to change the allocation attribute or access
protection attributes of any pages spanned by a memory object that the
suballocation functions are managing. Otherwise, unpredictable results
could occur.
Call DosSubUnsetMem when finished with the heap that was set up with
DosSubSetMem. This enables the suballocation function to free the resources
that it uses to manage the heap. When you are through with the memory object
that the heap was part of, use DosFreeMem to free the memory object.
ΓòÉΓòÉΓòÉ 1.3.3. Allocating a Block of Memory from a Heap ΓòÉΓòÉΓòÉ
DosSubAllocMem allocates a block of memory from a heap that was previously
initialized by DosSubSetMem. This is used when an application needs an area of
memory that is smaller than an entire heap.
The size of the memory block is rounded up to the next higher multiple of 8
bytes.
The following code fragment allocates a block of memory from a heap that was
previously initialized by DosSubSetMem. Assume that the Offset variable has
been set to the address of the initialized heap already.
#define INCL_DOSMEMMGR /* Memory Manager values */
#include <os2.h>
#include <stdio.h>
PVOID pOffset; /* The heap to suballocate from */
PPVOID ppBlockOffset; /* Pointer to the variable where the offset of */
/* the suballocated memory block is returned */
ULONG ulSize; /* Size in bytes of the memory block requested */
APIRET ulrc; /* Return code */
ulSize = 102; /* Ask for 102 bytes. This will be rounded */
/* to 104 bytes (a multiple of 8 bytes). */
ulrc = DosSubAllocMem(pOffset,
&ppBlockOffset,
ulSize);
if (ulrc != 0) {
printf("DosSubAllocMem error: return code = %ld",
ulrc);
return;
}
In this example, the address of the allocated block (from the heap) is stored
in the BlockOffset variable.
Remember to call DosSubFreeMem to free this block of memory when you are
finished with it.
ΓòÉΓòÉΓòÉ 1.3.4. Freeing Memory Blocks ΓòÉΓòÉΓòÉ
DosSubFreeMem frees a block of memory that was previously allocated by
DosSubAllocMem.
Call DosSubFreeMem to free a block of memory in the heap when you are finished
with that memory block.
The following code fragment frees a block of memory that was previously
allocated from a heap. DosSubFreeMem returns the block to the heap. Assume that
the Offset variable has been previously set to the address of the initialized
heap, and that the BlockOffset variable has been previously set to the address
of the block to be returned to the heap.
#define INCL_DOSMEMMGR /* Memory Manager values */
#include <os2.h>
#include <stdio.h>
PVOID pOffset; /* Offset of the heap to which the */
/* block is to be freed */
PVOID pBlockOffset; /* Offset of memory block to be freed */
ULONG ulSize; /* Size in bytes of block to be freed */
APIRET ulrc; /* Return code */
ulSize = 102; /* Return 102 bytes. This will be rounded */
/* to 104 bytes (a multiple of 8 bytes). */
ulrc = DosSubFreeMem(pOffset,
pBlockOffset,
ulSize);
if (ulrc != 0) {
printf("DosSubFreeMem error: return code = %ld",
ulrc);
return;
}
ΓòÉΓòÉΓòÉ 1.3.5. Ending the Use of the Heap ΓòÉΓòÉΓòÉ
DosSubUnsetMem terminates the use of a heap within a memory object. All calls
to DosSubSetMem must eventually be followed by a call to DosSubUnsetMem. This
enables the suballocation function to free the resources that it uses to manage
the heap.
The application must call DosSubUnsetMem before it frees the memory object that
contains this heap (with DosFreeMem).
The following code fragment shows the termination of a heap. Assume that the
address of the heap was placed into Offset already.
#define INCL_DOSMEMMGR /* Memory Manager values */
#include <os2.h>
#include <stdio.h>
PVOID pOffset; /* Offset of the heap whose use is being terminated */
APIRET ulrc; /* Return code */
ulrc = DosSubUnsetMem(pOffset);
if (ulrc != 0) {
printf("DosSubUnsetMem error: return code = %ld",
ulrc);
return;
}
ΓòÉΓòÉΓòÉ 1.3.6. Allocating and Freeing Thread Local Memory ΓòÉΓòÉΓòÉ
Thread local memory is a small region of thread-specific memory assigned to a
thread when it is started.
A thread can allocate thread local memory by calling DosAllocThreadLocalMemory.
Thread local memory is freed by calling DosFreeThreadLocalMemory.
The thread local memory region is 32 DWORDS (4 bytes per DWORD) in size, and up
to 8 DWORDS can be allocated with each call to DosAllocThreadLocalMemory. To
allocate more than 8 DWORDS, a thread must call DosAllocThreadLocalMemory more
than once.
Note that thread local memory should be used sparingly. You should not use the
entire 128 byte region.
The following code fragment allocates six DWORDS in thread local memory and
then frees these six DWORDS.
#define INCL_DOSPROCESS
#define INCL_DOSERRORS
#include <os2.h>
#include <stdio.h> /* Needed for printf */
PULONG pulMemBlock = NULL; /* Pointer to thread DWORDs returned */
APIRET ulrc = NO_ERROR; /* Return code */
ulrc = DosAllocThreadLocalMemory(6,
&pulMemBlock ); /* Allocate 6 DWORDs */
if (ulrc != NO_ERROR) {
printf("DosAllocThreadLocalMemory error: return code = %u\n",
ulrc);
return 1;
}
.
.
/* ... Use the thread-local memory block ... */
.
.
ulrc = DosFreeThreadLocalMemory(pulMemBlock); /* Free the memory block */
if (ulrc != NO_ERROR) {
printf("DosFreeThreadLocalMemory error: return code = %u\n",
ulrc);
return 1;
}
ΓòÉΓòÉΓòÉ 1.4. Using Shared Memory ΓòÉΓòÉΓòÉ
This section describes how you can use DosAllocSharedMem, DosGiveSharedMem,
DosGetSharedMem, and DosGetNamedSharedMem to use shared memory.
There are three types of shared memory:
Named, where a process allocates and names shared memory. A second
process can use the shared memory by using DosGetNamedSharedMem,
specifying the name of the shared memory.
Unnamed giveable, where a process gives another process access to shared
memory with DosGiveSharedMem, using the PID of the second process.
Unnamed gettable, where a process knows the address of shared memory
they want to use (allocated by another process), gets permission to use
that memory with DosGetSharedMem, and then uses the shared memory.
The difference among these different types of shared memory is not in how the
memory is allocated by the original process, but in how the second process
gets permission to use and access to the shared memory. All three types of
shared memory are allocated with the same call: DosAllocSharedMem, using
various parameters.
ΓòÉΓòÉΓòÉ 1.4.1. Using Named Shared Memory ΓòÉΓòÉΓòÉ
An application uses DosAllocSharedMem to allocate shared memory. When
allocating the shared memory, an application can assign a unique name to the
memory. Any application that has the name of the shared memory can use
DosGetNamedSharedMem to retrieve a pointer to the memory. This makes it
possible for two or more applications to share memory at the same time.
The name of a shared memory object has the following form:
\sharemem\name
The "\sharemem\" is required. The "name" parameter can be any name that
conforms to the rules for an OS/2 file name. No file is actually created for
the memory object. There is no actual "\sharemem\" subdirectory.
The following code fragment allocates 65536 bytes of named shared memory with
the name "\sharemem\mymem".
#define INCL_DOSMEMMGR /* Memory Manager values */
#include <os2.h>
APIRET ulrc;
CHAR szMem[] = { "\\sharemem\\mymem" };
PULONG pulPb;
ulrc = DosAllocSharedMem((PVOID *) &pulPb,
szMem,
65536,
fALLOC);
*pulPb = 2762;
Once the named memory is allocated, any other process can retrieve a pointer to
the named memory by using DosGetNamedSharedMem.
The following code fragment retrieves a pointer to the named memory allocated
above:
#define INCL_DOSMEMMGR /* Memory Manager values */
#include <os2.h>
#define HF_STDOUT 1 /* Standard output handle */
APIRET ulrc;
CHAR szMem[] = { "\\sharemem\\mymem" };
PULONG pulPb2;
ULONG ulWritten;
ulrc = DosGetNamedSharedMem((PVOID *) &pulPb2,
szMem,
PAG_READ |
PAG_WRITE);
if (*pulPb2 == 2762)
ulrc = DosWrite(HF_STDOUT, "\r\n Success!\r\n", 13,
&ulWritten);
ΓòÉΓòÉΓòÉ 1.4.2. Using Unnamed Giveable Shared Memory ΓòÉΓòÉΓòÉ
A process allocates unnamed giveable shared memory by using DosAllocSharedMem
with the object name (pszName parameter) set to NULL and the memory options
(flag parameter) set to OBJ_GIVEABLE. The process allocating the memory must
pass a pointer to the shared memory to another process. This is typically done
by using some form of interprocess communication, such as a queue or a named
pipe.
If a process allocates shared memory with the OBJ_GIVEABLE option, this process
can validate the pointer in another process with DosGiveSharedMem.
The following code fragment allocates 24576 bytes (24KB) of unnamed giveable
shared memory:
#define INCL_DOSMEMMGR /* Memory Manager values */
#include <os2.h>
APIRET ulrc;
PBYTE pb;
ulrc = DosAllocSharedMem((PVOID *) &pb,
(PSZ) NULL,
24576, /* amount of memory */
fALLOC |
OBJ_GIVEABLE); /* giveable memory */
Once the memory is allocated, the allocating process can pass the memory
pointer to a second process through interprocess communication. The second
process need not use DosGetSharedMem; the second process can just use the
shared memory.
ΓòÉΓòÉΓòÉ 1.4.3. Using Unnamed Gettable Shared Memory ΓòÉΓòÉΓòÉ
A process allocates unnamed gettable shared memory by using DosAllocSharedMem
with the object name (pszName parameter) set to NULL and the memory options
(flag parameter) set to OBJ_GETTABLE. The allocating process must pass a
pointer to the shared memory to another process. This is typically done by
using some form of interprocess communication, such as a queue or a named pipe.
If an application allocates shared memory with the OBJ_GETTABLE option, it
passes a pointer to the shared memory to the second process. The second process
gets access to the shared memory by using DosGetSharedMem to validate the
passed pointer.
The following code fragment allocates 24576 bytes (24KB) of unnamed gettable
shared memory:
#define INCL_DOSMEMMGR /* Memory Manager values */
#include <os2.h>
APIRET ulrc;
PBYTE pb;
ulrc = DosAllocSharedMem((PVOID *) &pb,
(PSZ) NULL,
24576,
fALLOC |
OBJ_GETTABLE); /* gettable memory */
Once the memory is allocated, the process can pass the memory pointer to a
second process through interprocess communication. Once the second process
receives the pointer, it validates the memory with DosGetSharedMem, as shown in
the following code:
#define INCL_DOSMEMMGR /* Memory Manager values */
#include <os2.h>
APIRET ulrc;
PBYTE pb2;
ulrc = DosGetSharedMem(pb2, /* validating the memory allocated by */
/* the allocating process */
PAG_READ |
PAG_WRITE);
ΓòÉΓòÉΓòÉ 2. Message Management ΓòÉΓòÉΓòÉ
This chapter describes the use of message files to hold an application's text
messages to the user. Keeping messages in a message file simplifies changing
those messages, for example when maintaining versions of the same application
for different countries.
The following topic is related to the information in this chapter:
National language support
ΓòÉΓòÉΓòÉ 2.1. About Message Management ΓòÉΓòÉΓòÉ
For full-screen applications, text messages-used by an application to display
information to the user-can be held in a message file.
To keep and maintain messages in a message file, create a separate message file
for each national language you intend to support. Use the MKMSGF utility
program to create a binary version of a message file, and the MSGBIND utility
program to bind the binary file to the application's executable file. Binding
the messages to an application's executable file inserts the messages into the
.EXE file. This enables faster access (but, of course, a larger .EXE file).
OS/2 provides several functions to assist in message management. Applications
can get messages from a message file, substitute variable information into the
messages, and write messages to the screen or to a file.
Code Page Considerations
You can have versions of the message file for each code page you choose to
support. When you use MKMSGF to create the message files, the utility will
insert the code page information and link together the message files of the
different versions.
When message files are linked together in this manner, DosGetMessage will
search for the appropriate version of the message for the code page that is
active at the time the function is called. If there is no version of the
message for the current code page, the function will return the first version
of the message, no matter which code page it is associated with.
Note: To create portable source code for message files, make sure you
specifically set the code page in CONFIG.SYS using the CODEPAGE statement. If
you have the wrong code page, or use the default code page, which could be
wrong, DosGetMessage returns error code 37 (ERROR_CODE_PAGE_MISMATCHED).
ΓòÉΓòÉΓòÉ 2.2. Using Message Management ΓòÉΓòÉΓòÉ
DosGetMessage retrieves a message from the specified system message file, and
inserts variable information into the body of the message.
DosInsertMessage inserts variable text-string information into the body of the
message, but does not retrieve the message.
DosPutMessage sends the message in a buffer, usually to a display screen.
DosPutMessage formats the screen buffer to prevent words from being split at
the end of a line.
DosQueryMessageCP retrieves the message file list of code pages and language
identifiers.
Note: In the example code fragments that follow, error checking was left out
to conserve space. Applications should always check the return code that
the functions return. Control Program functions return an APIRET value.
A return code of 0 indicates success. If a non-zero value is returned,
an error occurred.
ΓòÉΓòÉΓòÉ 2.2.1. Message Retrieval and String Substitution ΓòÉΓòÉΓòÉ
DosGetMessage retrieves a message from a system message file, and inserts
variable text-string information into the message.
In the following code fragment, the message file is "D:\MESSAGE\AUTOMSG.MSG".
The third message within the message file contains the string "%1 Error at
Station %2". The application calls DosGetMessage to convert this message into
the string "Automation Failure Error at Station 69B".
#define INCL_DOSMISC /* Miscellaneous values */
#include <os2.h>
#include <stdio.h>
UCHAR *ucIvTable[2]; /* Table of variables to insert */
ULONG ulIvCount; /* Number of variables */
UCHAR ucDataArea[80]; /* Message buffer (returned) */
ULONG ulDataLength; /* Length of buffer */
ULONG ulMsgNumber; /* Number of the message */
UCHAR ucFileName[40]; /* Message file path-name string */
ULONG ulMsgLength; /* Length of message (returned) */
UCHAR ucField1[20]; /* String to substitute into variable */
/* field %1 of the message */
UCHAR ucField2[20]; /* String to substitute into variable */
/* field %2 of the message */
APIRET ulrc; /* Return code */
strcpy(ucField1,
"Automation Failure"); /* Define the field with which to */
/* perform the first substitution */
strcpy(ucField2,
"69B"); /* Define the field with which to */
/* perform the second substitution */
ucIvTable[0] = ucField1; /* Set up the array of pointers to */
ucIvTable[1] = ucField2; /* substitute strings */
ulIvCount = 2; /* Two variable message fields in message */
ulDataLength = 80; /* Data buffer that will receive the */
/* complete message is 80 bytes in size */
ulMsgNumber = 3; /* Specify the third message in the */
/* message file */
strcpy(ucFileName,
"D:\\MESSAGE\\AUTOMSG.MSG");
/* Path name of the message file */
ulrc = DosGetMessage(ucIvTable,
ulIvCount,
ucDataArea,
ulDataLength,
ulMsgNumber,
ucFileName,
&ulMsgLength);
if (ulrc != 0) {
printf("DosGetMessage error: return code = %ld",
ulrc);
return;
}
On successful return, the DataArea buffer contains the complete message (with
the two variable fields appropriately updated), and the MsgLength variable
contains the length of the message that was placed into the DataArea buffer.
If an error occurs (that is, if the return code does not equal 0), a message
that is related to the error will be placed in the message buffer. See the
DosGetMessage API reference in Control Program Programming Reference for a
description of the default messages that can be placed into the user's buffer
if an error occurs during the processing of these requests.
ΓòÉΓòÉΓòÉ 2.2.2. Text String Substitution in Memory ΓòÉΓòÉΓòÉ
DosInsertMessage inserts variable text-string information into a message that
resides within program memory.
In the following code fragment, the message resides in a program string
variable named Message. The message is the string "%1 Error at Station %2". The
application calls DosInsertMessage to convert this message into the string
"Automation Failure Error at Station 69B".
#define INCL_DOSMISC /* Miscellaneous values */
#include <os2.h>
#include <stdio.h>
UCHAR *ucIvTable[2]; /* Table of variables to insert */
ULONG ulIvCount; /* Number of variables */
UCHAR ucMsgInput[40] = "%1 Error at Station %2"; /* The input message */
ULONG ulMsgInLength; /* Length of input message */
UCHAR ucDataArea[80]; /* Message buffer (returned) */
ULONG ulDataLength; /* Length of updated message buffer */
ULONG ulMsgLength; /* Length of updated message (returned) */
UCHAR ucField1[20]; /* String to substitute into variable */
/* field %1 of the message */
UCHAR ucField2[20]; /* String to substitute into variable */
/* field %2 of the message */
APIRET ulrc; /* Return code */
strcpy(ucField1,
"Automation Failure"); /* Define the field with which to */
/* perform the first substitution */
strcpy(ucField2,
"69B"); /* Define the field with which to */
/* perform the second substitution */
ucIvTable[0] = ucField1; /* Set up the array of pointers to */
ucIvTable[1] = ucField2; /* substitute strings */
ulIvCount = 2; /* Two variable message fields in */
/* message */
ulMsgInLength = strlen(ucMsgInput); /* Length of input message */
ulDataLength = 80; /* Data buffer that will receive */
/* the complete message is 80 */
/* bytes in size */
ulrc = DosInsertMessage(ucIvTable,
ulIvCount,
ucMsgInput,
ulMsgInLength,
ucDataArea,
ulDataLength,
&ulMsgLength);
if (ulrc != 0) {
printf("DosInsertMessage error: return code = %ld",
ulrc);
return;
}
On successful return, the DataArea buffer contains the complete message (with
the two variable fields appropriately updated), and the MsgLength variable
contains the length of the message that was placed into the DataArea buffer.
If an error occurs (that is, if the return code does not equal 0), a message
that is related to the error will be placed in the message buffer. See the
DosGetMessage API reference in Control Program Programming Reference for a
description of the default messages that can be placed into the user's buffer
if an error occurs during the processing of these requests.
ΓòÉΓòÉΓòÉ 2.2.3. Writing Messages ΓòÉΓòÉΓòÉ
DosPutMessage is used to write the message to the screen or to a file on a
disk.
The following code fragment writes the message string contained in
MessageBuffer to the file specified by FileHandle. The message string has
already been placed in MessageBuffer using either DosGetMessage or
DosInsertMessage. MsgLength was set to the length of the message string by the
same call that put the message into MessageBuffer.
#define INCL_DOSMISC /* Miscellaneous values */
#include <os2.h>
#include <stdio.h>
HFILE hfFileHandle; /* Handle of output file or device */
ULONG ulMsgLength; /* Length of message buffer */
UCHAR ucMessageBuffer[80]; /* Message buffer */
APIRET ulrc; /* Return code */
ulrc = DosPutMessage(hfFileHandle,
ulMsgLength,
ucMessageBuffer);
if (ulrc != 0) {
printf("DosPutMessage error: return code = %ld",
ulrc);
return;
}
To write a message to the screen, use the standard output file handle.
ΓòÉΓòÉΓòÉ 2.2.4. Code Page Information Associated with Message Files ΓòÉΓòÉΓòÉ
DosQueryMessageCP obtains a list of code page identifiers and language
identifiers that are associated with a specified message file.
In the following code fragment code page and language identifiers associated
with the message file "D:\MESSAGE\AUTOMSG.MSG" are retrieved.
#define INCL_DOSMISC /* Miscellaneous values */
#include <os2.h>
#include <stdio.h>
UCHAR ucBufferArea[20]; /* Buffer for the returned list */
ULONG ulBufferLength; /* Length of the buffer area */
UCHAR ucFileName[40]; /* Message file path-name string */
ULONG ulDataLength; /* Length of the returned data */
APIRET ulrc; /* Return code */
strcpy(ucFileName,
"D:\\MESSAGE\\AUTOMSG.MSG");
/* Path name of message file */
ulBufferLength = 20; /* Length of buffer area */
ulrc = DosQueryMessageCp(ucBufferArea,
ulBufferLength,
ucFileName,
&ulDataLength);
if (ulrc != 0) {
printf("DosQueryMessageCp error: return code = %ld",
ulrc);
return;
}
On successful return, the BufferArea buffer contains a set of information
concerning the code page identifiers and language identifiers that are
associated with the message file.
ΓòÉΓòÉΓòÉ 3. National Language Support ΓòÉΓòÉΓòÉ
Many applications need to be independent of a particular language. Rather than
being hard-coded in English, they want to support, for example, an English
version of the application, and a French version, and a German version;
preferably without having to change the program code for each version. Meeting
this requirement is simplified through the use of such resources as string
tables, menu templates, dialog templates, accelerator tables, and through the
use of code pages.
This chapter describes the functions an application uses to be NLS enabled, or
language independent.
The following topic is related to the information in this chapter:
Message management
ΓòÉΓòÉΓòÉ 3.1. About National Language Support ΓòÉΓòÉΓòÉ
The support of national languages by applications requires the following
considerations:
Displayed text must be translated into the appropriate language.
Symbols or icons might not convey the same meaning in all countries.
Alternative designs for different countries might be necessary.
Translation changes the length of text strings.
Different languages often have different text characters.
The use of national language resource files can help with the first three
items, and the ability of the application to receive input and display output
in any ASCII code page can help with the last item.
The use of ASCII code page 850 avoids many of the problems in this area, since
it contains most of the characters required for Latin-1 languages, which
include much of Western Europe and North and South America. However, older
programs use code page 437 for U.S. English, and code pages 860, 863, and 865
for various languages. The code page applies to both input and output data.
Note: Code page 850 was used for translating Presentation Manager text. Use
code page 850 whenever possible for all Presentation Manager
applications that might require translation.
ΓòÉΓòÉΓòÉ 3.1.1. National Language Resource Files ΓòÉΓòÉΓòÉ
When creating an application, define national language dependencies in
resources that are held in resource files separate from the program code. That
is:
Keep pure text strings in string tables.
Keep menus in menu templates.
Keep dialog boxes in dialog templates.
Keep accelerators in accelerator tables.
The language displayed by the application can then be changed by translating
the resources, in most cases without changing the application.
However, when translating from one language to another, the length of a text
string can change substantially. For example, when translating from English to
German, the length of a text string can double in length.
The following table furnishes a general idea of the amount of expansion that
can be expected during translation.
Translation Expansion
ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
ΓöéFor English Phrases ΓöéTranslation Expansion Factors Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéUp to 10 characters Γöé101 - 200% Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
Γöé11 - 20 characters Γöé81 - 100% Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
Γöé21 - 30 characters Γöé61 - 80% Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
Γöé31 - 50 characters Γöé41 - 60% Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
Γöé51 - 70 characters Γöé31 - 40% Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéOver 70 characters Γöé30% Γöé
ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
When designing your dialog boxes and text string messages, add white space to
allow for the expansion that will occur when the text is translated. You might
have to adapt the application program to allow for the change in the length of
text strings after they are translated. For example, a change in the length of
a text string can cause it to become misaligned with other displayed objects.
You can also use the Dialog Box Editor to adjust for misalignments, or to
change the size of the dialog box. This would enable you to leave your
application program unchanged.
Text strings explicitly displayed by the application program are more of a
problem. You will have to include program code that can handle text strings of
varying length and format them at runtime according to their size.
ΓòÉΓòÉΓòÉ 3.1.2. Language-Specific Versions of NLS-Enabled Applications ΓòÉΓòÉΓòÉ
There are two methods of creating a specific national language version of a
program designed to handle more than one national language. The choice of the
method depends on the amount of available disk space and whether the user wants
to change between different languages once the program is installed. The two
methods are:
Statically link the resources to the application's .EXE files. The
executable files are then language-specific and cannot be changed to
another national language. The specific .EXE files are then sent to the
user.
Place the resources into a language-specific, dynamic link library.
Designate one library file for each national language. Selecting a
particular library file for use with the application gives the desired
version of the program. Using this method, all national languages can be
shipped with the product; selection of the national language occurs
during installation (for example, by naming a specific .DLL file). It is
possible to change the national language setting while the program is
operating.
ΓòÉΓòÉΓòÉ 3.2. About Code Page Management ΓòÉΓòÉΓòÉ
A code page is a table that defines how the characters in a language or group
of languages are encoded. A specific value is given to each character in the
code page. For example, in code page 850 the letter "╨┤" (lowercase) is encoded
as hex A4 (decimal 164), and the letter "╨╡" (uppercase) is encoded as hex A5
(decimal 165).
Code page management enables a user to select a code page for keyboard input,
and screen and printer output before starting an application, a system command,
or a utility program in the OS/2 multitasking environment.
This means that a user in a particular country, such as England (code page
850), Norway (code page 865), or a language region such as Canadian French
(code page 863) can use a code page that defines an ASCII-based character set
containing characters used by that particular country or language.
Installable code page files include keyboard translate tables, display
character sets, printer character sets, and country/language information for
each code page supported.
Of particular interest are two code pages:
Code Page 850
Code Page 437
Code Page 850 (CP850)
Code Page 850 is also called the Latin-1, multilingual code page. This code
page supports the alphabetic characters of the Latin-1-based languages. It
contains characters required by 13 languages used in approximately 40
countries.
CP850 also provides the flexibility to develop new applications based on
non-Latin-based or special industry-based code pages.
Code Page 850 supports countries using the following languages:
ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
ΓöéBelgian French ΓöéCanadian French Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéDanish ΓöéDutch Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéFinnish ΓöéFlemish Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéFrench ΓöéGerman Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéItalian ΓöéNorwegian Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéPortuguese ΓöéSpanish Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéLAD Spanish ΓöéSwedish Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéSwiss French ΓöéSwiss German Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéU.K. English ΓöéU.S. English Γöé
ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
Code Page 437 (CP437)
Code Page 437 is the standard personal computer code page.
The lower 128 characters are based on the 7-bit ASCII code. The upper 128
characters contain characters from several European languages (including part
of the Greek alphabet) and various graphic characters. However, some of the
accented characters, such as those used in the Nordic countries, are not
represented. The missing characters are available in other code pages (code
page 850 will usually contain the desired characters).
Note: Some of the 256 symbols that can be displayed are printer control
characters, and are not printed.
ΓòÉΓòÉΓòÉ 3.2.1. ASCII and EBCDIC Code Page Support ΓòÉΓòÉΓòÉ
The two leading character-coding systems are ASCII and EBCDIC. Presentation
Manager applications can use an EBCDIC code page instead of an ASCII code page.
Code pages based on both systems are supported by OS/2.
Any code page that either is defined in the CONFIG.SYS file, or is one of the
EBCDIC code pages supported, can be selected.
ΓòÉΓòÉΓòÉ 3.2.2. Code Page Preparation ΓòÉΓòÉΓòÉ
During system initialization, the code pages specified in the CODEPAGE
statement are prepared to enable run-time code page switching of the display,
the keyboard, the printer, and the country information. The display, keyboard,
and printer must be defined in a DEVINFO statement in order to be prepared.
Country information is prepared for the system country code specified in the
COUNTRY statement.
If a resource cannot be prepared for the selected code page during system
initialization, it is prepared for a default code page. The following are the
defaults:
A keyboard layout defaults to the code page of the translate table
designated as the default layout in the KEYBOARD.DCP file. The default
layout is based on the national code page of its associated country. You
must explicitly specify KEYBOARD.DCP in the DEVINFO statement for the
keyboard in CONFIG.SYS.
The display defaults to the code page of ROM_0 for the device.
(ROM_0 means a device default code page that is the device native code
page or the lowest addressed ROM code page.)
The printer defaults to the code page of ROM_0 for the device.
(ROM_0 means a device default code page that is the device native code
page or the lowest addressed ROM code page.)
The country information defaults to the code page of the first entry
found in the COUNTRY.SYS file for the country code. Each entry is the
same information for a given country code, but is encoded in a different
code page. The first entry is based on the preferred country code page.
If country information cannot be prepared at system initialization because it
is not found in the COUNTRY.SYS file, for a code page selected with the
CODEPAGE statement, then it is prepared (maintained for run-time code page
switching in memory) in the default code page. Similarly, a keyboard layout is
prepared in its default code page if it cannot be prepared in the selected
code page, because it is not found in the KEYBOARD.DCP file.
COUNTRY.SYS contains one default entry per country code, and KEYBOARD.DCP
contains one default entry per keyboard layout based on these assignments.
ΓòÉΓòÉΓòÉ 3.2.3. Code Page Functions ΓòÉΓòÉΓòÉ
At the system level, OS/2 switches the code pages of supported displays and
printers to agree with the code page of the process sending the output. At the
application level, OS/2 functions enable a process to control code page
assignments.
ΓòÉΓòÉΓòÉ 3.3. Using Code Pages ΓòÉΓòÉΓòÉ
OS/2 provides applications with several functions to obtain information about
and manipulate code pages. These functions enable applications to determine and
set the current code page.
OS/2 code page management functions enable applications to read keyboard input
and write display and printer output for multiple processes using ASCII-based
data encoded in different code pages.
The system switches to the required code page, for a code-page-supported
device, before input or output.
Note: In the example code fragments that follow, error checking was left out
to conserve space. Applications should always check the return code that
the functions return. Control Program functions return an APIRET value.
A return code of 0 indicates success. If a non-zero value is returned,
an error occurred.
ΓòÉΓòÉΓòÉ 3.3.1. Querying Code Page Support and the Current Code Page ΓòÉΓòÉΓòÉ
DosQueryCp is used to determine the code page of the current process and the
prepared system code pages. The following code fragment shows how to get the
current code page, and then up to three other prepared pages:
#define INCL_DOSNLS /* National Language Support values */
#include <os2.h>
ULONG ulCpList[8];
ULONG ulCpSize;
APIRET ulrc; /* Return code */
ulrc = DosQueryCp(sizeof(ulCpList), /* Length of list */
ulCpList, /* List */
&ulCpSize); /* Length of returned list */
The required code page is the current code page of the process at the time it
opens a device, or a specific code page selected by the process with a
set-code-page function. A character set can also be specified for some devices,
for example, for some printers.
The country functions retrieve country- and language-dependent information in
the current code page of the calling process, or in a code page selected by the
process.
ΓòÉΓòÉΓòÉ 3.3.2. Setting the Code Page for Text Characters ΓòÉΓòÉΓòÉ
Each process has a code page tag maintained by OS/2. A code page tag is the
identifier of the current code page for the process.
A child process inherits the code page tag of its parent. The default code page
for the first process in a session is the same as the session code page. The
default code page for a new session is the primary code page specified in the
CODEPAGE configuration statement.
To change the code page tag of a process, call DosSetProcessCp. This will not
change the process code page tag of its parent or any child process.
ΓòÉΓòÉΓòÉ 3.3.3. Obtaining the Case Map String ΓòÉΓòÉΓòÉ
DosMapCase performs case mapping on a string of binary values that represent
ASCII characters.
The case map that is used is the one in the country file that corresponds to
the system country code or selected country code, and to the process code page
or selected code page. The default name of the country file is COUNTRY.SYS.
ΓòÉΓòÉΓòÉ 3.3.4. Obtaining the DBCS Environment Vector ΓòÉΓòÉΓòÉ
DosQueryDBCSEnv obtains a double-byte character set (DBCS) environment vector
that resides in the country file. The default name of the country file is
COUNTRY.SYS.
The vector corresponds to the system country code or selected country code, and
to the process code page or selected code page.
The following code fragment shows how to use DosQueryDBCSEnv:
#define INCL_DOSNLS /* National Language Support values */
#include <os2.h>
#include <stdio.h>
ULONG ulLength; /* Length of data area provided */
COUNTRYCODE ccStructure; /* Input data structure */
UCHAR ucMemoryBuffer[12]; /* DBCS environmental vector (returned) */
APIRET ulrc; /* Return code */
ulLength = 12; /* A length of 12 bytes is sufficient */
/* to contain the DBCS data returned */
ccStructure.country = 0; /* Use the default system country code */
ccStructure.codepage = 0; /* Return DBSC information for the */
/* caller's current process code page */
ulrc = DosQueryDBCSEnv(ulLength,
&ccStructure,
ucMemoryBuffer);
if (ulrc != 0) {
printf("DosQueryDBCSEnv error: return code = %ld",
ulrc);
return;
}
On successful return, the buffer MemoryBuffer will contain the country
dependent information for the DBCS environmental vector.
Instead of the single-byte character set (SBCS) representation used for Latin
text, some Asian countries use code pages that consist of double-byte character
set characters, in which each character is represented by a two-byte code. The
DBCS code pages enable single-byte data, double-byte data, or mixed
(single-byte and double-byte) data.
ΓòÉΓòÉΓòÉ 3.3.5. Obtaining Formatting Information ΓòÉΓòÉΓòÉ
DosQueryCtryInfo obtains country dependent formatting information that resides
in the country file. The default name of the country file is COUNTRY.SYS.
The information corresponds to the system country code or selected country
code, and to the process code page or selected code page.
ΓòÉΓòÉΓòÉ 3.3.6. Obtaining Collating Information for SORT ΓòÉΓòÉΓòÉ
DosQueryCollate obtains a collating sequence table (for characters 00H through
FFH) from the country file. The default name of the country file is
COUNTRY.SYS. The SORT utility program uses this table to sort text according to
the collating sequence.
The collating table returned corresponds to the system country code or selected
country code, and to the process code page or selected code page.
ΓòÉΓòÉΓòÉ 4. Pipes ΓòÉΓòÉΓòÉ
Communication between processes is valuable in a multitasking operating system
to enable concurrent processes to work together. Pipes are one of three forms
of interprocess communication (IPC), the other forms of IPC being semaphores
and queues.
This chapter describes how to create, manage, and use pipes. Pipes enable two
or more processes to communicate as if they were reading from and writing to a
file.
The following topics are related to the information in this chapter:
Memory (shared memory)
Program execution and control
Semaphores
Queues
ΓòÉΓòÉΓòÉ 4.1. About Pipes ΓòÉΓòÉΓòÉ
A pipe is a named or unnamed buffer used to pass data between processes. A
process writes to or reads from a pipe as if the pipe were standard input or
standard output. A parent process can use pipes to control the input that a
child process receives and to receive the output that the child process
produces.
There are two types of pipes-named and unnamed.
ΓòÉΓòÉΓòÉ 4.1.1. Unnamed Pipes ΓòÉΓòÉΓòÉ
An unnamed pipe is a circular buffer in memory. The buffer has in and out
pointers that are maintained by the system.
An unnamed pipe can transfer information only between related processes. A
child process started by a parent process with DosExecPgm inherits the handles
to any unnamed pipes created by its parent. This inheritance enables the parent
process and the child process to use the unnamed pipe to communicate with one
another. This type of pipe is typically used to redirect the standard input and
standard output of a child process.
To do this, a process opens a pipe and duplicates the read and write handles of
the pipe as the standard input and standard output files for the child process.
Once the handles are duplicated, the parent process can use DosExecPgm to start
the child process. When the child process reads and writes to its standard
input and standard output handles, it is reading and writing to the pipe. The
parent process can also communicate with the child process through the pipe.
Using an unnamed pipe, a text editor could run another program, such as a
compiler or assembler, and display the output of the compiler or assembler
within the editor.
DosCreatePipe creates an unnamed pipe. This function returns two file handles
for the pipe, one for writing to the pipe and another for reading from the
pipe. A process can then write to the pipe by using DosWrite and read from the
pipe by using DosRead.
A pipe exists until both handles are closed. The order in which the handles are
closed is sometimes important. For example, DosWrite might wait for data to be
read from the pipe before completing its operation. In this case, the read
handle is closed before the write handle is closed, writing to the pipe
generates an error.
No control or permission mechanisms or checks are performed on operations to
unnamed pipes.
ΓòÉΓòÉΓòÉ 4.1.2. Named Pipes ΓòÉΓòÉΓòÉ
Named pipes enable related or unrelated processes on either the same computer
system or different systems to communicate with each other. Any process that
knows the name of a pipe can open and use a named pipe. In addition, named pipe
data can be transparently redirected across a network, such as a local area
network (LAN). (Unnamed pipes, by contrast, can be used only by related
processes that are on the same computer system.)
One process (the server process) creates the pipe and connects to one end of
it. Other processes that access the named pipe are called client processes;
they connect to the other end of the pipe. The server and client processes can
then pass data back and forth by reading from and writing to the pipe. The
server process controls access to the named pipe.
The client process can be either local or remote. A local client process is one
that runs on the same computer system as the server process. A remote client
process runs on a different system and communicates with the server process
across a local area network (LAN).
When the server process creates a named pipe with DosCreateNPipe, it must
specify the direction that data will flow through the pipe. The process
specifies an inbound pipe if it intends to read data from the client process,
an outbound pipe if it intends to write data to the client process, or a duplex
pipe if it intends to read from and write to the client process.
The server process also specifies whether data passes through the pipe as bytes
or messages. A message is a block of data, with a system-supplied header, that
is read or written as a single unit. The server and client processes define the
size and format of a message.
The server process also specifies whether child processes will inherit the
named pipe and how information will be read from and written to the pipe. If
the server specifies wait mode, DosRead will be blocked (it will not return to
the process) until data is available in the pipe, and DosWrite will be blocked
until there is enough room in the pipe to contain the entire data buffer. If
the server specifies no-wait mode, reading from an empty pipe or writing to a
full pipe immediately returns an error value.
A named pipe consists of two pipe buffers, one for each direction of
communication. However, each end of the pipe has only one handle associated
with it. The server receives the handle for its end when it creates the pipe
with DosCreateNPipe. The client receives the handle for its end when it opens
the pipe with DosOpen.
The server and the client use their respective handles both to read from the
pipe and to write to it. (This is in contrast to unnamed pipes, for which both
the server and the client read from one handle and write to another.) In other
words, data that is written by the process at one end of the pipe is read by
the process at the other end.
A named pipe can have multiple instances, up to the number specified when the
pipe is first created. Pipe instances are actually separate pipes-that is,
unique sets of pipe buffers with unique handles-that share the same name. The
ability to create multiple pipe instances enables the server to communicate
with multiple client processes at the same time.
ΓòÉΓòÉΓòÉ 4.1.2.1. Server-Client Communications Using Named Pipes ΓòÉΓòÉΓòÉ
A server process initiates a connection to a client process by using
DosConnectNPipe. Once the pipe has been connected by the server process, the
client process must open the pipe by using DosOpen to complete the connection.
If no client process has opened the pipe when the server process calls
DosConnectNPipe, the function either waits until a client opens the pipe or
returns ERROR_PIPE_NOT_CONNECTED, depending on whether the server process
created the pipe to wait for data.
Each client process requires a separate instance of a pipe. For example, if a
server process creates a named pipe and specifies that four instances of the
pipe can be created, the process can then create three more instances of the
named pipe (for a total of four pipes, including the original). Each instance
has the same name, but each has a unique pipe handle. The process can then
connect each pipe to the server. (Each instance must be connected by an
explicit use of DosConnectNPipe.) In this example, the server must use each
function four times to create and connect four separate instances of the named
pipe. Each pipe is then available to a separate client process.
If a client process receives the ERROR_PIPE_BUSY return value from DosOpen, no
instances of the given pipe are available. The process can use DosWaitNPipe to
wait for an instance to become available. The function waits until an instance
is free or until the specified time interval elapses. When an instance becomes
free, the process can open the pipe. If several processes are waiting for an
instance to become available, the system gives the named pipe to the process
that has been waiting the longest.
The server process can disconnect a client process from a pipe by using
DosDisConnectNPipe. Ideally, the client process closes the pipe by using
DosClose before the server process disconnects the pipe. If the client process
has not closed the pipe when the server process disconnects it, the server
process forces the pipe closed and the client process subsequently receives
errors if it attempts to access the pipe. Note that forcing the closure of the
pipe might discard data in the pipe before the client process has had an
opportunity to read it.
A process can read and write bytes to a named pipe by using DosRead and
DosWrite. A process can read or write messages by using DosTransactNPipe.
Depending on the access mode, DosTransactNPipe writes a message to the pipe,
reads a message from the pipe, or both. If a named pipe contains unread data or
is not a message pipe, DosTransactNPipe fails.
Named pipes created with the NP_ACCESS_INBOUND or NP_ACCESS_OUTBOUND access
mode cannot use the DosTransactNPipe function. If the named pipe's client uses
the DosTransactNPipe function, the function returns error code 5
(ERROR_ACCESS_DENIED).
If it is reading from the pipe, DosTransactNPipe does not return until a
complete message is read, even if the server process specified no-wait mode
when the pipe was created.
A process can also read data from a named pipe without removing the data from
the pipe by using DosPeekNPipe. This function copies the specified number of
bytes from the pipe and returns the number of bytes of data left in the pipe
and the number of bytes left in the current message, if any.
DosPeekNPipe also returns the state of the pipe. A named pipe can be in one of
the following states:
Named Pipe States
ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
ΓöéState ΓöéDescription Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéConnected ΓöéThe pipe has been created and connected by Γöé
Γöé Γöéthe server process and has been opened by a Γöé
Γöé Γöéclient process. Only connected pipes can be Γöé
Γöé Γöéwritten to or read from. Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéClosing ΓöéThe pipe has been closed by the client Γöé
Γöé Γöéprocess but has not yet been disconnected by Γöé
Γöé Γöéthe server process. Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéDisconnected ΓöéThe pipe has been created by the server Γöé
Γöé Γöéprocess but not connected, or has been Γöé
Γöé Γöéexplicitly disconnected and not yet Γöé
Γöé Γöéreconnected. A disconnected pipe cannot Γöé
Γöé Γöéaccept a DosOpen request. Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéListening ΓöéThe pipe has been created and connected by Γöé
Γöé Γöéthe server process but has not yet been Γöé
Γöé Γöéopened by a client process. A listening pipe Γöé
Γöé Γöéis ready to accept a request to open. If the Γöé
Γöé Γöépipe is not in a listening state, DosOpen Γöé
Γöé Γöéreturns ERROR_PIPE_BUSY. Γöé
ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
DosCallNPipe is used to open, write to, read from, and close a named
message-format pipe.
Named pipes created with the NP_ACCESS_INBOUND or NP_ACCESS_OUTBOUND access
mode cannot use the DosCallNPipe function. If the named pipe's client uses the
DosCallNPipe function, the function returns error code 5 (ERROR_ACCESS_DENIED).
This function is equivalent to calling DosOpen, DosTransactNPipe, and DosClose
If no instances of the pipe are available, DosCallNPipe waits for an instance
or returns without opening the pipe if the specified interval of time elapses.
A process can retrieve information about the handle state of a named pipe by
using DosQueryNPHState. The handle state is a combination of the instance
count, the access mode, and the pipe type (byte or message). DosQueryNPHState
also specifies whether the process owning the handle is a server or client and
whether the pipe waits if reading and writing cannot proceed.
A process can modify the handle state of a named pipe by using DosSetNPHState.
For example, the process can change the reading mode for the pipe, enabling a
process to read bytes from the pipe instead of messages.
ΓòÉΓòÉΓòÉ 4.1.2.2. Steps in Managing Server-Client Transactions ΓòÉΓòÉΓòÉ
The following sequence summarizes the typical steps in the management of a
named pipe:
1. The server process creates the pipe by calling DosCreateNPipe.
DosCreateNPipe returns a handle for the server end of the pipe. (Note
that the server uses the same handle to both read from and write to the
pipe.) The pipe is now in the disconnected state and cannot be opened by
a client process. The server process calls DosConnectNPipe to put the
pipe into a listening state.
2. The pipe can now be opened by a client process.
3. A client process supplies the name of the pipe in a call to DosOpen and
receives a pipe handle in return. (The client uses the same handle to
both read from and write to the pipe.) The pipe is now in the connected
state and can be read from or written to by the client.
4. The server and client processes communicate by calling DosRead and
DosWrite. DosResetBuffer can be used to synchronize read and write
dialogs. A server process that supports a large number of clients for a
local named pipe can use DosSetNPipeSem and DosQueryNPipeSemState to
coordinate access to the pipe. Server and client processes can also use
DosTransactNPipe and DosCallNPipe to facilitate their communication.
5. After completing its transactions, the client process calls DosClose to
close its end of the pipe. The pipe is now in the closing state and
cannot be accessed by another client.
6. The server process calls DosDisConnectNPipe to acknowledge that the
client has closed its end of the pipe. The pipe is now in the
disconnected state again.
7. To enable another client process to open the pipe, the server must call
DosConnectNPipe again. This puts the pipe back into the listening state.
To end its access to the pipe, the server calls DosClose. When all of the
handles for both ends of the pipe have been closed, the pipe is
deallocated by the system.
ΓòÉΓòÉΓòÉ 4.1.2.3. Preparing a Named Pipe for a Client ΓòÉΓòÉΓòÉ
A server process uses DosConnectNPipe to put a newly created named pipe into
the listening state. The pipe must be in the listening state in order for a
client process to gain access to the pipe by calling DosOpen.
After successfully opening the pipe and finishing its transactions, the client
process calls DosClose to end its access to the pipe. The server process must
acknowledge the close by calling DosDisConnectNPipe. It can then call
DosConnectNPipe again to put the pipe into the listening state for the next
client.
Together, DosConnectNPipe and DosDisConnectNPipe enable a server to create a
named pipe and to reuse it for communication with different clients. Without
these functions, the server would have to delete and re-create the pipe for
each client.
Note: If multiple instances of a named pipe have been created, then each
instance of the pipe must be put into the listening state before it can
be opened by a client.
ΓòÉΓòÉΓòÉ 4.1.2.4. Facilitating Transaction Processing ΓòÉΓòÉΓòÉ
DosTransactNPipe and DosCallNPipe facilitate the use of named pipes by
combining other named pipe functions. Compared to calling the other functions
separately, DosTransactNPipe and DosCallNPipe provide significant performance
gains for applications that operate in a networked environment. They can also
be used by local processes. However, both of these functions can be used only
with duplex message pipes.
DosTransactNPipe performs a transaction (a DosWrite followed by DosRead)
on a duplex message pipe.
DosCallNPipe has the combined effect of DosOpen, DosTransactNPipe, and
DosClose, and is referred to as a procedure call. It provides an
efficient means of implementing local and remote procedure call
interfaces between processes.
ΓòÉΓòÉΓòÉ 4.1.2.5. Coordinating Access to a Local Named Pipe with Semaphores ΓòÉΓòÉΓòÉ
When a process writes to a named pipe, the process at the other end (or handle)
of the pipe might require notification that data is available to be read.
Similarly, when a process reads from a named pipe, the process at the other end
might require notification that write space has become available. As long as
the communicating processes are on the same computer system, shared event
semaphores and muxwait semaphores can be used to provide this notification.
Using shared semaphores for this purpose is more efficient than dedicating a
thread to periodically poll each pipe, particularly when a server process is
communicating with a large number of client processes. Whenever data is
available in the pipe, the system posts a semaphore to the server or client
(whichever is reading from the pipe). This means that the reading process can
use DosWaitEventSem or DosWaitMuxWaitSem to wait for data to arrive, rather
than devote a thread to periodically polling the pipe.
A process associates a semaphore with a named pipe by using DosSetNPipeSem.
First, create an event semaphore with DosCreateEventSem, specifying the initial
state of the semaphore as reset. Then call DosSetNPipeSem to attach the event
semaphore to a particular named-pipe handle. Up to two event semaphores can be
attached to each named pipe, one for the server process and one for the client
process. If there is already a semaphore associated with one end of the pipe,
that semaphore is replaced. A process can check the state of the semaphores by
using DosQueryNPipeSemState.
The server or client process must then call DosWaitEventSem. The particular
thread that calls this function will block until data is either read from or
written to the pipe. At that time, the system posts the event semaphore,
enabling the blocked thread to resume its execution.
If a process requires notification whenever any one of multiple named pipes has
been written to or read from, it can either attach the same event semaphore to
multiple pipes, or it can create a muxwait semaphore:
If the same event semaphore is attached to multiple pipes, then the
KeyHandle parameter of DosSetNPipeSem is used to assign a unique value to
each pipe. After the event semaphore has been posted, the process calls
DosQueryNPipeSemState. This function returns information about each of
the named pipes that are attached to the semaphore, including key-handle
values. The calling process can use this information to determine which
one of the named pipes has either data or write space available.
To use a muxwait semaphore, a process first creates an event semaphore
for each of the pipes that it wants to monitor. Each semaphore must then
be attached to a pipe by calling DosSetNPipeSem. Again, a unique
key-handle value must be assigned to each pipe.
Next, the process calls DosCreateMuxWaitSem to create the muxwait
semaphore, specifying DCMW_WAIT_ANY as one of the flAttr flags. The
muxwait semaphore will consist of a linked list of the previously created
event semaphores.
The process calls DosWaitMuxWaitSem so that it will be notified the next
time data is read from or written to any of the pipes. However, it must
call DosQueryNPipeSemState to determine which one of the pipes is ready
to be read from or written to.
ΓòÉΓòÉΓòÉ 4.2. Using Unnamed Pipes ΓòÉΓòÉΓòÉ
Unnamed pipes are useful in applications that transfer data between related
processes. They are commonly used to control the input and output of child
processes by redirecting the standard input and output of the child process to
a pipe controlled by the parent process.
Note: In the example code fragments that follow, error checking was left out
to conserve space. Applications should always check the return code that
the functions return. Control Program functions return an APIRET value.
A return code of 0 indicates success. If a non-zero value is returned,
an error occurred.
ΓòÉΓòÉΓòÉ 4.2.1. Creating Unnamed Pipes ΓòÉΓòÉΓòÉ
DosCreatePipe creates an unnamed pipe. Two handles are returned: one for read
access to the pipe and one for write access. The pipe size specified is
advisory; its actual size is dependent on the amount of available memory. If
the size parameter is 0, the pipe is created with the default size, which is
512 bytes.
This example creates an unnamed pipe. The current process can use the unnamed
pipe for communication between itself and a child process.
#define INCL_BASE /* Queue values */
#include <os2.h>
#include <stdio.h>
HFILE hfReadHandle; /* Pointer to the read handle */
HFILE hfWriteHandle; /* Pointer to the write handle */
ULONG ulPipeSize; /* Pipe size */
APIRET ulrc; /* Return code */
ulPipeSize = 4096; /* Ask for 4KB of internal storage */
/* for the pipe */
ulrc = DosCreatePipe(&hfReadHandle,
&hfWriteHandle,
ulPipeSize);
if (ulrc != 0) {
printf("DosCreatePipe error: return code = %ld",
ulrc);
return;
}
On successful return, the ReadHandle variable contains the read handle for the
pipe, and the WriteHandle variable contains the write handle for the pipe.
After a process creates a pipe, any child process started with DosExecPgm
inherits the pipe handles. Using shared memory, the parent process can pass one
of the pipe handles to the child process; thus, one process can store data in
the pipe and the other can retrieve it.
ΓòÉΓòÉΓòÉ 4.2.2. Reading from and Writing to Unnamed Pipes ΓòÉΓòÉΓòÉ
Applications use the OS/2 file system functions to read from and write to
unnamed pipes.
The handles returned by DosCreatePipe are used as file handles to DosRead and
DosWrite.
To write (or add data) to an unnamed pipe, call DosWrite, specifying the write
handle of the pipe in DosWrite's file handle parameter. DosWrite requests to a
pipe are processed in the order in which they are made. Multiple calls to
DosWrite can be made before data is read (or removed) from the pipe. When the
pipe becomes full, write requests are blocked until space is freed by read
requests.
When the pipe is too full to hold the entire contents of the write request, the
portion that will fit is written to the pipe before the writer is blocked.
To read from a pipe, call DosRead, specifying the read handle of the pipe in
DosRead's file handle parameter. Subsequent calls to DosRead can empty the pipe
if no further calls to DosWrite are made in the meantime.
Different threads writing to and reading from a pipe are not synchronized. It
is possible for the pipe reader to obtain partial contents of a write request
if the pipe becomes full during the write request.
If the process reading the pipe ends, the next DosWrite request for that pipe
returns ERROR_BROKEN_PIPE.
Calling DosClose terminates access to an unnamed pipe. However, the pipe is not
deleted from memory until all handles to the pipe have been closed, including
any handles that were defined with DosDupHandle.
ΓòÉΓòÉΓòÉ 4.2.3. Redirecting Standard I/O for Child Processes ΓòÉΓòÉΓòÉ
An application can use unnamed pipes to redirect the standard input and the
standard output for a child process.
A typical use of an unnamed pipe is to read the output of a child process. An
application creates a pipe and then duplicates the standard output handle. When
the child process is started, its standard output will be written into the
pipe, where the application can read and display it. The following code
fragment shows how to do this:
#define INCL_DOSPROCESS
#define INCL_DOSNMPIPES
#include <os2.h>
#define PIPESIZE 256
#define HF_STDOUT 1 /* Standard output handle */
HPIPE hpR, hpW;
RESULTCODES resc;
ULONG ulRead, ulWritten;
CHAR achBuf[PIPESIZE],
szFailName[CCHMAXPATH];
HFILE hfSave = -1,
hfNew = HF_STDOUT;
DosDupHandle(HF_STDOUT,
&hfSave); /* Saves standard output handle */
DosCreatePipe(&hpR,
&hpW,
PIPESIZE); /* Creates pipe */
DosDupHandle(hpW,
&hfNew); /* Duplicates standard output handle */
DosExecPgm(szFailName,
sizeof(szFailName), /* Starts child process */
EXEC_ASYNC,
(PSZ) NULL,
(PSZ) NULL,
&resc,
"DUMMY.EXE");
DosClose(hpW); /* Closes write handle to ensure */
/* Notification at child termination */
DosDupHandle(hfSave,
&hfNew); /* Brings stdout back */
/*
* Read from the pipe and write to the screen
* as long as there are bytes to read.
*
*/
do {
DosRead(hpR,
achBuf,
sizeof(achBuf),
&ulRead);
DosWrite(HF_STDOUT,
achBuf,
ulRead,
&ulWritten);
} while(ulRead);
A parent process can also use unnamed pipes to communicate with a child process
by redirecting both the standard input and the standard output for the child
process. To do this, the parent process:
1. Uses DosDupHandle to redefine the read handle of one pipe as standard
input (0000), and the write handle of the other pipe as standard output
(0001).
2. Starts the child process with DosExecPgm.
3. Uses the remaining pipe handles to read and write to the pipes.
The parent process controls the meanings for standard I/O for the child
process. Thus, when the child process uses standard I/O handles with DosRead
and DosWrite, it reads from and writes to the pipes of its parent instead of
reading from the keyboard and writing to the display.
ΓòÉΓòÉΓòÉ 4.3. Using Named Pipes ΓòÉΓòÉΓòÉ
Named pipes are useful in applications that transfer data between processes.
The processes using named pipes can be related, unrelated, or even on different
computers.
ΓòÉΓòÉΓòÉ 4.3.1. Creating Named Pipes ΓòÉΓòÉΓòÉ
The server process creates a named pipe by using DosCreateNPipe.
To create a named pipe, specify on the DosCreateNPipe function:
The name of the pipe
The access modes
The type of pipe (byte or message)
The sizes of the input and output buffers
DosCreateNPipe returns a pipe handle that can be used in subsequent pipe
operations.
Each named pipe must have a unique name of the following form:
\PIPE\PipeName
The "\PIPE\" in the name above is required, but need not be uppercase. It is
not the name of a subdirectory.
To open a pipe on a remote computer, the client process must specify the name
of the server process that opened the pipe as part of the pipe name, as
follows:
\\Server\PIPE\PipeName
"\\Server" in the name above is the name of the remote computer; again,
"\PIPE\" is required.
The name parameter must conform to the rules for OS/2 file names, but no
actual file is created for the pipe.
Named pipes created with certain access modes prevent the named pipes' clients
from using certain functions. If the named pipe is created with access mode
NP_ACCESS_INBOUND, the named pipe's client cannot use these functions:
DosCallNPipe
DosTransactNPipe
DosPeekNPipe
If the named pipe is created with access mode NP_ACCESS_OUTBOUND, the named
pipe's client cannot use these functions:
DosCallNPipe
DosTransactNPipe
DosWrite
If the named pipe's client uses an incorrect function, the function returns
error code 5 (ERROR_ACCESS_DENIED).
In the following code fragment, DosCreateNPipe creates a pipe named
\pipe\pipe1 and supplies a unique handle identifying the pipe. OpenMode is set
to NP_ACCESS_DUPLEX. This activates full duplex access to the named pipe.
There will be no inheritance to child process, and no write-through
(write-through only affects remote pipes). PipeMode is set to "NP_WMESG |
NP_RMESG | 0x01". This specifies that the pipe should be read as a message
stream for both reading and writing and an instance count of 1 (only one
instance of the named pipe can be created at a time). The pipe will block on
Read/Write if no data is available.
#define INCL_DOSNMPIPES /* Named-pipe values */
#include <os2.h>
#include <stdio.h>
UCHAR ucFileName[40]; /* Pipe name */
HPIPE hpPipeHandle; /* Pipe handle (returned) */
ULONG ulOpenMode; /* Open-mode parameters */
ULONG ulPipeMode; /* Pipe-mode parameters */
ULONG ulOutBufSize; /* Size of the out-buffer */
ULONG ulInBufSize; /* Size of the in-buffer */
ULONG ulTimeOut; /* Default value for */
/* DosWaitNPipe time-out */
/* parameter */
APIRET ulrc; /* Return code */
strcpy(ucFileName,
"\\PIPE\\PIPE1");
ulOpenMode = NP_ACCESS_DUPLEX; /* Full duplex, no inheritance, */
/* no write-through */
ulPipeMode = NP_WMESG |
NP_RMESG |
0x01; /* Block on read and write, message */
/* stream, instance count of 1 */
ulOutBufSize = 4096; /* The outgoing buffer must be 4KB in size */
ulInBufSize = 2048; /* The incoming buffer must be 2KB in size */
ulTimeOut = 10000; /* Time-out is 10 seconds (units are in milliseconds) */
ulrc = DosCreateNPipe(ucFileName,
&hpPipeHandle,
ulOpenMode,
ulPipeMode,
ulOutBufSize,
ulInBufSize,
ulTimeOut);
if (ulrc != 0) {
printf("DosCreateNPipe error: return code = %ld",
ulrc);
return;
}
Once the named pipe is created, the application can call DosConnectNPipe to
connect a client process to the pipe.
Once a client process connects to the pipe, the process can read from and
write to the pipe. The preceding example creates a byte pipe, so the process
can use DosRead and DosWrite to read from and write to the pipe.
After the client process finishes using the pipe, the server process can
disconnect the pipe by using DosDisConnectNPipe. The server process can either
connect again or close the named pipe by using DosClose.
When a server process creates a named pipe, it defines the pipe to the system
by specifying the file write-through mode, the inheritance mode, the access
and blocking modes, the pipe type, the read mode, the size of the in and out
buffers, and the instance count. The following list describes these modes,
types, and buffers.
The file write-through mode has significance only for communication with
remote client processes. When the file write-through bit is set, data is
sent across the network as soon as it is written; otherwise, OS/2 will in
some cases hold data briefly in a local buffer before sending it across
the network.
The inheritance mode specifies whether or not the pipe handle will be
inherited by a child process.
The access mode specifies the direction in which data will flow through
the pipe. The server creates an inbound pipe (a pipe with inbound access
mode) if it intends to read data from the client process, an outbound
pipe if it intends to write data to the client process, or a duplex pipe
if it intends to both read from and write to the client process.
The blocking mode specifies whether or not DosRead and DosWrite will
block when no data is available to read, or there is no room to write
data.
The pipe type is the form in which a stream of data is written to the
pipe. If the pipe is a byte pipe, the server and client processes write
data as an undifferentiated stream of bytes. If the pipe is a message
pipe, the processes write data as a stream of messages; messages are
blocks of data, each with a system-supplied header, that are written as
single units. The server and client processes define the size and format
of a message.
The read mode is the form in which data is read from the pipe. The data
in a pipe that was created as a byte pipe can only be read as bytes;
therefore, a byte pipe will always be in byte-read mode. The data in a
message pipe, however, can be read either as messages or as bytes. (If
it is to be read as bytes, DosRead skips over the message headers).
Therefore, message pipes can be in either message-read mode or byte-read
mode.
Note: The terms "byte pipe" and "message pipe" always refer to the pipe
type-the form in which data is written to the pipe. When the read
mode of a pipe is being referred to, it is always explicitly
identified as either message-read mode or byte-read mode.
The in and out buffers can be up to 64KB in size. If the pipe will be
read in message-read mode, and if the message size is known, the server
can control how many messages the buffer will hold at one time by
specifying the appropriate buffer size.
The instance count is the maximum number of instances of the named pipe
that can be created. A pipe instance is actually a separate pipe-that is,
a unique set of pipe buffers with unique handles. However, the term "pipe
instance" is used to distinguish pipes that share the same name from
pipes with different names. Because a client process uses only the name
of the pipe when opening it, the existence of multiple pipe instances is
transparent to a client process.
Creating Multiple Instances of a Named Pipe
Although each named pipe must have a unique name, a server process can create
multiple instances of a pipe, all of which have the same name. A pipe instance
is actually a separate pipe-that is, a unique set of pipe buffers with unique
handles.
The ability to create multiple pipe instances enables the server to
communicate with multiple client processes at the same time. Because a client
process uses only the name of the pipe when opening it, the existence of
multiple pipe instances is transparent to a client process.
The ICount parameter of DosCreateNPipe specifies the maximum number of named
pipe instances that can be created. (An unlimited number can also be
specified.) This parameter is specified only when the first instance of a
named pipe is created; any subsequent attempt to redefine the instance count
will be ignored.
If the instance count is greater than 1, the server process can create
additional pipe instances by specifying the same pipe name in subsequent calls
to DosCreateNPipe. Generally, the attributes of the subsequent pipe instances
are defined to be the same as those of the original pipe instance, because a
client process that requests the pipe has no way of controlling which pipe
instance will be assigned to it.
After an additional pipe instance has been created, it is used in the same
manner as the original pipe instance. That is, the same sequence of named
pipe functions is used in the control or management of all named pipe
instances. (See Steps in Managing Server-Client Transactions for more
information.)
Note: If all of the instances of a named pipe are in use when a client calls
DosOpen, ERROR_PIPE_BUSY is returned. However, the client can wait for
an instance of that pipe to become available by calling DosWaitNPipe.
Multiple instances of a named pipe can be created by different processes. That
is, multiple server processes can create and use instances of the same named
pipe to communicate with their clients.
ΓòÉΓòÉΓòÉ 4.3.2. Opening Named Pipes ΓòÉΓòÉΓòÉ
A client process can open the client end of a named pipe by using DosOpen.
DosOpen opens the client end of a pipe by name and returns a handle. The
application must use the appropriate pipe name and access modes to open the
pipe for reading, writing, or both. (To open a pipe on a remote computer, the
client process must also specify the name of the computer system as part of the
pipe name, as follows:
\\ComputerName\PIPE\PipeName.)
If a pipe name includes a remote LAN server name, DosOpen attempts to open the
pipe on a remote computer. The server process can then read input from the
client process through the pipe.
The following code fragment opens a remote pipe, reads from the standard input
(usually the keyboard), and sends the information to the server process through
the pipe:
#define INCL_DOSQUEUES /* Queue values */
#include <os2.h>
#define PIPESIZE 256
#define SERVER_PIPE_NAME "\\\\myserver\\pipe\\mypipe"
#define HF_STDIN 0 /* Standard input handle */
HPIPE hp;
BYTE abBuf[PIPESIZE];
ULONG ulAction, ulRead, ulWritten;
APIRET ulrc;
ulrc = DosOpen(SERVER_PIPE_NAME,
&hp,
&ulAction,
0,
FILE_NORMAL,
FILE_OPEN,
OPEN_ACCESS_READWRITE |
OPEN_SHARE_DENYNONE,
(PEAOP) NULL);
if (ulrc)
DosExit(EXIT_PROCESS,
0); /* Open pipe failed */
do { /* Open pipe succeeded */
DosRead(HF_STDIN,
abBuf,
sizeof(abBuf),
&ulRead);
DosWrite(hp,
abBuf,
ulRead,
&ulWritten); /* Writes to the pipe */
} while (ulRead > 2); /* Stop on a blank line */
DosClose(hp);
The client process checks the return value from DosOpen to verify that the pipe
was actually opened. If the server process has not yet created the pipe,
DosOpen returns an error. When the client process finishes using the pipe, it
closes the pipe by using DosClose.
When a named pipe is opened, its initial state is set by the system to block
read and write operations (blocking mode), and to read data as a byte stream
(byte-read mode). However, the client can change these modes by calling
DosSetNPHState. A call to DosOpen fails if all instances of the named pipe are
already open.
The open also fails if the pipe has been closed by a client, but the server has
not called DosDisConnectNPipe (to acknowledge the client's close), followed by
DosConnectNPipe (to prepare the pipe for the next client). In both of these
situations, ERROR_PIPE_BUSY is returned.
If all instances of a named pipe are busy, a client process can call
DosWaitNPipe to wait for an instance to become available before it calls
DosOpen again.
After a pipe instance has been opened by a client, that same instance cannot be
opened by another client at the same time. However, the opening process can
duplicate the handle as many times as desired by calling DosDupHandle. This
enables child processes to share access to a pipe instance with a parent
process.
The access-mode and sharing-mode fields that are specified for DosOpen must be
the same as those that were specified by the server when it created the pipe
with DosCreateNPipe.
ΓòÉΓòÉΓòÉ 4.3.3. Reading from Named Pipes ΓòÉΓòÉΓòÉ
Both the server and the client processes read data from a pipe by calling
DosRead. The server reads from the handle that was returned when it created the
pipe with DosCreateNPipe, and the client reads from the handle that was
returned to it by DosOpen.
When a pipe is created, the PipeMode parameter is used to specify both the pipe
type and the read mode for the server end of the pipe:
A byte pipe can be read-only in byte-read mode. (DosCreateNPipe and
DosSetNPHState return ERROR_INVALID_PARAMETER if message-read mode is
specified for a byte pipe.) In byte-read mode, all currently available
data is returned, up to the buffer size specified by DosRead.
A message pipe can be read in either byte-read mode or message-read mode,
as follows:
- When a message pipe is read in byte-read mode, the message headers
are skipped, and the pipe is read as if it were a byte pipe.
- When a message pipe is read in message-read mode, each message is
read either in its entirety, or not at all, depending on the size of
the message and the buffer length:
-- If the buffer length that was specified for DosRead is larger
than the next available message, then only that message is
read, and the Bytes-Read parameter indicates the size of the
message.
-- If the buffer length for DosRead is smaller than the next
available message, DosRead returns the number of bytes
requested and ERROR_MORE_DATA. Subsequent calls to DosRead are
blocked until the rest of the message can be transferred.
(DosPeekNPipe can be used to find out how many bytes are left
in the message.)
The PipeMode parameter of DosCreateNPipe also specifies the blocking mode for
the server end of the pipe:
If nonblocking mode was specified, DosRead returns immediately with 0 in
the Bytes-Read parameter if no data is available.
If blocking mode was specified, DosRead blocks until data is available;
the only time it will return with 0 in the Bytes-Read parameter is if it
reaches end-of-file.
DosRead works the same for both ends of the pipe. However, the read mode and
blocking mode are not necessarily the same for the client end of the pipe as
they are for the server end, because DosOpen always opens the CLIENT end in
byte-read mode and blocking mode.
The read mode and blocking mode for either end of the pipe can be changed by
calling DosSetNPHState. The pipe type, however, is always the same for both
the server and client ends of the pipe, and it cannot be changed.
ΓòÉΓòÉΓòÉ 4.3.4. Writing to Named Pipes ΓòÉΓòÉΓòÉ
Both the server and the client processes write to a pipe by calling DosWrite.
The server writes to the handle that was returned to it by DosCreateNPipe, and
the client writes to the handle that was returned to it by DosOpen.
Either bytes or messages can be written, depending on whether the pipe was
created as a byte pipe or as a message pipe.
Named pipes created with the NP_ACCESS_OUTBOUND access mode cannot use the
DosWrite function. If the named pipe's client uses the DosWrite function, the
function returns error code 5 (ERROR_ACCESS_DENIED).
An attempt to write to a pipe whose other end has been closed returns
ERROR_BROKEN_PIPE or, if the other end was closed without without reading all
pending data, ERROR_DISCARDED.
When a process writes to a message pipe, the buffer-length parameter for
DosWrite holds the size of the message that the process is writing. Because
DosWrite automatically encodes message lengths in the pipe, applications do not
have to encode this information in the data buffers.
The action taken by DosWrite depends on the blocking mode of the pipe, which is
not necessarily the same for the server and client ends of the pipe. For the
server process, the blocking mode of the pipe is specified when the pipe is
created. For a client process, the blocking mode is automatically set to
blocking when the pipe is opened. The blocking mode can also be reset by
calling DosSetNPHState.
If the end of the message pipe that is being written to is in blocking mode,
DosWrite does not return until all of the requested bytes have been written.
(It might have to wait for the first part of the message to be read before it
can write the rest of the message.)
If the message pipe is in nonblocking mode, DosWrite takes the following
action:
If the message is larger than the pipe buffer, DosWrite blocks until the
entire message has been written. (Again, it might have to wait for the
first part of the message to be read before it can write the rest of the
message.)
If the message is smaller than the pipe buffer, but there is currently
not enough room in the buffer, DosWrite returns with a value of 0 in the
Bytes-Written parameter.
If a byte pipe is in nonblocking mode, and if there is more data to be written
than will fit in the pipe buffer, then DosWrite writes as many bytes as will
fit in the buffer and returns the number of bytes that were actually written.
If a process tries to write to a pipe whose other end is closed,
ERROR_BROKEN_PIPE is returned.
ΓòÉΓòÉΓòÉ 4.3.5. Synchronizing Named Pipe Dialogs ΓòÉΓòÉΓòÉ
Communicating processes can synchronize their named pipe dialogs by calling
DosResetBuffer after each call to DosWrite.
When used with external files, DosResetBuffer flushes the buffer cache of the
requesting process to disk. When used with named pipes, this function blocks
the calling process at one end of the pipe until the data the calling process
has written to the pipe has been successfully read at the other end of the
pipe.
ΓòÉΓòÉΓòÉ 4.3.6. Determining Pipe Status ΓòÉΓòÉΓòÉ
DosQueryNPHState and DosQueryNPipeInfo can be used to obtain information about
named pipes.
DosQueryNPHState
A client process can read data from the pipe, write data to the pipe, or both,
depending on the access mode specified when the pipe was created. To check the
current access mode, the client process can call DosQueryNPHState.
The following code fragment shows how to use DosQueryNPHState to obtain
information about a named pipe:
#define INCL_DOSNMPIPES /* Named-pipe values */
#include <os2.h>
#include <stdio.h>
HPIPE hpHandle; /* Pipe handle */
ULONG ulPipeHandleState; /* Pipe-handle state */
APIRET ulrc; /* Return code */
ulrc = DosQueryNPHState(hpHandle, &ulPipeHandleState);
if (ulrc != 0) {
printf("DosQueryNPHState error: return code = %ld",
ulrc);
return;
}
On successful return, PipeHandleState will contain information that describes
the nature of the named pipe.
DosQueryNPHState returns the following information about the pipe handle and
the attributes of the pipe:
The end of the pipe that the handle is for (server or client end)
The pipe type (byte pipe or message pipe)
The instance count
The blocking mode (blocking or nonblocking)
The read mode (byte-read mode or message-read mode)
The values for pipe type and instance count cannot be changed, so they are
always the same as those that were specified when the pipe was created with
DosCreateNPipe. The information returned for blocking mode and read mode,
however, can come from different sources:
If the handle is for the server end of the pipe, then the blocking mode
and the read mode were set with DosCreateNPipe, but could have been reset
with DosSetNPHState.
If the handle is for the client end of the pipe, then the blocking mode
and the read mode were set to "blocking" and "byte-read" by the system
when the client called DosOpen. However, again, they could have been
reset with DosSetNPHState.
The pipe attributes are described in more detail in Creating Named Pipes.
An application can use DosSetNPHState to change the wait mode and the read
mode. The pipe cannot be changed to no-wait mode when another thread is
blocked on a read or write operation to the same end of the pipe.
DosQueryNPipeInfo
More detailed information about a named pipe can be obtained by using
DosQueryNPipeInfo. This function returns information in a PIPEINFO data
structure that includes the name of the pipe, the current and maximum instance
counts (the current number of pipes and the maximum number of times the pipe
can be created), the size of the input and output buffers for the pipe, and
the pipe identifier of the client process.
The following code fragment shows how to use DosQueryNPipeInfo:
#define INCL_DOSNMPIPES /* Named-pipe values */
#include <os2.h>
#include <stdio.h>
HPIPE hpHandle; /* Pipe handle */
ULONG ulInfoLevel; /* Pipe data required */
PIPEINFO pipInfoBuf; /* Pipe information data structure */
ULONG ulInfoBufSize; /* Pipe data-buffer size */
APIRET ulrc; /* Return code */
ulInfoLevel = 1; /* Ask for standard level of pipe info */
ulInfoBufSize = sizeof(PIPEINFO); /* Length of pipe info data structure */
ulrc = DosQueryNPipeInfo(hpHandle,
ulInfoLevel,
&pipInfoBuf,
ulInfoBufSize);
if (ulrc != 0) {
printf("DosQueryNPipeInfo error: return code = %ld",
ulrc);
return;
}
On successful return, the pipe information data structure contains a set of
information describing the nature and the current state of the named pipe.
DosQueryNPipeInfo returns level 1 or level 2 file information for the pipe.
Level 1 information includes the following:
The actual sizes of the in-buffer and out-buffer
The maximum number of pipe instances permitted
The current number of pipe instances
The length of the pipe name
The ASCIIZ name of the pipe, including \\ComputerName if the pipe is in a
remote computer system.
Level 2 information consists of a unique 2-byte identifier for each of
the pipe's client processes.
ΓòÉΓòÉΓòÉ 4.3.7. Examining the Contents of Named Pipes ΓòÉΓòÉΓòÉ
DosPeekNPipe examines the current contents of a named pipe.
Named pipes created with the NP_ACCESS_INBOUND access mode cannot use the
DosPeekNPipe function. If the named pipe's client uses the DosPeekNPipe
function, the function returns error code 5 (ERROR_ACCESS_DENIED).
It is similar to DosRead, except that DosPeekNPipe does not remove data from
the pipe. In addition, DosPeekNPipe never blocks, even if the pipe is in
blocking mode; if the pipe cannot be accessed immediately, ERROR_PIPE_BUSY is
returned.
Because DosPeekNPipe does not block, it returns only what is currently in the
pipe. Thus, if a message pipe is being examined, only a portion of a message
might be returned, even though the specified buffer length could accommodate
the entire message.
DosPeekNPipe also returns the state of the pipe. A named pipe can be in any of
the following states: Connected, Disconnected, Listening, Closing.
The following code fragment shows how to use DosPeekNPipe:
#define INCL_DOSNMPIPES /* Named-pipe values */
#include <os2.h>
#include <stdio.h>
HPIPE hpHandle; /* Pipe handle */
UCHAR ucBuffer[200]; /* Address of user buffer */
ULONG ulBufferLen; /* Buffer length */
ULONG ulBytesRead; /* Bytes read (returned) */
struct _AVAILDATA BytesAvail; /* Bytes available (returned) */
ULONG ulPipeState; /* Pipe state (returned) */
APIRET ulrc; /* Return code */
ulBufferLen = 200; /* Length of the read buffer */
ulrc = DosPeekNPipe(hpHandle,
ucBuffer,
ulBufferLen,
&ulBytesRead,
&BytesAvail,
&ulPipeState);
if (ulrc != 0) {
printf("DosPeekNPipe error: return code = %ld",
ulrc);
return;
}
On successful return, the input buffer Buffer will contain up to the first 200
bytes from the named pipe, BytesRead will contain the number of bytes read into
Buffer, BytesAvail will contain the total number of bytes that were available
in the pipe, and PipeState will contain a value indicating the state of the
named pipe.
ΓòÉΓòÉΓòÉ 4.3.8. Closing Named Pipes ΓòÉΓòÉΓòÉ
DosClose closes the specified pipe handle. When all of the handles that access
one end of a pipe have been closed, the pipe is referred to as a broken pipe.
If the client end of the pipe closes, no other process can reopen the pipe
until the server calls DosDisConnectNPipe (to acknowledge the client's close)
followed by DosConnectNPipe (to prepare the pipe for a new client). Until it
calls DosDisConnectNPipe, the server will receive ERROR_EOF if it tries to read
from the pipe, and ERROR_BROKEN_PIPE if it tries to write to it. Clients that
attempt to open the pipe receive ERROR_PIPE_BUSY.
If the server end closes when the client end is already closed, the pipe is
deallocated immediately; otherwise, the pipe is not deallocated until the last
client handle is closed.
The following code fragment shows how to close a named pipe. Assume that a
previous call to DosOpen provided the named pipe handle that is contained in
Handle.
#define INCL_DOSNMPIPES /* Named-pipe values */
#include <os2.h>
#include <stdio.h>
HPIPE hpHandle; /* Pipe handle */
APIRET ulrc; /* Return code */
ulrc = DosDisConnectNPipe(hpHandle);
if (ulrc != 0) {
printf("DosDisConnectNPipe error: return code = %ld",
ulrc);
return;
}
ΓòÉΓòÉΓòÉ 5. Program Execution Control ΓòÉΓòÉΓòÉ
Multitasking is the ability of OS/2 to manage the execution of more than one
application at a time. A multitasking operating system, such as OS/2 enables
users to run many applications simultaneously.
For the programmer, OS/2 supports two types of multitasking. An application can
start other programs, in separate processes, that will execute concurrently
with the application. These programs can be a new copy of the application, a
related program that is designed to work with the application, or an unrelated
program. Running multiple processes is the first type of multitasking provided
for programmers.
Running multiple threads is the second type of multitasking supported by OS/2.
OS/2 enables applications to run multiple threads of execution within the same
process; separate activities can be multitasked within the application. An
example of multiple-thread multitasking would be for the application to
dispatch a separate subroutine to load a file from the disk, and have the
subroutine execute at the same time the main program continues to monitor and
respond to user input.
This chapter describes processes, threads, and sessions, and the OS/2 functions
used to create and manage them. Additionally, there is a section describing CPU
scheduling.
The following topics are related to the information in this chapter:
Memory
Semaphores
Queues
Pipes
Exception handling
Debugging
ΓòÉΓòÉΓòÉ 5.1. About Program Execution Control-Thread, Processes, and Sessions ΓòÉΓòÉΓòÉ
To successfully use multitasking-multiple processes and multiple threads-in
your programs, you need to understand the difference between a thread, a
process, and a session.
A thread is a dispatchable unit of execution that consists of a set of
instructions, related CPU register values, and a stack. Each process has at
least one thread, called the main thread or thread 1, and can have many threads
running simultaneously. The application runs when OS/2 gives control to a
thread in the process. The thread is the basic unit of execution scheduling.
A process is the code, data, and other resources-such as file handles,
semaphores, pipes, queues, and so on-of an application in memory. OS/2
considers every application it loads to be a process. System resources are
allocated on a per-process basis.
A session is one (or more) processes with their own virtual console. (A virtual
console is a virtual screen-either a character-based, full screen or a
Presentation Manager window-and buffers for keyboard and mouse input.)
OS/2 supports up to 255 concurrent sessions and up to 4095 processes. OS/2
supports a system-wide maximum of 4095 threads, but the number of threads
available in a single process will be lower, and will vary, because of resource
usage within the process.
ΓòÉΓòÉΓòÉ 5.1.1. Threads ΓòÉΓòÉΓòÉ
Applications always have at least one thread of execution-thread 1. Using
multiple threads of execution, an application can do several things at the same
time.
For example, a simple Presentation Manager application consists of a single
process with two threads:
A user interface thread that listens and responds to user requests, and
that queues work for the second thread
A processing thread that handles lengthy processing
OS/2 creates the first thread of execution for a process when it starts the
executable file. To create another thread of execution, a thread calls
DosCreateThread, specifying the address within the program module where the
thread begins asynchronous execution. Although a thread can execute any part
of the application, including a part being executed by another thread, threads
typically are used to execute separate sections of the application. By using
several threads, the system can distribute the available CPU time and enable
an application to carry out several tasks simultaneously. For example, an
application can load a file and prompt the user for input at the same time.
Each thread in a process has a unique stack and register context. Threads
shares the resources of the process with the other threads in the process. For
example, threads in the same process have access to the memory spaces of other
threads within the process. However, threads of one process do not have access
to the data spaces of other processes.
Each thread has a priority, that determines the amount of CPU time the thread
is allocated. Threads inherit the priority of the thread that creates them.
The priority of a thread can be changed by the application; see Changing the
Priority of a Thread for details.
An application can use DosSuspendThread and DosResumeThread to suspend and
resume the execution of a given thread. When an application suspends a thread,
the thread remains suspended until the application calls DosResumeThread.
When an application has more than one thread, it might be necessary to ensure
that one thread is finished executing before another thread uses a shared
resource, such as a disk file. DosWaitThread causes the application to wait
until a specific thread has finished. DosWaitThread can also be used to
determine the state of a thread; the function can return immediately with an
error value if the identified thread is still running.
A thread ends when it calls DosExit.
ΓòÉΓòÉΓòÉ 5.1.2. Processes ΓòÉΓòÉΓòÉ
An OS/2 application that has been loaded into memory and prepared for execution
is called a process. As mentioned earlier, a process consists of the code,
data, and other resources (for example, open file handles) that belong to the
application. Each process has at least one thread, called the main thread or
thread 1.
When OS/2 runs an application, it confirms that the process code and data are
in memory and that the main thread's registers and stack are set before
starting the application. Each application has access to all resources of the
computer, such as memory, disk drives, screen, keyboard, and the CPU itself.
The system carefully manages these resources so that applications can access
them without conflict.
A process can have more than one thread. OS/2 creates the first thread of
execution for a process when it starts the executable file. More threads can be
created with DosCreateThread. Each thread runs independently, with its own
stack and register values. Unless the application changes a thread's priority,
each thread gets a slice of the CPU in a round-robin strategy. All the threads
in a process share the application's globally defined variables and other
resources (open file handles, and so on).
A process or thread ends when it calls DosExit. OS/2 automatically closes any
files or other resources left open by the process when the process ends. When a
thread ends, however, any open resources remain open until another thread
closes them or the process ends. A process can direct OS/2 to carry out other
actions when the process ends, by using DosExitList to create a list of
termination functions. OS/2 calls the termination functions, in the order
given, when the process is about to end. If the thread has registered any
exception handlers, the exception handlers will also be called before the
thread ends.
ΓòÉΓòÉΓòÉ 5.1.2.1. Creating Processes ΓòÉΓòÉΓòÉ
An application can load and execute other applications by using DosExecPgm. The
new application, once loaded, is called a child process. The process that
starts the new application is called the parent process.
A child process is like any other process. It has its own code, data, and
threads. The child process inherits the resources-such as file handles, pipes,
and queues-that belong to the parent process at the time the child process is
created, although not necessarily with the same access rights. The parent
process can place restrictions on the access of the child process to these
resources:
Files are inherited except for files that were opened with no inheritance
indicated.
Pipes are inherited.
Assuming that the parent process gives the child process appropriate access
rights, the child process can use the inherited resources without preparing
them. For example, if the parent process opens a file for reading and then
starts a child process, the child process can read from the file immediately;
it does not have to open the file. However, once the child process is created
additional resources that the parent process creates are not available to the
child process. Similarly, resources the child process creates are not
available to the parent process.
The parent process also has control over the meanings of standard input,
output, and error for the child process. For example, the parent can write a
series of records to a file, open the file as standard input, open a listing
file as standard output, and then execute a sort program that takes its input
from standard input and writes to standard output.
Note that memory is not included in the list of things that a child process
can inherit from its parent process. The child process is created with its own
process address space that is separate and distinct from the memory of the
parent process. A new linear address space is built for the new process. The
only way for a parent process and a child process to access the same memory is
to set up a shared memory area.
The executable file of the child process can be started either synchronously
or asynchronously to the parent process. If the parent process starts the
child process running synchronously, the parent process is suspended and waits
until the child process ends before continuing. A child process running
asynchronously executes independently of the parent process (that is, both run
at the same time). The parent process specifies how the child process is to
run by setting a parameter in the call to DosExecPgm.
The OS/2 command processor, CMD.EXE, starts most child processes
synchronously. The parent process waits for each child process to end before
it prompts the user for the next command. The command processor also enables
the user to start asynchronous applications by using the DETACH command. When
the user detaches an application, the command processor starts the application
asynchronously, in the background, and continues to prompt for input.
ΓòÉΓòÉΓòÉ 5.1.2.2. Process Termination ΓòÉΓòÉΓòÉ
A parent process can use DosWaitChild to determine the termination status of a
child process that is running independently. The parent process can have one of
its threads call DosWaitChild to wait for completion of the child process while
other threads of the parent continue processing.
If the child has started another process, DosWaitChild waits for the completion
of any grandchild processes before returning, but does not report their status.
If the specified child process has multiple threads, DosWaitChild returns the
result code of the last DosExit request.
If there are no child processes, either active or ended with a return code,
DosWaitChild returns with an error code. If no child processes have ended,
DosWaitChild can optionally wait until one ends before returning to the parent.
ΓòÉΓòÉΓòÉ 5.1.2.3. Process Exit Lists ΓòÉΓòÉΓòÉ
Because any process can end any other process for which it has a process
identifier, applications might lose information if a process ends the
application before it can save its work. To prevent this loss of data, you can
create a list of functions to clean up data and files before OS/2 ends the
process. This list is called an exit list. OS/2 maintains an exit list for each
process and calls these functions whenever the application is ended, whether by
another process or by itself.
You call DosExitList to add to the exit list a routine that is to be given
control when a process is ended (or finishes its execution). Multiple routines
can be added to the list. When the process is ending, OS/2 transfers control to
each address on the list.
Exit-list functions perform clean-up operations on resources. For example, an
exit-list function can be used in a dynamic link library module to free
resources or clear flags and semaphores when a client program has ended.
ΓòÉΓòÉΓòÉ 5.1.3. Multitasking with Threads and Multitasking with Processes ΓòÉΓòÉΓòÉ
The creation and termination of a process is relatively slow compared to the
creation and termination of a thread, and is more costly in terms of system
resources.
For example, sharing data and resources between processes requires shared
memory and the mechanisms of interprocess communication; threads, on the other
hand, have full access to the memory and other resources that belong to the
process the threads are part of and can be coordinated using semaphores. For
these reasons, thread-to-thread task context switches are faster than
process-to-process context switches.
Because OS/2 can create and execute threads more quickly than processes, the
preferred multitasking method for applications is to distribute tasks among
threads in the same process instead of among processes.
ΓòÉΓòÉΓòÉ 5.1.4. Sessions ΓòÉΓòÉΓòÉ
OS/2 uses sessions to help the user move from one application to the next
without disrupting the screen display of an application.
A session consists of at least one process and a virtual console-buffers for
keyboard and mouse input and either a character-based, full screen or a
Presentation Manager window. When the system creates a session, the process in
the session displays output in the screen or window. The user can view the
output and supply input by moving to the session. The user moves to a session
by pressing the Alt+Esc key combination, by selecting the title of the session
from the Window List, or, for windowed sessions, by clicking the mouse in the
session window.
A child session is under the control of the session that creates it. The
session that starts the child session is called the parent session. Any process
in the parent session can exercise control over a child session.
An unrelated session is not under the control of the session that started it.
The process that creates the unrelated session cannot select it, make it
nonselectable, bind it, or end it, nor can any other session. DosStartSession
does not even return a session identifier when an unrelated session is started.
Unrelated sessions are controlled entirely by the user. When OS/2 starts new
sessions, it starts them as unrelated sessions.
ΓòÉΓòÉΓòÉ 5.1.4.1. Creating Sessions ΓòÉΓòÉΓòÉ
A process creates a new session by using DosStartSession. DosStartSession
enables an application to start another session and to specify the name of the
application to be started in that session.
DosStartSession also specifies which of the five session types is to be
started:
Full screen, protect mode
Text windowed, protect mode
Presentation Manager (PM)
Full screen DOS Session
Windowed DOS Session
Protect mode applications run in full screen and text windowed sessions, PM
and AVIO applications run in PM windows, and DOS applications run in full
screen DOS Sessions and windowed DOS Sessions.
OS/2 applications running in any of the OS/2 session types-full screen, text
windowed, and PM-can start sessions of any other type, including DOS Sessions.
DOS Session applications cannot start other sessions.
An application can start another process in a separate session when the
application will not manage any I/O done by the process. For example, an
application that starts an unrelated application could start it in a separate
session.
A session can be started as a related or an unrelated session. A related
session is called a child session, and the session starting the child session
is called the parent session. An application can control its child sessions by
using the session identifier returned by DosStartSession with the
DosSetSession, DosSelectSession, and DosStopSession. If an application starts
an unrelated session, the new session cannot be controlled by the application.
The Related field in the STARTDATA structure specifies whether the new session
is related to the session calling DosStartSession.
After a process has started a child session, no other process in its session
can start a child session until all dependent sessions started by this process
have ended.
When a session is created, the title specified in the function call (or the
application name if no title is specified) is added to the Window List.
DosStartSession can be used to start either a foreground or a background
session, but a new session can be started in the foreground only when the
caller's session, or one of the caller's descendant sessions, is currently
executing in the foreground. The foreground session for windowed applications
is the session of the application that owns the window focus.
Termination Queues
The parent session must create a termination queue prior to specifying the
queue name in a call to DosStartSession. OS/2 will continue to notify the
parent session through the specified queue as long as the session calling
DosStartSession remains a parent session. In other words, when all the child
sessions for a particular parent session end, the termination queue is closed
by OS/2. An existing queue name must be specified on the next DosStartSession
call if the caller wants to continue receiving termination notification
messages.
OS/2 writes a data element to the specified queue when any child session ends.
The queue is posted regardless or who ends the child session (the child, the
parent, or the user) and whether the termination is normal or abnormal.
A parent session calls DosReadQueue to receive notification when a child
session has ended. The word that contains the request parameter, returned by
DosReadQueue, will be 0. The data element has the following format:
Termination Queue Element Format
ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
ΓöéSize ΓöéDescription Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéWORD ΓöéSession ID of the child session that ended Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéWORD ΓöéResult code Γöé
ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
The process that originally called the DosStartSession request should call
DosReadQueue, with the NOWAIT parameter set to 0. This is the only process
that has addressability to the notification data element. After reading and
processing the data element, the caller must free the segment containing the
data element by calling DosFreeMem.
When a child session ends, the result code returned in the termination queue's
data element is the result code of the program specified in the
DosStartSession call, providing either one of the following is true:
The program was run directly, with no intermediate secondary command
processor
The program is run indirectly through a secondary command processor, and
the /C parameter is specified
When a child session is running in the foreground at the time it ends, the
parent session becomes the new foreground session. When a parent session ends,
any child sessions are ended. When an unrelated session ends in the
foreground, OS/2 selects the next foreground session.
ΓòÉΓòÉΓòÉ 5.1.4.2. Child Session Control ΓòÉΓòÉΓòÉ
A session can be either a child session or an unrelated session. A child
session is under the control of the processes in the session that creates it
(the parent session). A process can select, set, or stop a child session by
using DosSelectSession, DosSetSession, or DosStopSession, respectively.
DosStartSession returns a unique session identifier for the child session for
use in these functions.
A session can run in either the foreground or background. A process can create
a foreground session only if the creating process or one of its descendant
sessions is executing in the current foreground session. A process can move a
child session to the foreground by selecting the child session using the
session identifier and calling DosSelectSession. A process can make a child
session nonselectable by using DosSetSession to change the SelectInd field in
the STATUSDATA structure. This prevents the user from selecting the session
from the Window List but does not prevent a process from selecting the child
session by using DosSelectSession.
A process can bind a child session to its own session by using DosSetSession.
Binding a session causes that session to move to the foreground whenever the
user selects the parent session from the Window List.
A parent session can use a session identifier with the DosSetSession function
only if the parent session created the child session associated with that
identifier. It cannot use identifiers for child sessions created by other
parent processes. This is true for all session management functions.
Although a child session is related to the session that started it, the
processes in the child and original sessions are not related. This means that
even though DosStartSession supplies the process identifier of the process in
the child session, the process identifier cannot be used with OS/2 functions
such as DosSetPriority.
ΓòÉΓòÉΓòÉ 5.1.4.3. Child Session Termination ΓòÉΓòÉΓòÉ
A parent session can stop a child session by using DosStopSession. Stopping the
child session ends the processes in that session. It also stops any sessions
related to the child session. If a child session is in the foreground when it
is stopped, the parent session becomes the foreground session. DosStopSession
breaks any bond that exists between the parent session and the specified child
session.
A process running in the session specified in the call to DosStopSession can
ignore the request to end. If this happens, DosStopSession still returns 0
(indicating success). The only way to be certain that the child session has
ended is to wait for notification through the termination queue specified in
the call to DosStartSession. OS/2 writes a data element into the specified
queue when the child session ends. The process in the parent session must call
DosReadQueue to retrieve this data element, which contains the session
identifier for the child session and the return value for the process in the
child session. Only the process that created the child session can read the
data element.
ΓòÉΓòÉΓòÉ 5.2. About CPU Scheduling ΓòÉΓòÉΓòÉ
OS/2 performs prioritized, preemptive, multitasking. Prioritized means that
OS/2 does not divide CPU time equally among all threads. All programs do not
get equal access to the CPU. A prioritizing, time-slicing strategy is used to
allocate access to the CPU among competing threads. Each thread has a priority
and OS/2 runs the highest priority thread that is ready to run. Programs with
higher priorities (a real-time robotic application, for example), are given
access to the CPU before programs with lower priorities. If a thread with a
higher priority than the currently running thread becomes ready to run, the
current thread is stopped immediately, or preempted, and the higher priority
thread is given the CPU. The lower priority thread does not get to complete its
time slice. Threads of equal priority are given CPU time in a round-robin
manner.
Preemptive means that the multitasking activity needs no cooperation from the
executing programs. OS/2 maintains control over executing programs, and stops,
or preempts, them when their time slice with the CPU is over or when a higher
priority program is ready to run.
CPU scheduling is based on four priority classes-Time Critical, Fixed-High,
Regular, and Idle-Time. Each class has 32 levels of execution ordering.
Scheduling parameters are user-selectable at the time the system is started or
can be varied dynamically based on system load.
Depending on a thread's priority class and level, OS/2 periodically gives each
thread in each process a small slice of CPU time. Threads with higher
priorities always run before threads having lower priorities. A thread runs
until its time is up or until a thread with a higher priority is ready to run.
At that time, OS/2 preempts the thread and starts another thread. Threads can
also voluntarily relinquish the CPU (for example, by calling DosSleep).
The amount of time in each time slice is defined by the TIMESLICE command in
the CONFIG.SYS file. The TIMESLICE command can be used by the user to customize
the size of the time slices that a thread gets. The default is for OS/2 to
dynamically vary the size of the time slice based on the activity of the thread
and the overall system load.
When a thread is created (using DosCreateThread), it inherits the priority of
the thread that started it. DosSetPriority enables threads to change their
priority classes and levels in response to changes in their execution
environments. DosSetPriority enables a thread to change its own priority, or
the priority of any thread within its process. DosSetPriority also enables
changing priorities for the entire process and for descendant processes. Within
each class, the priority level of a thread can vary because of a DosSetPriorty
request or, if dynamic priority variation is being used, because of action
taken by OS/2.
ΓòÉΓòÉΓòÉ 5.2.1. Priority Classes ΓòÉΓòÉΓòÉ
OS/2 uses four priority classes to determine when a thread receives a time
slice:
Priority Classes
ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
ΓöéPriority ΓöéDescription Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéTime-critical ΓöéHighest priority. For use Γöé
Γöé Γöéwhen response time is Γöé
Γöé Γöécritical. Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéFixed-high ΓöéUsed by threads that provide Γöé
Γöé Γöéservice to other threads. ThisΓöé
Γöé Γöépriority class is to be used Γöé
Γöé Γöéwhen it is desirable that the Γöé
Γöé Γöéthread not be too sensitive toΓöé
Γöé Γöéthe foreground/background Γöé
Γöé Γöéboost provided by dynamic Γöé
Γöé Γöépriority variation. It is Γöé
Γöé Γöémeant for programs that need Γöé
Γöé Γöéto execute before regular Γöé
Γöé Γöéprograms, but without the Γöé
Γöé Γöéimmediate response time Γöé
Γöé Γöérequirement called for by Γöé
Γöé Γöétime-critical threads. Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéRegular ΓöéDefault priority. Most Γöé
Γöé Γöéthreads belong in this class. Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéIdle-time ΓöéLowest priority. This Γöé
Γöé Γöépriority only gets CPU time Γöé
Γöé Γöéwhen there is no other work toΓöé
Γöé Γöédo. Γöé
ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
A time-critical thread always receives a time slice before a fixed-high thread,
a fixed-high thread always receives a time slice before a regular thread, and a
regular thread always receives a time slice before an idle-time thread.
Time-Critical Threads
Time-critical threads have the highest priority class and execute before any
fixed-high, regular, or idle-time threads.
The time-critical class is for threads that must react to events outside the
system. For example, in a communications application, a thread responsible for
reading data from the communications device needs enough time to read all
incoming data. Because more than a regular time slice might be needed, a
time-critical classification ensures that the thread gets all the time
required.
Time-critical threads have a static priority that is not varied by OS/2. They
are scheduled among themselves in priority level order, with round-robin
scheduling of threads of equal priority.
Time-critical threads must be executed quickly, then free the CPU for other
work until another time-critical event occurs. This is important to maintain
good interactive responsiveness to the user and enable communications and other
time critical applications to run concurrently. The time-critical activity
should, when possible, be in a thread separate from the rest of the
application, to isolate and minimize the time spent processing at the
time-critical level. A good rule of thumb is that a time-critical thread should
consist of no more than about 20,000 assembly language instructions.
Fixed-High Threads
A fixed-high thread has a priority class that is lower than time-critical but
executes before any regular or idle-time threads. This class of threads should
be used to provide service for other threads where it is desirable that the
thread not be too sensitive to the foreground/background boost provided by
dynamic priority variation. A messaging thread, would be a good example of this
type of thread.
OS/2 varies the priority of a fixed-high thread around a base value according
to the activity of the thread and the system at any point in time. The base
value can be set by the thread itself.
Regular Threads
A regular thread is the class that the majority of threads fall into. No
explicit action is necessary by the application to run at this priority, it is
the default.
OS/2 varies the priority level of a regular thread around a base value
according to the activity of the thread and the system at any point in time.
The base value can be set by the thread itself.
Idle-Time Threads
An idle-time thread is one with very low priority that executes only when there
are no regular, fixed-high, or time-critical threads to execute. Idle-time
threads get CPU time only when there is no other work to do. The idle-time
class is for threads that need very little CPU time.
Idle-time threads have a static priority that is not varied by OS/2.
ΓòÉΓòÉΓòÉ 5.2.2. Priority Levels ΓòÉΓòÉΓòÉ
Within each class, OS/2 maintains a priority level for a thread. For each of
the four priority classes, there are 32 priority levels-0 to 31. A thread with
priority level 31 always receives a time slice before a thread with priority
level 30, and so on.
If two or more threads have the same priority level, OS/2 distributes the CPU
time equally by using a round-robin scheme; that is, OS/2 gives a time slice to
first one, then another, and so on, and then goes back to the first. A thread
can use DosSetPriority to change its own priority or the priority of any other
thread within its process.
Although an application can set the priority level of a thread at any time,
only applications that use more than one thread or process should do so. The
best use of priority is to speed up threads or processes on which other threads
or processes depend. For example, an application might temporarily raise the
priority of a thread loading a file if another thread is waiting for that file
to be loaded. Because the priority of a thread is relative to all other threads
in the system, raising the priority of the threads in an application merely to
get the extra CPU time adversely affects the overall operation of the system.
There are other ways to affect the amount of CPU time a thread is given. A
thread can define a critical section of code by using DosEnterCritSec and
DosExitCritSec. While inside the critical section of code, a thread cannot be
preempted by any other thread within its process (threads in other processes
are still given their time slices). Using critical sections enables threads to
get more CPU time, while not unduly affecting the rest of the system.
The priority class and priority level are set using DosSetPriority. The
priority class is changed by passing the new priority class to the function.
The priority level, however, is changed by passing a value, called the
priority-delta, that is added to the existing priority level to produce the new
priority level; changes to the priority level are relative to the current
priority level. Specifying a positive priority-delta increases the priority
level, enabling the thread to obtain more CPU time than it normally would. A
negative priority-delta decreases the priority level, giving the thread less
CPU time than it would normally receive. The value is restricted to the valid
range, based upon the current priority class of the process.
If you change the priority level without changing the priority class, the
priority-delta is relative to the current priority level. However, if you
change the priority class at the same time that you change the priority level,
the priority-delta value is relative to 0. Whenever DosSetPriority is called
with a class specification, but no value is specified for priority-delta, the
base priority level defaults to 0.
The process identifier parameter of DosSetPriority specifies which process is
affected by the call. A process can change the priority of itself, of any
process that is a descendant of itself, or of one of its threads.
A thread can change the priority of any thread within its current process. When
a thread changes the priority of threads in a descendant process, however, only
those threads running at the default priority will be changed. You cannot
change the priority of a thread in a child process that has already changed its
priority from the default.
The initial thread of execution for an application is given a regular class
priority that varies by the system. When a thread is created, it is initially
dispatched in the same class and priority as the thread that started it. A
child process inherits the priority of the thread in the parent process that
creates it.
ΓòÉΓòÉΓòÉ 5.2.3. Priority Guidelines ΓòÉΓòÉΓòÉ
Within the two most common priority classes-time-critical and regular-there are
certain broad guidelines recommended for choosing the priority level for a
program.
TIME-CRITICAL CLASS
The guidelines for level within the time critical class are set to
maximize the number of different applications that can successfully
multitask in an OS/2 system. The guidelines are described in the
following table.
Recommended Priority Levels for Time-Critical Threads
ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
ΓöéActivity ΓöéRange of RecommendedΓöéJustification/Comments Γöé
Γöé ΓöéPriority Levels Γöé Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéRobotics/Real time Γöé20-31 ΓöéOS/2 systems can be used on manufacturing lines to control Γöé
Γöéprocess control Γöé Γöéequipment or in other real time process control Γöé
Γöé Γöé Γöéapplications. In this case a slow response from the PC couldΓöé
Γöé Γöé Γöécause expensive damage to equipment or even human injury. Γöé
Γöé Γöé ΓöéTherefore the highest priority levels should be reserved forΓöé
Γöé Γöé Γöéthese applications. Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéCommunications Γöé10-19 ΓöéIn communications, the inability to get the processor could Γöé
Γöé Γöé Γöécause a loss of data or communications sessions. Therefore Γöé
Γöé Γöé Γöéthis class of applications is next highest. Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéOther Γöé0-09 ΓöéOther threads might need to preempt the foreground in Γöé
Γöé Γöé Γöéspecial cases (for example, Control-Break). These should be Γöé
Γöé Γöé Γöéset below the other 2 classes. Γöé
ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
In general, application performance is not a good reason to make a thread
time critical.
REGULAR CLASS
In cases where explicit priority levels are set, they should follow the
guidelines listed below.
Recommended Priority Levels for Regular Priority Threads
ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
ΓöéActivity ΓöéRange of RecommendedΓöéJustification Γöé
Γöé ΓöéPriority Level Γöé Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéCommunications Γöé26-31 ΓöéCommunications should take priority over other Γöé
Γöé Γöé Γöébackground processing to increase overlap with Γöé
Γöé Γöé Γöétransmission and processing on the partner PC or Γöé
Γöé Γöé Γöéhost. This gives the best system performance. Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéOther Γöé0-25. ΓöéIf an application has multiple threads it might beΓöé
Γöé Γöé Γöénecessary to set them to several different Γöé
Γöé Γöé Γöépriorities to optimize the order in which they Γöé
Γöé Γöé Γöérun. A range of priority levels is provided to Γöé
Γöé Γöé Γöéfacilitate this. (The default priority is regular Γöé
Γöé Γöé Γöéclass, level = 0.) Γöé
ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
ΓòÉΓòÉΓòÉ 5.2.4. Dynamic Priority Alteration ΓòÉΓòÉΓòÉ
OS/2 can be configured to dynamically alter the priority of a process. The
PRIORITY statement in CONFIG.SYS can be set to either ABSOLUTE or DYNAMIC. If
PRIORITY specifies the ABSOLUTE option, all processes receive CPU time based on
the priority established by calls to DosSetPriority. If the PRIORITY command in
the CONFIG.SYS file specifies the DYNAMIC option, OS/2 adjusts process
priorities based on system load and process activity, and on whether the
process is in the foreground. DYNAMIC is the default setting; if the PRIORITY
command is not specified, the system uses DYNAMIC priority. DYNAMIC is designed
to gives the best overall system performance under most conditions.
When dynamic priority variation is enabled, OS/2 grants higher priority to the
foreground process than to background processes. System load and process
activity are also taken into consideration. The priority of the process
consists of a computed priority value that is based upon the display status of
the process (foreground or background), and its recent I/O and CPU time usage
history. When dynamic priority variation is enabled, I/O priority boosts are
generated for keyboard input, window, foreground, processor starvation, device
I/O, and DOS Session interrupts. This ensures that the foreground process-the
process most likely to be in use-receives enough CPU time to provide quick
response to user input.
There are times when dynamic priority variation can interfere with a
multi-threaded application's execution. For example, if you are doing a lot of
keyboard input on a thread, its priority will get boosted and other threads may
not get enough CPU time. A communication thread is an example of a time
sensitive background thread which would be one case. The solution is to either
set PRIORITY = ABSOLUTE or to call DosSetPriority on a regular basis to keep
the threads priority at the desired level.
ΓòÉΓòÉΓòÉ 5.2.5. Altering the Size of the Time Slice ΓòÉΓòÉΓòÉ
The TIMESLICE command in CONFIG.SYS sets the minimum and maximum amount of
processor time allocated to processes and programs for both OS/2 and DOS
sessions.
The first parameter selects the minimum TIMESLICE value in milliseconds. This
value is the minimum amount of time a thread is to be processed before yielding
the processor to a thread of the same priority level. This value must be an
integer greater than or equal to 32.
The second parameter selects the maximum TIMESLICE value in milliseconds. The
value of this parameter is the maximum amount of time a thread can be processed
before yielding processor time. This value must be an integer greater than or
equal to the minimum value, and less than 65536.
The default is dynamic time slicing, which varies the size of the time slice
depending on system load and paging activity. Dynamic time slicing is designed
to give the best performance in most situations.
ΓòÉΓòÉΓòÉ 5.3. Using Processes ΓòÉΓòÉΓòÉ
An OS/2 application that has been loaded into memory and prepared for execution
is called a process. A process is the code, data, and other resources of the
application, such as the open file handles, semaphores, pipes, queues and so
on. OS/2 considers every application it loads to be a process.
Each process has at least one thread, called the main thread or thread 1. The
application runs when the system scheduler gives control to a thread in the
process. For more on thread management, see Using Threads.
Note: In the example code fragments that follow, error checking was left out
to conserve space. Applications should always check the return code that
the functions return. Control Program functions return an APIRET value.
A return code of 0 indicates success. If a non-zero value is returned,
an error occurred.
ΓòÉΓòÉΓòÉ 5.3.1. Starting a Child Process ΓòÉΓòÉΓòÉ
You start a process by calling DosExecPgm. The process you start is a child of
the calling, or parent, process and inherits many of the resources owned by the
parent process, such as file handles.
DosExecPgm creates a process environment from an executable file. The target
program is loaded into storage, and it begins execution.
The following code fragment starts an application named ABC:
#define INCL_DOSPROCESS /* Process and thread values */
#include <os2.h>
CHAR szFailName[CCHMAXPATH];
RESULTCODES resc;
DosExecPgm(szFailName, /* Object-name buffer */
sizeof(szFailName), /* Length of buffer */
EXEC_SYNC, /* Sync flag */
(PSZ) NULL, /* Argument string */
(PSZ) NULL, /* Environment string */
&resc, /* Address for result */
"ABC.EXE"); /* Name of application */
In this example, ABC runs synchronously (as specified by EXEC_SYNC). This means
the parent process temporarily stops while the child process runs. The parent
process does not continue until the child process ends.
ΓòÉΓòÉΓòÉ 5.3.1.1. Starting an Asynchronous Child Process ΓòÉΓòÉΓòÉ
To start a child process and enable it to run asynchronously (that is, without
suspending the parent process until the child process ends), you use the
EXEC_ASYNC constant in a call to DosExecPgm. If you start a process in this
way, the function copies the process identifier of the child process to the
codeTerminate field of the RESULTCODES structure that is returned by
DosExecPgm. You can use this process identifier to check the progress of the
child process or to end the process.
You can also run a child process asynchronously by using DosExecPgm with the
EXEC_ASYNCRESULT constant. In addition to causing DosExecPgm to return to the
parent process immediately, this constant also directs OS/2 to save a copy of
the termination status when the child process ends. This status specifies the
reason the child process stopped. The parent process can retrieve the
termination status by using DosWaitChild.
The following code fragment starts the program SIMPLE.EXE, and then waits for
it to finish. It then prints the termination code and the return code.
#define INCL_DOSPROCESS /* Process and thread values */
#include <os2.h>
#include <stdio.h>
#define START_PROGRAM "SIMPLE.EXE"
CHAR szLoadError[100];
PSZ pszArgs;
PSZ pszEnvs;
RESULTCODES rcReturnCodes;
APIRET ulrc;
ulrc = DosExecPgm(szLoadError, /* Object name buffer */
sizeof(szLoadError), /* Length of object name buffer */
EXEC_SYNC, /* Asynchronous/Trace flags */
pszArgs, /* Argument string */
pszEnvs, /* Environment string */
&rcReturnCodes, /* Termination codes */
START_PROGRAM); /* Program file name */
printf("Termination Code %d Return Code %d \n",
rcReturnCodes.codeTerminate,
rcReturnCodes.codeResult);
/*----------------SIMPLE.EXE------------------*/
#define INCL_DOSPROCESS /* Process and thread values */
#include <os2.h>
#include <stdio.h>
#define RETURN_CODE 0
main()
{
printf("Hello!\n");
DosExit(EXIT_PROCESS, /* End the thread or process */
RETURN_CODE); /* Result code */
}
ΓòÉΓòÉΓòÉ 5.3.1.2. Starting a Background Process ΓòÉΓòÉΓòÉ
You can start a child process in the background by specifying the
EXEC_BACKGROUND constant in DosExecPgm. A background process runs independently
of the parent process and is called a detached process. A detached process
should not require any input from the keyboard or output to the video screen,
but it can use interprocess communication, such as pipes, queues, and shared
memory.
The following code fragment starts the program BATCH.EXE in the background.
#define INCL_DOSPROCESS /* Process and thread values */
#include <os2.h>
#include <stdio.h>
#define START_PROGRAM "BATCH.EXE"
CHAR szLoadError[100];
PSZ pszArgs;
PSZ pszEnvs;
RESULTCODES rcReturnCodes;
APIRET ulrc;
ulrc = DosExecPgm(szLoadError, /* Object name buffer */
sizeof(szLoadError), /* Length of object name buffer */
EXEC_BACKGROUND, /* Asynchronous/Trace flags */
pszArgs, /* Argument string */
pszEnvs, /* Environment string */
&rcReturnCodes, /* Termination codes */
START_PROGRAM); /* Program file name */
if (ulrc != 0) {
printf("DosExecPgm error: return code = %ld",
ulrc);
return;
}
ΓòÉΓòÉΓòÉ 5.3.1.3. Setting the Command Line and Environment for a Child Process ΓòÉΓòÉΓòÉ
When you start a process, it inherits many of the resources of the parent. This
includes file handles, such as the standard input and standard output files. A
child process also inherits the resources of the screen group, such as the
mouse and video modes, and the environment variables of the parent process.
The call to DosExecPgm determines the command line and environment that the
child process receives. The fourth and fifth parameters of the function are
pointers to the command line and the environment, respectively. If these
pointers are NULL, the child process receives nothing for a command line and
only an exact duplicate of the environment of the parent process. The parent
process can modify this information by creating a string (ending with two NULL
characters) and passing the address of the string to the function. The command
line string must include the name of the application, followed by a NULL
character, and the command line arguments, followed by two NULL characters. Any
number of arguments can be passed to the child process, as long as the argument
string ends with two NULL characters.
The following code fragment passes to the child process the string "test
-option1 -option2" as its command line:
#define INCL_DOSPROCESS /* Process and thread values */
#include <os2.h>
RESULTCODES resc;
CHAR szFailName[CCHMAXPATH];
CHAR szCommandLine[] = "test\0-option1 -option2\0";
DosExecPgm(szFailName, /* Object-name buffer */
sizeof(szFailName), /* Length of buffer */
EXEC_SYNC, /* Sync flag */
szCommandLine, /* Argument string */
(PSZ) NULL, /* Environment string */
&resc, /* Address of result */
"test.exe"); /* Name of application */
ΓòÉΓòÉΓòÉ 5.3.2. Changing the Priority of a Process ΓòÉΓòÉΓòÉ
Changing the priority of a process is simply a matter of changing the priority
of every thread executing in the process. For the details see the section on
changing thread priorities, Changing the Priority of a Thread.
ΓòÉΓòÉΓòÉ 5.3.3. Obtaining Information about Child Processes ΓòÉΓòÉΓòÉ
OS/2 creates and maintains a process information block for every process. An
application can use DosGetInfoBlocks to access the process information block.
This function returns a pointer to a PIB data structure, which contains the
information from the process information block.
The following code fragment returns the address of the process information
block of the current process. The calling thread can subsequently browse either
the PIB block.
#define INCL_DOSPROCESS /* Process and thread values */
#include <os2.h>
PTIB ptib; /* Address of pointer to thread information block */
PPIB ppib; /* Address of pointer to process information block */
APIRET rc; /* Return code */
rc = DosGetInfoBlocks(&ptib,
&ppib);
DosGetInfoBlocks also returns the address of the thread information block of
the current thread.
ΓòÉΓòÉΓòÉ 5.3.4. Waiting for a Child Process to End ΓòÉΓòÉΓòÉ
You can synchronize the execution of a process with the execution of one of its
child processes by calling DosWaitChild. DosWaitChild does not return until the
specified child process ends. This can be useful, for example, if the parent
process needs to ensure that the child process has completed its task before
the parent process continues with its own task.
In the following code fragment, the parent process starts a child process and
then waits for the child process to finish:
#define INCL_DOSPROCESS /* Process and thread values */
#include <os2.h>
RESULTCODES resc;
PID pidEnded;
CHAR szFailName[CCHMAXPATH];
CHAR szCommandLine[] = "APP\0test\0";
DosExecPgm(szFailName, /* Failed-name buffer */
sizeof(szFailName), /* Length of buffer */
EXEC_ASYNC, /* Sync flag */
szCommandLine, /* Argument string */
(PSZ) NULL, /* Environment string */
&resc, /* Address of result */
"APP.EXE"); /* Name of application */
DosWaitChild(DCWA_PROCESS, /* Only the process */
DCWW_WAIT, /* Waits until it is done */
&resc, /* Puts the result here */
&pidEnded, /* PID of ended process */
resc.codeTerminate); /* Child to wait for */
You can cause a process to wait for all its child processes to end by using the
DCWA_PROCESSTREE constant in the call to DosWaitChild.
ΓòÉΓòÉΓòÉ 5.3.5. Ending the Current Process ΓòÉΓòÉΓòÉ
You end the current process by calling DosExit. When you exit, the system stops
the process and frees any existing resources the process owns.
In the following code fragment, DosExit is used to end the process if the given
file does not exist:
#define INCL_DOSPROCESS /* Process and thread values */
#include <os2.h>
#define HF_STDERR 2 /* Standard error handle */
HFILE hf;
ULONG ulAction, ulWritten;
APIRET rc;
rc = DosOpen("SAMPLE.TXT",
&hf,
&ulAction,
0,
FILE_NORMAL,
FILE_OPEN,
OPEN_ACCESS_WRITEONLY |
OPEN_SHARE_DENYWRITE,
(PEAOP2) NULL);
if (rc) {
DosWrite(HF_STDERR,
"Cannot open file\r\n",
18,
&ulWritten);
DosExit(EXIT_PROCESS,
rc);
}
EXIT_PROCESS directs DosExit to end all the threads in a process including the
calling thread, thus ending the process. DosExit includes an error value that
is returned to the parent process through the RESULTCODES structure specified
in the DosExecPgm call that started the process. If you started the application
from the command line, the command processor, CMD.EXE, makes this value
available through the ERRORLEVEL variable. If another process started the
application, that process can call DosWaitChild to determine the error value.
If you want to exit only from a given thread, you can call DosExit with the
EXIT_THREAD constant. This will end only the calling thread; other threads in
the process are not affected. If the thread you end is the last thread in the
process, the process also ends. If the thread consists of a function, the
thread ends when the function returns.
ΓòÉΓòÉΓòÉ 5.3.6. Terminating a Process ΓòÉΓòÉΓòÉ
A process can end the execution of a descendant process by calling
DosKillProcess. This causes OS/2 to send a XCPT_SIGNAL_KILLPROC exception to
the target process. The child processes of the target process can also be
ended.
The following code fragment ends the specified process and all child processes
belonging to that process:
#define INCL_DOSPROCESS /* Process and thread values */
#include <os2.h>
PID pidProcess;
DosKillProcess(DKP_PROCESSTREE,
pidProcess);
In this example, the pidProcess parameter specifies which descendant process to
end. The process identifier is returned by DosExecPgm in the codeTerminate
field of the RESULTCODES structure when you start the child process.
The parameter DKP_PROCESSTREE in the example indicates that the specified
process, pidProcess, and all of its descendant processes are to be ended.
If you specify DKP_PROCESS in a call to DosKillProcess, only the specified
process is ended. Its child processes, if any, continue to run.
The process to be ended must either be the current process, or it must have
been directly created by the current process with DosExecPgm for asynchronous
execution. That is, a process can end itself and its descendants.
The process to be ended need not still be executing. If it has started its own
child processes, but has stopped executing, its children can still be flagged
for termination.
Obtaining the Termination Status of a Child Process
OS/2 saves the termination status for a process if the process was started by
using the EXEC_ASYNCRESULT constant in the call to DosExecPgm.
You can retrieve the termination status of the most recently ended process by
using the DCWW_NOWAIT constant with DosWaitChild and setting the child process
identification parameter to 0. The DCWW_NOWAIT constant directs the function to
return immediately, without waiting for a process to end. Instead, the function
retrieves the termination status from the process that most recently ended. If
you specify a child process identification with DCWW_NOWAIT, DosWaitChild
returns ERROR_CHILD_NOT_COMPLETE if the child process has not ended. Once the
specified process has ended, DosWaitChild returns its termination code.
The following code fragment starts a child session (the program SIMPLE.EXE),
and then retrieves the termination status from the process that most recently
ended.
#define INCL_DOSPROCESS /* Process and thread values */
#include <os2.h>
#include <stdio.h>
#define START_PROGRAM "SIMPLE.EXE"
CHAR szLoadError[100];
PSZ pszArgs;
PSZ pszEnvs;
RESULTCODES rcReturnCodes;
ULONG ulPid; /* Process ID (returned) */
ULONG ulTarget; /* Process ID of process to wait for */
APIRET ulrc; /* Return code */
strcpy(pszArgs,
"-a2 -l"); /* Pass arguments "-a2" and "-l" */
ulTarget = 0; /* Process ID for the most recently ended process */
ulrc = DosExecPgm(szLoadError, /* Object name buffer */
sizeof(szLoadError), /* Length of object name buffer */
EXEC_ASYNCRESULT, /* Asynchronous/Trace flags */
pszArgs, /* Argument string */
pszEnvs, /* Environment string */
&rcReturnCodes, /* Termination codes */
START_PROGRAM); /* Program file name */
if (ulrc != 0) {
printf("DosExecPgm error: return code = %ld",
ulrc);
return;
}
ulrc = DosWaitChild(DCWA_PROCESS, /* Execution options */
DCWW_NOWAIT, /* Wait options */
&rcReturnCodes, /* Termination codes */
&ulPid, /* Process ID (returned) */
ulTarget); /* Process ID of process to wait for */
if (ulrc != 0) {
printf("DosWaitChild error: return code = %ld",
ulrc);
return;
}
ΓòÉΓòÉΓòÉ 5.3.7. Creating an Exit List ΓòÉΓòÉΓòÉ
You call DosExitList to add to the exit list a routine that is to be given
control when a process is ended (or finishes its execution). Multiple routines
can be added to the list. When the process is ending, OS/2 transfers control to
each address on the list.
If there are multiple addresses on the list, each function gets control in
numerical order (with 0 being first and 0FFH being last), based on a value
supplied by the application when it calls DosExitList. In case of duplicate
entries for this parameter, the routines will be executed in LIFO (last in,
first out) order.
DosExitList requires a function code that specifies an action and a pointer to
the function that is to receive control upon termination.
The following code fragment adds the locally defined function SaveFiles to the
exit list:
#define INCL_DOSPROCESS /* Process and thread values */
#include <os2.h>
#define HF_STDOUT 1 /* Standard output handle */
VOID main(VOID)
{
.
.
.
DosExitList(EXLST_ADD,
(PFNEXITLIST) SaveFiles);
.
.
.
DosExit(EXIT_PROCESS,
0);
}
VOID APIENTRY SaveFiles(ULONG ulTermCode)
{
ULONG ulWritten;
switch (ulTermCode) {
case TC_EXIT:
case TC_KILLPROCESS:
DosWrite(HF_STDOUT,
"Goodbye\r\n",
10,
&ulWritten);
break;
case TC_HARDERROR:
case TC_TRAP:
break;
}
DosExitList(EXLST_EXIT,
0);
}
Any function that you add to the list must take one parameter. The function can
carry out any task, as shown in the preceding example, but as its last action
it must call DosExitList, specifying the EXLST_EXIT constant. An exit-list
function must not have a return value and must not call DosExit to end.
When an exit-list routine receives control, the parameter (located at ESP+4 on
the stack) contains an indicator of why the process ended. The values returned
are the same as those for termination codes returned by DosWaitChild or
DosExecPgm requests. These values are:
TC_EXIT (0) Normal exit
TC_HARDERROR (1) Hard-error halt
TC_TRAP (2) Trap operation for a 16-bit child process
TC_KILLPROCESS (3) Unintercepted DosKillProcess
TC_EXCEPTION (4) Exception operation for a 32-bit child process
To execute the exit-list functions, OS/2 reassigns thread 1 after ending all
other threads in the process. If thread 1 has already exited (for example, if
it called DosExit without ending other threads in the process), the exit-list
functions cannot be executed. In general, it is poor practice to end thread 1
without ending all other threads.
Before transferring control to the termination routines, OS/2 resets the stack
to its initial value. Transfer is by way of an assembly language JMP
instruction. The routine must be in the address space of the ending process.
The termination routine at that address takes the necessary steps and then
calls DosExitList with FunctionOrder=EXLST_EXIT. Control is then transferred
to the next address in the invocation order of the exit list. When all such
addresses have been processed, the process completes exiting. If a routine on
the list does not call DosExitList at the completion of its processing, the
process waits, and OS/2 prevents termination.
During DosExitList processing, the process is in a state of partial
termination. All threads of the process are ended, except for the one
executing the exit-list routines. To ensure good response to a user request to
end a program, there should be minimal delay in completing termination.
Termination routines should be short and fail-safe.
You can use DosExitList with the EXLST_REMOVE constant to remove a function
from the list.
The designer of an exit-list routine must carefully consider which functions
will be used by the routine. In general, calls to most OS/2 functions are
valid in a DosExitList routine, but certain functions, such as DosCreateThread
and DosExecPgm, are not.
ΓòÉΓòÉΓòÉ 5.4. Using Threads ΓòÉΓòÉΓòÉ
A thread is a dispatchable unit of execution that consists of a set of
instructions, related CPU register values, and a stack. Every process has at
least one thread and can have many threads running at the same time. The
application runs when OS/2 gives control to a thread in the process. The thread
is the basic unit of execution scheduling.
Every process has at least one thread, called the main thread or thread 1. To
execute different parts of an application simultaneously, you can start several
threads.
A new thread inherits all the resources currently owned by the process. This
means that if you opened a file before creating the thread, the file is
available to the thread. Similarly, if the new thread creates or opens a
resource, such as another file, that resource is available to the other threads
in the process.
ΓòÉΓòÉΓòÉ 5.4.1. Creating a Thread ΓòÉΓòÉΓòÉ
You use DosCreateThread to create a new thread for a process.
DosCreateThread requires the address of the code to execute and a variable to
receive the identifier of the thread. The address of the code is typically the
address of a function that is defined within the application.
You can pass one ULONG parameter to the thread when you start it. To pass more
information to the thread, pass the address of a data structure.
You specify how you want the thread to run when you call DosCreateThread. If
bit 1 of the flag parameter in the function call is 0, the thread starts
immediately. If bit 1 of the flag parameter is 1, the thread starts suspended
and will not run until the application calls DosResumeThread.
Each thread maintains its own stack. You specify the size of the stack when you
call DosCreateThread. The amount of space needed depends on a number of
factors, including the number of function calls the thread makes and the number
of parameters and local variables used by each function. If you plan to call
OS/2 functions, a reasonable stack size is 8192 bytes (8KB); 4096 bytes (4KB)
should be the absolute minimum. If bit 1 of the flag parameter is 0, OS/2 uses
the default method for initializing the thread's stack. If bit 1 of the flag
parameter is 1, memory for the thread's entire stack is pre-committed.
The following code fragment creates a thread:
#define INCL_DOSPROCESS /* Process and thread values */
#include <os2.h>
#include <stdio.h>
#define HF_STDOUT 1 /* Standard output handle */
VOID _System ThreadFunc(ULONG ulBeepLen);
INT main(VOID)
{
ULONG ulBeepLen;
TID tidThread;
ulBeepLen = 1000;
DosCreateThread(&tidThread, /* Thread ID returned by DosCreateThread */
&ThreadFunc, /* Address of the thread function */
ulBeepLen, /* Parameter passed to thread */
0, /* Immediate execution, default stack */
/* initialization */
4096); /* Stack size */
DosWaitThread(&tidThread,
DCWW_WAIT);
return 0;
} /* end main */
/***************************************************/
/* ThreadFunc */
/***************************************************/
VOID _System ThreadFunc(ULONG ulBeepLen)
{
ULONG ulWritten; /* needed for DosWrite */
DosBeep(750, ulBeepLen);
DosWrite(HF_STDOUT,
"Message from new thread\r\n",
25,
&ulWritten);
DosExit(EXIT_PROCESS, 0);
} /* end ThreadFunc */
A thread continues to run until it calls DosExit, returns control to OS/2, or
is ended by a DosKillThread call.
In the preceding example, the thread exits when the function implicitly returns
control at the end of the function.
ΓòÉΓòÉΓòÉ 5.4.2. Obtaining Information about a Thread ΓòÉΓòÉΓòÉ
OS/2 creates and maintains a thread information block for each thread. An
application can use DosGetInfoBlocks to access the thread information block.
This function returns a pointer to a TIB data structure.
The code fragment below returns the address of the thread information block of
the current thread. The calling thread can subsequently browse the TIB.
DosGetInfoBlocks also returns the address of the process information block of
the current process.
ΓòÉΓòÉΓòÉ 5.4.3. Changing the Priority of a Thread ΓòÉΓòÉΓòÉ
You can use DosSetPriority to change the execution priority of threads in a
process. The execution priority defines when or how often a thread receives an
execution time slice. Threads with higher priorities receive time slices before
those with lower priorities. When a thread that is higher in priority than the
currently running thread becomes ready to run, it immediately preempts the
lower priority thread (the lower priority thread does not get to complete its
time slice). Threads with equal priority receive time slices in a round-robin
order. If you raise the priority of a thread, the thread is executed more
frequently.
You can use DosSetPriority to set the priority for one thread in a process, for
all threads in a process (and thus the process itself), or for threads in a
child process.
A process can change the priority of any thread within itself. When a process
changes the priority of threads in a descendant process, however, only those
with default priorities are changed. The priority of any thread in a descendant
process that has already explicitly changed its priority from the default with
DosSetPriority is not changed.
In the following code fragment, DosSetPriority lowers the priority of a process
to be used as a background process:
#define INCL_DOSPROCESS /* Process and thread values */
#include <os2.h>
PTIB ptib; /* thread information block */
PPIB ppib; /* process information block */
APIRET rc; /* return code from DosGetInfoBlocks */
rc = DosGetInfoBlocks(&ptib,
&ppib);
DosSetPriority(PRTYS_PROCESSTREE,
PRTYC_IDLETIME,
0,
ppib->pib_ulpid);
DosGetInfoBlocks retrieves the process information blocks and thread
information blocks. DosSetPriority then uses the process identifier to change
the priority to idle time (idle-time processes receive the least attention by
OS/2).
If you specify PRTYS_PROCESS when calling DosSetPriority, only the priority of
the specified process changes. The priorities of all child processes remain
unchanged.
If you specify PRTYS_THREAD in the call to DosSetPriority, you must specify a
thread identifier as the last parameter. The priority of the specified thread
changes, but the priorities of all other threads in the process remain
unchanged.
Whenever DosSetPriority is called with a class specification, but no value is
specified for priority-delta, the base priority level defaults to 0.
ΓòÉΓòÉΓòÉ 5.4.4. Suspending the Current Thread ΓòÉΓòÉΓòÉ
You can temporarily suspend the execution of the current thread for a set
amount of time by using DosSleep. This function suspends execution of the
thread for the specified number of milliseconds. DosSleep is useful when you
need to delay the execution of a task. For example, you can use DosSleep to
delay a response when the user presses a DIRECTION key. The delay provides the
user with enough time to observe the results and release the key.
The following code fragment uses DosSleep to suspend execution of a thread for
1000 milliseconds (1 second):
#define INCL_DOSPROCESS /* Process and thread values */
#include <os2.h>
DosSleep(1000);
ΓòÉΓòÉΓòÉ 5.4.5. Suspending and Resuming Execution of a Thread ΓòÉΓòÉΓòÉ
DosSuspendThread and DosResumeThread are used to temporarily suspend the
execution of a thread when it is not needed and resume execution when the
thread is needed.
These functions are best used when it is necessary for a process to temporarily
suspend execution of a thread that is in the middle of a task. For example,
consider a thread that opens and reads files from a disk. If other threads in
the process do not require input from these files, the process can suspend
execution of the thread so that OS/2 does not needlessly grant control to it.
The specified thread might not be suspended immediately if it has some system
resources locked that must be freed first. However, the thread is not permitted
to execute further application program instructions until a corresponding
DosResumeThread is called.
A thread can only suspend another thread that is within its process.
DosResumeThread is used to enable the suspended thread to resume execution.
The following code fragment temporarily suspends the execution of another
thread within the same process. A subsequent call to DosResumeThread restarts
the suspended thread. Assume that the thread identifier of the target thread
has been placed int ThreadID already.
#define INCL_DOSPROCESS /* Process and thread values */
#include <os2.h>
#include <stdio.h>
TID tidThreadID; /* Thread identifier */
APIRET ulrc; /* Return code */
ulrc = DosSuspendThread(tidThreadID);
if (ulrc != 0) {
printf("DosSuspendThread error: return code = %ld",
ulrc);
return;
}
ulrc = DosResumeThread(tidThreadID);
if (ulrc != 0) {
printf("DosResumeThread error: return code = %ld",
ulrc);
return;
}
ΓòÉΓòÉΓòÉ 5.4.6. Entering Critical Sections ΓòÉΓòÉΓòÉ
A thread can prevent execution of any of the other threads in its process by
calling DosEnterCritSec.
This function temporarily prevents a thread from being preempted by other
threads within its process. The other threads in the process will not be
executed until the current thread calls DosExitCritSec. This enables the
calling thread to access a time-critical resource of the process.
The following code fragment enters a section that will not be preempted,
performs a simple task, and then exits quickly.
#define INCL_DOSPROCESS /* Process and thread values */
#include <os2.h>
#include <stdio.h>
BOOL flag; /* Program control flag */
APIRET ulrc; /* Return code */
ulrc = DosEnterCritSec();
if (ulrc != 0) {
printf("DosEnterCritSec error: return code = %ld",
ulrc);
return;
}
flag = TRUE; /* Set the flag */
ulrc = DosExitCritSec();
if (ulrc != 0) {
printf("DosExitCritSec error: return code = %ld",
ulrc);
return;
}
A count is maintained of the outstanding DosEnterCritSec requests. The count is
incremented when a DosEnterCritSec request is made, and decremented when a
DosExitCritSec request is made. A DosExitCritSec request will not cause normal
thread dispatching to be restored while the count is greater than 0.
This count is maintained in a WORD-sized variable. If overflow occurs, the
count is set to its maximum value, and an error is returned. The operation is
not performed when this occurs.
Threads that call DosEnterCritSec must not must not make dynamic link calls
within these critical sections. The dynamic link procedure could be using
semaphores to serialize a resource. If a thread entering the critical section
blocks another thread that already owns the resource which the dynamic link
function is about to request, a deadlock occurs.
For example, threads of an application are serializing their access to a queue
by means of a semaphore. A thread enters a critical section and makes a request
to read the queue while another thread already has the semaphore that controls
access to the queue. The thread that has the semaphore is now effectively
blocked by DosEnterCritSec, and the thread that has requested the queue waits
forever to access it.
Note: Thread 1 is the initial thread of execution. It handles all signals
(Ctrl+C, Ctrl+Break, and KillProcess). If a signal occurs while
DosEnterCritSec is active, thread 1 can begin execution to process the
signal. Thread 1 must not access the critical resource that is being
protected by the use of DosEnterCritSec.
ΓòÉΓòÉΓòÉ 5.4.7. Waiting for a Thread to End ΓòÉΓòÉΓòÉ
An application might need to ensure that one thread has finished executing
before another thread continues with its own task. For example, one thread
might have to finish reading a disk file into memory before another thread can
use the information. You can use DosWaitThread to suspend a thread until
another thread has ended.
DosWaitThread places the current thread into a wait state until another thread
in the current process has ended. It then returns the thread identifier of the
ending thread.
The following code fragment creates three threads. The thread identifier for
each thread is returned by DosCreateThread in the atid array. Using &atid[0] as
a parameter in the call to DosWaitThread causes OS/2 to wait until the thread
with that identifier (the thread running Thread2Func) ends.
#define INCL_DOSPROCESS /* Process and thread values */
#include <os2.h>
#define HF_STDOUT 1 /* Standard output handle */
TID tidAtid[3];
ULONG ulWritten;
DosCreateThread(&tidAtid[0],
Thread2Func,
0,
0,
4096);
DosCreateThread(&tidAtid[1],
Thread3Func,
0,
0,
4096);
DosCreateThread(&tidAtid[2],
Thread4Func,
0,
0,
4096);
DosWaitThread(&tidAtid[0],
DCWW_WAIT);
DosWrite(HF_STDOUT,
"The thread has ended\r\n",
27,
&ulWritten);
If you set the tid parameter to 0 in the call to DosWaitThread, OS/2 waits only
until the next thread (any thread in the process) ends. The identifier for the
ended thread is then returned in the tid parameter.
After the threads are created as in the preceding example, the following code
fragment waits until one of the threads ends, and then returns its thread
identifier:
#define INCL_DOSPROCESS /* Process and thread values */
#include <os2.h>
TID tid;
tid = 0;
DosWaitThread(&tid,
DCWW_WAIT);
The thread identifier of the next thread to end after the DosWaitThread call is
returned in the tid parameter.
You can use DosWaitThread so that you can recover thread resources when the
thread ends, or to synchronize the execution of a thread with the execution of
other threads.
ΓòÉΓòÉΓòÉ 5.4.8. Ending the Current Thread ΓòÉΓòÉΓòÉ
To end the execution of the current thread, call DosExit, specifying the action
code as 0. It is good practice to end each thread in the application
individually.
If the thread that is ending is the last thread in the process, or if the
request is to end all threads in the process, then the process also ends. All
threads except one are ended, and that thread executes any routines in the list
specified by DosExitList. When this is complete, the resources of the process
are released, and the result code that was specified in the DosExit call is
passed to any thread that calls DosWaitChild for this process.
In the following code fragment, the main routine starts another program,
SIMPLE.EXE, and then expects a return code of 3 to be returned. SIMPLE.EXE sets
the return code with DosExit.
#define INCL_DOSPROCESS /* Process and thread values */
#include <os2.h>
#include <stdio.h>
#define START_PROGRAM "SIMPLE.EXE"
#define RETURN_OK 3
CHAR szLoadError[100];
PSZ pszArgs;
PSZ pszEnvs;
RESULTCODES rcReturnCodes;
APIRET ulrc;
ulrc = DosExecPgm(szLoadError, /* Object name buffer */
sizeof(szLoadError), /* Length of object name buffer */
EXEC_SYNC, /* Asynchronous/Trace flags */
pszArgs, /* Argument string */
pszEnvs, /* Environment string */
&rcReturnCodes, /* Termination codes */
START_PROGRAM); /* Program file name */
if (ReturnCodes.codeResult == RETURN_OK) /* Check result code */
printf("Things are ok...");
else
printf("Something is wrong...");
/*----------------SIMPLE.EXE------------------*/
#define INCL_DOSPROCESS /* Process and thread values */
#include <os2.h>
#include <stdio.h>
#define RETURN_CODE 3
main()
{
printf("Hello!\n");
DosExit(EXIT_THREAD, /* End thread/process */
RETURN_CODE); /* Result code */
}
When you specify DosExit for thread 1 (the initial thread of execution started
by OS/2 for this process), all of the threads in the process are ended, and the
process is ended.
ΓòÉΓòÉΓòÉ 5.4.9. Ending a Thread ΓòÉΓòÉΓòÉ
DosKillThread ends a thread in the current process. DosKillThread enables a
thread in a process to end any other thread in the process.
DosKillThread is used to force a thread within the current process to end
without causing the entire process to be ended.
#define INCL_DOSPROCESS /* Process and thread values */
#include <os2.h>
TID tidThread; /* ThreadID of the thread to be ended */
DosCreateThread(&tidThread,
ThreadFunction,
0,
0,
4096);
.
.
.
DosKillThread(tidThread);
DosKillThread returns to the requestor without waiting for the target thread to
complete its termination processing.
It is an invalid operation to use DosKillThread to kill the current thread.
Terminating thread 1 will cause the entire process to end similar to executing
DosExit on thread 1. DosKillThread will not end a thread that is suspended.
Instead the suspended thread will be ended when it resumes execution. For this
reason, you should not kill the main thread of an application if there are any
secondary threads that are suspended.
If the target thread is executing 16-bit code or was created by a 16-bit
requester, ERROR_BUSY is returned.
ΓòÉΓòÉΓòÉ 5.5. Using Sessions ΓòÉΓòÉΓòÉ
A session consists of at least one process and a virtual console (either full
screen, or Presentation Manager window, and buffers for keyboard and mouse
input). An application can manage its own child sessions by using
DosStartSession, DosStopSession, DosSelectSession, and DosSetSession.
ΓòÉΓòÉΓòÉ 5.5.1. Starting a Session ΓòÉΓòÉΓòÉ
DosStartSession is used to start new sessions and to specify the name of the
application to be started in the new session.
There are five types of sessions that you can start: full screen, text window,
Presentation Manager (PM), full screen DOS Session, and windowed DOS Session.
OS/2 applications running in any of the OS/2 session types-full screen, text
window, and PM-can start a session for any other application type, including
DOS Sessions. Applications running in DOS Sessions cannot start sessions.
DosStartSession can be used to start either a foreground or a background
session, but a new session can be started in the foreground only when the
session of the caller, or one of the descendant sessions of the caller, is
currently executing in the foreground.
A session can be started as an unrelated session or as a child session.
In the following code fragment, an unrelated, foreground session is created,
and the application, SIMON.EXE, is started in the new session:
#define INCL_DOSPROCESS /* Process and thread values */
#define INCL_DOSSESMGR
#include <os2.h>
#define HF_STDOUT 1 /* Standard output handle */
STARTDATA sd;
PID pidProcess;
CHAR szBuf[CCHMAXPATH];
ULONG ulSessionID, cbWritten;
APIRET rc;
CHAR szPgmName[] = "SIMON.EXE";
sd.Length = sizeof(sd); /* Length of the structure */
sd.Related = SSF_RELATED_INDEPENDENT; /* Unrelated session */
sd.FgBg = SSF_FGBG_FORE; /* In the foreground */
sd.TraceOpt = SSF_TRACEOPT_NONE; /* No tracing */
sd.PgmTitle = (PSZ) NULL; /* Title is PgmName */
sd.PgmName = szPgmName; /* Address of szPgmName */
sd.PgmInputs = (PBYTE) NULL; /* No command line args */
sd.TermQ = (PBYTE) NULL; /* No terminal queue */
sd.Environment = (PBYTE) NULL; /* Inherits environment */
sd.InheritOpt = SSF_INHERTOPT_PARENT; /* Uses parent environment */
sd.SessionType = SSF_TYPE_PM; /* PM session */
sd.IconFile = (PSZ) NULL; /* Uses default icon */
sd.PgmHandle = 0; /* Used by Win calls */
sd.PgmControl = SSF_CONTROL_MAXIMIZE; /* Starts app maximized */
sd.InitXPos = 0; /* Lower left corner */
sd.InitYPos = 0; /* Lower left corner */
sd.InitXSize = 0; /* Ignored for maximized */
sd.InitYSize = 0; /* Ignored for maximized */
sd.ObjectBuffer = szBuf; /* Fail-name buffer */
sd.ObjectBuffLen = sizeof(szBuf); /* Buffer length */
rc = DosStartSession(&sd, &ulSessionID, &pidProcess);
if (rc) {
DosBeep(750,250);
DosWrite(HF_STDOUT, "error starting new session\r\n", 28, &cbWritten);
DosExit(EXIT_PROCESS, rc);
}
Before calling DosStartSession, you must create a STARTDATA data structure that
defines the session to be started. Different lengths for the data structure are
supported to provide compatibility and various levels of application control.
DosStartSession uses the STARTDATA structure to specify the details of the new
session, such as the name of the application to start in the session, whether
the new session should be started in the foreground or background, and whether
the new session is unrelated or is a child session of the session calling
DosStartSession.
When a session is created, the title specified in STARTDATA, (or the
application title if no title is specified in STARTDATA) is added to the Window
List.
The Related field in the STARTDATA structure specifies whether the new session
is related to the session calling DosStartSession.
If the InheritOpt field in the STARTDATA data structure is set to 1, the new
session inherits the environment and open file handles of the calling process.
This applies for both unrelated and related sessions.
ΓòÉΓòÉΓòÉ 5.5.2. Controlling the Execution of Child Sessions ΓòÉΓòÉΓòÉ
Once a process has started a child session, it can use DosSelectSession to
control the child session.
A process calls DosSetSession to set the selectability and bonding of a child
session.
ΓòÉΓòÉΓòÉ 5.5.2.1. Setting User Selectability of a Child Session ΓòÉΓòÉΓòÉ
A process calls DosSetSession to set the selectability of a child session.
When a child session is selectable, the user can select it from the Window List
or by using Alt+Esc. When a child session is nonselectable, the user cannot
select the session from the Window List or move to it by using the Alt+Esc
keys.
In the following code fragment, DosSetSession makes a child session
nonselectable:
#define INCL_DOSPROCESS /* Process and thread values */
#define INCL_DOSSESMGR
#include <os2.h>
ULONG ulSessionID;
STATUSDATA stsdata;
stsdata.Length = sizeof(stsdata);
stsdata.SelectInd = SET_SESSION_NON_SELECTABLE; /* Non-selectable */
stsdata.BondInd = SET_SESSION_UNCHANGED; /* Leaves session bonding */
/* index unchanged */
DosSetSession(ulSessionID,
&stsdata);
Once a child session is made nonselectable, the user cannot select the session
from the Window List or move to it by using the Alt+Esc keys. However, the
parent session can still bring the child session to the foreground by using
DosSelectSession. If the session contains a Presentation Manager application or
is a windowed session, the user will still be able to select it with a mouse.
The parent session can make a nonselectable child session selectable by setting
the SelectInd field to SET_SESSION_SELECTABLE in the STATUSDATA structure.
DosSetSession can be called only by a parent session and only for a child
session. That is, the calling process must be the process that started the
child session using DosStartSession. Neither the parent session itself nor any
grandchild, nor any other descendant session beyond a child session can be the
target of this call.
Additionally, DosSetSession cannot be used to change the status of a session
that was started as an unrelated session. The Related field in the STARTDATA
structure must have been set to 1 when the session was started.
ΓòÉΓòÉΓòÉ 5.5.2.2. Binding Child Sessions to Parent Sessions ΓòÉΓòÉΓòÉ
An application can use DosSetSession to establish a bond between a parent
session and one of its child sessions. When the two sessions are bound, OS/2
brings the child session to the foreground when the user selects the parent
session.
In the following code fragment, a parent session is bound to the child session
specified by the ulSessionID parameter:
#define INCL_DOSPROCESS /* Process and thread values */
#define INCL_DOSSESMGR
#include <os2.h>
ULONG ulSessionID;
STATUSDATA stsdata;
stsdata.Length = sizeof(stsdata);
stsdata.SelectInd = SET_SESSION_UNCHANGED; /* Leaves select setting alone */
stsdata.BondInd = SET_SESSION_BOND; /* Binds parent and child */
DosSetSession(ulSessionID, &stsdata);
When the application uses DosSetSession to establish a parent-child bond, any
bond the parent has with another child session is broken. The application can
remove the parent-child bond by calling DosSetSession with the BondInd field
(in the STATUSDATA structure) set to SET_SESSION_NO_BOND.
A parent session can be executing in either the foreground or the background
when it calls DosSetSession.
ΓòÉΓòÉΓòÉ 5.5.2.3. Switching a Session to the Foreground ΓòÉΓòÉΓòÉ
An application can bring a session to the foreground, or select the session, by
calling DosSelectSession.
DosSelectSession can only be used to select the current session or one of the
current session's child sessions. It cannot be used to select a grandchild
session, or any other descendant session beyond a child session, or any
sessions that were started as unrelated sessions.
The session making the call, or one of its child sessions, must be executing in
the foreground at the time the function is called. A process can call
DosSelectSession with its own session identifier to switch itself to the
foreground when one of its descendants is executing in the foreground.
The following code fragment uses DosSelectSession to switch the child session
specified by the ulSessionID parameter to the foreground for five seconds. The
application then switches the parent session back to the foreground:
#define INCL_DOSPROCESS /* Process and thread values */
#include <os2.h>
ULONG ulSessionID;
DosSelectSession(ulSessionID); /* Switches child to foreground */
DosSleep(5000); /* Sleeps for 5 seconds */
DosSelectSession(0); /* Switches parent back */
ΓòÉΓòÉΓòÉ 5.5.3. Terminating a Session ΓòÉΓòÉΓòÉ
DosStopSession can be used by a parent session to stop one or all of its child
sessions. If the child session specified in the call to DosStopSession has
related sessions, the related sessions are also ended. The parent session can
be running in the foreground or the background when it calls DosStopSession. If
the child session is running in the foreground when it is ended, the parent
session becomes the foreground session.
DosStopSession can only be called by a parent session for a child session.
Neither the parent session itself, nor any grandchild, nor any other descendant
session beyond a child session, nor any unrelated session, can be the target of
this call.
In the following code fragment, the child session specified by the ulSessionID
parameter is ended:
#define INCL_DOSPROCESS /* Process and thread values */
#define INCL_DOSSESMGR
#include <os2.h>
ULONG ulSessionID;
DosStopSession(STOP_SESSION_SPECIFIED,
ulSessionID);
An application can end all its child sessions by setting the first parameter to
STOP_SESSION_ALL in the call to DosStopSession. If this is specified, the
second parameter is ignored.
A process running in a child session can ignore the request to end. If the
process has set up its own exception handler, it might not end immediately
after the call to DosStopSession. The only way the parent process can be
certain that the child session has ended is to wait for notification through
the termination queue specified in the call to DosStartSession that started the
session. When the child session ends, OS/2 writes a data element into the
termination queue, specifying the child process identifier and the termination
status.
If the process in the session specified by DosStopSession has not ended, then
DosStopSession still returns a normal return code. You can ensure that a
process in a session has ended by waiting for notification from the termination
queue specified with DosStartSession.
ΓòÉΓòÉΓòÉ 6. Queues ΓòÉΓòÉΓòÉ
Communication between processes is valuable in a multitasking operating system
to enable concurrent processes to work together. Queues are one of three forms
of interprocess communication (IPC), the other forms of IPC being semaphores
and pipes.
This chapter describes how to create and use queues. Queues enable one or more
processes to transfer data to a specific target process.
Note: The queues used for interprocess communication should not to be confused
with the message queues used for communication between Presentation
Manager (PM) and PM applications, nor with the printer queues used by
the print spooler in managing print jobs.
The following topics are related to the information in this chapter:
Memory (shared memory)
Program execution and control
Semaphores
Pipes
ΓòÉΓòÉΓòÉ 6.1. About Queues ΓòÉΓòÉΓòÉ
A queue is a named, ordered list of elements that is used to pass information
between threads of the same (related) process or between different (unrelated)
processes.
Processes pass information to a queue in the form of elements. An element is a
32-bit unit of information. Queue elements can be values, flags, pointers to
shared memory regions, anything that can fit into 32 bits. The format of a
queue element depends entirely on the process that creates the queue (the queue
owner). Only the queue owner can read elements from the queue; other processes
can only write to the queue. Reading an element automatically removes it from
the queue.
The process that creates the queue is known as the server process of the queue.
The other processes that access the queue are known as client processes.
The owner of the queue (the server process) can choose the order in which to
read incoming information and can examine queue elements without removing them
from the queue. Queue elements can be added and accessed in First-In-First-Out
(FIFO), Last-In-First-Out (LIFO), or priority-based order.
Any process that has the name of a queue can open the queue and write to it.
The processes writing elements to the queue must use the format determined by
the queue owner.
Queues are very efficient. They pass only 32-bit sized elements, rather than
large data structures. However, queues can be used only for one-way
communication, because a client process can write to a queue but cannot read
from one.
Typically, processes use queues to transfer information about the contents of a
shared memory. The elements in the queue could contain the address and length
of data areas in shared memory objects. The sending process allocates a shared
memory object and gives access to the shared memory to the queue owner. The
sending process can free the shared memory after writing the elements to the
queue because the shared memory will not be deallocated until the queue owner
frees it.
Any thread in the process that owns the queue can examine queue elements
without removing them. This is called peeking at the queue.
OS/2 supplies the process identifier of the process that writes an element to
the queue, so that a process reading from or peeking at the queue can determine
the origin of the element. The process identifier is returned as part of a
REQUESTDATA data structure. Threads can use the ulData field of the REQUESTDATA
data structure to pass additional information about the queue element.
If the queue is empty when a process attempts to read from it, the process can
either wait for an element to become available or continue executing without
reading from the queue. Semaphores can be used to indicate when an element is
in the queue.
ΓòÉΓòÉΓòÉ 6.1.1. Queues and Semaphores ΓòÉΓòÉΓòÉ
If a process manages only one queue, it typically waits for an element to
become available. However, if a process manages several queues, waiting for one
queue means that other queues cannot be read. To avoid wasting time while
waiting, a process can supply an event semaphore when it calls DosReadQueue or
DosPeekQueue. The process can then continue to execute without actually reading
an element from the queue, because DosWriteQueue will post the semaphore only
when an element is ready. The semaphore remains posted until someone resets it;
usually the queue owner process resets the semaphore after it reads all the
available information from the queue.
If a process uses a unique semaphore for each queue, it can use
DosWaitMuxWaitSem to wait for the first queue to receive an element.
Only one semaphore is permitted per queue.
ΓòÉΓòÉΓòÉ 6.1.2. Queue Servers and Clients ΓòÉΓòÉΓòÉ
The server process and its threads have certain queue-managing privileges. Only
the server process and its threads can:
Examine queue elements without removing them (DosPeekQueue)
Remove elements from the queue (DosReadQueue)
Purge all the elements in a queue (DosPurgeQueue)
Write to the queue without opening it first (DosWriteQueue)
Delete the queue (DosCloseQueue).
Both server and client processes can query the number of elements in the queue
using DosQueryQueue.
Client processes can query the queue (DosQueryQueue) and add elements to it
(DosWriteQueue), but they must first gain access to the queue by calling
DosOpenQueue. When a client process is finished with a queue, it ends its
access to the queue by calling DosCloseQueue. (Note that, unlike the server
process and its threads, a client process cannot use DosCloseQueue to delete a
queue.)
When a queue is opened by a client process, an access count is set to 1. Each
client process has its own access count. The access count is incremented
whenever a thread in a process opens the queue and decremented whenever a
thread in the process closes the queue. Access to the queue by the client
process ends when the access count for the process reaches 0. When the server
process closes the queue, the queue is terminated and removed from the system.
ΓòÉΓòÉΓòÉ 6.1.3. Queue Element Order ΓòÉΓòÉΓòÉ
DosReadQueue reads either a specified element or the first element in the
queue. The first element in the queue depends on the queue type, which is
specified when the queue is created. A queue can have FIFO, LIFO, or priority
ordering.
Priority values range from 0 (lowest priority) through 15 (highest priority).
The writing process assigns a priority to a queue element when the element is
written to the queue. DosReadQueue reads elements from the queue in descending
order of priority, regardless of the order in which DosWriteQueue placed the
elements in the queue. Elements with equal priority are read in FIFO order.
ΓòÉΓòÉΓòÉ 6.1.4. Obtaining Information about Queues and Queue Elements ΓòÉΓòÉΓòÉ
Any thread in the process that owns the queue can use DosPeekQueue to examine
the elements in the queue to determine which one to actually read. Each call to
DosPeekQueue returns the identifier of the next element in the queue, so the
function can be called repeatedly to move through the queue. The identifier of
the desired element can then be supplied to DosReadQueue.
Any process that has opened a queue can use DosQueryQueue to determine the
number of elements in the queue. This function also returns an error value if
the queue owner has closed the queue.
ΓòÉΓòÉΓòÉ 6.2. Using Queues ΓòÉΓòÉΓòÉ
Queues are useful for a process to manage input from other processes. The
examples in the following sections show how to create and use queues.
Note: In the example code fragments that follow, error checking was left out
to conserve space. Applications should always check the return code that
the functions return. Control Program functions return an APIRET value.
A return code of 0 indicates success. If a non-zero value is returned,
an error occurred.
ΓòÉΓòÉΓòÉ 6.2.1. Creating a Queue ΓòÉΓòÉΓòÉ
A thread creates a queue by using DosCreateQueue and specifying a queue name
and the queue type as arguments. The queue name must be unique and have the
following form:
\QUEUES\QueName
The "\QUEUES\" is required, though it need not be uppercase. It is not a
subdirectory.
The QueName parameter must conform to the rules for OS/2 file names, although
no actual file is created for the queue.
The process that creates the queue is known as the server process of the queue.
The other processes that access the queue are known as client processes.
The following code fragment creates a FIFO queue named \queues\sample.que:
#define INCL_DOSQUEUES /* Queue values */
#include <os2.h>
HQUEUE hq;
DosCreateQueue(&hq, QUE_FIFO |
QUE_CONVERT_ADDRESS,
"\\queues\\sample.que");
When the server process creates the queue, it determines whether the ordering
of queue elements is based on arrival (FIFO or LIFO) or priority. If the
ordering is based on priority, then priority values must be assigned whenever
data is added to the queue.
The server must also specify whether OS/2 is to convert 16-bit addresses of
elements placed in the queue by 16-bit processes to 32-bit addresses.
After a process has created a queue, any thread in that process can access the
queue with equal authority.
ΓòÉΓòÉΓòÉ 6.2.2. Allocating Memory for Queue Data ΓòÉΓòÉΓòÉ
When queues are used only to pass the addresses to data rather than the data
itself, processes must allocate shared memory objects for storing queue data.
The two most common methods of storing queue data are:
Using a named shared memory object - for related processes
Using unnamed shared memory objects - for unrelated processes
ΓòÉΓòÉΓòÉ 6.2.2.1. Named Shared Memory Objects ΓòÉΓòÉΓòÉ
Related processes generally use a single named shared memory object for storing
queue data. The server process allocates the memory object by calling
DosAllocSharedMem. Care must be taken to ensure that the memory object is large
enough to meet application requirements.
The name of the shared memory object is established by agreement among the
server and the client processes. For simplicity, the name can be the same as
the queue name, except that the prefix \SHAREMEM\ must be used instead of
\QUEUES\.
A client process accesses the named shared memory object by calling
DosGetNamedSharedMem. It must then call DosOpenQueue to gain access to the
queue of the server.
Before the server process ends, it releases the memory object by calling
DosFreeMem.
ΓòÉΓòÉΓòÉ 6.2.2.2. Unnamed Shared Memory Objects ΓòÉΓòÉΓòÉ
Unrelated processes generally use unnamed shared memory objects for storing
queue data. This makes it possible for a client process to store data in a
shared memory object without knowing its name. To use unnamed shared memory
objects for storing queue data, the server process must take the following
steps whenever it is called by a client:
1. Save the process identification (PID) of the client process.
2. Allocate an unnamed shared memory object for the data of the client
process by calling DosAllocSharedMem.
3. Give the client process the capability of accessing the memory object by
calling DosGiveSharedMem with the client's PID.
The client process must then call DosOpenQueue to gain access to the server's
queue.
After each client completes its queue requests or ends, the server calls
DosFreeMem to release the client's memory object.
ΓòÉΓòÉΓòÉ 6.2.3. Opening a Queue ΓòÉΓòÉΓòÉ
Once the queue is created, the server process of the queue and the threads of
the server process have immediate access to the queue and can proceed to access
the queue. A client process must request access to a queue by calling
DosOpenQueue. Once the queue is open, the client process can add an element to
the queue with DosWriteQueue, and it can query the number of elements in the
queue with DosQueryQueue.
DosOpenQueue retrieves the queue handle and the process identifier of the queue
owner. The function also increments the queue's access count.
The following code fragment shows how another process would open the queue
created with DosCreateQueue.
#define INCL_DOSQUEUES
#include<os2.h>
#define HF_STDOUT 1 /* Standard output handle */
HQUEUE hq;
PID pidOwner;
ULONG ulWritten;
APIRET ulrc;
ulrc = DosOpenQueue(&pidOwner,
&hq,
"\\queues\\sample.que");
if (ulrc) {
DosWrite(HF_STDOUT,
"\r\n Queue open failed. \r\n",
24,
&ulWritten);
DosExit(EXIT_PROCESS,
1);
}
else {
DosWrite(HF_STDOUT,
"\r\n Queue opened. \r\n",
19,
&ulWritten);
}
When it is finished with the queue, a thread in the client process ends its
access by calling DosCloseQueue. DosCloseQueue decrements the access count for
the process each time it is called. When the access count reaches 0, the
connection between the client process and the queue is terminated.
After a process has opened a queue, any thread in that process can access the
queue with equal authority.
Note: If a queue was created by a call to the 16-bit DosCreateQueue, then it
is not accessible to 32-bit DosOpenQueue requests, and
ERROR_QUE_PROC_NO_ACCESS will be returned.
ΓòÉΓòÉΓòÉ 6.2.4. Writing to a Queue ΓòÉΓòÉΓòÉ
The server process and any of its threads can add an element to a queue simply
by calling DosWriteQueue. A client process, however, must first request access
to the queue by calling DosOpenQueue.
Processes that communicate by passing the addresses of shared memory objects
through the queue must have a shared memory object that they each have access
to. Once a process opens the queue, it can allocate shared memory by using
DosAllocMem with the OBJ_GIVEABLE attribute and then give the shared memory to
the queue owner with DosGiveSharedMem.
A process that has opened a queue can write to the queue by using
DosWriteQueue. The writing process must create elements in a form that the
queue owner can read.
The following code fragment adds an element to a queue. Assume that the caller
has placed the handle of the queue into QueueHandle already. Assume also that
DataBuffer has been set to point to a data element in shared memory, and that
DataLength has been set to contain the length of the data element in shared
memory.
#define INCL_DOSQUEUES /* Queue values */
#include <os2.h>
#include <stdio.h>
HQUEUE hqQueueHandle; /* Queue handle */
ULONG ulRequest; /* Request-identification data */
ULONG ulDataLength; /* Length of element being added */
PVOID pDataBuffer; /* Element being added */
ULONG ulElemPriority; /* Priority of element being added */
APIRET ulrc; /* Return code */
ulRequest = 0; /* Assume that no special data is being */
/* sent along with this write request */
ulElemPriority = 0; /* For priority-based queues: add the */
/* new queue element at the logical end */
/* of the queue */
ulrc = DosWriteQueue(hqQueueHandle,
ulRequest,
ulDataLength,
pDataBuffer,
ulElemPriority);
if (ulrc != 0) {
printf("DosWriteQueue error: return code = %ld",
ulrc);
return;
}
Once the process has written to the queue, it frees the shared memory. However,
the memory will not be freed until the queue owner also frees it.
If the queue was created as a priority-based queue (as specified in the
QueueFlags parameter of DosCreateQueue), then the priority of the element that
is being added must be specified.
If the server process has ended, or if it has closed the queue before
DosWriteQueue is called, then ERROR_QUE_INVALID_HANDLE is returned.
ΓòÉΓòÉΓòÉ 6.2.5. Reading from a Queue ΓòÉΓòÉΓòÉ
The queue owner (server process) and its threads can read an element from the
queue by using DosReadQueue. The owner can read the first element in the queue
by specifying 0 as the element number. Alternatively, the owner can read a
particular element in the queue by specifying an element code returned from
DosPeekQueue. This function is not available to client processes.
DosReadQueue can either remove queue elements in the order that was specified
when the queue was created (FIFO, LIFO, or priority), or it can use an element
identifier from DosPeekQueue as input to remove a previously examined element.
The following code fragment reads an element from the queue. Assume that the
caller has placed the handle of the queue into QueueHandle already and that the
identifier of the process that owns the queue has been placed into OwningPID
already.
#define INCL_DOSQUEUES /* Queue values */
#include <os2.h>
#include <stdio.h>
HQUEUE hqQueueHandle; /* Queue handle */
REQUESTDATA rqRequest; /* Request-identification data */
ULONG ulDataLength; /* Length of element received */
PULONG pulDataAddress; /* Address of element received */
ULONG ulElementCode; /* Request a particular element */
BOOL32 bNoWait; /* No wait if queue is empty */
BYTE bElemPriority; /* Priority of element received */
HEV hevSemHandle; /* Semaphore handle */
PID pidOwningPID; /* PID of queue owner */
APIRET ulrc; /* Return code */
rqRequest.pid = pidOwningPID; /* Set request data block to indicate */
/* queue owner */
ulElementCode = 0; /* Indicate that the read should start */
/* at the front of the queue */
bNoWait = 0; /* Indicate that the read should wait */
/* if the queue is currently empty */
hevSemHandle = 0; /* Unused since this is a call that */
/* waits synchronously */
ulrc = DosReadQueue(hqQueueHandle,
&rqRequest,
&ulDataLength,
(PVOID *) &pulDataAddress,
ulElementCode,
bNoWait,
&bElemPriority,
hevSemHandle);
if (ulrc != 0) {
printf("DosReadQueue error: return code = %ld",
ulrc);
return;
}
On successful return, DataLength contains the size of the element on the queue
that is pointed to by the pointer within DataAddress, ElemPriority has been
updated to contain the priority of the queue element pointed to by DataAddress,
and Request.ulData contains any special data that the DosWriteQueue caller
placed into the queue.
If the queue is empty and NoWait is set to DCWW_WAIT (0), the calling thread
waits until an element is placed in the queue. If the queue is empty and NoWait
is set to DCWW_NOWAIT (1), DosReadQueue returns immediately with
ERROR_QUE_EMPTY.
If NoWait is set to DCWW_NOWAIT, an event semaphore must be provided so that
the calling thread can determine when an element has been placed in the queue.
The semaphore is created by calling DosCreateEventSem, and its handle is
supplied as a DosReadQueue parameter. The first time an event semaphore handle
is supplied in a DosReadQueue or DosPeekQueue request for which DCWW_NOWAIT has
been specified for a particular queue, the handle is saved by the system. The
same handle must be supplied in all subsequent DosReadQueue and DosPeekQueue
requests that are called for that queue; if a different handle is supplied,
ERROR_INVALID_PARAMETER is returned.
When a client process adds an element to the queue, the system automatically
opens the semaphore (if necessary) and posts it. The server can either call
DosQueryEventSem periodically to determine whether the semaphore has been
posted, or it can call DosWaitEventSem. DosWaitEventSem causes the calling
thread to block until the semaphore is posted.
After the event semaphore has been posted, the calling thread must call
DosReadQueue again to remove the newly added queue element.
If QUE_CONVERT_ADDRESS is specified in the call to DosCreateQueue, OS/2 will
automatically convert 16-bit addresses to 32-bit addresses.
ΓòÉΓòÉΓòÉ 6.2.6. Peeking at a Queue ΓòÉΓòÉΓòÉ
The server process and its threads can examine a queue element by calling
DosPeekQueue. This function is not available to client processes.
Unlike DosReadQueue, DosPeekQueue does not remove the element from the queue.
DosPeekQueue can either examine elements in the order that was specified when
the queue was created (FIFO, LIFO, or priority), or it can examine the next
element in the queue after a previous DosPeekQueue request has been called. By
making multiple DosPeekQueue requests, the server process can search through a
queue, examining each element in turn. When it locates the element it is
searching for, the server process can remove the element from the queue by
calling DosReadQueue.
If several threads are using the same queue, the process writing to the queue
can use the ulData field of the REQUESTDATA data structure to indicate that an
element is directed to a particular thread. The thread can peek at the queue
whenever data is available and read any elements containing the appropriate
value in the ulData field.
The following code fragment shows how a thread can use DosPeekQueue to examine
the elements in a queue. Assume that a previous call to DosOpenQueue provided
the queue handle that is contained in QueueHandle. Assume that the identifier
of the process that owns the queue has been placed into OwningPID already.
#define INCL_DOSQUEUES /* Queue values */
#define INCL_DOSPROCESS /* needed for DCWW_WAIT */
#include <os2.h>
#include <stdio.h>
HQUEUE hqQueueHandle; /* Queue handle */
REQUESTDATA rqRequest; /* Request-identification data */
ULONG ulDataLength; /* Length of examined element */
PVOID pDataAddress; /* Address of examined element */
ULONG ulElementCode; /* Indicator of examined element */
BOOL32 bNoWait; /* No wait if queue is empty */
BYTE bElemPriority; /* Priority of examined element */
HEV hevSemHandle; /* Semaphore handle */
PID pidOwningPID; /* PID of queue owner */
APIRET ulrc; /* Return code */
rqRequest.pid = pidOwningPID; /* Set request data block to indicate */
/* queue owner */
ulElementCode = 0; /* Indicate that the peek should start */
/* at the front of the queue */
bNoWait = DCWW_WAIT; /* Indicate that the peek call should */
/* wait if the queue is currently empty */
hevSemHandle = 0; /* Unused since this is a call that */
/* synchronously waits */
ulrc = DosPeekQueue(hqQueueHandle,
&rqRequest,
&ulDataLength,
&pDataAddress,
&ulElementCode,
bNoWait,
&bElemPriority,
hevSemHandle);
if (ulrc != 0) {
printf("DosPeekQueue error: return code = %ld",
ulrc);
return;
}
On successful return, DataLength contains the size of the element on the queue
that is pointed to by the pointer within DataAddress, ElementCode has been
updated to indicate the next queue element, ElemPriority has been updated to
contain the priority of the queue element pointed to by DataAddress, and
Request.ulData contains any special data that the DosWriteQueue caller placed
into the queue.
If the queue is empty and NoWait is set to DCWW_WAIT (0), the calling thread
waits until an element is placed in the queue. If the queue is empty and NoWait
is set to DCWW_NOWAIT (1), DosPeekQueue returns immediately with
ERROR_QUE_EMPTY.
If NoWait is set to DCWW_NOWAIT, an event semaphore must be provided so that
the calling thread can determine when an element has been placed in the queue.
The semaphore is created by calling DosCreateEventSem, and its handle is
supplied as a DosPeekQueue parameter. The first time an event semaphore handle
is supplied in a DosPeekQueue or DosReadQueue request for which DCWW_NOWAIT has
been specified for a particular queue, the handle is saved by the system. The
same handle must be supplied in all subsequent DosPeekQueue and DosReadQueue
requests that are called for that queue; if a different handle is supplied,
ERROR_INVALID_PARAMETER is returned.
When a client process adds an element to the queue, the system automatically
opens the semaphore (if necessary) and posts it. The server can either call
DosQueryEventSem periodically to determine whether the semaphore has been
posted, or it can call DosWaitEventSem. DosWaitEventSem causes the calling
thread to block until the semaphore is posted.
After the event semaphore has been posted, the calling thread must call
DosPeekQueue again to examine the newly added queue element.
If QUE_CONVERT_ADDRESS is specified in the call to DosCreateQueue, OS/2 will
automatically convert 16-bit addresses to 32-bit addresses.
ΓòÉΓòÉΓòÉ 6.2.7. Purging a Queue ΓòÉΓòÉΓòÉ
The server process or any of its threads can empty a queue of all its elements
by calling DosPurgeQueue. This function is not available to client processes.
Warning: This is an unconditional purge of all elements in the queue.
The following code fragment shows how the owner of a queue can empty the queue
of all data elements. Assume that the owner of the queue has saved the queue's
handle (obtained in a previous call to DosCreateQueue) in QueueHandle.
#define INCL_DOSQUEUES /* Queue values */
#include <os2.h>
#include <stdio.h>
HQUEUE hqQueueHandle; /* Queue handle */
APIRET ulrc; /* Return code */
ulrc = DosPurgeQueue(hqQueueHandle);
if (ulrc != 0) {
printf("DosPurgeQueue error: return code = %ld",
ulrc);
return;
}
ΓòÉΓòÉΓòÉ 6.2.8. Closing a Queue ΓòÉΓòÉΓòÉ
DosCloseQueue can be used both to end access to a queue and to delete a queue.
The action taken as a result of a DosCloseQueue request depends on:
Whether the requesting process is the server process or a client process
The value of the access count, which is maintained for each client
process by OS/2. The access count for a client process is incremented
whenever DosOpenQueue is called, and decremented whenever DosCloseQueue
is called.
If the requesting process is a client, and the access count equals 0,
DosCloseQueue ends the client's access to the queue, but the queue itself is
not affected. If the access count does not equal 0, the count is decremented,
but the process retains access to the queue.
If the requesting process is the server, DosCloseQueue purges any outstanding
elements from the queue and deletes the queue regardless of the access count;
client processes that still have the queue open receive
ERROR_QUE_INVALID_HANDLE on their next request.
ΓòÉΓòÉΓòÉ 7. Semaphores ΓòÉΓòÉΓòÉ
Communication between processes is valuable in a multitasking operating system
to enable concurrent processes to work together. Semaphores are one of three
forms of interprocess communication (IPC), the other forms of IPC being pipes
and queues.
This chapter describes how to create and use semaphores. Semaphores enable an
application to signal the completion of tasks and control access to resources
that are shared between more than one thread or process.
The following topics are related to the information in this chapter:
Memory (shared memory)
Program execution and control
Pipes
Queues
ΓòÉΓòÉΓòÉ 7.1. About Semaphores ΓòÉΓòÉΓòÉ
Semaphores signal the beginning or ending of an operation and provide mutually
exclusive ownership of resources. Typically, semaphores are used to prevent
more than one process or thread within a process from accessing a resource,
such as shared memory, at the same time.
Semaphores are defined by OS/2 and reside in an internal memory buffer. They
are divided into three types, according to the functionality they provide:
Event semaphores enable a thread to notify waiting threads that an event
has occurred. The waiting threads then resume execution, performing
operations that are dependent on the completion of the signaled event.
Mutual exclusion (mutex) semaphores enable threads to serialize their
access to shared resources. That is, ownership of a mutex semaphore is
used by cooperating threads as a prerequisite for performing operations
on a resource. (Threads cooperate by using the mutex semaphore functions
to ensure that access to the resource is mutually exclusive.)
Multiple wait (muxwait) semaphores enable threads to wait either for
multiple events to occur, or for multiple resources to become available.
Alternatively, a flag can be set so that a thread waits for any one of
multiple events to occur, or for any one of multiple resources to become
available.
ΓòÉΓòÉΓòÉ 7.1.1. Event Semaphores ΓòÉΓòÉΓòÉ
An event semaphore provides a signaling mechanism among threads or processes,
ensuring that events occur in the desired sequence. Event semaphores are used
by one thread to signal other threads that an event has occurred. An
application can use this type of semaphore to block a thread or process until
the event has occurred.
An event semaphore has two states, reset and posted. When an event semaphore is
in the reset state, OS/2 blocks any thread or process that is waiting on the
semaphore. When an event semaphore is in the posted state, all threads or
processes waiting on the semaphore resume execution.
For example, assume thread 1 is allocating a shared memory object and threads 2
and 3 must wait for the memory to be allocated before they attempt to examine
its contents. Before thread 1 allocates the memory, it creates an event
semaphore, specifying the initial state of the semaphore as reset. (If the
event semaphore has already been created, thread 1 simply resets the
semaphore.) Threads 2 and 3 use DosWaitEventSem to wait for the semaphore to
signal that the event, in this case the allocation and preparation of the
shared memory object, has been completed. Because the semaphore was reset by
thread 1, threads 2 and 3 are blocked when they call DosWaitEventSem. After
thread 1 has finished allocating and placing data in the shared memory object,
it signals the completion of its task by posting the event semaphore. The
posting of the event semaphore unblocks threads 2 and 3, enabling them to
resume execution. They can then proceed to examine the contents of the
allocated memory.
In the example above, one thread controls the resetting and posting of the
event semaphore, while other threads merely wait on the semaphore. Another
approach could be for an application or thread to reset an event semaphore,
then block itself on that semaphore. At a later time, another application or
thread would post the event semaphore, unblocking the first thread.
ΓòÉΓòÉΓòÉ 7.1.2. Mutual Exclusion (Mutex) Semaphores ΓòÉΓòÉΓòÉ
A mutual exclusion (mutex) semaphore protects resources (such as files, data in
memory, and peripheral devices) from simultaneous access by several processes.
Mutex semaphores enable threads to serialize their access to resources. It does
so by preventing the processes from concurrently executing the sections of code
through which access is made. These sections of code are called critical
sections. For example, a mutex semaphore could be used to prevent two or more
threads from simultaneously writing to the same file on a disk.
Before a thread can execute a mutex-protected critical section, it must request
and receive ownership of the mutex semaphore. Only the thread that has gained
ownership of the mutex semaphore is permitted to perform operations on the
protected resource. Only one thread at a time can own the mutex semaphore, and
the owner thread retains ownership until it finishes executing its critical
section. When finished, the owner thread releases the mutex semaphore, enabling
another thread to become the owner.
When a thread requests ownership of a mutex semaphore that is already owned,
OS/2 blocks the thread. When more than one thread requests ownership of the
same semaphore, OS/2 queues the requests and grants subsequent ownership based
on the thread's priority and the order in which the requests were received.
If more than one thread is blocked on a DosRequestMutexSem request, then
ownership is given to the thread that has the highest priority level. If more
than one of the waiting threads have the same priority level, then FIFO
ordering is used to determine which thread is unblocked and given ownership of
the semaphore.
For example, both thread 1 and thread 2 must write information to the same disk
file. Thread 1 claims ownership of an agreed-upon mutex semaphore and starts
writing its information to the file. If thread 2 also requests ownership of the
semaphore, it will be blocked. When thread 1 has finished writing to the file,
it releases the semaphore. OS/2 then unblocks thread 2 and designates it as the
new owner of the semaphore so that it can write to the file.
During process termination, after delivery of process-termination exceptions
and unwind exceptions, if any threads in the process aside from Thread 1 (the
main thread) own a mutex semaphore, ownership of the semaphore (and therefore,
the shared resource) passes to Thread 1. This gives Thread 1 a last chance to
clean up the semaphore and the shared resource before the process ends. If
Thread 1 ends without releasing the semaphore, all threads that are currently
waiting on ownership of the semaphore will be unblocked with the SEM_OWNER_DIED
return code. Any thread that attempts to open it or request ownership of the
semaphore will receive a SEM_OWNER_DIED return code.
The recommended way to clean up semaphores, and other resources, is for each
thread, especially Thread 1, to have an exception handler to handle clean up
during process termination (the XCPT_PROCESS_TERMINATE or
XCPT_ASYNC_PROCESS_TERMINATE exceptions). When it is not possible to register
an exception handler for a thread, (a DLL, for example, must de-register its
exception handlers when it returns control to the thread that called it), you
should add a clean up routine to the exit list of the process.
ΓòÉΓòÉΓòÉ 7.1.3. Multiple Wait (Muxwait) Semaphores ΓòÉΓòÉΓòÉ
A multiple wait (muxwait) semaphore enables a thread to wait on several event
or mutex semaphores simultaneously. A muxwait semaphore is a compound semaphore
that consists of a list of up to 64 event semaphores or mutex semaphores (the
two types cannot be mixed).
A flag is set when the muxwait semaphore is created to enable threads to use
the semaphore in either of two ways:
Threads can wait for all of the mutex semaphores to be released, or for
all of the event semaphores to be posted.
Threads can wait for any one of the mutex semaphores in the list to be
released, or for any one of the event semaphores in the list to be
posted.
Depending on the value of the flag, a muxwait semaphore is said to have
cleared when either any or all of the semaphores in the muxwait list have been
posted or released.
For example, suppose a thread requires access to several regions of shared
memory at the same time. OS/2 blocks the thread until the thread acquires
ownership of all the mutex semaphores protecting the shared regions. The
thread can then access all the memory regions. Meanwhile, OS/2 prevents access
by other threads.
ΓòÉΓòÉΓòÉ 7.1.4. Named and Anonymous Semaphores ΓòÉΓòÉΓòÉ
A semaphore can be either named or anonymous. A named semaphore is always
shared; that is, it is always available to any process that knows the name. An
anonymous semaphore can be either private to a process or shared among
processes, depending on whether the application includes the DC_SEM_SHARED flag
in the function that creates the semaphore. A semaphore intended for use solely
among threads of the same process can be anonymous and private.
OS/2 creates a named semaphore when an application specifies a name in the
function that creates the semaphore. The name must have the following form:
\SEM32\SemName
The "\SEM32\" is required, though it need not be uppercase. The semaphore name
must conform to the rules for OS/2 file names, although no actual file is
created for the semaphore. If the application does not specify a name in the
function that creates the semaphore, OS/2 creates an anonymous semaphore.
OS/2 permits a system-wide maximum of 65536 (64K) shared semaphores. In
addition, each process can use up to 65536 (64K) private semaphores.
A shared muxwait semaphore must contain either all shared event semaphores or
all shared mutex semaphores. However, a private muxwait semaphore can contain a
combination of shared and private event or mutex semaphores. OS/2 generates a
unique handle when it creates a semaphore. Processes must obtain this handle
before they can access the semaphore. A semaphore's handle is always available
to the process that created the semaphore. A process can obtain the handle of a
named semaphore created in another process by using the appropriate
semaphore-opening function. A process that requires access to an anonymous
shared semaphore that was created in another process must obtain the handle of
the semaphore through some other form of interprocess communication, such as a
pipe or a queue.
ΓòÉΓòÉΓòÉ 7.1.5. Semaphore Management ΓòÉΓòÉΓòÉ
After one process creates a semaphore, threads in other processes must open the
semaphore before they can access it. (Creating a semaphore automatically opens
it for the creating process.) The open operation ensures that the process is a
valid user of the semaphore. OS/2 keeps track of the number of open operations
that each process performs on a semaphore. A process can have up to 65535 (64K
- 1) open operations performed on a semaphore at any one time.
If a process finishes using a semaphore and will not use it again, the process
should close the semaphore so that OS/2 can free the memory the semaphore is
using. OS/2 returns the ERROR_SEM_BUSY error value if a thread tries to close a
semaphore that has another thread in the same process still waiting for it.
If a process terminates with open semaphores, OS/2 automatically closes the
semaphores for that process.
Semaphores reside in a memory buffer rather than a disk file. Therefore, when
the last process that has a semaphore open exits or closes that semaphore, OS/2
frees the associated handle or name.
When an application calls a function that causes a thread to wait on a
semaphore, the application can specify the amount of time for the thread to
wait. When the interval elapses without the semaphore being posted or released,
the function returns the ERROR_TIMEOUT error value and the thread continues
running. The application can provide a specific time-out value in milliseconds,
or it can specify either the SEM_INDEFINITE_WAIT or the SEM_IMMEDIATE_RETURN
flag. If a thread is interrupted while it is waiting on a semaphore, the
ERROR_INTERRUPT error value is returned to the caller.
ΓòÉΓòÉΓòÉ 7.2. Using Event Semaphores ΓòÉΓòÉΓòÉ
An application can use an event semaphore to trigger execution of other
processes. This is useful if, for example, one process provides data to many
other processes. Using an event semaphore frees the other process from the
trouble of polling to determine when new data is available.
Note: In the example code fragments that follow, error checking was left out
to conserve space. Applications should always check the return code that
the functions return. Control Program functions return an APIRET value.
A return code of 0 indicates success. If a non-zero value is returned,
an error occurred.
ΓòÉΓòÉΓòÉ 7.2.1. Creating an Event Semaphore ΓòÉΓòÉΓòÉ
Processes create an event semaphore by using DosCreateEventSem. The process
that controls the event or resource is usually the one that creates the
semaphore, but it does not have to be.
Threads in the process that creates the semaphore do not have to open the
semaphore before using it. DosCreateEventSem obtains access to the semaphore
for the calling process and its threads. Threads in other processes must call
DosOpenEventSem to open the semaphore before they can use it.
Event semaphores can be defined as either private or shared:
Private semaphores are always unnamed and are therefore always identified
by their handles. They can be used only by threads within a single
process.
Shared semaphores can be either named or unnamed. If named, they can be
opened using either the name or the handle. The handle returned by
DosOpenEventSem is then used to identify the semaphore for all other
functions. Semaphore names must include the prefix \SEM32\ and must
conform to file system naming conventions. Shared semaphores can be used
by threads in multiple processes.
In the following code fragment, the controlling process creates a named event
semaphore and posts the semaphore after writing data to a shared file:
#define INCL_DOSSEMAPHORES /* Semaphore values */
#include <os2.h>
HEV hevWriteEvent;
DosCreateEventSem("\\sem32\\wrtevent", /* Named-shared semaphore */
&hevWriteEvent, 0, FALSE); /* Initially reset */
.
.
/* Write data to shared file. */
.
.
DosPostEventSem(hevWriteEvent); /* Posts the event */
.
. /* Continue execution. */
.
There is a system-wide limit of 65536 (64K) shared semaphores (including
mutex, event, and muxwait semaphores); in addition, each process can have up
to 65536 (64K) private semaphores.
When an event semaphore is created, a flag is used to specify the initial
state of the event semaphore, either reset or posted. If the initial state is
reset, a thread that calls DosWaitEventSem will be blocked until a process
that has access to the semaphore uses DosPostEventSem to post the event
semaphore. If the initial state is posted, then a thread that calls
DosWaitEventSem will return immediately to continue its execution. If the
thread calling DosWaitEventSem is not in the process that created the
semaphore, the thread must open the semaphore with DosOpenEventSem before
calling DosWaitEventSem.
OS/2 maintains a usage count for each semaphore. DosCreateEventSem initializes
the usage count to 1. Thereafter, each call to DosOpenEventSem increments the
count, and each call to DosCloseEventSem decrements it.
ΓòÉΓòÉΓòÉ 7.2.2. Opening an Event Semaphore ΓòÉΓòÉΓòÉ
When a process creates an event semaphore, all of the threads that belong to
the process have immediate access to the semaphore.
Threads in other processes must open the semaphore by calling DosOpenEventSem
before they can use the semaphore in any other event semaphore function.
The following code fragment shows how processes can open an event semaphore
that was created in a different process and then wait for the event to be
posted:
#define INCL_DOSSEMAPHORES /* Semaphore values */
#include <os2.h>
HEV hevEventHandle = 0; /* Must be 0 because we are opening */
/* the semaphore by name */
DosOpenEventSem("\\sem32\\wrtevent", &hevEventHandle);
DosWaitEventSem(hevEventHandle,
SEM_INDEFINITE_WAIT); /* Waits until event is posted */
.
. /* Read from file when event is posted. */
.
Applications can open an event semaphore by name or by handle. If the name is
used to open the semaphore, as in the code fragment above, the handle parameter
must be 0. If the handle is used to open the semaphore, the name parameter must
be NULL.
Access to semaphores is on a per-process basis. Therefore, a semaphore that has
been opened by one thread in a process is open to all other threads in that
process as well.
DosOpenEventSem merely provides access to an event semaphore. In order to wait
for an event semaphore to be posted, a thread must call DosWaitEventSem. In
order to post or reset an open event semaphore, a thread uses DosPostEventSem
or DosResetEventSem respectively.
When a process no longer requires access to an event semaphore, it closes the
semaphore by calling DosCloseEventSem. If a process ends without closing an
open semaphore, the semaphore is closed by OS/2.
Each call to DosOpenEventSem increments the usage count of the semaphore. This
count is initialized to 1 when the semaphore is created and is decremented by
each call to DosCloseEventSem. When the usage count reaches 0, the semaphore is
deleted by OS/2.
Calls to DosOpenEventSem and DosCloseEventSem can be nested, but the usage
count for a semaphore cannot exceed 65535. If an attempt is made to exceed this
number, ERROR_TOO_MANY_OPENS is returned.
ΓòÉΓòÉΓòÉ 7.2.3. Closing an Event Semaphore ΓòÉΓòÉΓòÉ
When a process no longer requires access to an event semaphore, it closes the
semaphore by calling DosCloseEventSem.
The following code fragment closes an event semaphore. Assume that the handle
of the semaphore has been placed into HEV already.
#define INCL_DOSSEMAPHORES /* Semaphore values */
#include <os2.h>
#include <stdio.h>
HEV hev; /* Event semaphore handle */
APIRET ulrc; /* Return code */
ulrc = DosCloseEventSem(hev);
if (ulrc != 0) {
printf("DosCloseEventSem error: return code = %ld",
ulrc);
return;
}
Calls to DosOpenEventSem and DosCloseEventSem can be nested, but the usage
count for a semaphore cannot exceed 65535. If an attempt is made to exceed this
number, ERROR_TOO_MANY_OPENS is returned.
If a process ends without closing an open semaphore, the semaphore is closed by
OS/2.
Each call to DosCloseEventSem decrements the usage count of the semaphore. This
count is initialized to 1 when the semaphore is created and is incremented by
each call to DosOpenEventSem. When the usage count reaches 0, the semaphore is
deleted from OS/2. The call to DosCloseEventSem that decrements the usage count
to 0 and causes the semaphore to be deleted is referred to as the final close.
If a thread attempts to perform the final close for a semaphore while another
thread in the same process is still waiting for it, ERROR_SEM_BUSY is returned.
ΓòÉΓòÉΓòÉ 7.2.4. Resetting an Event Semaphore ΓòÉΓòÉΓòÉ
DosResetEventSem resets an event semaphore if it is not already reset, and
returns the number of times the semaphore was posted since it was last reset.
All threads that subsequently call DosWaitEventSem for this semaphore will be
blocked.
Any thread belonging to the process that created the event semaphore can change
the state of the semaphore to reset by calling DosResetEventSem. Threads in
other processes can also call DosResetEventSem, but they must first gain access
to the semaphore by calling DosOpenEventSem.
When an event semaphore is in the reset state, any thread that calls
DosWaitEventSem to wait for the semaphore will be blocked. When the event
semaphore is posted, all of the threads that are waiting for the semaphore are
released to continue execution.
The following code fragment resets an event semaphore. Assume that the handle
of the semaphore has been placed into HEV already.
#define INCL_DOSSEMAPHORES /* Semaphore values */
#include <os2.h>
#include <stdio.h>
HEV hev; /* Event semaphore handle */
ULONG ulPostCt; /* Post count for the event semaphore (returned) */
APIRET ulrc; /* Return code */
ulrc = DosResetEventSem(hev, &ulPostCt);
if (ulrc != 0) {
printf("DosResetEventSem error: return code = %ld",
ulrc);
return;
}
DosResetEventSem returns the post count of the event semaphore and resets the
post count to 0. The post count is the number of times the semaphore has been
posted (using DosPostEventSem) since the last time the semaphore was in the
reset state. (An event semaphore can be reset when it is created, as well as by
calling DosResetEventSem.) The post count can also be obtained by calling
DosQueryEventSem.
If the event semaphore is already reset when DosResetEventSem is called,
ERROR_ALREADY_RESET is returned, along with a post count of 0. The semaphore is
not reset a second time.
ΓòÉΓòÉΓòÉ 7.2.5. Posting an Event Semaphore ΓòÉΓòÉΓòÉ
DosPostEventSem posts the semaphore, if it is not already posted, and
increments the post count. All threads that have called DosWaitEventSem for
this semaphore are unblocked and resume execution. Threads that call
DosWaitEventSem after the event semaphore has been posted and before the next
time it is reset, will return immediately from a call to DosWaitEventSem and
continue execution. If the semaphore is subsequently reset, threads that call
DosWaitEventSem will again be blocked.
Any thread in the process that created an event semaphore can post the
semaphore by calling DosPostEventSem. Threads in other processes can also call
DosPostEventSem, but they must first gain access to the semaphore by calling
DosOpenEventSem.
The following code fragment posts a system event semaphore. Assume that the
handle of the semaphore has been placed into HEV already.
#define INCL_DOSSEMAPHORES /* Semaphore values */
#include <os2.h>
#include <stdio.h>
HEV hev; /* Event semaphore handle */
APIRET ulrc; /* Return code */
ulrc = DosPostEventSem(hev);
if (ulrc != 0) {
printf("DosPostEventSem error: return code = %ld",
ulrc);
return;
}
OS/2 maintains a post count for each event semaphore. The post count is the
number of times the semaphore has been posted (with DosPostEventSem) since the
last time the semaphore was in the reset state.
If the event semaphore is reset when DosPostEventSem is called, the semaphore
is posted and the post count is set to 1. If the event semaphore is already
posted when DosPostEventSem is called, the post count is incremented, and
ERROR_ALREADY_POSTED is returned to the calling thread.
The post count is returned as output by DosResetEventSem; it can also be
obtained by calling DosQueryEventSem.
The maximum number of times an event semaphore can be posted is 65535. The
value of the post count cannot exceed 65535. If an attempt is made to exceed
this number, DosPostEventSem returns ERROR_TOO_MANY_POSTS.
ΓòÉΓòÉΓòÉ 7.2.6. Waiting for an Event Semaphore ΓòÉΓòÉΓòÉ
Any thread in the process that created an event semaphore can wait for the
semaphore to be posted by calling DosWaitEventSem. Threads in other processes
can also call DosWaitEventSem, but they must first gain access to the semaphore
by calling DosOpenEventSem.
If the semaphore is already posted when DosWaitEventSem is called, the function
returns immediately, and the thread continues to run. Otherwise, the thread is
blocked until the semaphore is posted.
The following code fragment causes the calling thread to wait until the
specified event semaphore is posted. Assume that the handle of the semaphore
has been placed into HEV already. ulTimeout is the number of milliseconds that
the calling thread will wait for the event semaphore to be posted. If the
specified event semaphore is not posted during this time interval, the request
times out.
#define INCL_DOSSEMAPHORES /* Semaphore values */
#define INCL_DOSERRORS /* error codes */
#include <os2.h>
#include <stdio.h>
HEV hev; /* Event semaphore handle */
ULONG ulTimeout; /* Number of milliseconds to wait */
APIRET ulrc; /* Return code */
ulTimeout = 60000; /* Wait for a maximum of 1 minute */
ulrc = DosWaitEventSem(hev,
ulTimeout);
if (ulrc == ERROR_TIMEOUT) {
printf("DosWaitEventSem call timed out");
return;
}
if (ulrc == ERROR_INTERRUPT) {
printf("DosWaitEventSem call was interrupted");
return;
}
if (ulrc != 0) {
printf("DosWaitEventSem error: return code = %ld",
ulrc);
return;
}
If the time limit specified in ulTimeout is reached before the semaphore is
posted, ERROR_TIMEOUT is returned. If the waiting period is interrupted for
some reason before the semaphore is posted, ERROR_INTERRUPT is returned. If
SEM_IMMEDIATE_RETURN is specified for the time limit, DosWaitEventSem returns
to the calling thread immediately. If SEM_INDEFINITE_WAIT is specified for the
time limit, the thread waits indefinitely.
Unlike multiple event semaphores in a muxwait list, which are level-triggered,
single event semaphores are edge-triggered. This means that if an event
semaphore is posted and then reset before a waiting thread gets a chance to
run, the semaphore is considered to be posted for the rest of that thread's
waiting period; the thread does not have to wait for the semaphore to be posted
again.
ΓòÉΓòÉΓòÉ 7.2.7. Querying an Event Semaphore ΓòÉΓòÉΓòÉ
DosQueryEventSem returns the current post count of a semaphore. The post count
is the number of times that the semaphore has been posted (with
DosPostEventSem) since the last time the semaphore was reset. A count of 0
indicates that the semaphore is in the reset state; therefore, OS/2 will block
any threads that call DosWaitEventSem to wait on the semaphore.
Any thread in the process that created an event semaphore can obtain the post
count for the semaphore by calling DosQueryEventSem. Threads in other processes
can also call DosQueryEventSem, but they must first gain access to the
semaphore by calling DosOpenEventSem.
The following code fragment retrieves the post count for an event semaphore.
Assume that the handle of the semaphore has been placed into HEV already.
#define INCL_DOSSEMAPHORES /* Semaphore values */
#include <os2.h>
#include <stdio.h>
HEV hev; /* Event semaphore handle */
ULONG ulPostCt; /* Current post count for the semaphore (returned) */
APIRET ulrc; /* Return code */
ulrc = DosQueryEventSem(hev,
&ulPostCt);
if (ulrc != 0) {
printf("DosQueryEventSem error: return code = %ld",
ulrc);
return;
}
If the specified event semaphore does not exist, ERROR_INVALID_HANDLE is
returned.
ΓòÉΓòÉΓòÉ 7.3. Using Mutex Semaphores ΓòÉΓòÉΓòÉ
An application can use a mutual exclusion (mutex) semaphore to protect a shared
resource from simultaneous access by multiple threads or processes. For
example, if several processes must write to the same disk file, the mutex
semaphore ensures that only one process at a time writes to the file.
ΓòÉΓòÉΓòÉ 7.3.1. Creating a Mutex Semaphore ΓòÉΓòÉΓòÉ
Mutex semaphores are created by calling DosCreateMutexSem. This function also
opens the semaphore for the calling process and its threads.
When a mutex semaphore is created, a flag is set to specify the initial state
of the semaphore, owned or unowned. If the semaphore is owned by a thread,
other threads requesting the semaphore are blocked. If the semaphore is
unowned-not owned by any thread- then any thread requesting ownership will be
granted ownership immediately.
If the calling thread sets the initial state to owned, it owns the semaphore as
soon as OS/2 creates the semaphore and can proceed to access the resource that
the semaphore was created to protect.
If the semaphore is unowned, any thread in the creating process can
subsequently request ownership of the semaphore by calling DosRequestMutexSem.
Threads in other processes can gain ownership of the semaphore, but they must
call DosOpenMutexSem to acquire access to the semaphore before they can call
DosRequestMutexSem.
Mutex semaphores can be defined as either private or shared.
Private semaphores are always unnamed and are therefore identified by
their handles. They can be used only by threads within a single process.
Shared semaphores can be either named or unnamed. If named, they can be
opened using either the name or the handle. The handle returned by
DosOpenMutexSem is then used to identify the semaphore for all other
functions. Semaphore names must include the prefix \SEM32\ and must
conform to file system naming conventions. Shared semaphores can be used
by threads in multiple processes.
The following code fragment creates a mutex semaphore:
#define INCL_DOSSEMAPHORES /* Semaphore values */
#include <os2.h>
HMTX hmtxProtFile;
DosCreateMutexSem("\\sem32\\ProtFile", /* Named-shared semaphore */
&hmtxProtFile,
0,
FALSE); /* Initially unowned */
.
. /* Get data to write to shared file. */
.
There is a system-wide limit of 65536 shared semaphores (including mutex,
event, and muxwait semaphores); in addition, each process can have up to 65536
private semaphores.
OS/2 maintains a usage count for each semaphore. DosCreateMutexSem initializes
the usage count to 1. Thereafter, each call to DosOpenMutexSem increments the
count, and each call to DosCloseMutexSem decrements it.
ΓòÉΓòÉΓòÉ 7.3.2. Opening a Mutex Semaphore ΓòÉΓòÉΓòÉ
All of the threads belonging to the process that creates a mutex semaphore have
immediate access to the semaphore. Threads in other processes must request
access to the semaphore by calling DosOpenMutexSem before they can use the
semaphore in other mutex semaphore functions.
Access to system resources is granted on a per-process basis. Therefore, a
semaphore that has been opened by one thread in a process is open to all other
threads in that process as well.
DosOpenMutexSem merely provides access to a mutex semaphore. To request
ownership of a mutex semaphore, a thread must call DosRequestMutexSem.
When a process no longer requires access to a mutex semaphore, it should close
the semaphore by calling DosCloseMutexSem. However, if a process ends without
closing an open semaphore, the semaphore is closed by OS/2.
Each call to DosOpenMutexSem. increments the usage count of the semaphore. This
count is initialized to 1 when the semaphore is created and is decremented by
each call to DosCloseMutexSem. When the usage count reaches 0, the semaphore is
deleted by the system.
Calls to DosOpenMutexSem and DosCloseMutexSem. can be nested, but the usage
count for a semaphore cannot exceed 65535. If an attempt is made to exceed this
number, ERROR_TOO_MANY_OPENS is returned.
If a process ends without releasing a mutex semaphore that it owns, any other
thread that subsequently tries to open the semaphore will receive
ERROR_SEM_OWNER_DIED. This return code indicates that the owning process ended
abnormally, leaving the protected resource in an indeterminate state. However,
the semaphore is still opened for the calling thread, enabling the thread to
call DosQueryMutexSem to find out which process ended without releasing the
semaphore. The thread can then take appropriate action concerning the semaphore
and the protected resource.
ΓòÉΓòÉΓòÉ 7.3.3. Requesting a Mutex Semaphore ΓòÉΓòÉΓòÉ
In order to access a shared resource, a process must own the mutex semaphore
that is protecting the shared resource. Ownership is obtained by first opening
the mutex semaphore with DosOpenMutexSem, then using DosRequestMutexSem to
request ownership of the semaphore. If another process already owns the
semaphore, the requesting process is blocked. If the semaphore is not owned,
OS/2 grants ownership to the requesting process and the process can access the
shared resource. When the process is finished using the shared resource, it
uses DosReleaseMutexSem to relinquish its ownership of the semaphore, thereby
enabling another process to gain ownership.
A process can gain ownership of a mutex semaphore in three ways:
1. The thread that creates a mutex semaphore can designate itself as the
owner by setting a flag when it calls DosCreateMutexSem.
2. Any thread in the process that created the semaphore can request
ownership by calling DosRequestMutexSem.
3. A thread in another process must request access to the semaphore with
DosOpenMutexSem before it can call DosRequestMutexSem.
Note that ownership of a mutex semaphore is given only to the requesting
thread; it is not shared by other threads in the same process.
If a mutex semaphore is unowned, DosRequestMutexSem sets it as owned and
returns immediately to the caller. If the semaphore is already owned, the
calling thread is blocked until either the owning thread calls
DosReleaseMutexSem to release the semaphore, or a specified time limit is
reached.
The following code fragment shows how a process opens a mutex semaphore,
requests it, and, after writing to the shared file, releases and closes the
semaphore:
#define INCL_DOSSEMAPHORES /* Semaphore values */
#include <os2.h>
HMTX hmtxProtFile;
DosOpenMutexSem("\\sem32\\ProtFile",
&hmtxProtFile); /* Opens for this process */
DosRequestMutexSem(hmtxProtFile,
5000); /* Returns in 5 seconds if */
. /* Ownership not obtained */
.
. /* Write data to shared file */
.
.
DosReleaseMutexSem(hmtxProtFile); /* Releases ownership */
.
. /* Continue execution */
.
.
DosCloseMutexSem(hmtxProtFile); /* Finished with shared file */
If more than one thread is blocked on a DosRequestMutexSem request, the thread
with the highest priority level is the first to be unblocked and given
ownership of the semaphore. If more than 1 of the waiting threads have the
same priority level, then FIFO ordering is used to determine which thread is
unblocked and given ownership.
The time-out parameter (5000 milliseconds in the example above) places a limit
on the amount of time a thread blocks on a DosRequestMutexSem request. If the
time limit is reached before the thread gains ownership of the semaphore,
ERROR_TIMEOUT is returned. If SEM_IMMEDIATE_RETURN is specified for the time
limit, DosRequestMutexSem returns without blocking the thread. The thread can
then perform other operations and call DosRequestMutexSem again later if it
still requires access to the protected resource. If SEM_INDEFINITE_WAIT is
specified for the time limit, the thread waits indefinitely. If the thread is
unblocked by an external event while it is waiting for the mutex semaphore (as
when a No Wait I/O request has just been completed), ERROR_INTERRUPT is
returned to the caller.
In addition to the usage count that OS/2 maintains for all semaphores, OS/2
maintains a request count for each mutex semaphore. Each call to
DosRequestMutexSem increments the count, and each call to DosReleaseMutexSem
decrements it.
Calls to DosRequestMutexSem and DosReleaseMutexSem can be nested, but the
request count for a semaphore cannot exceed 65535. If an attempt is made to
exceed this number, ERROR_TOO_MANY_SEM_REQUESTS is returned. When calls to
DosRequestMutexSem and DosReleaseMutexSem are nested, a call to
DosReleaseMutexSem merely decrements the request count for the semaphore; the
semaphore is not actually released to another thread until its request count
is 0. If a process ends while it owns a mutex semaphore, all of the currently
blocked DosRequestMutexSem requests, as well as any future requests for the
semaphore, return ERROR_SEM_OWNER_DIED. This return code indicates that the
owning process ended abnormally, leaving the protected resource in an
indeterminate state. An application that receives this error should close the
mutex semaphore (so that it can be deleted from OS/2), because it is no longer
valid. Appropriate action should also be taken concerning the protected
resource.
ΓòÉΓòÉΓòÉ 7.3.4. Releasing a Mutex Semaphore ΓòÉΓòÉΓòÉ
A thread can release ownership of a mutex semaphore by calling
DosReleaseMutexSem. Each call to DosReleaseMutexSem decrements the request
count that is maintained for the semaphore by OS/2. Each call to
DosRequestMutexSem increments the count.
The following code fragment relinquishes ownership of a mutex semaphore. Assume
that the handle of the semaphore has been placed into hmtx already.
#define INCL_DOSSEMAPHORES /* Semaphore values */
#include <os2.h>
#include <stdio.h>
HMTX hmtx; /* Mutex semaphore handle */
APIRET ulrc; /* Return code */
ulrc = DosReleaseMutexSem(hmtx);
if (ulrc != 0) {
printf("DosReleaseMutexSem error: return code = %ld",
ulrc);
return;
}
Calls to DosRequestMutexSem and DosReleaseMutexSem can be nested, but the
request count cannot exceed 65535. If an attempt is made to exceed this number,
ERROR_TOO_MANY_SEM_REQUESTS is returned. When calls to DosRequestMutexSem and
DosReleaseMutexSem are nested, a call to DosReleaseMutexSem merely decrements
the request count for the semaphore; the semaphore is not actually released to
another thread until its request count is 0.
ΓòÉΓòÉΓòÉ 7.3.5. Closing a Mutex Semaphore ΓòÉΓòÉΓòÉ
When a process no longer requires access to a mutex semaphore, it can close the
semaphore by calling DosCloseMutexSem. However, if a process ends without
closing an open semaphore, the semaphore is closed by OS/2.
The following code fragment closes a mutex semaphore. Assume that the handle of
the semaphore has been placed into hmtx already.
#define INCL_DOSSEMAPHORES /* Semaphore values */
#include <os2.h>
#include <stdio.h>
HMTX hmtx; /* Mutex semaphore handle */
APIRET ulrc; /* Return code */
ulrc = DosCloseMutexSem(hmtx);
if (ulrc != 0) {
printf("DosCloseMutexSem error: return code = %ld",
ulrc);
return;
}
Each call to DosCloseMutexSem decrements the usage count of the semaphore. This
count is initialized to 1 when the semaphore is created and is incremented by
each call to DosOpenMutexSem. When the usage count reaches 0, the semaphore is
deleted by OS/2.
The call to DosCloseMutexSem that decrements the usage count to 0 and causes
the semaphore to be deleted is referred to as the final close. The final close
will not succeed if either of the following conditions exists:
The semaphore is owned by another thread in the same process.
Another thread in the same process is still blocked on a
DosRequestMutexSem request for the semaphore.
For both conditions, ERROR_SEM_BUSY is returned.
ERROR_SEM_BUSY is also returned if a thread tries to close a mutex semaphore
that it still owns. The thread must first relinquish ownership of the
semaphore by calling DosReleaseMutexSem.
Calls to DosOpenMutexSem and DosCloseMutexSem can be nested, but the usage
count for a semaphore cannot exceed 65535. If an attempt is made to exceed
this number, ERROR_TOO_MANY_OPENS is returned.
ΓòÉΓòÉΓòÉ 7.3.6. Querying a Mutex Semaphore ΓòÉΓòÉΓòÉ
An application can use DosQueryMutexSem to determine the current owner of a
mutex semaphore and to obtain a count of the number of requests on it. If the
mutex semaphore is not owned, the request count is 0.
Any thread in the process that created a mutex semaphore can obtain information
about the semaphore by calling DosQueryMutexSem. Threads in other processes can
also call DosQueryMutexSem, but they must first gain access to the semaphore by
calling DosOpenMutexSem.
If the mutex semaphore exists and is owned, DosQueryMutexSem returns the
process and thread identifications of the owner, as well as the request count
for the semaphore. The request count is the number of DosRequestMutexSem calls
minus the number of DosReleaseMutexSem calls that have been made for the
semaphore by the owning thread.
If DosQueryMutexSem returns a request count of 0, the mutex semaphore is
unowned.
If the owning process ended without calling DosCloseMutexSem, then
ERROR_SEM_OWNER_DIED is returned, and the output parameters contain information
about the ended owning process.
ΓòÉΓòÉΓòÉ 7.4. Using Muxwait Semaphores ΓòÉΓòÉΓòÉ
A process that requires exclusive use of several shared resources at once can
use a multiple wait (muxwait) semaphore to obtain ownership of all the mutex
semaphores protecting the shared resources. A process can also use a muxwait
semaphore to wait on a group of event semaphores so that the process continues
running whenever events of interest occur.
A muxwait semaphore can refer to up to 64 event or mutex semaphores. An
application cannot refer to event and mutex semaphores in a single muxwait
semaphore, or include a muxwait semaphore in another muxwait semaphore.
ΓòÉΓòÉΓòÉ 7.4.1. Creating a Muxwait Semaphore ΓòÉΓòÉΓòÉ
DosCreateMuxWaitSem is used to create muxwait semaphores. This function also
opens (obtains access to) the semaphore for the calling process and its
threads. Threads in other processes must call DosOpenMuxWaitSem to open the
semaphore before they can use it in any other muxwait semaphore function.
All the semaphores in the muxwait list must be created and opened before the
muxwait list can be created.
The following code fragment creates five event semaphores and a corresponding
array of semaphore records. The array is used to specify the semaphores
included in the muxwait semaphore in the subsequent call to
DosCreateMuxWaitSem.
#define INCL_DOSSEMAPHORES /* DOS semaphore values */
#define INCL_DOSERRORS /* DOS error values */
#include <os2.h>
#include <stdio.h>
int main(VOID) {
HMUX hmuxHandAny = NULLHANDLE; /* Muxwait handle */
HEV hev[5] = {0}; /* Event semaphores */
SEMRECORD apsr[5] = {{0}}; /* Semaphore records */
APIRET ulrc = NO_ERROR; /* Return code */
ULONG ulLoop = 0; /* Loop count */
ULONG ulSem = 0;
for (ulLoop = 0; ulLoop < 5; ulLoop++) {
ulrc = DosCreateEventSem((PSZ) NULL,
&hev[ulLoop],
0,
FALSE);
if (ulrc != NO_ERROR) {
printf("DosCreateEventSem error: return code = %u\n",
ulrc);
return 1;
}
apsr[ulLoop].hsemCur = (HSEM) hev[ulLoop],
apsr[ulLoop].ulUser = 0;
} /* end for */
ulrc = DosCreateMuxWaitSem((PSZ) NULL,
&hmuxHandAny,
5L, /* Number of semaphores in list */
apsr, /* Semaphore list */
DCMW_WAIT_ANY); /* Wait for any semaphore */
if (ulrc != NO_ERROR) {
printf("DosCreateMuxWaitSem error: return code = %u\n",
ulrc);
return 1;
}
ulrc = DosWaitMuxWaitSem(hmuxHandAny,
SEM_IMMEDIATE_RETURN,
&ulSem); /* No semaphores have been posted, so
we should see a timeout below... */
if (ulrc != ERROR_TIMEOUT) {
printf("DosWaitMuxWaitSem error: return code = %u\n",
ulrc);
return 1;
}
ulrc = DosDeleteMuxWaitSem(hmuxHandAny,
apsr[0].hsemCur);
if (ulrc != NO_ERROR) {
printf("DosDeleteMuxWaitSem error: return code = %u\n",
ulrc);
return 1;
}
ulrc = DosCloseMuxWaitSem(hmuxHandAny);
if (ulrc != NO_ERROR) {
printf("DosCloseMuxWaitSem error: return code = %u\n",
ulrc);
return 1;
}
return NO_ERROR;
}
Muxwait semaphores can be defined as either private or shared:
Private semaphores are always unnamed and are therefore always identified
by their handles. They can be used only by threads within a single
process.
Shared semaphores can be either named or unnamed. If named, they can be
opened using either the name or the handle. The handle returned by
DosOpenMuxWaitSem is then used to identify the semaphore for all other
functions. Semaphore names must include the prefix \SEM32\ and must
conform to file system naming conventions. Shared semaphores can be used
by threads in multiple processes.
There is a system-wide limit of 65536 (64K) shared semaphores (including
mutex, event, and muxwait semaphores); in addition, each process can have up
to 65536 (64K) private semaphores.
The following conditions apply to the kinds of semaphores that can be included
in a muxwait-semaphore list:
The list must contain either mutex semaphores or event semaphores. It
cannot contain both at the same time and it cannot contain other muxwait
semaphores.
If the muxwait semaphore is shared, then all the semaphores in the list
must also be shared.
If the muxwait semaphore is private, then the semaphores in its list can
be either private or shared.
If any of these conditions is violated, ERROR_WRONG_TYPE is returned.
The muxwait list can contain a maximum of 64 event semaphores or mutex
semaphores. If an attempt is made to exceed this maximum,
ERROR_TOO_MANY_SEMAPHORES is returned.
If the owners of any of the mutex semaphores in the muxwait semaphore list
have ended without releasing them, ERROR_SEM_OWNER_DIED is returned. The
thread should call DosQueryMutexSem for each mutex semaphore in the
muxwait-semaphore list so that it can determine which semaphores are in the
Owner Died state.
Each mutex semaphore that returns ERROR_SEM_OWNER_DIED from the query should
be closed by calling DosCloseMutexSem. Also, because semaphore handles can be
reused, the mutex semaphores that are closed must be deleted from the
muxwait-semaphore list by calling DosDeleteMuxWaitSem.
OS/2 maintains a usage count for each semaphore. DosCreateMuxWaitSem
initializes the usage count to 1. Thereafter, each call to DosOpenMuxWaitSem
increments the count, and each call to DosCloseMuxWaitSem decrements it.
One parameter of this function is a pointer to an array of SEMRECORD data
structures. Each data structure contains one semaphore record for each of the
semaphores to be included in the muxwait semaphore. A semaphore record
contains the handle and a programmer-defined identifier for that semaphore.
ΓòÉΓòÉΓòÉ 7.4.2. Opening a Muxwait Semaphore ΓòÉΓòÉΓòÉ
Processes other than the semaphore-creating process must use DosOpenMuxWaitSem
to gain access to the muxwait semaphore before they can use the semaphore in
any other muxwait semaphore function. All of the threads that belong to the
process that creates the muxwait semaphore have immediate access to the
semaphore.
The following code fragment opens a system muxwait semaphore.
#define INCL_DOSSEMAPHORES /* Semaphore values */
#include <os2.h>
#include <stdio.h>
#include <string.h>
UCHAR ucName[40]; /* Semaphore name */
HMUX hmux; /* Muxwait semaphore handle */
APIRET ulrc; /* Return code */
strcpy(ucName,
"\\SEM32\\MUXWAIT1"); /* Name of the system muxwait semaphore */
ulrc = DosOpenMuxWaitSem(ucName,
&hmux);
if (ulrc != 0) {
printf("DosOpenMuxWaitSem error: return code = %ld",
ulrc);
return;
}
On successful return, hmux contains the handle of the system muxwait semaphore.
Opening a muxwait semaphore does not open the semaphores in its muxwait list. A
process must open each of the semaphores included in a muxwait semaphore before
it opens the muxwait semaphore. Otherwise, DosOpenMuxWaitSem returns the
ERROR_INVALID_HANDLE error value to the calling function.
Access to semaphores is on a per-process basis. Therefore, a semaphore that has
been opened by one thread in a process is open to all other threads in that
process as well.
Note that DosOpenMuxWaitSem merely provides access to a muxwait semaphore. In
order to wait for a muxwait semaphore to clear, a thread must call
DosWaitMuxWaitSem.
When a process no longer requires access to a muxwait semaphore, it closes the
semaphore by calling DosCloseMuxWaitSem. However, if a process ends without
closing an open semaphore, the semaphore is closed by OS/2.
Each call to DosOpenMuxWaitSem increments the usage count of the semaphore.
This count is initialized to 1 when the semaphore is created and is decremented
by each call to DosCloseMuxWaitSem. When the usage count reaches 0, the
semaphore is deleted by OS/2.
Calls to DosOpenMuxWaitSem and DosCloseMuxWaitSem can be nested, but the usage
count for a semaphore cannot exceed 65535. If an attempt is made to exceed this
number, ERROR_TOO_MANY_OPENS is returned.
Even if the owner of a mutex semaphore in a muxwait-semaphore list has ended
without releasing the semaphore, the muxwait semaphore is still opened.
Subsequent calls to the muxwait semaphore will return ERROR_SEM_OWNER_DIED. But
because the process has opened the semaphore, it can then call
DosQueryMuxWaitSem to identify all the mutex semaphores in the muxwait list.
Next, the process can call DosQueryMutexSem for each mutex semaphore in the
list to find out which ones are in the Owner Died state. Each mutex semaphore
that returns ERROR_SEM_OWNER_DIED from the query should be closed by calling
DosCloseMutexSem. Also, because semaphore handles can be reused, the mutex
semaphores that are closed should be deleted from the muxwait-semaphore list by
calling DosDeleteMuxWaitSem.
ΓòÉΓòÉΓòÉ 7.4.3. Closing a Muxwait Semaphore ΓòÉΓòÉΓòÉ
When a process no longer requires access to a muxwait semaphore, it closes the
semaphore by calling DosCloseMuxWaitSem. However, if a process ends without
closing an open semaphore, the semaphore is closed by OS/2.
Each call to DosCloseMuxWaitSem decrements the usage count of the semaphore.
This count is initialized to 1 when the semaphore is created and is incremented
by each call to DosOpenMuxWaitSem. When the usage count reaches 0, the
semaphore is deleted by OS/2.
The call to DosCloseMuxWaitSem that decrements the usage count to 0 and causes
the semaphore to be deleted is referred to as the final close. If a thread
attempts to perform the final close for a semaphore while another thread in the
same process is still waiting for it, ERROR_SEM_BUSY is returned.
Calls to DosOpenMuxWaitSem and DosCloseMuxWaitSem can be nested, but the usage
count for a semaphore cannot exceed 65535. If an attempt is made to exceed this
number, ERROR_TOO_MANY_OPENS is returned.
ΓòÉΓòÉΓòÉ 7.4.4. Waiting for a Muxwait Semaphore ΓòÉΓòÉΓòÉ
A thread can wait on a muxwait semaphore by using DosWaitMuxWaitSem.
Any thread in the process that created a muxwait semaphore can wait for the
semaphore to clear by calling DosWaitMuxWaitSem. Threads in other processes can
also call DosWaitMuxWaitSem, but they must first gain access to the semaphore
by calling DosOpenMuxWaitSem.
The following code fragment waits for a muxwait semaphore to clear. Assume that
the handle of the semaphore has been placed into hmux already. ulTimeout is the
number of milliseconds that the calling thread will wait for the muxwait
semaphore to clear. If the specified muxwait semaphore is not cleared during
this time interval, the request times out.
#define INCL_DOSSEMAPHORES /* Semaphore values */
#include <os2.h>
#include <stdio.h>
HMUX hmux; /* Muxwait semaphore handle */
ULONG ulTimeout; /* Number of milliseconds to wait */
ULONG ulUser; /* User field for the semaphore that was */
/* posted or released (returned) */
APIRET ulrc; /* Return code */
ulTimeout = 60000; /* Wait for a maximum of 1 minute */
ulrc = DosWaitMuxWaitSem(hmux,
ulTimeout,
&ulUser);
if (ulrc == ERROR_TIMEOUT) {
printf("DosWaitMuxWaitSem call timed out");
return;
}
if (ulrc == ERROR_INTERRUPT) {
printf("DosWaitMuxWaitSem call was interrupted");
return;
}
if (ulrc != 0) {
printf("DosWaitMuxWaitSem error: return code = %ld",
ulrc);
return;
}
On successful return, the ulUser variable contains the user identifier of the
semaphore that caused the wait to terminate. If the caller had to wait for all
the semaphores within the muxwait semaphore to clear, then the value
corresponds to the last semaphore within the muxwait semaphore to clear. If the
caller had to wait for any semaphore with the muxwait semaphore to clear, then
the value corresponds to that semaphore.
An application can use the DCMW_WAIT_ANY flag in DosCreateMuxWaitSem to block a
thread until any one of the event or mutex semaphores included in the muxwait
semaphore is posted or released. If the muxwait semaphore refers to mutex
semaphores, the thread only gains ownership of the one mutex semaphore that was
released.
An application can use the DCMW_WAIT_ALL flag in DosCreateMuxWaitSem to block a
thread until all of the event or mutex semaphores included in the muxwait
semaphore are posted or released. If the muxwait semaphore refers to mutex
semaphores, the thread does not gain ownership of any of the mutex semaphores
until they are all released. When all are released, the thread becomes owner of
all the mutex semaphores included in the muxwait semaphore. If the muxwait
semaphore refers to event semaphores, the thread will not run until all of the
event semaphores are in the posted state at the same time. This is because
event semaphores in a muxwait list are level-triggered, unlike individual event
semaphores, which are edge-triggered.
For example, suppose that a thread is waiting for five event semaphores in a
muxwait list to be posted. The first semaphore is posted and then reset. Next,
the remaining semaphores are all posted, and they remain in the posted state.
The thread that is waiting for the muxwait semaphore will not run until the
first semaphore is posted again.
If an application specifies the DCMW_WAIT_ANY flag when the semaphore is
created, DosWaitMuxWaitSem returns the programmer-defined identifier of the
semaphore that is subsequently posted or released. If an application specifies
the DCMW_WAIT_ALL flag, DosWaitMuxWaitSem returns the programmer-defined
identifier of the last semaphore that was posted or released.
The ulTimeout parameter places a limit on the amount of time a thread blocks on
a DosWaitMuxWaitSem request. If the time limit is reached before the semaphore
has cleared, ERROR_TIMEOUT is returned. If SEM_IMMEDIATE_RETURN is specified as
the time limit, DosWaitMuxWaitSem returns without blocking the thread. The
thread can then go on to perform other operations and call DosWaitMuxWaitSem
again later to wait for the event or mutex semaphores in the muxwait list to be
posted or released. If a time limit of SEM_INDEFINITE_WAIT is specified, the
thread waits (is blocked) indefinitely. If the thread is unblocked by an
external event while it is waiting for the muxwait semaphore (as when a "no
wait" I/O request has just been completed), DosWaitMuxWaitSem returns
ERROR_INTERRUPT.
When a thread is waiting for any one of the semaphores in a muxwait list to be
posted or released, the semaphores are checked in the order in which they are
defined in the list.
Waiting for Multiple Event Semaphores
The following information pertains only to muxwait semaphores that consist of
multiple event semaphores:
Unlike individual event semaphores, which are edge-triggered, event semaphores
in a muxwait list are level-triggered. This means that if a thread is waiting
for all of the event semaphores in the muxwait list, it will not run until all
of the event semaphores are in the posted state at the same time.
For example, a thread is waiting for five event semaphores in a muxwait list to
be posted. The first semaphore is posted and then reset. Next, the remaining
semaphores are all posted, and they remain in the posted state. The thread that
is waiting for the muxwait semaphore will not run until the first semaphore is
posted again.
Waiting for Multiple Mutex Semaphores
The following information pertains only to muxwait semaphores that consist of
multiple mutex semaphores:
If a thread is waiting for all of the mutex semaphores in a muxwait list
to be released, it does not receive ownership of any of the semaphores
until all of the semaphores have been released.
If a thread is waiting for any one of the mutex semaphores in a muxwait
list, then the thread gains ownership only of the first mutex semaphore
that is released. The ownership of all other mutex semaphores in the
muxwait list remains unchanged.
If two threads have the same priority, then a thread that is waiting for
a mutex semaphore in a muxwait list takes precedence over a thread that
has requested ownership of only the individual semaphore, provided all
other mutex semaphores in the muxwait list have been released. For
example, a mutex semaphore that is part of a muxwait semaphore is
released. One thread has requested ownership of that single mutex
semaphore, and another thread with the same priority is waiting for the
muxwait semaphore that contains the same mutex semaphore. If all of the
other mutex semaphores in the muxwait list are unowned and ready to be
given to the muxwait semaphore, then the thread that is waiting for the
muxwait semaphore will run first.
If the owners of any of the mutex semaphores in the muxwait semaphore
list have ended without releasing them, ERROR_SEM_OWNER_DIED is returned.
The thread must then call DosQueryMuxWaitSem to obtain the records of all
the semaphores in the muxwait list. Next, the thread must call
DosQueryMutexSem for each mutex semaphore in the muxwait-semaphore list
so that it can determine which semaphores are in the Owner Died state.
Each mutex semaphore that returns ERROR_SEM_OWNER_DIED from the query
should be closed by calling DosCloseMutexSem. Also, because semaphore
handles can be reused, the mutex semaphores that are closed should be
deleted from the muxwait-semaphore list by calling DosDeleteMuxWaitSem.
If any of the mutex semaphores in the muxwait list are owned by the
calling thread, ERROR_MUTEX_OWNED is returned.
ΓòÉΓòÉΓòÉ 7.4.5. Adding a Semaphore to a Muxwait List ΓòÉΓòÉΓòÉ
An application uses DosAddMuxWaitSem to add semaphores to a muxwait semaphore
that has already been created, even while threads are waiting on the muxwait
semaphore.
Any thread in the process that created a muxwait semaphore can add a mutex
semaphore or an event semaphore to the muxwait list by calling
DosAddMuxWaitSem. Threads in other processes can also use this function, but
they must first gain access to the semaphore by calling DosOpenMuxWaitSem.
A maximum of 64 semaphores can be included in a muxwait-semaphore list. If an
attempt is made to exceed this maximum, ERROR_TOO_MANY_SEMAPHORES is returned.
All of the semaphores in a muxwait-semaphore list must be of the same type.
That is, if a mutex semaphore is being added, then the other semaphores in the
list must be mutex semaphores. If an event semaphore is being added, then the
other semaphores in the list must be event semaphores. A shared muxwait
semaphore can contain only shared semaphores in its list. A private muxwait
semaphore can contain both private and shared semaphores. If any of these
conditions is violated, ERROR_WRONG_TYPE is returned.
If the semaphore is successfully added to the muxwait list, DosAddMuxWaitSem
checks to see whether each thread that is waiting for the muxwait semaphore has
the newly added semaphore open in its process. The muxwait semaphore is invalid
for any waiting threads that do not have the newly added semaphore open in
their process; these threads are unblocked with a return code of
ERROR_INVALID_HANDLE. Any processes that opened the muxwait semaphore before
the add operation and that do not have the new semaphore open, will have to
open the new semaphore before making any further use of the muxwait semaphore.
Any future calls concerning the muxwait semaphore by processes that do not have
the new semaphore open will have ERROR_INVALID_HANDLE returned until the new
semaphore is opened.
A thread that receives a return code of ERROR_INVALID_HANDLE can take the
following corrective action:
1. First, the thread can obtain the records of all the semaphores in the
muxwait list by calling DosQueryMuxWaitSem.
2. Next, it can query each semaphore in the muxwait list, using
DosQueryMutexSem or DosQueryEventSem, to find out which semaphore is not
open to its process.
3. Finally, it can open the semaphores that are not open by calling
DosOpenMutexSem or DosOpenEventSem.
As soon as this semaphore is opened, the muxwait semaphore becomes valid again
for the process, as long as no other changes have been made to the muxwait
list to make it invalid. However, in order to successfully wait for the
muxwait semaphore, the process must call DosWaitMuxWaitSem again.
A semaphore must be open for a process before the process can add that
semaphore to a muxwait semaphore. If it is not open and a thread is waiting on
the muxwait semaphore, DosAddMuxWaitSem returns ERROR_INVALID_HANDLE to the
process adding the new semaphore, and the waiting thread continues waiting.
ΓòÉΓòÉΓòÉ 7.4.6. Deleting a Semaphore from a Muxwait List ΓòÉΓòÉΓòÉ
An application can delete semaphores from a muxwait semaphore by using
DosDeleteMuxWaitSem.
Any thread in the process that created a muxwait semaphore can delete a mutex
or event semaphore from the muxwait list by calling DosDeleteMuxWaitSem.
Threads in other processes can also use this function, but they must first gain
access to the semaphore by calling DosOpenMuxWaitSem.
Semaphores can be deleted from the muxwait list even while threads are
currently waiting for the semaphore. If the deleted semaphore is the only one
in the muxwait list that has not yet been posted or released, then threads that
are waiting for the muxwait semaphore are unblocked. Also, if the deleted
semaphore happens to be the last one that a particular thread was waiting for,
that thread is unblocked. Also, if the deleted semaphore is the last one in the
muxwait list (that is, if the list is now empty), then all the threads that are
waiting for the muxwait semaphore are unblocked.
ΓòÉΓòÉΓòÉ 7.4.7. Querying a Muxwait Semaphore ΓòÉΓòÉΓòÉ
Processes use DosQueryMuxWaitSem to obtain the semaph ore records for each of
the semaphores included in the muxwait semaphore.
Any thread in the process that created a muxwait semaphore can obtain
information about the semaphores in the muxwait list by calling
DosQueryMuxWaitSem. Threads in other processes can also use this function, but
they must first gain access to the semaphore by calling DosOpenMuxWaitSem.
An application must provide this function with an array in which to store the
semaphore records. If the array is not large enough to hold all of the
semaphore records that are in the muxwait list, then ERROR_PARAM_TOO_SMALL is
returned, and the record-counting parameter of DosQueryMuxWaitSem will contain
the number of semaphore records that are in the muxwait list. The calling
thread can then allocate the correct amount of space and call
DosQueryMuxWaitSem again with the correct amount of space for the list of
records.
If the owner of any mutex semaphore in the muxwait-semaphore list has ended
without releasing the semaphore, the records of all the semaphores in the list
are still returned, but DosQueryMuxWaitSem also returns ERROR_SEM_OWNER_DIED.
The calling thread can call DosQueryMutexSem for each mutex semaphore in the
muxwait-semaphore list so that it can determine which semaphores are in the
Owner Died state. The process can then close the unowned mutex semaphores.
Each mutex semaphore that returns ERROR_SEM_OWNER_DIED from the query should be
closed by calling DosCloseMutexSem. Also, because semaphore handles can be
reused, the mutex semaphores that are closed should be deleted from the
muxwait-semaphore list by calling DosDeleteMuxWaitSem.
If the specified muxwait semaphore does not exist, ERROR_INVALID_HANDLE is
returned.
ΓòÉΓòÉΓòÉ 8. Timers ΓòÉΓòÉΓòÉ
This chapter describes how to create and use timers. Timers enable applications
to time events by waiting for an interval to elapse or by waiting for a
semaphore to be posted.
The following topics are related to the information in this chapter:
Program execution and control
Semaphores
ΓòÉΓòÉΓòÉ 8.1. About Timers ΓòÉΓòÉΓòÉ
Because OS/2 is a multitasking system, an application cannot predict when it
will lose execution control or how much time will elapse before control
returns. A timer enables an application to suspend operation for a specific
length of time, to block a thread until an interval has elapsed, or to post an
event semaphore at repeated intervals.
Timers are managed by OS/2. When an application requests a timer, the system
monitors the system clock and notifies the application when the interval has
elapsed.
The system clock counts the number of system-clock interrupts (clock ticks)
that have occurred since the system was started. On most hardware, clock ticks
occur approximately 32 times a second, so the length of a tick is approximately
31.25 milliseconds.
When an application specifies a timer interval, the system rounds up the
interval to the next clock tick. For example, if an application requests a 10
millisecond interval, it will sleep for at least 31.25 milliseconds. If an
application requests a 100 millisecond interval, the actual interval will be at
least 125 milliseconds (4 ticks).
Because OS/2 is a preemptive operating system, there is no guarantee that a
thread will resume immediately after the timer interval. If a higher priority
process or thread is executing, the timed thread must wait.
Although timers are not absolutely accurate, they can be used where the
inaccuracy can be ignored. In a real-time control application, for example, an
event can be timed in seconds or minutes, so an error of a few milliseconds is
unimportant. If an application requires as much accuracy as the system can
provide, it can dedicate a thread to managing timer intervals and then elevate
the priority of that thread.
ΓòÉΓòÉΓòÉ 8.1.1. Suspending Threads ΓòÉΓòÉΓòÉ
An application can use DosSleep to suspend operation of a thread for a
specified interval. The system waits the specified number of milliseconds
(subject to the round-off error just discussed) before returning control to the
application. Because a sleeping application yields execution control to the
system, the system can execute other processes or threads while the application
sleeps.
The following code fragment shows how to suspend the calling thread for one
minute:
#define INCL_DOSPROCESS /* Process and thread values */
#include <os2.h>
#include <stdio.h>
ULONG ulTimeInterval; /* Interval in milliseconds */
APIRET ulrc; /* Return code */
ulTimeInterval = 60000;
ulrc = DosSleep(ulTimeInterval);
if (ulrc != 0) {
printf("DosSleep error: return code = %ld",
ulrc);
return;
}
See Suspending the Current Thread for more information on DosSleep.
ΓòÉΓòÉΓòÉ 8.1.2. Asynchronous Timers ΓòÉΓòÉΓòÉ
DosSleep is useful for temporarily suspending a thread but is much less useful
for timing. Typically, an application carries out part of its task and then
waits an interval. If the execution time varies (as it will if the application
runs on different hardware), the overall interval varies. In these situations,
asynchronous timers provide greater precision than DosSleep.
OS/2 supports two types of asynchronous timers, single-interval (one-shot) and
repeated. DosAsyncTimer starts a single-interval timer. During the timing
interval, the application can carry out other tasks. The system posts an event
semaphore when the timing interval elapses. The application can reset the
semaphore with DosResetEventSem before starting the timer. DosAsyncTimer yields
a more accurate timing interval than DosSleep because the interval is
independent of the execution time.
DosStartTimer starts a repeated timer. The system posts an event semaphore each
time the interval expires. The application can reset the semaphore before
starting the timer and after each posting. When the application resets the
semaphore with DosResetEventSem, it can check the cPosts value to determine how
many times the semaphore has been posted. If the semaphore has been posted more
than once, the application has missed a timer interval.
ΓòÉΓòÉΓòÉ 8.2. Using Timers ΓòÉΓòÉΓòÉ
Applications frequently need to synchronize the execution of threads, to cause
an event to occur after a specified interval, or to cause an event to occur at
regular intervals. Timers are typically used to enable an application to pause
before processing user input or to carry out a task at a given time.
OS/2 provides the following timer functions:
DosSleep suspends the execution of the calling thread, enabling other
threads to run while the calling thread sleeps.
DosAsyncTimer starts a single-interval timer.
DosStartTimer starts a repeated-interval timer.
DosStopTimer stops a single-interval or repeated-interval timer.
The system also provides two functions, DosGetDateTime and DosSetDateTime, for
getting and setting the system date and time.
The timers that are started by DosAsyncTimer and DosStartTimer are
asynchronous timers; that is, the timers run independently of the calling
thread, enabling the calling thread to perform other operations while the
timer is running. When an asynchronous timer interval expires, the system
notifies the application by posting an event semaphore.
Time intervals for DosAsyncTimer, DosStartTimer, and DosSleep are specified in
milliseconds; however, it is important to recognize that the actual duration
of the specified time interval will be affected by two factors:
First, the system clock keeps track of time in less precise units known
as clock ticks. On most hardware, clock ticks occur approximately 32
times a second, so each tick interval lasts approximately 31.25
milliseconds. (To determine the duration of a clock tick on your
computer, call DosQuerySysInfo, and examine the timer-interval field.)
Because clock ticks are less precise than millisecond values, any time
interval that is specified in milliseconds will essentially be rounded up
to the next clock tick.
Second, because OS/2 is a priority-based, multitasking operating system,
there is no guarantee that a thread will resume execution immediately
after the timer interval expires. If a higher priority process or thread
is running, or if a hardware interrupt occurs, the timed thread blocks.
(To minimize delays caused by preemptive scheduling, an application can
dedicate a thread to managing time-critical tasks, and then raise that
thread to a higher priority.)
These factors usually cause the timer interval to be longer than requested;
however, it will generally be within a few clock ticks.
Timers for Presentation Manager applications are provided through the message
queue. Therefore, a Presentation Manager application will not use the timer
functions unless it performs some real-time control task.
Note: In the example code fragments that follow, error checking was left out
to conserve space. Applications should always check the return code
that the functions return. Control Program functions return an APIRET
value. A return code of 0 indicates success. If a non-zero value is
returned, an error occurred.
ΓòÉΓòÉΓòÉ 8.2.1. Suspending the Current Thread ΓòÉΓòÉΓòÉ
An application can suspend a thread by using DosSleep. DosSleep suspends the
execution of the calling thread for a specified time interval.
DosSleep requires one argument-the amount of time (in milliseconds) to suspend
the thread. This value is rounded up to the nearest clock tick. If a time
interval of 0 is specified, the thread gives up the remainder of the current
time slice, enabling other ready threads of equal or higher priority to run;
the calling thread will run again during its next scheduled time slice. If
there is no other ready thread of equal or higher priority, DosSleep returns
immediately; it does not yield to a thread of lower priority.
If there is a round-off error or if other threads in the system have higher
priority, a thread might not resume execution immediately after the sleep
interval.
The following DosSleep call suspends a thread for at least 5 seconds:
DosSleep(5000);
Note that the specified time interval refers to execution time (accumulated
scheduled time slices), not to elapsed real time. Elapsed real time will be
longer and will vary, depending on the hardware and on the number and
priorities of other threads running in the system. In addition, even though the
calling thread is scheduled for execution as soon as the specified time
interval has elapsed, its execution could be delayed if a higher priority
thread is running or if a hardware interrupt occurs.
Because the above factors usually cause the sleep interval to be longer than
requested (though generally within a few clock ticks), DosSleep should not be
used as a substitute for a real-time clock.
Note:
1. Elapsed real time for the asynchronous timers (started by DosAsyncTimer
and DosStartTimer) will be much closer to their specified time intervals
because these timers run independent of the execution of the calling
thread.
2. To ensure optimal performance, do not use DosSleep in a single-thread
Presentation Manager application. (Use WinStartTimer.)
ΓòÉΓòÉΓòÉ 8.2.2. Timing a Single Interval ΓòÉΓòÉΓòÉ
To carry out other tasks while the timer counts an interval, an application can
use DosAsyncTimer. This function sets a single-interval timer without stopping
the application-the timer runs asynchronously to the calling thread, enabling
the thread to perform other operations while it is waiting for the specified
time interval to expire. When the interval elapses, OS/2 notifies the
application of the expiration of the timer by posting an event semaphore. The
application resets the semaphore before starting the timer and monitors the
semaphore to determine when the time has elapsed. The application can use
DosCreateEventSem with the initial state FALSE to create a reset semaphore. For
more information on semaphores, see Semaphores.
The following code fragment creates an event semaphore and then calls
DosAsyncTimer to count an interval while the application performs other tasks:
#define INCL_DOSDATETIME /* Date/Time and Timer Support */
#define INCL_DOSSEMAPHORES /* for semaphores */
#include <os2.h>
HEV hev;
HTIMER hTimer;
/* First create a private, reset, event semaphore. */
DosCreateEventSem((PSZ) NULL,
&hev,
DC_SEM_SHARED,
FALSE);
/* Start async (one-shot) timer; post semaphore in 10 seconds. */
DosAsyncTimer(10000, /* Time in milliseconds (10 sec) */
(HSEM) hev, /* Semaphore handle */
&hTimer); /* Timer handle (used to stop timer) */
.
. /* Do other processing here, then wait for semaphore. */
.
DosWaitEventSem(hev,
SEM_INDEFINITE_WAIT);
Before starting the timer, the thread creates the event semaphore with
DosCreateEventSem, specifying its initial state as reset. If the semaphore was
previously created by the same process, the thread resets it by calling
DosResetEventSem. If the semaphore was previously created by another process,
then the thread must call DosOpenEventSem to gain access to the semaphore
before calling DosResetEventSem.
Next, the thread calls DosAsyncTimer, specifying the handle of the event
semaphore and the desired time interval. The thread can then perform other
tasks. However, in order for the application to be notified of the expiration
of the timer, one or more threads in the application must call DosWaitEventSem.
When the time interval expires, the system posts the semaphore, and any threads
that were blocked on DosWaitEventSem requests can resume their execution. If
another time interval is required, the semaphore is reset, and both
DosAsyncTimer and DosWaitEventSem are called again. (To time regular repeated
intervals, use DosStartTimer.)
The timer can be canceled before its time interval expires by calling
DosStopTimer.
ΓòÉΓòÉΓòÉ 8.2.3. Timing Repeated Intervals ΓòÉΓòÉΓòÉ
To count an interval repeatedly, an application can use DosStartTimer. This
function starts a repeated-interval timer.
Unlike DosAsyncTimer, DosStartTimer does not stop after the first interval is
counted. The timer runs asynchronously to the calling thread, enabling the
thread to perform other operations while it is waiting for the specified time
intervals to expire. The system notifies the application of the timer's
expirations by posting an event semaphore.
The application resets the semaphore before starting the timer and whenever the
system posts the semaphore. The application can use the value returned in the
post-counting parameter by DosResetEventSem to assure the semaphore was posted
only once before it was reset.
The following code fragment starts a timer and then waits on and resets the
associated event semaphore. Assume that the handle of the targeted event
semaphore has been placed into SemHandle.
#define INCL_DOSDATETIME /* Date and time values */
#include <os2.h>
#include <stdio.h>
ULONG ulTimeInterval; /* Interval (milliseconds) */
HSEM hsemSemHandle; /* Event-semaphore handle */
HTIMER hHandle; /* Timer handle (returned) */
APIRET ulrc; /* Return code */
ulTimeInterval = 30000; /* Set the periodic time interval to */
/* elapse every 30 seconds */
ulrc = DosStartTimer(ulTimeInterval,
hsemSemHandle,
&hHandle);
if (ulrc != 0) {
printf("DosStartTimer error: return code = %ld",
ulrc);
return;
}
On successful return, Handle will contain the handle of this periodic timer.
DosStopTimer can be used later to stop the periodic timer.
A repeated timer will continue to count the interval and post the semaphore
until the application terminates or the application uses DosStopTimer to stop
the timer explicitly. The following code fragment shows how to stop a periodic
timer that has been started previously with DosStartTimer:
#define INCL_DOSDATETIME /* Date and time values */
#include <os2.h>
#include <stdio.h>
HTIMER hHandle; /* Handle of the timer */
APIRET ulrc; /* Return code */
ulrc = DosStopTimer(hHandle);
if (ulrc != 0) {
printf("DosStopTimer error: return code = %ld",
ulrc);
return;
}
Before starting the timer, the event semaphore must be reset. If the semaphore
does not exist, the thread can create it with DosCreateEventSem, specifying its
initial state as reset. If the semaphore was previously created by the same
process, the thread resets it by calling DosResetEventSem. If the semaphore was
previously created by another process, then the thread calls DosOpenEventSem to
gain access to the semaphore before calling DosResetEventSem.
Next, the thread calls DosStartTimer, specifying the handle of the event
semaphore and the desired time interval. The thread can then perform other
tasks. However, in order for the application to be notified of the timer's
expirations, one or more threads in the application must call DosWaitEventSem.
When the time interval expires, the system posts the semaphore, and any threads
that were blocked on DosWaitEventSem requests can resume their execution. Each
time the semaphore is posted, it must be reset with DosResetEventSem before the
next timer expiration. DosWaitEventSem must also be called to wait for the
semaphore to be posted again.
In addition to resetting the event semaphore, DosResetEventSem returns the
semaphore's post count (the number of times the semaphore has been posted since
the last time it was in the set state). An application can use the post count
to ensure that it has not missed a timer interval; if the post count is greater
than one, the application missed a timer interval.
ΓòÉΓòÉΓòÉ 9. Glossary ΓòÉΓòÉΓòÉ
This glossary defines many of the terms used in this book. It includes terms
and definitions from the IBM Dictionary of Computing, as well as terms specific
to the OS/2 operating system and the Presentation Manager. It is not a complete
glossary for the entire OS/2 operating system; nor is it a complete dictionary
of computer terms.
Other primary sources for these definitions are:
The American National Standard Dictionary for Information Systems, ANSI
X3.172-1990, copyrighted 1990 by the American National Standards
Institute, 11 West 42nd Street, New York, New York 10036. These
definitions are identified by the symbol (A) after the definition.
The Information Technology Vocabulary, developed by Subcommittee 1, Joint
Technical Committee 1, of the International Organization for
Standardization and the International Electrotechnical Commission
(ISO/IEC JTC1/SC1). Definitions of published parts of this vocabulary are
identified by the symbol (I) after the definition; definitions taken from
draft international standards, committee drafts, and working papers being
developed by ISO/IEC JTC1/SC1 are identified by the symbol (T) after the
definition, indicating that final agreement has not yet been reached
among the participating National Bodies of SC1.
ΓòÉΓòÉΓòÉ 9.1. Glossary Listing ΓòÉΓòÉΓòÉ
Select a starting letter of glossary terms:
A N
B O
C P
D Q
E R
F S
G T
H U
I V
J W
K X
L Y
M Z
ΓòÉΓòÉΓòÉ <hidden> Glossary - A ΓòÉΓòÉΓòÉ
accelerator - In SAA Common User Access architecture, a key or combination of
keys that invokes an application-defined function.
accelerator table - A table used to define which key strokes are treated as
accelerators and the commands they are translated into.
access mode - The manner in which an application gains access to a file it has
opened. Examples of access modes are read-only, write-only, and read/write.
access permission - All access rights that a user has regarding an object. (I)
action - One of a set of defined tasks that a computer performs. Users request
the application to perform an action in several ways, such as typing a
command, pressing a function key, or selecting the action name from an
action bar or menu.
action bar - In SAA Common User Access architecture, the area at the top of a
window that contains choices that give a user access to actions available in
that window.
action point - The current position on the screen at which the pointer is
pointing. Contrast with hot spot and input focus.
active program - A program currently running on the computer. An active
program can be interactive (running and receiving input from the user) or
noninteractive (running but not receiving input from the user). See also
interactive program and noninteractive program.
active window - The window with which the user is currently interacting.
address space - (1) The range of addresses available to a program. (A) (2)
The area of virtual storage available for a particular job.
alphanumeric video output - Output to the logical video buffer when the video
adapter is in text mode and the logical video buffer is addressed by an
application as a rectangular array of character cells.
American National Standard Code for Information Interchange - The standard
code, using a coded character set consisting of 7-bit coded characters (8
bits including parity check), that is used for information interchange among
data processing systems, data communication systems, and associated
equipment. The ASCII set consists of control characters and graphic
characters. (A)
Note: IBM has defined an extension to ASCII code (characters 128-255).
anchor - A window procedure that handles Presentation Manager message
conversions between an icon procedure and an application.
anchor block - An area of Presentation-Manager-internal resources to allocated
process or thread that calls WinInitialize.
anchor point - A point in a window used by a program designer or by a window
manager to position a subsequently appearing window.
ANSI - American National Standards Institute.
APA - All points addressable.
API - Application programming interface.
application - A collection of software components used to perform specific
types of work on a computer; for example, a payroll application, an airline
reservation application, a network application.
application object - In SAA Advanced Common User Access architecture, a form
that an application provides for a user; for example, a spreadsheet form.
Contrast with user object.
application programming interface (API) - A functional interface supplied by
the operating system or by a separately orderable licensed program that
allows an application program written in a high-level language to use
specific data or functions of the operating system or the licensed program.
application-modal - Pertaining to a message box or dialog box for which
processing must be completed before further interaction with any other
window owned by the same application may take place.
area - In computer graphics, a filled shape such as a solid rectangle.
ASCII - American National Standard Code for Information Interchange.
ASCIIZ - A string of ASCII characters that is terminated with a byte
containing the value 0.
aspect ratio - In computer graphics, the width-to-height ratio of an area,
symbol, or shape.
asynchronous (ASYNC) - (1) Pertaining to two or more processes that do not
depend upon the occurrence of specific events such as common timing
signals. (T) (2) Without regular time relationship; unexpected or
unpredictable with respect to the execution of program instructions. See
also synchronous.
atom - A constant that represents a string. As soon as a string has been
defined as an atom, the atom can be used in place of the string to save
space. Strings are associated with their respective atoms in an atom table.
See also integer atom.
atom table - A table used to relate atoms with the strings that they
represent. Also in the table is the mechanism by which the presence of a
string can be checked.
atomic operation - An operation that completes its work on an object before
another operation can be performed on the same object.
attribute - A characteristic or property that can be controlled, usually to
obtain a required appearance; for example, the color of a line. See also
graphics attributes and segment attributes.
automatic link - In Information Presentation Facility (IPF), a link that
begins a chain reaction at the primary window. When the user selects the
primary window, an automatic link is activated to display secondary windows.
AVIO - Advanced Video Input/Output.
ΓòÉΓòÉΓòÉ <hidden> Glossary - B ΓòÉΓòÉΓòÉ
BВzier curve - (1) A mathematical technique of specifying smooth continuous
lines and surfaces, which require a starting point and a finishing point
with several intermediate points that influence or control the path of the
linking curve. Named after Dr. P. BВzier. (2) (D of C) In the AIX Graphics
Library, a cubic spline approximation to a set of four control points that
passes through the first and fourth control points and that has a continuous
slope where two spline segments meet. Named after Dr. P. BВzier.
background - (1) In multiprogramming, the conditions under which low-priority
programs are executed. Contrast with foreground. (2) An active session that
is not currently displayed on the screen.
background color - The color in which the background of a graphic primitive is
drawn.
background mix - An attribute that determines how the background of a graphic
primitive is combined with the existing color of the graphics presentation
space. Contrast with mix.
background program - In multiprogramming, a program that executes with a low
priority. Contrast with foreground program.
bit map - A representation in memory of the data displayed on an APA device,
usually the screen.
block - (1) A string of data elements recorded or transmitted as a unit. The
elements may be characters, words, or logical records. (T) (2) To record
data in a block. (3) A collection of contiguous records recorded as a unit.
Blocks are separated by interblock gaps and each block may contain one or
more records. (A)
block device - A storage device that performs I/O operations on blocks of data
called sectors. Data on block devices can be randomly accessed. Block
devices are designated by a drive letter (for example, C:).
blocking mode - A condition set by an application that determines when its
threads might block. For example, an application might set the Pipemode
parameter for the DosCreateNPipe function so that its threads perform I/O
operations to the named pipe block when no data is available.
border - A visual indication (for example, a separator line or a background
color) of the boundaries of a window.
boundary determination - An operation used to compute the size of the smallest
rectangle that encloses a graphics object on the screen.
breakpoint - (1) A point in a computer program where execution may be halted.
A breakpoint is usually at the beginning of an instruction where halts,
caused by external intervention, are convenient for resuming
execution. (T) (2) A place in a program, specified by a command or a
condition, where the system halts execution and gives control to the
workstation user or to a specified program.
broken pipe - When all of the handles that access one end of a pipe have been
closed.
bucket - One or more fields in which the result of an operation is kept.
buffer - (1) A portion of storage used to hold input or output data
temporarily. (2) To allocate and schedule the use of buffers. (A)
button - A mechanism used to request or initiate an action. See also barrel
buttons, bezel buttons, mouse button, push button, and radio button.
byte pipe - Pipes that handle data as byte streams. All unnamed pipes are byte
pipes. Named pipes can be byte pipes or message pipes. See byte stream.
byte stream - Data that consists of an unbroken stream of bytes.
ΓòÉΓòÉΓòÉ <hidden> Glossary - C ΓòÉΓòÉΓòÉ
cache - A high-speed buffer storage that contains frequently accessed
instructions and data; it is used to reduce access time.
cached micro presentation space - A presentation space from a
Presentation-Manager-owned store of micro presentation spaces. It can be
used for drawing to a window only, and must be returned to the store when
the task is complete.
CAD - Computer-Aided Design.
call - (1) The action of bringing a computer program, a routine, or a
subroutine into effect, usually by specifying the entry conditions and
jumping to an entry point. (I) (A) (2) To transfer control to a procedure,
program, routine, or subroutine.
calling sequence - A sequence of instructions together with any associated
data necessary to execute a call. (T)
Cancel - An action that removes the current window or menu without processing
it, and returns the previous window.
cascaded menu - In the OS/2 operating system, a menu that appears when the
arrow to the right of a cascading choice is selected. It contains a set of
choices that are related to the cascading choice. Cascaded menus are used to
reduce the length of a menu. See also cascading choice.
cascading choice - In SAA Common User Access architecture, a choice in a menu
that, when selected, produces a cascaded menu containing other choices. An
arrow () appears to the right of the cascading choice.
CASE statement - In PM programming, provides the body of a window procedure.
There is usually one CASE statement for each message type supported by an
application.
CGA - Color graphics adapter.
chained list - A list in which the data elements may be dispersed but in which
each data element contains information for locating the
next. (T)Synonymous with linked list.
character - A letter, digit, or other symbol.
character box - In computer graphics, the boundary that defines, in world
coordinates, the horizontal and vertical space occupied by a single
character from a character set. See also character mode. Contrast with
character cell.
character cell - The physical, rectangular space in which any single character
is displayed on a screen or printer device. Position is addressed by row and
column coordinates. Contrast with character box.
character code - The means of addressing a character in a character set,
sometimes called code point.
character device - A device that performs I/O operations on one character at a
time. Because character devices view data as a stream of bytes,
character-device data cannot be randomly accessed. Character devices include
the keyboard, mouse, and printer, and are referred to by name.
character mode - A mode that, in conjunction with the font type, determines
the extent to which graphics characters are affected by the character box,
shear, and angle attributes.
character set - (1) An ordered set of unique representations called
characters; for example, the 26 letters of English alphabet, Boolean 0 and
1, the set of symbols in the Morse code, and the 128 ASCII
characters. (A) (2) All the valid characters for a programming language or
for a computer system. (3) A group of characters used for a specific reason;
for example, the set of characters a printer can print.
check box - In SAA Advanced Common User Access architecture, a square box with
associated text that represents a choice. When a user selects a choice, an X
appears in the check box to indicate that the choice is in effect. The user
can clear the check box by selecting the choice again. Contrast with radio
button.
check mark - (1) (D of C) In SAA Advanced Common User Access architecture, a
symbol that shows that a choice is currently in effect. (2) The symbol that
is used to indicate a selected item on a pull-down menu.
child process - In the OS/2 operating system, a process started by another
process, which is called the parent process. Contrast with parent process.
child window - A window that appears within the border of its parent window
(either a primary window or another child window). When the parent window is
resized, moved, or destroyed, the child window also is resized, moved, or
destroyed; however, the child window can be moved or resized independently
from the parent window, within the boundaries of the parent window. Contrast
with parent window.
choice - (1) An option that can be selected. The choice can be presented as
text, as a symbol (number or letter), or as an icon (a pictorial symbol).
(2) (D of C) In SAA Common User Access architecture, an item that a user can
select.
chord - (1) To press more than one button on a pointing device while the
pointer is within the limits that the user has specified for the operating
environment. (2) (D of C) In graphics, a short line segment whose end points
lie on a circle. Chords are a means for producing a circular image from
straight lines. The higher the number of chords per circle, the smoother the
circular image.
class - A way of categorizing objects based on their behavior and shape. A
class is, in effect, a definition of a generic object. In SOM, a class is a
special kind of object that can manufacture other objects that all have a
common shape and exhibit similar behavior (more precisely, all of the
objects manufactured by a class have the same memory layout and share a
common set of methods). New classes can be defined in terms of existing
classes through a technique known as inheritance.
class method - A class method of class <X> is a method provided by the
metaclass of class <X>. Class methods are executed without requiring any
instances of class <X> to exist, and are frequently used to create
instances. In System Object Model, an action that can be performed on a
class object.
class object - In System Object Model, the run-time implementation of a class.
class style - The set of properties that apply to every window in a window
class.
client - (1) A functional unit that receives shared services from a
server. (T) (2) A user, as in a client process that uses a named pipe or
queue that is created and owned by a server process.
client area - The part of the window, inside the border, that is below the
menu bar. It is the user's work space, where a user types information and
selects choices from selection fields. In primary windows, it is where an
application programmer presents the objects that a user works on.
client program - An application that creates and manipulates instances of
classes.
client window - The window in which the application displays output and
receives input. This window is located inside the frame window, under the
window title bar and any menu bar, and within any scroll bars.
clip limits - The area of the paper that can be reached by a printer or
plotter.
clipboard - In SAA Common User Access architecture, an area of computer
memory, or storage, that temporarily holds data. Data in the clipboard is
available to other applications.
clipping - In computer graphics, removing those parts of a display image that
lie outside a given boundary. (I) (A)
clipping area - The area in which the window can paint.
clipping path - A clipping boundary in world-coordinate space.
clock tick - The minimum unit of time that the system tracks. If the system
timer currently counts at a rate of X Hz, the system tracks the time every
1/X of a second. Also known as time tick.
CLOCK$ - Character-device name reserved for the system clock.
code page - An assignment of graphic characters and control-function meanings
to all code points.
code point - (1) Synonym for character code. (2) (D of C) A 1-byte code
representing one of 256 potential characters.
code segment - An executable section of programming code within a load module.
color dithering - See dithering.
color graphics adapter (CGA) - An adapter that simultaneously provides four
colors and is supported by all IBM Personal Computer and Personal System/2
models.
command - The name and parameters associated with an action that a program can
perform.
command area - An area composed of a command field prompt and a command entry
field.
command entry field - An entry field in which users type commands.
command line - On a display screen, a display line, sometimes at the bottom of
the screen, in which only commands can be entered.
command mode - A state of a system or device in which the user can enter
commands.
command prompt - A field prompt showing the location of the command entry
field in a panel.
Common Programming Interface (CPI) - Definitions of those application
development languages and services that have, or are intended to have,
implementations on and a high degree of commonality across the SAA
environments. One of the three SAA architectural areas. See also Common User
Access architecture.
Common User Access (CUA) architecture - Guidelines for the dialog between a
human and a workstation or terminal. One of the three SAA architectural
areas. See also Common Programming Interface.
compile - To translate a program written in a higher-level programming
language into a machine language program.
composite window - A window composed of other windows (such as a frame window,
frame-control windows, and a client window) that are kept together as a unit
and that interact with each other.
computer-aided design (CAD) - The use of a computer to design or change a
product, tool, or machine, such as using a computer for drafting or
illustrating.
COM1, COM2, COM3 - Character-device names reserved for serial ports 1 through
3.
CON - Character-device name reserved for the console keyboard and screen.
conditional cascaded menu - A pull-down menu associated with a menu item that
has a cascade mini-push button beside it in an object's pop-up menu. The
conditional cascaded menu is displayed when the user selects the mini-push
button.
container - In SAA Common User Access architecture, an object that holds other
objects. A folder is an example of a container object. See also folder and
object.
contextual help - In SAA Common User Access Architecture, help that gives
specific information about the item the cursor is on. The help is contextual
because it provides information about a specific item as it is currently
being used. Contrast with extended help.
contiguous - Touching or joining at a common edge or boundary, for example, an
unbroken consecutive series of storage locations.
control - In SAA Advanced Common User Access architecture, a component of the
user interface that allows a user to select choices or type information; for
example, a check box, an entry field, a radio button.
control area - A storage area used by a computer program to hold control information. (I) (A)
Control Panel - In the Presentation Manager, a program used to set up user
preferences that act globally across the system.
Control Program - (1) The basic functions of the operating system, including
DOS emulation and the support for keyboard, mouse, and video input/output.
(2) A computer program designed to schedule and to supervise the execution
of programs of a computer system. (I) (A)
control window - A window that is used as part of a composite window to
perform simple input and output tasks. Radio buttons and check boxes are
examples.
control word - An instruction within a document that identifies its parts or
indicates how to format the document.
coordinate space - A two-dimensional set of points used to generate output on
a video display of printer.
Copy - A choice that places onto the clipboard, a copy of what the user has
selected. See also Cut and Paste.
correlation - The action of determining which element or object within a
picture is at a given position on the display. This follows a pick
operation.
coverpage window - A window in which the application's help information is
displayed.
CPI - Common Programming Interface.
critical extended attribute - An extended attribute that is necessary for the
correct operation of the system or a particular application.
critical section - (1) In programming languages, a part of an asynchronous
procedure that cannot be executed simultaneously with a certain part of
another asynchronous procedure. (I)
Note: Part of the other asynchronous procedure also is a critical section.
(2) A section of code that is not reentrant; that is, code that can be
executed by only one thread at a time.
CUA architecture - Common User Access architecture.
current position - In computer graphics, the position, in user coordinates,
that becomes the starting point for the next graphics routine, if that
routine does not explicitly specify a starting point.
cursor - A symbol displayed on the screen and associated with an input device.
The cursor indicates where input from the device will be placed. Types of
cursors include text cursors, graphics cursors, and selection cursors.
Contrast with pointer and input focus.
Cut - In SAA Common User Access architecture, a choice that removes a selected
object, or a part of an object, to the clipboard, usually compressing the
space it occupied in a window. See also Copy and Paste.
ΓòÉΓòÉΓòÉ <hidden> Glossary - D ΓòÉΓòÉΓòÉ
daisy chain - A method of device interconnection for determining interrupt
priority by connecting the interrupt sources serially.
data segment - A nonexecutable section of a program module; that is, a section
of a program that contains data definitions.
data structure - The syntactic structure of symbolic expressions and their
storage-allocation characteristics. (T)
data transfer - The movement of data from one object to another by way of the
clipboard or by direct manipulation.
DBCS - Double-byte character set.
DDE - Dynamic data exchange.
deadlock - (1) Unresolved contention for the use of a resource. (2) An error
condition in which processing cannot continue because each of two elements
of the process is waiting for an action by, or a response from, the other.
(3) An impasse that occurs when multiple processes are waiting for the
availability of a resource that will not become available because it is
being held by another process that is in a similar wait state.
debug - To detect, diagnose, and eliminate errors in programs. (T)
decipoint - In printing, one tenth of a point. There are 72 points in an
inch.
default procedure - A function provided by the Presentation Manager Interface
that may be used to process standard messages from dialogs or windows.
default value - A value assumed when no value has been specified. Synonymous
with assumed value. For example, in the graphics programming interface, the
default line-type is 'solid'.
definition list - A type of list that pairs a term and its description.
delta - An application-defined threshold, or number of container items, from
either end of the list.
descendant - See child process.
descriptive text - Text used in addition to a field prompt to give more
information about a field.
Deselect all - A choice that cancels the selection of all of the objects that
have been selected in that window.
Desktop Manager - In the Presentation Manager, a window that displays a list
of groups of programs, each of which can be started or stopped.
desktop window - The window, corresponding to the physical device, against
which all other types of windows are established.
detached process - A background process that runs independent of the parent
process.
detent - A point on a slider that represents an exact value to which a user
can move the slider arm.
device context - A logical description of a data destination such as memory,
metafile, display, printer, or plotter. See also direct device context,
information device context, memory device context, metafile device context,
queued device context, and screen device context.
device driver - A file that contains the code needed to attach and use a
device such as a display, printer, or plotter.
device space - (1) Coordinate space in which graphics are assembled after all
GPI transformations have been applied. Device space is defined in
device-specific units. (2) ( D of C) In computer graphics, a space defined
by the complete set of addressable points of a display device. (A)
dialog - The interchange of information between a computer and its user
through a sequence of requests by the user and the presentation of responses
by the computer.
dialog box - In SAA Advanced Common User Access architecture, a movable
window, fixed in size, containing controls that a user uses to provide
information required by an application so that it can continue to process a
user request. See also message box, primary window, secondary window. Also
known as a pop-up window.
Dialog Box Editor - A WYSIWYG editor that creates dialog boxes for
communicating with the application user.
dialog item - A component (for example, a menu or a button) of a dialog box.
Dialog items are also used when creating dialog templates.
dialog procedure - A dialog window that is controlled by a window procedure.
It is responsible for responding to all messages sent to the dialog window.
dialog tag language - A markup language used by the DTL compiler to create
dialog objects.
dialog template - The definition of a dialog box, which contains details of
its position, appearance, and window ID, and the window ID of each of its
child windows.
direct device context - A logical description of a data destination that is a
device other than the screen (for example, a printer or plotter), and where
the output is not to go through the spooler. Its purpose is to satisfy
queries. See also device context.
direct manipulation - The user's ability to interact with an object by using
the mouse, typically by dragging an object around on the Desktop and
dropping it on other objects.
direct memory access (DMA) - A technique for moving data directly between main
storage and peripheral equipment without requiring processing of the data by
the processing unit.(T)
directory - A type of file containing the names and controlling information
for other files or other directories.
display point - Synonym for pel.
dithering - (1) The process used in color displays whereby every other pel is
set to one color, and the intermediate pels are set to another. Together
they produce the effect of a third color at normal viewing distances. This
process can only be used on solid areas of color; it does not work, for
example, on narrow lines. (2) (D of C ) In computer graphics, a technique of
interleaving dark and light pixels so that the resulting image looks
smoothly shaded when viewed from a distance.
DMA - Direct memory access.
DOS Protect Mode Interface (DPMI) - An interface between protect mode and real
mode programs.
double-byte character set (DBCS) - A set of characters in which each character
is represented by two bytes. Languages such as Japanese, Chinese, and
Korean, which contain more characters than can be represented by 256 code
points, require double-byte character sets. Since each character requires
two bytes, the entering, displaying, and printing of DBCS characters
requires hardware and software that can support DBCS.
doubleword - A contiguous sequence of bits or characters that comprises two
computer words and is capable of being addressed as a unit. (A)
DPMI - DOS Protect Mode Interface.
drag - In SAA Common User Access, to use a pointing device to move an object;
for example, clicking on a window border, and dragging it to make the window
larger.
dragging - (1) In computer graphics, moving an object on the display screen as
if it were attached to the pointer. (2) (D of C) In computer graphics,
moving one or more segments on a display surface by translating. (I) (A)
drawing chain - See segment chain.
drop - To fix the position of an object that is being dragged, by releasing
the select button of the pointing device. See also drag.
DTL - Dialog tag language.
dual-boot function - A feature of the OS/2 operating system that allows the
user to start DOS from within the operating system, or an OS/2 session from
within DOS.
duplex - Pertaining to communication in which data can be sent and received at
the same time. Synonymous with full duplex.
dynamic data exchange (DDE) - A message protocol used to communicate between
applications that share data. The protocol uses shared memory as the means
of exchanging data between applications.
dynamic data formatting - A formatting procedure that enables you to
incorporate text, bit maps or metafiles in an IPF window at execution time.
dynamic link library - A collection of executable programming code and data
that is bound to an application at load time or run time, rather than during
linking. The programming code and data in a dynamic link library can be
shared by several applications simultaneously.
dynamic linking - The process of resolving external references in a program
module at load time or run time rather than during linking.
dynamic segments - Graphics segments drawn in exclusive-OR mix mode so that
they can be moved from one screen position to another without affecting the
rest of the displayed picture.
dynamic storage - (1) A device that stores data in a manner that permits the
data to move or vary with time such that the specified data is not always
available for recovery. (A) (2) A storage in which the cells require
repetitive application of control signals in order to retain stored data.
Such repetitive application of the control signals is called a refresh
operation. A dynamic storage may use static addressing or sensing
circuits. (A) (3) See also static storage.
dynamic time slicing - Varies the size of the time slice depending on system
load and paging activity.
dynamic-link module - A module that is linked at load time or run time.
ΓòÉΓòÉΓòÉ <hidden> Glossary - E ΓòÉΓòÉΓòÉ
EBCDIC - Extended binary-coded decimal interchange code. A coded character set
consisting of 8-bit coded characters (9 bits including parity check), used
for information interchange among data processing systems, data
communications systems, and associated equipment.
edge-triggered - Pertaining to an event semaphore that is posted then reset
before a waiting thread gets a chance to run. The semaphore is considered to
be posted for the rest of that thread's waiting period; the thread does not
have to wait for the semaphore to be posted again.
EGA - Extended graphics adapter.
element - An entry in a graphics segment that comprises one or more graphics
orders and that is addressed by the element pointer.
EMS - Expanded Memory Specification.
encapsulation - Hiding an object's implementation, that is, its private,
internal data and methods. Private variables and methods are accessible only
to the object that contains them.
entry field - In SAA Common User Access architecture, an area where a user
types information. Its boundaries are usually indicated. See also selection
field.
entry panel - A defined panel type containing one or more entry fields and
protected information such as headings, prompts, and explanatory text.
entry-field control - The component of a user interface that provides the
means by which the application receives data entered by the user in an entry
field. When it has the input focus, the entry field displays a flashing
pointer at the position where the next typed character will go.
environment segment - The list of environment variables and their values for a
process.
environment strings - ASCII text strings that define the value of environment
variables.
environment variables - Variables that describe the execution environment of a
process. These variables are named by the operating system or by the
application. Environment variables named by the operating system are PATH,
DPATH, INCLUDE, INIT, LIB, PROMPT, and TEMP. The values of environment
variables are defined by the user in the CONFIG.SYS file, or by using the
SET command at the OS/2 command prompt.
error message - An indication that an error has been detected. (A)
event semaphore - A semaphore that enables a thread to signal a waiting thread
or threads that an event has occurred or that a task has been completed. The
waiting threads can then perform an action that is dependent on the
completion of the signaled event.
exception - An abnormal condition such as an I/O error encountered in
processing a data set or a file.
exclusive system semaphore - A system semaphore that can be modified only by
threads within the same process.
executable file - (1) A file that contains programs or commands that perform
operations or actions to be taken. (2) A collection of related data records
that execute programs.
exit - To execute an instruction within a portion of a computer program in
order to terminate the execution of that portion. Such portions of computer
programs include loops, subroutines, modules, and so on. (T) Repeated exit
requests return the user to the point from which all functions provided to
the system are accessible. Contrast with cancel.
expanded memory specification (EMS) - Enables DOS applications to access
memory above the 1MB real mode addressing limit.
extended attribute - An additional piece of information about a file object,
such as its data format or category. It consists of a name and a value. A
file object may have more than one extended attribute associated with it.
extended help - In SAA Common User Access architecture, a help action that
provides information about the contents of the application window from which
a user requested help. Contrast with contextual help.
extended-choice selection - A mode that allows the user to select more than
one item from a window. Not all windows allow extended choice selection.
Contrast with multiple-choice selection.
extent - Continuous space on a disk or diskette that is occupied by or
reserved for a particular data set, data space, or file.
external link - In Information Presentation Facility, a link that connects
external online document files.
ΓòÉΓòÉΓòÉ <hidden> Glossary - F ΓòÉΓòÉΓòÉ
family-mode application - An application program that can run in the OS/2
environment and in the DOS environment; however, it cannot take advantage of
many of the OS/2-mode facilities, such as multitasking, interprocess
communication, and dynamic linking.
FAT - File allocation table.
FEA - Full extended attribute.
field-level help - Information specific to the field on which the cursor is
positioned. This help function is "contextual" because it provides
information about a specific item as it is currently used; the information
is dependent upon the context within the work session.
FIFO - First-in-first-out. (A)
file - A named set of records stored or processed as a unit. (T)
file allocation table (FAT) - In IBM personal computers, a table used by the
operating system to allocate space on a disk for a file, and to locate and
chain together parts of the file that may be scattered on different sectors
so that the file can be used in a random or sequential manner.
file attribute - Any of the attributes that describe the characteristics of a
file.
File Manager - In the Presentation Manager, a program that displays
directories and files, and allows various actions on them.
file specification - The full identifier for a file, which includes its drive
designation, path, file name, and extension.
file system - The combination of software and hardware that supports storing
information on a storage device.
file system driver (FSD) - A program that manages file I\O and controls the
format of information on the storage media.
fillet - A curve that is tangential to the end points of two adjoining lines.
See also polyfillet.
filtering - An application process that changes the order of data in a queue.
first-in-first-out (FIFO) - A queuing technique in which the next item to be
retrieved is the item that has been in the queue for the longest time. (A)
flag - (1) An indicator or parameter that shows the setting of a switch. (2) A
character that signals the occurrence of some condition, such as the end of
a word. (A) (3) (D of C) A characteristic of a file or directory that
enables it to be used in certain ways. See also archive flag, hidden flag,
and read-only flag.
focus - See input focus.
folder - A container used to organize objects.
font - A particular size and style of typeface that contains definitions of
character sets, marker sets, and pattern sets.
Font Editor - A utility program provided with the IBM Developers Toolkit that
enables the design and creation of new fonts.
foreground program - (1) The program with which the user is currently
interacting. Also known as interactive program. Contrast with background
program. (2) (D of C) In multiprogramming, a high-priority program.
frame - The part of a window that can contain several different visual
elements specified by the application, but drawn and controlled by the
Presentation Manager. The frame encloses the client area.
frame styles - Standard window layouts provided by the Presentation Manager.
FSD - File system driver.
full-duplex - Synonym for duplex.
full-screen application - An application that has complete control of the
screen.
function - (1) In a programming language, a block, with or without formal
parameters, whose execution is invoked by means of a call. (2) A set of
related control statements that cause one or more programs to be performed.
function key - A key that causes a specified sequence of operations to be
performed when it is pressed, for example, F1 and Alt-K.
function key area - The area at the bottom of a window that contains function
key assignments such as F1=Help.
ΓòÉΓòÉΓòÉ <hidden> Glossary - G ΓòÉΓòÉΓòÉ
GDT - Global Descriptor Table.
general protection fault - An exception condition that occurs when a process
attempts to use storage or a module that has some level of protection
assigned to it, such as I/O privilege level. See also IOPL code segment.
Global Descriptor Table (GDT) - A table that defines code and data segments
available to all tasks in an application.
global dynamic-link module - A dynamic-link module that can be shared by all
processes in the system that refer to the module name.
global file-name character - Either a question mark (?) or an asterisk (*)
used as a variable in a file name or file name extension when referring to a
particular file or group of files.
glyph - A graphic symbol whose appearance conveys information.
GPI - Graphics programming interface.
graphic primitive - In computer graphics, a basic element, such as an arc or a
line, that is not made up of smaller parts and that is used to create
diagrams and pictures. See also graphics segment.
graphics - (1) A picture defined in terms of graphic primitives and graphics
attributes. (2) (D of C) The making of charts and pictures. (3) Pertaining
to charts, tables, and their creation. (4) See computer graphics, coordinate
graphics, fixed-image graphics, interactive graphics, passive graphics,
raster graphics.
graphics attributes - Attributes that apply to graphic primitives. Examples
are color, line type, and shading-pattern definition. See also segment
attributes.
graphics field - The clipping boundary that defines the visible part of the
presentation-page contents.
graphics mode - One of several states of a display. The mode determines the
resolution and color content of the screen.
graphics model space - The conceptual coordinate space in which a picture is
constructed after any model transforms have been applied. Also known as
model space.
Graphics programming interface - The formally defined programming language
that is between an IBM graphics program and the user of the program.
graphics segment - A sequence of related graphic primitives and graphics
attributes. See also graphic primitive.
graying - The indication that a choice on a pull-down is unavailable.
group - A collection of logically connected controls. For example, the buttons
controlling paper size for a printer could be called a group. See also
program group.
ΓòÉΓòÉΓòÉ <hidden> Glossary - H ΓòÉΓòÉΓòÉ
handle - (1) An identifier that represents an object, such as a device or
window, to the Presentation Interface. (2) (D of C) In the Advanced DOS and
OS/2 operating systems, a binary value created by the system that identifies
a drive, directory, and file so that the file can be found and opened.
hard error - An error condition on a network that requires either that the
system be reconfigured or that the source of the error be removed before the
system can resume reliable operation.
header - (1) System-defined control information that precedes user data. (2)
The portion of a message that contains control information for the message,
such as one or more destination fields, name of the originating station,
input sequence number, character string indicating the type of message, and
priority level for the message.
heading tags - A document element that enables information to be displayed in
windows, and that controls entries in the contents window controls placement
of push buttons in a window, and defines the shape and size of windows.
heap - An area of free storage available for dynamic allocation by an
application. Its size varies according to the storage requirements of the
application.
help function - (1) A function that provides information about a specific
field, an application panel, or information about the help facility. (2) (D
of C) One or more display images that describe how to use application
software or how to do a system operation.
Help index - In SAA Common User Access architecture, a help action that
provides an index of the help information available for an application.
help panel - A panel with information to assist users that is displayed in
response to a help request from the user.
help window - A Common-User-Access-defined secondary window that displays
information when the user requests help.
hidden file - An operating system file that is not displayed by a directory
listing.
hide button - In the OS/2 operating system, a small, square button located in
the right-hand corner of the title bar of a window that, when selected,
removes from the screen all the windows associated with that window.
Contrast with maximize button. See also restore button.
hierarchical inheritance - The relationship between parent and child classes.
An object that is lower in the inheritance hierarchy than another object,
inherits all the characteristics and behaviors of the objects above it in
the hierarchy.
hierarchy - A tree of segments beginning with the root segment and proceeding
downward to dependent segment types.
high-performance file system (HPFS) - In the OS/2 operating system, an
installable file system that uses high-speed buffer storage, known as a
cache, to provide fast access to large disk volumes. The file system also
supports the coexistence of multiple, active file systems on a single
personal computer, with the capability of multiple and different storage
devices. File names used with the HPFS can have as many as 254 characters.
hit testing - The means of identifying which window is associated with which
input device event.
hook - A point in a system-defined function where an application can supply
additional code that the system processes as though it were part of the
function.
hook chain - A sequence of hook procedures that are "chained" together so that
each event is passed, in turn, to each procedure in the chain.
hot spot - The part of the pointer that must touch an object before it can be
selected. This is usually the tip of the pointer. Contrast with action
point.
HPFS - high-performance file system.
hypergraphic link - A connection between one piece of information and another
through the use of graphics.
hypertext - A way of presenting information online with connections between
one piece of information and another, called hypertext links. See also
hypertext link.
hypertext link - A connection between one piece of information and another.
ΓòÉΓòÉΓòÉ <hidden> Glossary - I ΓòÉΓòÉΓòÉ
I/O operation - An input operation to, or output operation from a device
attached to a computer.
I-beam pointer - A pointer that indicates an area, such as an entry field in
which text can be edited.
icon - In SAA Advanced Common User Access architecture, a graphical
representation of an object, consisting of an image, image background, and a
label. Icons can represent items (such as a document file) that the user
wants to work on, and actions that the user wants to perform. In the
Presentation Manager, icons are used for data objects, system actions, and
minimized programs.
icon area - In the Presentation Manager, the area at the bottom of the screen
that is normally used to display the icons for minimized programs.
Icon Editor - The Presentation Manager-provided tool for creating icons.
IDL - Interface Definition Language.
image font - A set of symbols, each of which is described in a rectangular
array of pels. Some of the pels in the array are set to produce the image of
one of the symbols. Contrast with outline font.
implied metaclass - Subclassing the metaclass of a parent class without a
separate CSC for the resultant metaclass.
indirect manipulation - Interaction with an object through choices and
controls.
information device context - A logical description of a data destination other
than the screen (for example, a printer or plotter), but where no output
will occur. Its purpose is to satisfy queries. See also device context.
information panel - A defined panel type characterized by a body containing
only protected information.
Information Presentation Facility (IPF) - A facility provided by the OS/2
operating system, by which application developers can produce online
documentation and context-sensitive online help panels for their
applications.
inheritance - The technique of specifying the shape and behavior of one class
(called a subclass) as incremental differences from another class (called
the parent class or superclass). The subclass inherits the superclass' state
representation and methods, and can provide additional data elements and
methods. The subclass also can provide new functions with the same method
names used by the superclass. Such a subclass method is said to override the
superclass method, and will be selected automatically by method resolution
on subclass instances. An overriding method can elect to call upon the
superclass' method as part of its own implementation.
input focus - (1) The area of a window where user interaction is possible
using an input device, such as a mouse or the keyboard. (2) The position in
the active window where a user's normal interaction with the keyboard will
appear.
input router - An internal OS/2 process that removes messages from the system
queue.
input/output control - A device-specific command that requests a function of a
device driver.
installable file system (IFS) - A file system in which software is installed
when the operating system is started.
instance - (Or object instance). A specific object, as distinguished from the
abstract definition of an object referred to as its class.
instance method - A method valid for a particular object.
instruction pointer - In System/38, a pointer that provides addressability for
a machine interface instruction in a program.
integer atom - An atom that represents a predefined system constant and
carries no storage overhead. For example, names of window classes provided
by Presentation Manager are expressed as integer atoms.
interactive graphics - Graphics that can be moved or manipulated by a user at
a terminal.
interactive program - (1) A program that is running (active) and is ready to
receive (or is receiving) input from a user. (2) A running program that can
receive input from the keyboard or another input device. Compare with active
program and contrast with noninteractive program.
Also known as a foreground program.
interchange file - A file containing data that can be sent from one
Presentation Manager interface application to another.
Interface Definition Language (IDL) - Language-neutral interface specification
for a SOM class.
interpreter - A program that translates and executes each instruction of a
high-level programming language before it translates and executes.
interprocess communication (IPC) - In the OS/2 operating system, the exchange
of information between processes or threads through semaphores, pipes,
queues, and shared memory.
interval timer - (1) A timer that provides program interruptions on a
program-controlled basis. (2) An electronic counter that counts intervals of
time under program control.
IOCtl - Input/output control.
IOPL - Input/output privilege level.
IOPL code segment - An IOPL executable section of programming code that
enables an application to directly manipulate hardware interrupts and ports
without replacing the device driver. See also privilege level.
IPC - Interprocess communication.
IPF - Information Presentation Facility.
IPF compiler - A text compiler that interpret tags in a source file and
converts the information into the specified format.
IPF tag language - A markup language that provides the instructions for
displaying online information.
item - A data object that can be passed in a DDE transaction.
ΓòÉΓòÉΓòÉ <hidden> Glossary - J ΓòÉΓòÉΓòÉ
journal - A special-purpose file that is used to record changes made in the
system.
ΓòÉΓòÉΓòÉ <hidden> Glossary - K ΓòÉΓòÉΓòÉ
Kanji - A graphic character set used in Japanese ideographic alphabets.
KBD$ - Character-device name reserved for the keyboard.
kernel - The part of an operating system that performs basic functions, such
as allocating hardware resources.
kerning - The design of graphics characters so that their character boxes
overlap. Used to space text proportionally.
keyboard accelerator - A keystroke that generates a command message for an
application.
keyboard augmentation - A function that enables a user to press a keyboard key
while pressing a mouse button.
keyboard focus - A temporary attribute of a window. The window that has a
keyboard focus receives all keyboard input until the focus changes to a
different window.
Keys help - In SAA Common User Access architecture, a help action that
provides a listing of the application keys and their assigned functions.
ΓòÉΓòÉΓòÉ <hidden> Glossary - L ΓòÉΓòÉΓòÉ
label - In a graphics segment, an identifier of one or more elements that is
used when editing the segment.
LAN - Local area network.
language support procedure - A function provided by the Presentation Manager
Interface for applications that do not, or cannot (as in the case of COBOL
and FORTRAN programs), provide their own dialog or window procedures.
lazy drag - See pickup and drop.
lazy drag set - See pickup set.
LDT - In the OS/2 operating system, Local Descriptor Table.
LIFO stack - A stack from which data is retrieved in last-in, first-out order.
linear address - A unique value that identifies the memory object.
linked list - Synonym for chained list.
list box - In SAA Advanced Common User Access architecture, a control that
contains scrollable choices from which a user can select one choice.
Note: In CUA architecture, this is a programmer term. The end user term is
selection list.
list button - A button labeled with an underlined down-arrow that presents a
list of valid objects or choices that can be selected for that field.
list panel - A defined panel type that displays a list of items from which
users can select one or more choices and then specify one or more actions to
work on those choices.
load time - The point in time at which a program module is loaded into main
storage for execution.
load-on-call - A function of a linkage editor that allows selected segments of
the module to be disk resident while other segments are executing. Disk
resident segments are loaded for execution and given control when any entry
point that they contain is called.
local area network (LAN) - (1) A computer network located on a user's premises
within a limited geographical area. Communication within a local area
network is not subject to external regulations; however, communication
across the LAN boundary may be subject to some form of regulation. (T)
Note: A LAN does not use store and forward techniques. (2) A network in
which a set of devices are connected to one another for communication and
that can be connected to a larger network.
Local Descriptor Table (LDT) - Defines code and data segments specific to a
single task.
lock - A serialization mechanism by means of which a resource is restricted
for use by the holder of the lock.
logical storage device - A device that the user can map to a physical (actual)
device.
LPT1, LPT2, LPT3 - Character-device names reserved for parallel printers 1
through 3.
ΓòÉΓòÉΓòÉ <hidden> Glossary - M ΓòÉΓòÉΓòÉ
main window - The window that is positioned relative to the desktop window.
manipulation button - The button on a pointing device a user presses to
directly manipulate an object.
map - (1) A set of values having a defined correspondence with the quantities
or values of another set. (I) (A) (2) To establish a set of values having
a defined correspondence with the quantities or values of another set. (I)
marker box - In computer graphics, the boundary that defines, in world
coordinates, the horizontal and vertical space occupied by a single marker
from a marker set.
marker symbol - A symbol centered on a point. Graphs and charts can use marker
symbols to indicate the plotted points.
marquee box - The rectangle that appears during a selection technique in which
a user selects objects by drawing a box around them with a pointing device.
Master Help Index - In the OS/2 operating system, an alphabetic list of help
topics related to using the operating system.
maximize - To enlarge a window to its largest possible size.
media window - The part of the physical device (display, printer, or plotter)
on which a picture is presented.
memory block - Part memory within a heap.
memory device context - A logical description of a data destination that is a
memory bit map. See also device context.
memory management - A feature of the operating system for allocating, sharing,
and freeing main storage.
memory object - Logical unit of memory requested by an application, which
forms the granular unit of memory manipulation from the application
viewpoint.
menu - In SAA Advanced Common User Access architecture, an extension of the
menu bar that displays a list of choices available for a selected choice in
the menu bar. After a user selects a choice in menu bar, the corresponding
menu appears. Additional pop-up windows can appear from menu choices.
menu bar - In SAA Advanced Common User Access architecture, the area near the
top of a window, below the title bar and above the rest of the window, that
contains choices that provide access to other menus.
menu button - The button on a pointing device that a user presses to view a
pop-up menu associated with an object.
message - (1) In the Presentation Manager, a packet of data used for
communication between the Presentation Manager interface and Presentation
Manager applications (2) In a user interface, information not requested by
users but presented to users by the computer in response to a user action or
internal process.
message box - (1) A dialog window predefined by the system and used as a
simple interface for applications, without the necessity of creating
dialog-template resources or dialog procedures. (2) (D of C) In SAA Advanced
Common User Access architecture, a type of window that shows messages to
users. See also dialog box, primary window, secondary window.
message filter - The means of selecting which messages from a specific window
will be handled by the application.
message queue - A sequenced collection of messages to be read by the
application.
message stream mode - A method of operation in which data is treated as a
stream of messages. Contrast with byte stream.
metacharacter - See global file-name character.
metaclass - A class whose instances are all classes. In SOM, any class
descended from SOMClass is a metaclass. The methods of a metaclass are
sometimes called "class" methods.
metafile - A file containing a series of attributes that set color, shape and
size, usually of a picture or a drawing. Using a program that can interpret
these attributes, a user can view the assembled image.
metafile device context - A logical description of a data destination that is
a metafile, which is used for graphics interchange. See also device context.
metalanguage - A language used to specify another language. For example, data
types can be described using a metalanguage so as to make the descriptions
independent of any one computer language.
method - One of the units that makes up the behavior of an object. A method is
a combination of a function and a name, such that many different functions
can have the same name. Which function the name refers to at any point in
time depends on the object that is to execute the method and is the subject
of method resolution.
method override - The replacement, by a child class, of the implementation of
a method inherited from a parent and an ancestor class.
mickey - A unit of measurement for physical mouse motion whose value depends
on the mouse device driver currently loaded.
micro presentation space - A graphics presentation space in which a restricted
set of the GPI function calls is available.
minimize - To remove from the screen all windows associated with an
application and replace them with an icon that represents the application.
mix - An attribute that determines how the foreground of a graphic primitive
is combined with the existing color of graphics output. Also known as
foreground mix. Contrast with background mix.
mixed character string - A string containing a mixture of one-byte and Kanji
or Hangeul (two-byte) characters.
mnemonic - (1) A method of selecting an item on a pull-down by means of typing
the highlighted letter in the menu item. (2) (D of C) In SAA Advanced Common
User Access architecture, usually a single character, within the text of a
choice, identified by an underscore beneath the character. If all characters
in a choice already serve as mnemonics for other choices, another character,
placed in parentheses immediately following the choice, can be used. When a
user types the mnemonic for a choice, the choice is either selected or the
cursor is moved to that choice.
modal dialog box - In SAA Advanced Common User Access architecture, a type of
movable window, fixed in size, that requires a user to enter information
before continuing to work in the application window from which it was
displayed. Contrast with modeless dialog box. Also known as a serial dialog
box. Contrast with parallel dialog box.
Note: In CUA architecture, this is a programmer term. The end user term is
pop-up window.
model space - See graphics model space.
modeless dialog box - In SAA Advanced Common User Access architecture, a type
of movable window, fixed in size, that allows users to continue their dialog
with the application without entering information in the dialog box. Also
known as a parallel dialog box. Contrast with modal dialog box.
Note: In CUA architecture, this is a programmer term. The end user term is
pop-up window.
module definition file - A file that describes the code segments within a load
module. For example, it indicates whether a code segment is loadable before
module execution begins (preload), or loadable only when referred to at run
time (load-on-call).
mouse - In SAA usage, a device that a user moves on a flat surface to position
a pointer on the screen. It allows a user to select a choice o function to
be performed or to perform operations on the screen, such as dragging or
drawing lines from one position to another.
MOUSE$ - Character-device name reserved for a mouse.
multiple-choice selection - In SAA Basic Common User Access architecture, a
type of field from which a user can select one or more choices or select
none. See also check box. Contrast with extended-choice selection.
multiple-line entry field - In SAA Advanced Common User Access architecture, a
control into which a user types more than one line of information. See also
single-line entry field.
multitasking - The concurrent processing of applications or parts of
applications. A running application and its data are protected from other
concurrently running applications.
mutex semaphore - (Mutual exclusion semaphore). A semaphore that enables
threads to serialize their access to resources. Only the thread that
currently owns the mutex semaphore can gain access to the resource, thus
preventing one thread from interrupting operations being performed by
another.
muxwait semaphore - (Multiple wait semaphore). A semaphore that enables a
thread to wait either for multiple event semaphores to be posted or for
multiple mutex semaphores to be released. Alternatively, a muxwait semaphore
can be set to enable a thread to wait for any ONE of the event or mutex
semaphores in the muxwait semaphore's list to be posted or released.
ΓòÉΓòÉΓòÉ <hidden> Glossary - N ΓòÉΓòÉΓòÉ
named pipe - A named buffer that provides client-to-server, server-to-client,
or full duplex communication between unrelated processes. Contrast with
unnamed pipe.
national language support (NLS) - The modification or conversion of a United
States English product to conform to the requirements of another language or
country. This can include the enabling or retrofitting of a product and the
translation of nomenclature, MRI, or documentation of a product.
nested list - A list that is contained within another list.
NLS - national language support.
non-8.3 file-name format - A file-naming convention in which file names can
consist of up to 255 characters. See also 8.3 file-name format.
noncritical extended attribute - An extended attribute that is not necessary
for the function of an application.
nondestructive read - Reading that does not erase the data in the source
location. (T)
noninteractive program - A running program that cannot receive input from the
keyboard or other input device. Compare with active program, and contrast
with interactive program.
nonretained graphics - Graphic primitives that are not remembered by the
Presentation Manager interface when they have been drawn. Contrast with
retained graphics.
null character (NUL) - (1) Character-device name reserved for a nonexistent
(dummy) device. (2) (D of C) A control character that is used to accomplish
media-fill or time-fill and that may be inserted into or removed from a
sequence of characters without affecting the meaning of the sequence;
however, the control of equipment or the format may be affected by this
character. (I) (A)
null-terminated string - A string of (n+1) characters where the (n+1)th
character is the 'null' character (0x00) Also known as 'zero-terminated'
string and 'ASCIIZ' string.
ΓòÉΓòÉΓòÉ <hidden> Glossary - O ΓòÉΓòÉΓòÉ
object - The elements of data and function that programs create, manipulate,
pass as arguments, and so forth. An object is a way of associating specific
data values with a specific set of named functions (called methods) for a
period of time (referred to as the lifetime of the object). The data values
of an object are referred to as its state. In SOM, objects are created by
other objects called classes. The specification of what comprises the set of
functions and data elements that make up an object is referred to as the
definition of a class.
SOM objects offer a high degree of encapsulation. This property permits many
aspects of the implementation of an object to change without affecting
client programs that depend on the object's behavior.
object definition - See class.
object instance - See instance.
Object Interface Definition Language (OIDL) - Specification language used in
SOM Version 1 for defining classes. Replaced by Interface Definition
Language (IDL).
object window - A window that does not have a parent but which might have
child windows. An object window cannot be presented on a device.
OIDL - Object Interface Definition Language.
open - To start working with a file, directory, or other object.
ordered list - Vertical arrangements of items, with each item in the list
preceded by a number or letter.
outline font - A set of symbols, each of which is created as a series of lines
and curves. Synonymous with vector font. Contrast with image font.
output area - An area of storage reserved for output. (A)
owner window - A window into which specific events that occur in another
(owned) window are reported.
ownership - The determination of how windows communicate using messages.
owning process - The process that owns the resources that might be shared with
other processes.
ΓòÉΓòÉΓòÉ <hidden> Glossary - P ΓòÉΓòÉΓòÉ
page - (1) A 4KB segment of contiguous physical memory. (2) (D of C) A defined
unit of space on a storage medium.
page viewport - A boundary in device coordinates that defines the area of the
output device in which graphics are to be displayed. The presentation-page
contents are transformed automatically to the page viewport in device space.
paint - (1) The action of drawing or redrawing the contents of a window. (2)
In computer graphics, to shade an area of a display image; for example,
with crosshatching or color.
panel - In SAA Basic Common User Access architecture, a particular arrangement
of information that is presented in a window or pop-up. If some of the
information is not visible, a user can scroll through the information.
panel area - An area within a panel that contains related information. The
three major Common User Access-defined panel areas are the action bar, the
function key area, and the panel body.
panel area separator - In SAA Basic Common User Access architecture, a solid,
dashed, or blank line that provides a visual distinction between two
adjacent areas of a panel.
panel body - The portion of a panel not occupied by the action bar, function
key area, title or scroll bars. The panel body can contain protected
information, selection fields, and entry fields. The layout and content of
the panel body determine the panel type.
panel body area - See client area.
panel definition - A description of the contents and characteristics of a
panel. A panel definition is the application developer's mechanism for
predefining the format to be presented to users in a window.
panel ID - In SAA Basic Common User Access architecture, a panel identifier,
located in the upper-left corner of a panel. A user can choose whether to
display the panel ID.
panel title - In SAA Basic Common User Access architecture, a particular
arrangement of information that is presented in a window or pop-up. If some
of the information is not visible, a user can scroll through the
information.
paper size - The size of paper, defined in either standard U.S. or European
names (for example, A, B, A4), and measured in inches or millimeters
respectively.
parallel dialog box - See modeless dialog box.
parameter list - A list of values that provides a means of associating
addressability of data defined in a called program with data in the calling
program. It contains parameter names and the order in which they are to be
associated in the calling and called program.
parent class - See inheritance.
parent process - In the OS/2 operating system, a process that creates other
processes. Contrast with child process.
parent window - In the OS/2 operating system, a window that creates a child
window. The child window is drawn within the parent window. If the parent
window is moved, resized, or destroyed, the child window also will be moved,
resized, or destroyed. However, the child window can be moved and resized
independently from the parent window, within the boundaries of the parent
window. Contrast with child window.
partition - (1) A fixed-size division of storage. (2) On an IBM personal
computer fixed disk, one of four possible storage areas of variable size;
one may be accessed by DOS, and each of the others may be assigned to
another operating system.
Paste - A choice in the Edit pull-down that a user selects to move the
contents of the clipboard into a preselected location. See also Copy and
Cut.
path - The route used to locate files; the storage location of a file. A fully
qualified path lists the drive identifier, directory name, subdirectory name
(if any), and file name with the associated extension.
PDD - Physical device driver.
peeking - An action taken by any thread in the process that owns the queue to
examine queue elements without removing them.
pel - (1) The smallest area of a display screen capable of being addressed and
switched between visible and invisible states. Synonym for display point,
pixel, and picture element. (2) (D of C) Picture element.
persistent object - An object whose instance data and state are preserved
between system shutdown and system startup.
physical device driver (PDD) - A system interface that handles hardware
interrupts and supports a set of input and output functions.
pick - To select part of a displayed object using the pointer.
pickup - To add an object or set of objects to the pickup set.
pickup and drop - A drag operation that does not require the direct
manipulation button to be pressed for the duration of the drag.
pickup set - The set of objects that have been picked up as part of a pickup
and drop operation.
picture chain - See segment chain.
picture element - (1) Synonym for pel. (2) (D of C) In computer graphics, the
smallest element of a display surface that can be independently assigned
color and intensity. (T) . (3) The area of the finest detail that can be
reproduced effectively on the recording medium.
PID - Process identification.
pipe - (1) A named or unnamed buffer used to pass data between processes. A
process reads from or writes to a pipe as if the pipe were a standard-input
or standard-output file. See also named pipe and unnamed pipe. (2) (D of C)
To direct data so that the output from one process becomes the input to
another process. The standard output of one command can be connected to the
standard input of another with the pipe operator (|).
pixel - (1) Synonym for pel. (2) (D of C) Picture element.
plotter - An output unit that directly produces a hardcopy record of data on a
removable medium, in the form of a two-dimensional graphic representation. (T)
PM - Presentation Manager.
pointer - (1) The symbol displayed on the screen that is moved by a pointing
device, such as a mouse. The pointer is used to point at items that users
can select. Contrast with cursor. (2) A data element that indicates the
location of another data element. (T)
POINTER$ - Character-device name reserved for a pointer device (mouse screen
support).
pointing device - In SAA Advanced Common User Access architecture, an
instrument, such as a mouse, trackball, or joystick, used to move a pointer
on the screen.
pointings - Pairs of x-y coordinates produced by an operator defining
positions on a screen with a pointing device, such as a mouse.
polyfillet - A curve based on a sequence of lines. The curve is tangential to
the end points of the first and last lines, and tangential also to the
midpoints of all other lines. See also fillet.
polygon - One or more closed figures that can be drawn filled, outlined, or
filled and outlined.
polyline - A sequence of adjoining lines.
polymorphism - The ability to have different implementations of the same
method for two or more classes of objects.
pop - To retrieve an item from a last-in-first-out stack of items. Contrast
with push.
pop-up menu - A menu that lists the actions that a user can perform on an
object. The contents of the pop-up menu can vary depending on the context,
or state, of the object.
pop-up window - (1) A window that appears on top of another window in a
dialog. Each pop-up window must be completed before returning to the
underlying window. (2) (D of C) In SAA Advanced Common User Access
architecture, a movable window, fixed in size, in which a user provides
information required by an application so that it can continue to process a
user request.
presentation drivers - Special purpose I/O routines that handle field
device-independent I/O requests from the PM and its applications.
Presentation Manager (PM) - The interface of the OS/2 operating system that
presents, in windows a graphics-based interface to applications and files
installed and running under the OS/2 operating system.
presentation page - The coordinate space in which a picture is assembled for
display.
presentation space (PS) - (1) Contains the device-independent definition of a
picture. (2) (D of C) The display space on a display device.
primary window - In SAA Common User Access architecture, the window in which
the main interaction between the user and the application takes place. In a
multiprogramming environment, each application starts in its own primary
window. The primary window remains for the duration of the application,
although the panel displayed will change as the user's dialog moves forward.
See also secondary window.
primitive - In computer graphics, one of several simple functions for drawing
on the screen, including, for example, the rectangle, line, ellipse,
polygon, and so on.
primitive attribute - A specifiable characteristic of a graphic primitive. See
graphics attributes.
print job - The result of sending a document or picture to be printed.
Print Manager - In the Presentation Manager, the part of the spooler that
manages the spooling process. It also allows users to view print queues and
to manipulate print jobs.
privilege level - A protection level imposed by the hardware architecture of
the IBM personal computer. There are four privilege levels (number 0
through 3). Only certain types of programs are allowed to execute at each
privilege level. See also IOPL code segment.
procedure call - In programming languages, a language construct for invoking
execution of a procedure.
process - An instance of an executing application and the resources it is
using.
program - A sequence of instructions that a computer can interpret and
execute.
program details - Information about a program that is specified in the Program
Manager window and is used when the program is started.
program group - In the Presentation Manager, several programs that can be
acted upon as a single entity.
program name - The full file specification of a program. Contrast with program
title.
program title - The name of a program as it is listed in the Program Manager
window. Contrast with program name.
prompt - A displayed symbol or message that requests input from the user or
gives operational information; for example, on the display screen of an IBM
personal computer, the DOS A> prompt. The user must respond to the prompt in
order to proceed.
protect mode - A method of program operation that limits or prevents access to
certain instructions or areas of storage. Contrast with real mode.
protocol - A set of semantic and syntactic rules that determines the behavior
of functional units in achieving communication. (I)
pseudocode - An artificial language used to describe computer program
algorithms without using the syntax of any particular programming language. (A)
pull-down - (1) An action bar extension that displays a list of choices
available for a selected action bar choice. After users select an action bar
choice, the pull-down appears with the list of choices. Additional pop-up
windows may appear from pull-down choices to further extend the actions
available to users. (2) (D of C) In SAA Common User Access architecture,
pertaining to a choice in an action bar pull-down.
push - To add an item to a last-in-first-out stack of items. Contrast with
pop.
push button - In SAA Advanced Common User Access architecture, a rectangle
with text inside. Push buttons are used in windows for actions that occur
immediately when the push button is selected.
putback - To remove an object or set of objects from the lazy drag set. This
has the effect of undoing the pickup operation for those objects
putdown - To drop the objects in the lazy drag set on the target object.
ΓòÉΓòÉΓòÉ <hidden> Glossary - Q ΓòÉΓòÉΓòÉ
queue - (1) A linked list of elements waiting to be processed in FIFO order.
For example, a queue may be a list of print jobs waiting to be printed. (2)
(D of C) A line or list of items waiting to be processed; for example, work
to be performed or messages to be displayed.
queued device context - A logical description of a data destination (for
example, a printer or plotter) where the output is to go through the
spooler. See also device context.
ΓòÉΓòÉΓòÉ <hidden> Glossary - R ΓòÉΓòÉΓòÉ
radio button - (1) A control window, shaped like a round button on the screen,
that can be in a checked or unchecked state. It is used to select a single
item from a list. Contrast with check box. (2) In SAA Advanced Common User
Access architecture, a circle with text beside it. Radio buttons are
combined to show a user a fixed set of choices from which only one can be
selected. The circle is partially filled when a choice is selected.
RAS - Reliability, availability, and serviceability.
raster - (1) In computer graphics, a predetermined pattern of lines that
provides uniform coverage of a display space. (T) (2) The coordinate grid
that divides the display area of a display device. (A)
read-only file - A file that can be read from but not written to.
real mode - A method of program operation that does not limit or prevent
access to any instructions or areas of storage. The operating system loads
the entire program into storage and gives the program access to all system
resources. Contrast with protect mode.
realize - To cause the system to ensure, wherever possible, that the physical
color table of a device is set to the closest possible match in the logical
color table.
recursive routine - A routine that can call itself, or be called by another
routine that was called by the recursive routine.
reentrant - The attribute of a program or routine that allows the same copy of
the program or routine to be used concurrently by two or more tasks.
reference phrase - (1) A word or phrase that is emphasized in a
device-dependent manner to inform the user that additional information for
the word or phrase is available. (2) (D of C) In hypertext, text that is
highlighted and preceded by a single-character input field used to signify
the existence of a hypertext link.
reference phrase help - In SAA Common User Access architecture, highlighted
words or phrases within help information that a user selects to get
additional information.
refresh - To update a window, with changed information, to its current status.
region - A clipping boundary in device space.
register - A part of internal storage having a specified storage capacity and
usually intended for a specific purpose. (T)
remote file system - A file-system driver that gains access to a remote system
without a block device driver.
resource - The means of providing extra information used in the definition of
a window. A resource can contain definitions of fonts, templates,
accelerators, and mnemonics; the definitions are held in a resource file.
resource file - A file containing information used in the definition of a
window. Definitions can be of fonts, templates, accelerators, and mnemonics.
restore - To return a window to its original size or position following a
sizing or moving action.
retained graphics - Graphic primitives that are remembered by the Presentation
Manager interface after they have been drawn. Contrast with nonretained
graphics.
return code - (1) A value returned to a program to indicate the results of an
operation requested by that program. (2) A code used to influence the
execution of succeeding instructions.(A)
reverse video - (1) A form of highlighting a character, field, or cursor by
reversing the color of the character, field, or cursor with its background;
for example, changing a red character on a black background to a black
character on a red background. (2) In SAA Basic Common User Access
architecture, a screen emphasis feature that interchanges the foreground and
background colors of an item.
REXX Language - Restructured Extended Executor. A procedural language that
provides batch language functions along with structured programming
constructs such as loops; conditional testing and subroutines.
RGB - (1) Color coding in which the brightness of the additive primary colors
of light, red, green, and blue, are specified as three distinct values of
white light. (2) Pertaining to a color display that accepts signals
representing red, green, and blue.
roman - Relating to a type style with upright characters.
root segment - In a hierarchical database, the highest segment in the tree
structure.
round-robin scheduling - A process that allows each thread to run for a
specified amount of time.
run time - (1) Any instant at which the execution of a particular computer
program takes place. (T) (2) The amount of time needed for the execution of
a particular computer program. (T) (3) The time during which an instruction
in an instruction register is decoded and performed. Synonym for execution
time.
ΓòÉΓòÉΓòÉ <hidden> Glossary - S ΓòÉΓòÉΓòÉ
SAA - Systems Application Architecture.
SBCS - Single-byte character set.
scheduler - A computer program designed to perform functions such as
scheduling, initiation, and termination of jobs.
screen - In SAA Basic Common User Access architecture, the physical surface of
a display device upon which information is shown to a user.
screen device context - A logical description of a data destination that is a
particular window on the screen. See also device context.
SCREEN$ - Character-device name reserved for the display screen.
scroll bar - In SAA Advanced Common User Access architecture, a part of a
window, associated with a scrollable area, that a user interacts with to see
information that is not currently allows visible.
scrollable entry field - An entry field larger than the visible field.
scrollable selection field - A selection field that contains more choices than
are visible.
scrolling - Moving a display image vertically or horizontally in a manner such
that new data appears at one edge, as existing data disappears at the
opposite edge.
secondary window - A window that contains information that is dependent on
information in a primary window and is used to supplement the interaction in
the primary window.
sector - On disk or diskette storage, an addressable subdivision of a track
used to record one block of a program or data.
segment - See graphics segment.
segment attributes - Attributes that apply to the segment as an entity, as
opposed to the individual primitives within the segment. For example, the
visibility or detectability of a segment.
segment chain - All segments in a graphics presentation space that are defined
with the 'chained' attribute. Synonym for picture chain.
segment priority - The order in which segments are drawn.
segment store - An area in a normal graphics presentation space where retained
graphics segments are stored.
select - To mark or choose an item. Note that select means to mark or type in
a choice on the screen; enter means to send all selected choices to the
computer for processing.
select button - The button on a pointing device, such as a mouse, that is
pressed to select a menu choice. Also known as button 1.
selection cursor - In SAA Advanced Common User Access architecture, a visual
indication that a user has selected a choice. It is represented by outlining
the choice with a dotted box. See also text cursor.
selection field - (1) In SAA Advanced Common User Access architecture, a set
of related choices. See also entry field. (2) In SAA Basic Common User
Access architecture, an area of a panel that cannot be scrolled and contains
a fixed number of choices.
semantics - The relationships between symbols and their meanings.
semaphore - An object used by applications for signalling purposes and for
controlling access to serially reusable resources.
separator - In SAA Advanced Common User Access architecture, a line or color
boundary that provides a visual distinction between two adjacent areas.
serial dialog box - See modal dialog box.
serialization - The consecutive ordering of items.
serialize - To ensure that one or more events occur in a specified sequence.
serially reusable resource (SRR) - A logical resource or object that can be
accessed by only one task at a time.
session - (1) A routing mechanism for user interaction via the console; a
complete environment that determines how an application runs and how users
interact with the application. OS/2 can manage more than one session at a
time, and more than one process can run in a session. Each session has its
own set of environment variables that determine where OS/2 looks for
dynamic-link libraries and other important files. (2) (D of C) In the OS/2
operating system, one instance of a started program or command prompt. Each
session is separate from all other sessions that might be running on the
computer. The operating system is responsible for coordinating the resources
that each session uses, such as computer memory, allocation of processor
time, and windows on the screen.
Settings Notebook - A control window that is used to display the settings for
an object and to enable the user to change them.
shadow - An object that refers to another object. A shadow is not a copy of
another object, but is another representation of the object.
shadow box - The area on the screen that follows mouse movements and shows
what shape the window will take if the mouse button is released.
shared data - Data that is used by two or more programs.
shared memory - In the OS/2 operating system, a segment that can be used by
more than one program.
shear - In computer graphics, the forward or backward slant of a graphics
symbol or string of such symbols relative to a line perpendicular to the
baseline of the symbol.
shell - (1) A software interface between a user and the operating system of a
computer. Shell programs interpret commands and user interactions on devices
such as keyboards, pointing devices, and touch-sensitive screens, and
communicate them to the operating system. (2) Software that allows a kernel
program to run under different operating-system environments.
shutdown - The process of ending operation of a system or a subsystem,
following a defined procedure.
sibling processes - Child processes that have the same parent process.
sibling windows - Child windows that have the same parent window.
simple list - A list of like values; for example, a list of user names.
Contrast with mixed list.
single-byte character set (SBCS) - A character set in which each character is
represented by a one-byte code. Contrast with double-byte character set.
slider box - In SAA Advanced Common User Access architecture: a part of the
scroll bar that shows the position and size of the visible information in a
window relative to the total amount of information available. Also known as
thumb mark.
SOM - System Object Model.
source file - A file that contains source statements for items such as
high-level language programs and data description specifications.
source statement - A statement written in a programming language.
specific dynamic-link module - A dynamic-link module created for the exclusive
use of an application.
spin button - In SAA Advanced Common User Access architecture, a type of entry
field that shows a scrollable ring of choices from which a user can select a
choice. After the last choice is displayed, the first choice is displayed
again. A user can also type a choice from the scrollable ring into the
entry field without interacting with the spin button.
spline - A sequence of one or more BВzier curves.
spooler - A program that intercepts the data going to printer devices and
writes it to disk. The data is printed or plotted when it is complete and
the required device is available. The spooler prevents output from
different sources from being intermixed.
stack - A list constructed and maintained so that the next data element to be
retrieved is the most recently stored. This method is characterized as
last-in-first-out (LIFO).
standard window - A collection of window elements that form a panel. The
standard window can include one or more of the following window elements:
sizing borders, system menu icon, title bar, maximize/minimize/restore
icons, action bar and pull-downs, scroll bars, and client area.
static control - The means by which the application presents descriptive
information (for example, headings and descriptors) to the user. The user
cannot change this information.
static storage - (1) A read/write storage unit in which data is retained in
the absence of control signals. (A) Static storage may use dynamic
addressing or sensing circuits. (2) Storage other than dynamic storage. (A)
style - See window style.
subclass - A class that inherits from another class. See also Inheritance.
subdirectory - In an IBM personal computer, a file referred to in a root
directory that contains the names of other files stored on the diskette or
fixed disk.
superclass - A class from which another class inherits. See also inheritance.
swapping - (1) A process that interchanges the contents of an area of real
storage with the contents of an area in auxiliary storage. (I) (A) (2) In
a system with virtual storage, a paging technique that writes the active
pages of a job to auxiliary storage and reads pages of another job from
auxiliary storage into real storage. (3) The process of temporarily removing
an active job from main storage, saving it on disk, and processing another
job in the area of main storage formerly occupied by the first job.
switch - (1) In SAA usage, to move the cursor from one point of interest to
another; for example, to move from one screen or window to another or from
a place within a displayed image to another place on the same displayed
image. (2) In a computer program, a conditional instruction and an indicator
to be interrogated by that instruction. (3) A device or programming
technique for making a selection, for example, a toggle, a conditional jump.
switch list - See Task List.
symbolic identifier - A text string that equates to an integer value in an
include file, which is used to identify a programming object.
symbols - In Information Presentation Facility, a document element used to
produce characters that cannot be entered from the keyboard.
synchronous - Pertaining to two or more processes that depend upon the
occurrence of specific events such as common timing signals. (T) See also
asynchronous.
System Menu - In the Presentation Manager, the pull-down in the top left
corner of a window that allows it to be moved and sized with the keyboard.
System Object Model (SOM) - A mechanism for language-neutral, object-oriented
programming in the OS/2 environment.
system queue - The master queue for all pointer device or keyboard events.
system-defined messages - Messages that control the operations of applications
and provides input an other information for applications to process.
Systems Application Architecture (SAA) - A set of IBM software interfaces,
conventions, and protocols that provide a framework for designing and
developing applications that are consistent across systems.
ΓòÉΓòÉΓòÉ <hidden> Glossary - T ΓòÉΓòÉΓòÉ
table tags - In Information Presentation Facility, a document element that
formats text in an arrangement of rows and columns.
tag - (1) One or more characters attached to a set of data that contain
information about the set, including its identification. (I) (A) (2) In
Generalized Markup Language markup, a name for a type of document or
document element that is entered in the source document to identify it.
target object - An object to which the user is transferring information.
Task List - In the Presentation Manager, the list of programs that are active.
The list can be used to switch to a program and to stop programs.
terminate-and-stay-resident (TSR) - Pertaining to an application that modifies
an operating system interrupt vector to point to its own location (known as
hooking an interrupt).
text - Characters or symbols.
text cursor - A symbol displayed in an entry field that indicates where typed
input will appear.
text window - Also known as the VIO window.
text-windowed application - The environment in which the operating system
performs advanced-video input and output operations.
thread - A unit of execution within a process. It uses the resources of the
process.
thumb mark - The portion of the scroll bar that describes the range and
properties of the data that is currently visible in a window. Also known as
a slider box.
thunk - Term used to describe the process of address conversion, stack and
structure realignment, etc., necessary when passing control between 16-bit
and 32-bit modules.
tilde - A mark used to denote the character that is to be used as a mnemonic
when selecting text items within a menu.
time slice - (1) An interval of time on the processing unit allocated for use
in performing a task. After the interval has expired, processing-unit time
is allocated to another task, so a task cannot monopolize processing-unit
time beyond a fixed limit. (2) In systems with time sharing, a segment of
time allocated to a terminal job.
time-critical process - A process that must be performed within a specified
time after an event has occurred.
timer - A facility provided under the Presentation Manager, whereby
Presentation Manager will dispatch a message of class WM_TIMER to a
particular window at specified intervals. This capability may be used by an
application to perform a specific processing task at predetermined
intervals, without the necessity for the application to explicitly keep
track of the passage of time.
timer tick - See clock tick.
title bar - In SAA Advanced Common User Access architecture, the area at the
top of each window that contains the window title and system menu icon. When
appropriate, it also contains the minimize, maximize, and restore icons.
Contrast with panel title.
TLB - Translation lookaside buffer.
transaction - An exchange between a workstation and another device that
accomplishes a particular action or result.
transform - (1) The action of modifying a picture by scaling, shearing,
reflecting, rotating, or translating. (2) The object that performs or
defines such a modification; also referred to as a transformation.
Translation lookaside buffer (TLB) - A hardware-based address caching
mechanism for paging information.
Tree - In the Presentation Manager, the window in the File Manager that shows
the organization of drives and directories.
truncate - (1) To terminate a computational process in accordance with some
rule (A) (2) To remove the beginning or ending elements of a string. (3) To
drop data that cannot be printed or displayed in the line width specified or
available. (4) To shorten a field or statement to a specified length.
TSR - Terminate-and-stay-resident.
ΓòÉΓòÉΓòÉ <hidden> Glossary - U ΓòÉΓòÉΓòÉ
unnamed pipe - A circular buffer, created in memory, used by related processes
to communicate with one another. Contrast with named pipe.
unordered list - In Information Presentation Facility, a vertical arrangement
of items in a list, with each item in the list preceded by a special
character or bullet.
update region - A system-provided area of dynamic storage containing one or
more (not necessarily contiguous) rectangular areas of a window that are
visually invalid or incorrect, and therefore are in need of repainting.
user interface - Hardware, software, or both that allows a user to interact
with and perform operations on a system, program, or device.
User Shell - A component of OS/2 that uses a graphics-based, windowed
interface to allow the user to manage applications and files installed and
running under OS/2.
utility program - (1) A computer program in general support of computer
processes; for example, a diagnostic program, a trace program, a sort
program. (T) (2) A program designed to perform an everyday task such as
copying data from one storage device to another. (A)
ΓòÉΓòÉΓòÉ <hidden> Glossary - V ΓòÉΓòÉΓòÉ
value set control - A visual component that enables a user to select one
choice from a group of mutually exclusive choices.
vector font - A set of symbols, each of which is created as a series of lines
and curves. Synonymous with outline font. Contrast with image font.
VGA - Video graphics array.
view - A way of looking at an object's information.
viewing pipeline - The series of transformations applied to a graphic object
to map the object to the device on which it is to be presented.
viewing window - A clipping boundary that defines the visible part of model
space.
VIO - Video Input/Output.
virtual memory (VM) - Synonymous with virtual storage.
virtual storage - (1) The storage space that may be regarded as addressable
main storage by the user of a computer system in which virtual addresses are
mapped into real addresses. The size of virtual storage is limited by the
addressing scheme of the computer system and by the amount of auxiliary
storage available, not by the actual number of main storage
locations. (I) (A) (2) Addressable space that is apparent to the user as
the processor storage space, from which the instructions and the data are
mapped into the processor storage locations. (3) Synonymous with virtual
memory.
visible region - A window's presentation space, clipped to the boundary of the
window and the boundaries of any overlying window.
volume - (1) A file-system driver that uses a block device driver for input
and output operations to a local or remote device. (I) (2) A portion of
data, together with its data carrier, that can be handled conveniently as a
unit.
ΓòÉΓòÉΓòÉ <hidden> Glossary - W ΓòÉΓòÉΓòÉ
wildcard character - Synonymous with global file-name character.
window - (1) A portion of a display surface in which display images pertaining
to a particular application can be presented. Different applications can be
displayed simultaneously in different windows. (A) (2) An area of the
screen with visible boundaries within which information is displayed. A
window can be smaller than or the same size as the screen. Windows can
appear to overlap on the screen.
window class - The grouping of windows whose processing needs conform to the
services provided by one window procedure.
window coordinates - A set of coordinates by which a window position or size
is defined; measured in device units, or pels.
window handle - Unique identifier of a window, generated by Presentation
Manager when the window is created, and used by applications to direct
messages to the window.
window procedure - Code that is activated in response to a message. The
procedure controls the appearance and behavior of its associated windows.
window rectangle - The means by which the size and position of a window is
described in relation to the desktop window.
window resource - A read-only data segment stored in the .EXE file of an
application o the .DLL file of a dynamic link library.
window style - The set of properties that influence how events related to a
particular window will be processed.
window title - In SAA Advanced Common User Access architecture, the area in
the title bar that contains the name of the application and the OS/2
operating system file name, if applicable.
Workplace Shell - The OS/2 object-oriented, graphical user interface.
workstation - (1) A display screen together with attachments such as a
keyboard, a local copy device, or a tablet. (2) (D of C) One or more
programmable or nonprogrammable devices that allow a user to do work.
world coordinates - A device-independent Cartesian coordinate system used by
the application program for specifying graphical input and output. (I) (A)
world-coordinate space - Coordinate space in which graphics are defined before
transformations are applied.
WYSIWYG - What-You-See-Is-What-You-Get. A capability of a text editor to
continually display pages exactly as they will be printed.
ΓòÉΓòÉΓòÉ <hidden> Glossary - X ΓòÉΓòÉΓòÉ
There are no glossary terms for this starting letter.
ΓòÉΓòÉΓòÉ <hidden> Glossary - Y ΓòÉΓòÉΓòÉ
There are no glossary terms for this starting letter.
ΓòÉΓòÉΓòÉ <hidden> Glossary - Z ΓòÉΓòÉΓòÉ
z-order - The order in which sibling windows are presented. The topmost
sibling window obscures any portion of the siblings that it overlaps; the
same effect occurs down through the order of lower sibling windows.
zooming - The progressive scaling of an entire display image in order to give
the visual impression of movement of all or part of a display group toward
or away from an observer. (I) (A)
8.3 file-name format - A file-naming convention in which file names are
limited to eight characters before and three characters after a single dot.
Usually pronounced "eight-dot-three." See also non-8.3 file-name format.
ΓòÉΓòÉΓòÉ 10. Notices ΓòÉΓòÉΓòÉ
November 1996
The following paragraph does not apply to the United Kingdom or any country
where such provisions are inconsistent with local law: INTERNATIONAL BUSINESS
MACHINES CORPORATION PROVIDES THIS PUBLICATION "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Some states
do not allow disclaimer of express or implied warranties in certain
transactions, therefore, this statement may not apply to you.
This publication could include technical inaccuracies or typographical errors.
Changes are periodically made to the information herein; these changes will be
incorporated in new editions of the publication. IBM may make improvements
and/or changes in the product(s) and/or the program(s) described in this
publication at any time.
It is possible that this publication may contain reference to, or information
about, IBM products (machines and programs), programming, or services that are
not announced in your country. Such references or information must not be
construed to mean that IBM intends to announce such IBM products, programming,
or services in your country.
Requests for technical information about IBM products should be made to your
IBM reseller or IBM marketing representative.
ΓòÉΓòÉΓòÉ 10.1. Copyright Notices ΓòÉΓòÉΓòÉ
COPYRIGHT LICENSE: This publication contains printed sample application
programs in source language, which illustrate OS/2 programming techniques. You
may copy, modify, and distribute these sample programs in any form without
payment to IBM, for the purposes of developing, using, marketing or
distributing application programs conforming to the OS/2 application
programming interface.
Each copy of any portion of these sample programs or any derivative work, which
is distributed to others, must include a copyright notice as follows: "(C)
(your company name) (year). All rights reserved."
(C) Copyright International Business Machines Corporation 1994,1996. All rights
reserved.
Note to U.S. Government Users - Documentation related to restricted rights -
Use, duplication or disclosure is subject to restrictions set forth in GSA ADP
Schedule Contract with IBM Corp.
ΓòÉΓòÉΓòÉ 10.2. Disclaimers ΓòÉΓòÉΓòÉ
References in this publication to IBM products, programs, or services do not
imply that IBM intends to make these available in all countries in which IBM
operates. Any reference to an IBM product, program, or service is not intended
to state or imply that only that IBM product, program, or service may be used.
Subject to IBM's valid intellectual property or other legally protectable
rights, any functionally equivalent product, program, or service may be used
instead of the IBM product, program, or service. The evaluation and
verification of operation in conjunction with other products, except those
expressly designated by IBM, are the responsibility of the user.
IBM may have patents or pending patent applications covering subject matter in
this document. The furnishing of this document does not give you any license to
these patents. You can send license inquiries, in writing, to:
IBM Director of Licensing
IBM Corporation
500 Columbus Avenue
Thornwood, NY 10594
U.S.A.
ΓòÉΓòÉΓòÉ 10.3. Trademarks ΓòÉΓòÉΓòÉ
The following terms are trademarks of the IBM Corporation in the United States
or other countries or both:
AT
Common User Access
CUA
IBM
IBM PC AT
OS/2
Personal System/2
Presentation Manager
PS/2
SAA
Systems Application Architecture
The following terms are trademarks of other companies:
Intel Intel Corporation