home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / VSCPPv4.zip / VACPP / IBMCPP / HELP / CP3.INF (.txt) < prev    next >
OS/2 Help File  |  1995-03-10  |  260KB  |  9,073 lines

  1.  
  2. ΓòÉΓòÉΓòÉ 1. Memory Management ΓòÉΓòÉΓòÉ
  3.  
  4. This chapter describes the memory management features and functions of the OS/2 
  5. operating system. The key features of OS/2 memory management are paged virtual 
  6. memory and a 32-bit linear (flat) address space that is mapped through page 
  7. tables to physical memory. An OS/2 application can allocate memory for its own 
  8. use or to be shared with other applications. 
  9.  
  10. The following topics are related to the information in this chapter: 
  11.  
  12.    o  Exception Handling 
  13.    o  Program Execution and Control 
  14.    o  Semaphores 
  15.    o  Queues 
  16.  
  17.  
  18. ΓòÉΓòÉΓòÉ 1.1. About Memory Management ΓòÉΓòÉΓòÉ
  19.  
  20. The OS/2 operating system offers developers a 32-bit, linear (flat) memory 
  21. address space. The OS/2 operating system uses a paged memory structure. The 
  22. operating system allocates, protects, and manipulates memory in terms of pages. 
  23.  
  24.  
  25. ΓòÉΓòÉΓòÉ 1.1.1. Process Address Space ΓòÉΓòÉΓòÉ
  26.  
  27. The OS/2 memory allocation functions return a 32-bit pointer to the allocated 
  28. memory object. While a 32-bit pointer is sufficient to address the entire 4 
  29. gigabyte global address space, applications can access only the first 512MB of 
  30. linear memory, called the process address space. Of this 512MB process address 
  31. space, a minimum of 64MB is reserved for shared memory regions, leaving 448MB. 
  32. Of this 448MB, some will be used by the application itself and a small amount 
  33. will be taken by operating system overhead. The remainder is available for 
  34. allocation. The amount of memory that can actually be committed and used is, of 
  35. course, determined by the physical memory and hard disk space available on the 
  36. machine. 
  37.  
  38. Keep in mind that the amount of memory that can be committed for actual use is 
  39. limited by the amount of physical memory and free hard disk space that is 
  40. available on the computer on which the application is executing. 
  41.  
  42.  
  43. ΓòÉΓòÉΓòÉ 1.1.2. Memory Objects ΓòÉΓòÉΓòÉ
  44.  
  45. Applications allocate and manipulate memory in terms of memory objects. A 
  46. memory object consists of one or more pages of memory. An OS/2 application can 
  47. allocate any number of memory objects, within the following limits: 
  48.  
  49.    o  the physical memory in the system 
  50.    o  the free hard disk space on the hard disk containing the swap file 
  51.    o  the 512MB process address space limit (see Process Address Space). 
  52.  When requesting memory, the size of the memory object is rounded up to the 
  53.  next higher multiple of 4KB. An application can suballocate a memory object 
  54.  into memory blocks whose size can range from 1 byte to the size of the memory 
  55.  object. 
  56.  
  57.  Memory objects have the following characteristics: 
  58.  
  59.    o  They are not relocatable. 
  60.    o  They are allocated in units of 4KB. One 4KB unit is called a page. 
  61.    o  They can be larger than 64KB in size. 
  62.  
  63.  
  64. ΓòÉΓòÉΓòÉ 1.1.3. Memory Pages ΓòÉΓòÉΓòÉ
  65.  
  66. The operating system allocates and commits memory objects in pages. A memory 
  67. page is a 4KB (4096 bytes) piece of memory. Memory access protection is also 
  68. done on a page-basis, rather than the segment-based protection used in previous 
  69. versions of the operating system. 
  70.  
  71. A page range is a linearly contiguous group of pages within a memory object. A 
  72. page range can be: 
  73.  
  74.    o  the entire memory object, 
  75.    o  part of the memory object, or 
  76.    o  a single page within a memory object 
  77.  
  78.  If an application requests 512 bytes of memory, it will receive a 32-bit 
  79.  pointer to a 4KB page. All 4096 bytes are available to the application, even 
  80.  though the request specified only 512 bytes. If an application requests 62000 
  81.  bytes, it will receive a pointer to a 65536-byte (64KB, 16-page) object. 
  82.  Again, all 65536 bytes are available for use. 
  83.  
  84.  Each page in the virtual address space of the process is either free 
  85.  (unallocated), private (available only to the process that allocated it), or 
  86.  shared (memory that is shared between processes). 
  87.  
  88.  Each page within a memory object can be in one of two states, either 
  89.  uncommitted (that is, the linear address range has been reserved, but is not 
  90.  yet backed by physical storage) or committed (physical storage has been 
  91.  allotted for the logical address range). 
  92.  
  93.  Access to a committed page is controlled by the page's access protection 
  94.  attribute. These protection attributes are read access, write access, execute 
  95.  access (on the 80386, this is the same as read access), and guard page access. 
  96.  
  97.  An uncommitted page is not accessible. 
  98.  
  99.  
  100. ΓòÉΓòÉΓòÉ 1.1.4. Memory Overcommitment and Swapping ΓòÉΓòÉΓòÉ
  101.  
  102. Memory overcommitment occurs when applications allocate and commit more memory 
  103. than is actually available in the computer. The operating system handles memory 
  104. overcommitment by copying memory to the system swap file, SWAPPER.DAT, on the 
  105. hard disk then reusing the memory for another allocation. The operating system 
  106. copies as many pages of memory as are necessary to make room for the new 
  107. allocation. The swapped memory can be retrieved the next time it is accessed; 
  108. at that time, some other memory might be written to the swap file. 
  109.  
  110. The operating system selects the memory to swap based on when it was last used. 
  111. The page that is least-recently-used, that is, the page that has gone the 
  112. longest since its last access, is the page chosen to swap to disk. 
  113.  
  114. Swapping is transparent to an application, although excessive swapping can 
  115. cause an application to run slowly. 
  116.  
  117. Through swapping, the OS/2 operating system enables applications to allocate 
  118. more memory than actually exists in the computer, bounded only by the amount of 
  119. free space on the hard disk that contains the swap file. 
  120.  
  121.  
  122. ΓòÉΓòÉΓòÉ 1.1.5. User Configuration of Memory Swapping ΓòÉΓòÉΓòÉ
  123.  
  124. Although an application cannot control swapping, the user can specify whether 
  125. the system can swap memory by including the MEMMAN command in the CONFIG.SYS 
  126. file. 
  127.  
  128. If the MEMMAN command specifies SWAP, the operating system writes selected 
  129. memory pages to the SWAPPER.DAT file whenever insufficient physical memory 
  130. exists to satisfy an allocation request. This is the default choice. If the 
  131. MEMMAN command specifies NOSWAP, the operating system does not swap memory. 
  132.  
  133. Note:  Be aware that disabling swapping will severely limit the number of 
  134.        applications that the user will be able to run concurrently; if there is 
  135.        not enough physical memory present, the operating system might not even 
  136.        boot. 
  137.  
  138.  The exact amount of memory available to an application depends on the amount 
  139.  of physical memory in the machine and the amount of free disk space on the 
  140.  partition that contains the SWAPPER.DAT file. The location of the SWAPPER.DAT 
  141.  file can be specified by including the SWAPPATH command in the CONFIG.SYS 
  142.  file. With the SWAPPATH command, one can specify the location of the 
  143.  SWAPPER.DAT file, the amount of free disk space to reserve in the partition 
  144.  which will contain SWAPPER.DAT, and the initial size of SWAPPER.DAT. The 
  145.  operating system adjusts the size of SWAPPER.DAT as necessary, leaving other 
  146.  files on the drive and the requested free space untouched. 
  147.  
  148.  
  149. ΓòÉΓòÉΓòÉ 1.1.6. Memory Allocation and Commitment ΓòÉΓòÉΓòÉ
  150.  
  151. When an application asks the operating system to allocate memory, a linear 
  152. address range is reserved. The range is not backed by physical memory until the 
  153. memory is committed. Commitment assigns physical memory to the linear address 
  154. range. 
  155.  
  156. A memory object that is allocated, but not committed is called a sparse memory 
  157. object. A sparse memory object must be committed before it can be used. An 
  158. attempt to read from or write to uncommitted memory will cause an access 
  159. violation. 
  160.  
  161. An application can ask the operating system to commit the memory at the same 
  162. time it is allocated, thus making it immediately usable, or the memory can be 
  163. committed at a later time. If the application commits the memory at the same 
  164. time the memory is allocated, the entire memory object is committed. If the 
  165. application commits the memory at a later time, it can commit the entire sparse 
  166. memory object or only commit a portion of it. 
  167.  
  168. When multiple pages are committed at the same time (a page range), the pages 
  169. will have sequential linear addresses. 
  170.  
  171. Managing Memory Allocation and Commitment 
  172. The recommended way to manage memory is to make a large memory allocation early 
  173. in program execution, then to commit or suballocate memory as the need occurs. 
  174.  
  175. The initial allocation should be for as much space as you expect to use during 
  176. program execution. Allocation without commitment does not actually use any 
  177. physical memory, so there is no waste involved in allocating several megabytes. 
  178.  
  179. After the memory object is allocated, the application uses one of two ways to 
  180. manage the memory object: 
  181.  
  182.    o  Commit and decommit the memory as it is required 
  183.    o  Set up the memory object as a heap and suballocate memory from the heap. 
  184.  
  185.  Committing and decommitting memory gives the application more control over the 
  186.  process, but the application will have to keep track of which pages are 
  187.  committed and which pages are not. When suballocating memory from a heap, the 
  188.  application can have the operating system track commitment and decommitment of 
  189.  physical memory pages, so the application does not have to. If you want 
  190.  DosSubAllocMem to manage the commitment of the pages spanned by the heap, all 
  191.  of the pages spanned by the memory object must be uncommitted initially. 
  192.  
  193.  Remember, no matter how much memory is originally allocated, the amount that 
  194.  an application will ultimately be able to commit and use is limited by the 
  195.  amount of physical memory and free disk space available on the machine. 
  196.  
  197.  Applications are not limited to a single large allocation of memory-other 
  198.  memory allocations can be made as necessary during execution-but large 
  199.  allocations and small commitments or suballocations are the most efficient way 
  200.  to manage memory. 
  201.  
  202.  
  203. ΓòÉΓòÉΓòÉ 1.1.7. Memory Resizing and Reallocation ΓòÉΓòÉΓòÉ
  204.  
  205. In earlier versions of the operating system, an application could increase or 
  206. decrease the size of an allocated memory segment by reallocating the segment. 
  207.  
  208. Memory objects cannot be resized. Instead, an application should allocate a 
  209. sparse memory object of whatever size might be necessary, then commit or 
  210. decommit portions of the object. 
  211.  
  212. If the amount of memory required cannot be determined at the time the memory is 
  213. allocated, the application should allocate a sparse memory object large enough 
  214. to meet the largest memory requirement. The application can then change the 
  215. amount of committed memory as necessary. 
  216.  
  217. For example, if you anticipate your application will use around 512KB of memory 
  218. for most purposes, but might use 5MB under certain circumstances, you might 
  219. take the following steps: 
  220.  
  221.    o  During program initialization, use DosAllocMem to allocate 5MB. 
  222.  
  223.    o  Commit the first 512KB (or some part of it) using DosSetMem. 
  224.  
  225.    o  Proceed with normal processing. 
  226.  
  227.    o  If extra memory is required occasionally, commit it and decommit it using 
  228.       DosSetMem. 
  229.  
  230.    o  When the situation arises that the application requires the full 5MB, 
  231.       commit it at that time, using DosSetMem, then decommit it after you are 
  232.       finished with it, also using DosSetMem. 
  233.  
  234.    o  When the application is finished with the memory, use DosFreeMem to 
  235.       release the memory back to the system. 
  236.  
  237.  
  238. ΓòÉΓòÉΓòÉ 1.1.8. Memory Protection ΓòÉΓòÉΓòÉ
  239.  
  240. When an application allocates a memory object, it can specify the type of 
  241. access to allow to the object. Memory access protection provides a program with 
  242. control over the type of access that its threads have to a page of memory. 
  243.  
  244. Access protection can only be defined for committed pages of memory and is 
  245. initially set at the time the memory is committed. Different pages within the 
  246. same memory object can have different access attributes and access attributes 
  247. can be changed on a page-by-page basis at any time. 
  248.  
  249. An application can request any combination of the following access protection 
  250. attributes: 
  251.  
  252. Memory Access Protection Attributes 
  253.  
  254. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  255. ΓöéAccess              ΓöéDefined Constant    ΓöéDescription         Γöé
  256. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  257. ΓöéRead Access         ΓöéPAG_READ            ΓöéThe object can be   Γöé
  258. Γöé                    Γöé                    Γöéread from, but not  Γöé
  259. Γöé                    Γöé                    Γöéwritten to.         Γöé
  260. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  261. ΓöéWrite Access        ΓöéPAG_WRITE           ΓöéThe object can be   Γöé
  262. Γöé                    Γöé                    Γöéwritten to.  On the Γöé
  263. Γöé                    Γöé                    Γöé80386               Γöé
  264. Γöé                    Γöé                    Γöémicroprocessor,     Γöé
  265. Γöé                    Γöé                    Γöéwrite access impliesΓöé
  266. Γöé                    Γöé                    Γöéboth read and       Γöé
  267. Γöé                    Γöé                    Γöéexecute access.     Γöé
  268. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  269. ΓöéExecute Access      ΓöéPAG_EXECUTE         ΓöéThis is equivalent  Γöé
  270. Γöé                    Γöé                    Γöéto read access on   Γöé
  271. Γöé                    Γöé                    Γöéthe 80386.          Γöé
  272. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  273. ΓöéGuard Page Access   ΓöéPAG_GUARD           ΓöéCauses a            Γöé
  274. Γöé                    Γöé                    Γöéguard-page-entered  Γöé
  275. Γöé                    Γöé                    Γöéexception to be     Γöé
  276. Γöé                    Γöé                    Γöéraised in a process Γöé
  277. Γöé                    Γöé                    Γöéthat attempts to    Γöé
  278. Γöé                    Γöé                    Γöéaccess the memory.  Γöé
  279. Γöé                    Γöé                    ΓöéThis exception can  Γöé
  280. Γöé                    Γöé                    Γöébe ignored or       Γöé
  281. Γöé                    Γöé                    Γöéhandled by the      Γöé
  282. Γöé                    Γöé                    Γöéapplication's       Γöé
  283. Γöé                    Γöé                    Γöéexception handler,  Γöé
  284. Γöé                    Γöé                    Γöéif one is           Γöé
  285. Γöé                    Γöé                    Γöéregistered.         Γöé
  286. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  287.  
  288. The guard page attribute is intended to provide automatic stack growth and 
  289. stack limit checking. An application can also use it in other data structures, 
  290. such as arrays. For example, if an application is using an array of 4096 bytes 
  291. (one page), the application can allocate and commit two pages, one with read 
  292. and write access and one designated as a guard page. If the application tries 
  293. to write past the end of the array a page guard exception will be generated. 
  294.  
  295. Any reference-read, write, or execute-to a guard page causes an access 
  296. violation (page fault) to be generated. This fault causes a Guard Page Entered 
  297. exception to occur for the thread that referred to the guard page. The 
  298. exception can be handled by the exception handler of the process, if one is 
  299. registered. If the process does not have an exception handler registered, the 
  300. operating system's default exception handler will handle the exception. The 
  301. default action by the system exception handler is to convert the page from a 
  302. guard page to a committed page, then try to mark the next page in memory as a 
  303. guard page. If the system is not successful in marking the next page as a guard 
  304. page, an Unable-To-Grow-Stack exception occurs. The thread is allowed to 
  305. continue execution, but must be aware that it has at most 4KB of stack 
  306. remaining. 
  307.  
  308.  
  309. ΓòÉΓòÉΓòÉ 1.1.9. Obtaining Information about a Page Range ΓòÉΓòÉΓòÉ
  310.  
  311. DosQueryMem is used to obtain information about a range of pages within the 
  312. virtual address space of the current process. 
  313.  
  314. Each page in the virtual address space of a process is either free, private, or 
  315. shared. 
  316.  
  317. Each page within a memory object can be in one of two states, either committed 
  318. or uncommitted. 
  319.  
  320. A committed page has its access controlled by an access protection attribute. 
  321. These protection attributes are read protection (PAG_READ), write protection 
  322. (PAG_WRITE), execute protection (PAG_EXECUTE), and guard page protection 
  323. (PAG_GUARD). 
  324.  
  325.  
  326. ΓòÉΓòÉΓòÉ 1.1.10. Protection Violations ΓòÉΓòÉΓòÉ
  327.  
  328. The operating system fully utilizes the memory protection capabilities of the 
  329. 80386 microprocessor. The operating system grants an application access to a 
  330. memory object only if the object has been explicitly allocated by the 
  331. application or made available for use by the application. 
  332.  
  333. If an application attempts to access memory that it is not assigned, the system 
  334. interrupts the application and executes the exception handling routine for 
  335. protection violations. Protection violations can be handled by the application 
  336. (in its own exception handling routines) or by the operating system. If the 
  337. protection violation is handled by the operating system, the system exception 
  338. handling routine determines the cause of the exception, displays an error 
  339. message, and then terminates the application. 
  340.  
  341. It is usually not possible for an application to recover from a protection 
  342. violation. Therefore, programmers should ensure that all pointers are valid. 
  343. Because protection violations commonly occur during application debugging, each 
  344. message displayed for a protection violation includes the contents of the 
  345. registers when the violation occurred. If the violation occurred as a result of 
  346. passing an invalid pointer to a memory function, an error code is returned by 
  347. the memory function. 
  348.  
  349. In earlier versions of the operating system, protection violations could be 
  350. used to find bugs when an application accessed memory that was not allocated to 
  351. the application. This approach will no longer work because memory objects can 
  352. be larger than the size requested by the application because the memory objects 
  353. are allocated on 4KB page boundaries. For example, a pointer to the 513th byte 
  354. of a 512 byte memory object is valid and does not cause a protection violation. 
  355. This means that programmers cannot always rely on protection violations to spot 
  356. memory addressing errors. 
  357.  
  358.  
  359. ΓòÉΓòÉΓòÉ 1.1.11. Memory Suballocation and Using Heaps ΓòÉΓòÉΓòÉ
  360.  
  361. There are times when a process requires only small amounts of memory rather 
  362. than an entire memory object. It would be wasteful to allocate an entire page 
  363. of memory when only a few bytes are necessary, so a mechanism is provided for 
  364. applications to allocate a large block of memory and then suballocate portions 
  365. of the memory as necessary to fulfill small requests from an application. This 
  366. is done by creating a heap. 
  367.  
  368. A heap is a region of storage within a memory object from which an application 
  369. can allocate blocks of memory. A memory block is a piece of memory within a 
  370. heap. The size of the memory block is rounded up to the next higher multiple of 
  371. 8 bytes. 
  372.  
  373. Because the operating system allocates a 4KB page for each memory allocation, 
  374. using a heap to suballocate amounts of memory smaller than 4KB is more 
  375. efficient than using DosAllocMem. 
  376.  
  377. When an application creates a heap, it can have the operating system track the 
  378. committing and decommitting of memory within the heap. When the application 
  379. commits and decommits memory itself, it has to keep track of the access state 
  380. of each page as they are accessed. 
  381.  
  382. Applications use DosSubSetMem to initialize a memory object for suballocation, 
  383. then use DosSubAllocMem and DosSubFreeMem to allocate and free the memory. 
  384.  
  385. Memory is still committed in pages when an application uses suballocation. If 
  386. the application suballocates 512 bytes, 4096 bytes will be committed. Accessing 
  387. the 513th byte will not cause a protection violation, but you could be 
  388. accessing memory that was suballocated by another thread in the process. 
  389.  
  390.  
  391. ΓòÉΓòÉΓòÉ 1.1.12. Shared Memory ΓòÉΓòÉΓòÉ
  392.  
  393. Shared memory is memory that two or more applications can read from and write 
  394. to. Shared memory is prepared in such a way that any application can receive a 
  395. pointer to the memory and access the data. Applications must explicitly request 
  396. access to shared memory; the shared memory is protected from applications that 
  397. are not granted access. 
  398.  
  399. There are two kinds of shared memory:  named and unnamed. For named shared 
  400. memory, any application that knows the name of the shared memory can access it. 
  401. For unnamed shared memory, a pointer to the shared memory must be passed from 
  402. the process that created the shared memory to the process being given access. 
  403. Access can be granted to any application; it is not necessary that the process 
  404. being granted access be related (parent-child) to the application that created 
  405. the shared memory. 
  406.  
  407. Since memory sharing is done by sharing linear addresses, the linear address 
  408. range of the shared memory object is reserved in all process address spaces. 
  409.  
  410. There are two basic methods of managing shared memory: 
  411.  
  412.    o  In one method, two or more applications share the same memory at the same 
  413.       time. These applications read from and write to the memory object, 
  414.       usually controlling access to the memory by using a semaphore. 
  415.  
  416.    o  In the other method of managing shared memory, one application prepares 
  417.       data in memory, then passes that memory to another application for 
  418.       further processing. The first application releases the memory after 
  419.       passing it along, so that only one application accesses the memory at a 
  420.       time. 
  421.  
  422.  
  423. ΓòÉΓòÉΓòÉ 1.1.13. Thread Local Memory ΓòÉΓòÉΓòÉ
  424.  
  425. Thread local memory is a 128-byte region of thread-specific memory that the 
  426. operating system assigns to a thread when the thread is created. Thread local 
  427. memory for each thread is always at the same virtual address, but each thread's 
  428. local memory region is backed by different physical memory, so the memory is 
  429. specific to each thread. This memory region is divided into 32 DWORDS (4 bytes 
  430. per DWORD), and is normally used to store a small number of pointers. 
  431.  
  432. A thread can allocate thread local memory by calling DosAllocThreadLocalMemory. 
  433. Thread local memory is freed by calling DosFreeThreadLocalMemory. 
  434.  
  435. Note that thread local memory should be used sparingly. You should not use the 
  436. entire 128 byte region. 
  437.  
  438.  
  439. ΓòÉΓòÉΓòÉ 1.2. Using Memory Management ΓòÉΓòÉΓòÉ
  440.  
  441. This section describes how to use the OS/2 memory management functions and 
  442. configuration commands to control the use of memory for OS/2 applications. 
  443.  
  444. Note:  In the example code fragments that follow, error checking was left out 
  445.        to conserve space. Applications should always check the return code that 
  446.        the functions return. Control Program functions return an APIRET value. 
  447.        A return code of 0 indicates success. If a non-zero value is returned, 
  448.        an error occurred. 
  449.  
  450.  
  451. ΓòÉΓòÉΓòÉ 1.2.1. Allocating Private Memory ΓòÉΓòÉΓòÉ
  452.  
  453. An application can allocate regions of storage within the virtual address space 
  454. of the process. Such an allocated region is called a memory object. 
  455.  
  456. DosAllocMem is used to allocate a memory object. You specify a variable to 
  457. receive the pointer that will address the new object, the amount of memory 
  458. needed, and the allocation attributes and access protection attributes of the 
  459. new memory object. When choosing the size of the memory object to allocate, 
  460. remember that the maximum size of the memory object is defined when it is 
  461. allocated, and memory objects cannot be resized. 
  462.  
  463. When applications call DosAllocMem, the operating system reserves a range of 
  464. private pages large enough to fulfill the specified allocation request from the 
  465. private virtual address space of the subject process. 
  466.  
  467. DosAllocMem will reserve this linear space and return zero if the allocation 
  468. was successful. If it was unsuccessful, DosAllocMem will return an error code. 
  469. An application should always test the return value before attempting to use the 
  470. memory. 
  471.  
  472. The following code fragment requests an allocation of 512 bytes. Remember that 
  473. 4096 bytes will actually be allocated for this request: 
  474.  
  475.     #define  INCL_DOSMEMMGR   /* Memory Manager values */
  476.     #include <os2.h>
  477.  
  478.     PBYTE   pb;
  479.     APIRET  rc;
  480.  
  481.     rc = DosAllocMem((PVOID *) &pb, 512, fALLOC);
  482.          /* pb receives the base address of the 4KB memory object     */
  483.  
  484.     if (!rc) {           /* If the allocation was successful, rc == 0 */
  485.         *pb = 3000;      /* Use the allocated memory                  */
  486.     }
  487.  
  488. In this example, DosAllocMem returns a 32-bit pointer to a 4096 byte committed 
  489. memory object and allows the application to write to and read from the memory. 
  490. This pointer is valid only for the 4096 bytes allocated by the system. An 
  491. attempt to use the pointer outside the allocated memory will cause a protection 
  492. violation. 
  493.  
  494.  
  495. ΓòÉΓòÉΓòÉ 1.2.2. Committing and Decommitting Page Ranges ΓòÉΓòÉΓòÉ
  496.  
  497. If an application allocates a sparse memory object, no physical memory location 
  498. is committed for the object. Memory in a sparse object must be committed before 
  499. it can be used. DosSetMem is used to commit or decommit a range of previously 
  500. allocated pages in a private or shared memory object. Applications can make 
  501. specific address ranges within a memory object valid or invalid. Commitment and 
  502. decommitment always take place in multiples of one or more pages. 
  503.  
  504. Applications can also use DosSetMem to change the access protection attributes 
  505. of a range of pages within a memory object. 
  506.  
  507. The following code fragment requests allocation of 2MB of uncommitted memory 
  508. and then commits 4096 bytes of the memory: 
  509.  
  510.     #define  INCL_DOSMEMMGR   /* Memory Manager values */
  511.     #include <os2.h>
  512.  
  513.     APIRET  rc;
  514.     PBYTE   pb;
  515.  
  516.     /* Allocate 16KB object */
  517.     rc = DosAllocMem((PVOID *) &pb, 2097152, PAG_READ | PAG_WRITE);
  518.  
  519.     /* Commit 4KB           */
  520.     rc = DosSetMem(pb, 4096, PAG_COMMIT | PAG_DEFAULT);
  521.  
  522. An application can also allocate a large committed object and then decommit 
  523. portions of it as they are no longer needed. Decommitment, like commitment, is 
  524. done on page boundaries; an application can decommit no less than a 4096 byte 
  525. page. 
  526.  
  527. The following code fragment allocates 16384 bytes of committed memory and then 
  528. decommits the first 4096 bytes of the memory: 
  529.  
  530.     #define  INCL_DOSMEMMGR   /* Memory Manager values */
  531.     #include <os2.h>
  532.  
  533.     APIRET  rc;
  534.     PBYTE   pb;
  535.  
  536.     rc = DosAllocMem((PVOID *) &pb, 16384, fALLOC);    /* Allocate 16 K object */
  537.  
  538.     rc = DosSetMem(pb, 4096, PAG_DECOMMIT);            /* Decommit 4KB         */
  539.  
  540. After memory is decommitted, an attempt to access the decommitted memory will 
  541. cause a protection violation. 
  542.  
  543. You cannot pass an argument that crosses multiple memory objects. The function 
  544. will return an error. 
  545.  
  546.  
  547. ΓòÉΓòÉΓòÉ 1.2.3. Establishing Access Protection ΓòÉΓòÉΓòÉ
  548.  
  549. When an OS/2 application commits a memory object, it specifies the types of 
  550. access permitted for the memory object. This can be done at the same time the 
  551. memory object is allocated, with DosAllocMem, or at a later time, using 
  552. DosSetMem. 
  553.  
  554. Any combination of read, write, execute, or guard-page access can be set, but 
  555. at least read or write access must be specified when the memory object is 
  556. committed; it is not possible to commit an object with no access protection 
  557. attributes. 
  558.  
  559. The application can also use DosSetMem to change the access permission of pages 
  560. within a previously committed memory object. An application can permit read 
  561. access to one page of the memory object and write access to the rest. 
  562.  
  563. When using DosSetMem, all the pages in the range being changed must be either 
  564. committed or decommitted. 
  565.  
  566. The following code fragment commits a region of two pages within a previously 
  567. allocated memory object, and sets read-only access rights for the region. 
  568. Assume that the base address for DosSetMem was previously obtained by the 
  569. process. 
  570.  
  571.     #define  INCL_DOSMEMMGR   /* Memory Manager values */
  572.     #include <os2.h>
  573.     #include <stdio.h>
  574.  
  575.     PVOID   BaseAddress;      /* Pointer to the range of pages to be changed */
  576.     ULONG   RegionSize;       /* Size, in bytes, of the region to be changed */
  577.     ULONG   AttributeFlags;   /* Flag describing the page range              */
  578.     APIRET  rc;               /* Return code                                 */
  579.  
  580.     RegionSize = 8192;        /* Specify a two-page region                   */
  581.  
  582.     AttributeFlags = PAG_COMMIT | PAG_READ;
  583.  
  584.     rc = DosSetMem(BaseAddress, RegionSize, AttributeFlags);
  585.  
  586.     if (rc != 0) {
  587.         printf("DosSetMem error: return code = %ld", rc);
  588.         return;
  589.     }
  590.  
  591.  
  592. ΓòÉΓòÉΓòÉ 1.2.4. Querying Memory Object Information ΓòÉΓòÉΓòÉ
  593.  
  594. DosQueryMem is used to determine the allocation state and access protection for 
  595. a specified memory object. The application can query an entire memory object or 
  596. a range of pages within an object. 
  597.  
  598. The following code fragment uses DosQueryMem to ensure that memory is committed 
  599. before the application attempts to use the memory: 
  600.  
  601.     #define  INCL_DOSMEMMGR   /* Memory Manager values  */
  602.     #include <os2.h>
  603.     #define HF_STDOUT 1       /* Standard output handle */
  604.  
  605.     PBYTE   pb;       /* Base address of an allocated object */
  606.     ULONG   ulSize, flFlags, ulWritten;
  607.     APIRET  rc;       /* Return Code                         */
  608.  
  609.     ulSize = 4096;
  610.  
  611.     rc = DosQueryMem(pb, &ulSize, &flFlags);     /* Queries first 4096 bytes */
  612.  
  613.     if (flFlags & PAG_COMMIT) {            /* If memory is committed, use it */
  614.         rc = DosWrite(HF_STDOUT, "\r\n 4KB is committed.\r\n", 21, &ulWritten);
  615.     }
  616.  
  617.  
  618. ΓòÉΓòÉΓòÉ 1.2.5. Freeing Memory ΓòÉΓòÉΓòÉ
  619.  
  620. When memory object is no longer needed, the application uses the DosFreeMem 
  621. function to release the memory. 
  622.  
  623. If applications do not release memory, the operating system either swaps the 
  624. memory to the hard disk (if swapping is enabled) or uses memory that could be 
  625. used by other applications. If the operating system swaps the memory to the 
  626. hard disk, the SWAPPER.DAT swap file could become very large. Therefore, 
  627. applications should release memory as soon as it is no longer needed. Any 
  628. memory that is still allocated when the application ends is released by the 
  629. operating system. 
  630.  
  631. DosFreeMem frees a private or shared memory object from the virtual address 
  632. space of the process. The released pages are returned to the system. 
  633.  
  634. The following code fragment allocates 8192 bytes of committed memory and then 
  635. releases the memory: 
  636.  
  637.     #define  INCL_DOSMEMMGR   /* Memory Manager values */
  638.     #include <os2.h>
  639.  
  640.     PBYTE   pb;
  641.     APIRET  rc;
  642.  
  643.     rc = DosAllocMem((PVOID *) &pb, 8192, fALLOC);    /* Allocate 8KB object */
  644.         .
  645.         .
  646.         .
  647.     rc = DosFreeMem(pb);                              /* Free the object     */
  648.  
  649.  
  650. ΓòÉΓòÉΓòÉ 1.3. Using Suballocation and Heaps ΓòÉΓòÉΓòÉ
  651.  
  652. This section describes how you can use DosAllocMem, DosSubSetMem, 
  653. DosSubAllocMem, DosSubFreeMem, and DosSubUnsetMem to manage a memory heap. 
  654.  
  655.  
  656. ΓòÉΓòÉΓòÉ 1.3.1. Suballocating Memory ΓòÉΓòÉΓòÉ
  657.  
  658. DosAllocMem can be used to create a memory heap. 
  659.  
  660. Before an application can allocate small portions of the heap, it must use the 
  661. DosSubSetMem function to set up the memory for suballocation. The size of the 
  662. heap is rounded up to the next higher multiple of 8 bytes. 
  663.  
  664. Then, the application uses DosSubAllocMem to allocate sections of the heap and 
  665. the DosSubFreeMem function to release the memory. 
  666.  
  667. DosSubAllocMem returns a 32-bit pointer to a block of memory. The pointer can 
  668. be used to access the memory without further modification. 
  669.  
  670. The following code fragment sets up 8192 bytes for suballocation and then 
  671. allocates two small blocks of memory: 
  672.  
  673.     #define  INCL_DOSMEMMGR   /* Memory Manager values */
  674.     #include <os2.h>
  675.  
  676.     APIRET  rc;
  677.     PBYTE   pbBase, pb1, pb2;
  678.  
  679.     rc = DosAllocMem((PVOID *) &pbBase, 8192, fALLOC); /* Allocate 8 K object   */
  680.  
  681.     rc = DosSubSetMem(pbBase, DOSSUB_INIT, 8192);      /* Set up object         */
  682.                                                        /* for suballocation     */
  683.  
  684.     rc = DosSubAllocMem(pbBase, (PVOID *) &pb1, 100);  /* Suballocate 100 bytes */
  685.  
  686.     rc = DosSubAllocMem(pbBase, (PVOID *) &pb2, 500);  /* Suballocate 500 bytes */
  687.  
  688.     rc = DosSubFreeMem(pbBase, pb1, 100);              /* Free 1st suballocation*/
  689.  
  690.     rc = DosSubAllocMem(pbBase, (PVOID *) &pb1, 50);   /* Suballocate 50 bytes  */
  691.  
  692.  
  693. ΓòÉΓòÉΓòÉ 1.3.2. Increasing the Size of a Heap ΓòÉΓòÉΓòÉ
  694.  
  695. DosSubSetMem can also be used to increase the size of a previously initialized 
  696. heap. The heap size can be increased up to the size of the memory object that 
  697. contains it. 
  698.  
  699. The size of the heap is rounded up to the next higher multiple of 8 bytes. 
  700.  
  701. The following code fragment increases the size of a heap. Assume that a memory 
  702. object was previously allocated for the heap, and that the Offset variable was 
  703. previously loaded with the virtual address of the memory object. 
  704.  
  705.     #define  INCL_DOSMEMMGR   /* Memory Manager values */
  706.     #include <os2.h>
  707.     #include <stdio.h>
  708.  
  709.     PVOID   Offset;   /* Address of the heap to be used for suballocation */
  710.     ULONG   Flags;    /* Flags describing the memory object being resized */
  711.     ULONG   Size;     /* Size in bytes to increase the size of the heap   */
  712.     APIRET  rc;       /* Return code                                      */
  713.  
  714.     Size = 20000;     /* Indicate a heap size increase of 20000 bytes     */
  715.  
  716.     Flags = DOSSUB_GROW | DOSSUB_SPARSE_OBJ;
  717.  
  718.     rc = DosSubSetMem(Offset, Flags, Size);
  719.  
  720.     if (rc != 0) {
  721.         printf("DosSubSetMem error: return code = %ld", rc);
  722.         return;
  723.     }
  724.  
  725. In this example, the heap is incremented, and that memory commitment is managed 
  726. internally within subsequent DosSubAllocMem calls. 
  727.  
  728. When using DosSubSetMem to increase the size of the heap, the Flags parameter 
  729. must have the same setting as when the heap was initialized. 
  730.  
  731. Note:  Do not call DosSetMem to change the allocation attribute or access 
  732.        protection attributes of any pages spanned by a memory object that the 
  733.        suballocation functions are managing. Otherwise, unpredictable results 
  734.        could occur. 
  735.  
  736.  Call DosSubUnsetMem when finished with the heap that was set up with 
  737.  DosSubSetMem. This enables the suballocation function to free the resources 
  738.  that it uses to manage the heap. When you are through with the memory object 
  739.  that the heap was part of, use DosFreeMem to free the memory object. 
  740.  
  741.  
  742. ΓòÉΓòÉΓòÉ 1.3.3. Allocating a Block of Memory from a Heap ΓòÉΓòÉΓòÉ
  743.  
  744. DosSubAllocMem allocates a block of memory from a heap that was previously 
  745. initialized by DosSubSetMem. This is used when an application needs an area of 
  746. memory that is smaller than an entire heap. 
  747.  
  748. The size of the memory block is rounded up to the next higher multiple of 8 
  749. bytes. 
  750.  
  751. The following code fragment allocates a block of memory from a heap that was 
  752. previously initialized by DosSubSetMem. Assume that the Offset variable has 
  753. been set to the address of the initialized heap already. 
  754.  
  755.     #define  INCL_DOSMEMMGR   /* Memory Manager values */
  756.     #include <os2.h>
  757.     #include <stdio.h>
  758.  
  759.     PVOID    Offset;        /* The heap to suballocate from                */
  760.     PPVOID   BlockOffset;   /* Pointer to the variable where the offset of */
  761.                             /* the suballocated memory block is returned   */
  762.     ULONG    Size;          /* Size in bytes of the memory block requested */
  763.     APIRET   rc;            /* Return code                                 */
  764.  
  765.     Size = 102;             /* Ask for 102 bytes.  This will be rounded    */
  766.                             /* to 104 bytes (a multiple of 8 bytes).       */
  767.  
  768.     rc = DosSubAllocMem(Offset, &BlockOffset, Size);
  769.  
  770.     if (rc != 0) {
  771.         printf("DosSubAllocMem error: return code = %ld", rc);
  772.         return;
  773.     }
  774.  
  775. In this example, the address of the allocated block (from the heap) is stored 
  776. in the BlockOffset variable. 
  777.  
  778. Remember to call DosSubFreeMem to free this block of memory when you are 
  779. finished with it. 
  780.  
  781.  
  782. ΓòÉΓòÉΓòÉ 1.3.4. Freeing Memory Blocks ΓòÉΓòÉΓòÉ
  783.  
  784. DosSubFreeMem frees a block of memory that was previously allocated by 
  785. DosSubAllocMem. 
  786.  
  787. Call DosSubFreeMem to free a block of memory in the heap when you are finished 
  788. with that memory block. 
  789.  
  790. The following code fragment frees a block of memory that was previously 
  791. allocated from a heap. DosSubFreeMem returns the block to the heap. Assume that 
  792. the Offset variable has been previously set to the address of the initialized 
  793. heap, and that the BlockOffset variable has been previously set to the address 
  794. of the block to be returned to the heap. 
  795.  
  796.     #define  INCL_DOSMEMMGR   /* Memory Manager values */
  797.     #include <os2.h>
  798.     #include <stdio.h>
  799.  
  800.     PVOID   Offset;        /* Offset of the heap to which the          */
  801.                            /* block is to be freed                     */
  802.     PVOID   BlockOffset;   /* Offset of memory block to be freed       */
  803.     ULONG   Size;          /* Size in bytes of block to be freed       */
  804.     APIRET  rc;            /* Return code                              */
  805.  
  806.     Size = 102;            /* Return 102 bytes.  This will be rounded  */
  807.                            /* to 104 bytes (a multiple of 8 bytes).    */
  808.  
  809.     rc = DosSubFreeMem(Offset, BlockOffset, Size);
  810.  
  811.     if (rc != 0) {
  812.         printf("DosSubFreeMem error: return code = %ld", rc);
  813.         return;
  814.     }
  815.  
  816.  
  817. ΓòÉΓòÉΓòÉ 1.3.5. Ending the Use of the Heap ΓòÉΓòÉΓòÉ
  818.  
  819. DosSubUnsetMem terminates the use of a heap within a memory object. All calls 
  820. to DosSubSetMem must eventually be followed by a call to DosSubUnsetMem. This 
  821. enables the suballocation function to free the resources that it uses to manage 
  822. the heap. 
  823.  
  824. The application must call DosSubUnsetMem before it frees the memory object that 
  825. contains this heap (with DosFreeMem). 
  826.  
  827. The following code fragment shows the termination of a heap. Assume that the 
  828. address of the heap was placed into Offset already. 
  829.  
  830.     #define  INCL_DOSMEMMGR   /* Memory Manager values */
  831.     #include <os2.h>
  832.     #include <stdio.h>
  833.  
  834.     PVOID   Offset;   /* Offset of the heap whose use is being terminated */
  835.     APIRET  rc;       /* Return code                                      */
  836.  
  837.     rc = DosSubUnsetMem(Offset);
  838.  
  839.     if (rc != 0) {
  840.         printf("DosSubUnsetMem error: return code = %ld", rc);
  841.         return;
  842.     }
  843.  
  844.  
  845. ΓòÉΓòÉΓòÉ 1.3.6. Allocating and Freeing Thread Local Memory ΓòÉΓòÉΓòÉ
  846.  
  847. Thread local memory is a small region of thread-specific memory assigned to a 
  848. thread when it is started. 
  849.  
  850. A thread can allocate thread local memory by calling DosAllocThreadLocalMemory. 
  851. Thread local memory is freed by calling DosFreeThreadLocalMemory. 
  852.  
  853. The thread local memory region is 32 DWORDS (4 bytes per DWORD) in size, and up 
  854. to 8 DWORDS can be allocated with each call to DosAllocThreadLocalMemory. To 
  855. allocate more than 8 DWORDS, a thread must call DosAllocThreadLocalMemory more 
  856. than once. 
  857.  
  858. Note that thread local memory should be used sparingly. You should not use the 
  859. entire 128 byte region. 
  860.  
  861. The following code fragment allocates six DWORDS in thread local memory and 
  862. then frees these six DWORDS. 
  863.  
  864. #define  INCL_DOSPROCESS
  865. #define  INCL_DOSERRORS
  866. #include <os2.h>
  867. #include <stdio.h>          /* Needed for printf */
  868.  
  869. PULONG   pulMemBlock  = NULL;       /* Pointer to thread DWORDs returned */
  870. APIRET   rc           = NO_ERROR;   /* Return code */
  871.  
  872.   rc = DosAllocThreadLocalMemory( 6, &pulMemBlock );   /* Allocate 6 DWORDs */
  873.  
  874.   if (rc != NO_ERROR) {
  875.     printf("DosAllocThreadLocalMemory error: return code = %u\n", rc);
  876.     return 1;
  877.   }
  878.  
  879.  
  880.           /* ... Use the thread-local memory block ... */
  881.  
  882.  
  883.   rc = DosFreeThreadLocalMemory( pulMemBlock );       /* Free the memory block */
  884.  
  885.   if (rc != NO_ERROR) {
  886.     printf("DosFreeThreadLocalMemory error: return code = %u\n", rc);
  887.     return 1;
  888.   }
  889.  
  890.  
  891. ΓòÉΓòÉΓòÉ 1.4. Using Shared Memory ΓòÉΓòÉΓòÉ
  892.  
  893. This section describes how you can use DosAllocSharedMem, DosGiveSharedMem, 
  894. DosGetSharedMem, and DosGetNamedSharedMem to use shared memory. 
  895.  
  896.  
  897. ΓòÉΓòÉΓòÉ 1.4.1. Using Named Shared Memory ΓòÉΓòÉΓòÉ
  898.  
  899. An application uses DosAllocSharedMem to allocate shared memory. When 
  900. allocating the shared memory, an application can assign a unique name to the 
  901. memory. Any application that has the name of the shared memory can use 
  902. DosGetNamedSharedMem to retrieve a pointer to the memory. This makes it 
  903. possible for two or more applications to share memory at the same time. 
  904.  
  905. The name of a shared memory object has the following form: 
  906.  
  907.     \sharemem\name
  908.  
  909. The "\sharemem\" is required. The "name" parameter can be any name that 
  910. conforms to the rules for an OS/2 file name. No file is actually created for 
  911. the memory object. There is no actual "\sharemem\" subdirectory. 
  912.  
  913. The following code fragment allocates 65536 bytes of named shared memory with 
  914. the name "\sharemem\mymem". 
  915.  
  916.     #define  INCL_DOSMEMMGR   /* Memory Manager values */
  917.     #include <os2.h>
  918.  
  919.     APIRET  rc;
  920.     CHAR    szMem[] = { "\\sharemem\\mymem" };
  921.     PULONG  pb;
  922.  
  923.     rc = DosAllocSharedMem((PVOID *) &pb, szMem, 65536, fALLOC);
  924.  
  925.     *pb = 2762;
  926.  
  927. Once the named memory is allocated, any other process can retrieve a pointer to 
  928. the named memory by using DosGetNamedSharedMem. 
  929.  
  930. The following code fragment retrieves a pointer to the named memory allocated 
  931. above: 
  932.  
  933.     #define  INCL_DOSMEMMGR   /* Memory Manager values */
  934.     #include <os2.h>
  935.     #define HF_STDOUT 1       /* Standard output handle */
  936.  
  937.     APIRET  rc;
  938.     CHAR    szMem[] = { "\\sharemem\\mymem" };
  939.     PULONG  pb2;
  940.     ULONG   ulWritten;
  941.  
  942.     rc = DosGetNamedSharedMem((PVOID *) &pb2, szMem, PAG_READ | PAG_WRITE);
  943.  
  944.     if (*pb2 == 2762)
  945.         rc = DosWrite(HF_STDOUT, "\r\n Success!\r\n", 13, &ulWritten);
  946.  
  947.  
  948. ΓòÉΓòÉΓòÉ 1.4.2. Using Unnamed Shared Memory ΓòÉΓòÉΓòÉ
  949.  
  950. An application can allocate unnamed shared memory by using DosAllocSharedMem 
  951. with the object name set to NULL and the memory options set to OBJ_GIVEABLE or 
  952. OBJ_GETTABLE. Sharing unnamed memory is more difficult than sharing named 
  953. memory because the application allocating the memory must somehow pass a 
  954. pointer to another application. This is typically done by using some form of 
  955. interprocess communication, such as a queue or a named pipe. 
  956.  
  957. If an application allocates shared memory with the OBJ_GETTABLE option, it can 
  958. pass a pointer to another application. The second application can then gain 
  959. access to the shared memory by using DosGetSharedMem to validate the passed 
  960. pointer. If an application allocates shared memory with the OBJ_GIVEABLE 
  961. option, the process that allocates the memory can validate the pointer in 
  962. another process with DosGiveSharedMem. The allocating process must still pass a 
  963. pointer to the second process, but the second process need not use 
  964. DosGetSharedMem. 
  965.  
  966. The following code fragment allocates 24576 bytes (24KB) of unnamed shared 
  967. memory: 
  968.  
  969.     #define  INCL_DOSMEMMGR   /* Memory Manager values */
  970.     #include <os2.h>
  971.  
  972.     APIRET  rc;
  973.     PBYTE   pb;
  974.  
  975.     rc = DosAllocSharedMem((PVOID *) &pb, (PSZ) NULL, 24576,
  976.                            fALLOC | OBJ_GETTABLE);
  977.  
  978. Once the memory is allocated, the process can pass the memory pointer to a 
  979. second process via interprocess communication. Once the second process receives 
  980. the pointer, it can validate the memory with DosGetSharedMem, as shown in the 
  981. following code: 
  982.  
  983.     #define  INCL_DOSMEMMGR   /* Memory Manager values */
  984.     #include <os2.h>
  985.  
  986.     APIRET  rc;
  987.     PBYTE  pb2;
  988.  
  989.     rc = DosGetSharedMem(pb2, PAG_READ | PAG_WRITE);
  990.  
  991.  
  992. ΓòÉΓòÉΓòÉ 2. Message Management ΓòÉΓòÉΓòÉ
  993.  
  994. This chapter describes the use of message files to hold an application's text 
  995. messages to the user. Keeping messages in a message file simplifies changing 
  996. those messages, for example when maintaining versions of the same application 
  997. for different countries. 
  998.  
  999. The following topic is related to the information in this chapter: 
  1000.  
  1001.       National Language Support 
  1002.  
  1003.  
  1004. ΓòÉΓòÉΓòÉ 2.1. About Message Management ΓòÉΓòÉΓòÉ
  1005.  
  1006. For full-screen applications, text messages-used by an application to display 
  1007. information to the user-can be held in a message file. 
  1008.  
  1009. To keep and maintain messages in a message file, create a separate message file 
  1010. for each national language you intend to support. Use the MKMSGF utility 
  1011. program to create a binary version of a message file, and the MSGBIND utility 
  1012. program to bind the binary file to the application's executable file. Binding 
  1013. the messages to an application's executable file inserts the messages into the 
  1014. .EXE file. This enables faster access (but, of course, a larger .EXE file). 
  1015.  
  1016. The OS/2 operating system provides several functions to assist in message 
  1017. management. Applications can get messages from a message file, substitute 
  1018. variable information into the messages, and write messages to the screen or to 
  1019. a file. 
  1020.  
  1021. Code Page Considerations 
  1022. You can have versions of the message file for each code page you choose to 
  1023. support. When you use MKMSGF to create the message files, the utility will 
  1024. insert the code page information and link together the message files of the 
  1025. different versions. 
  1026.  
  1027. When message files are linked together in this manner, DosGetMessage will 
  1028. search for the appropriate version of the message for the code page that is 
  1029. active at the time the function is called. If there is no version of the 
  1030. message for the current code page, the function will return the first version 
  1031. of the message, no matter which code page it is associated with. 
  1032.  
  1033.  
  1034. ΓòÉΓòÉΓòÉ 2.2. Using Message Management ΓòÉΓòÉΓòÉ
  1035.  
  1036. DosGetMessage retrieves a message from the specified system message file, and 
  1037. inserts variable information into the body of the message. 
  1038.  
  1039. DosInsertMessage inserts variable text-string information into the body of the 
  1040. message, but does not retrieve the message. 
  1041.  
  1042. DosPutMessage sends the message in a buffer, usually to a display screen. 
  1043. DosPutMessage formats the screen buffer to prevent words from being split at 
  1044. the end of a line. 
  1045.  
  1046. DosQueryMessageCP retrieves the message file list of code pages and language 
  1047. identifiers. 
  1048.  
  1049. Note:  In the example code fragments that follow, error checking was left out 
  1050.        to conserve space. Applications should always check the return code that 
  1051.        the functions return. Control Program functions return an APIRET value. 
  1052.        A return code of 0 indicates success. If a non-zero value is returned, 
  1053.        an error occurred. 
  1054.  
  1055.  
  1056. ΓòÉΓòÉΓòÉ 2.2.1. Message Retrieval and String Substitution ΓòÉΓòÉΓòÉ
  1057.  
  1058. DosGetMessage retrieves a message from a system message file, and inserts 
  1059. variable text-string information into the message. 
  1060.  
  1061. In the following code fragment, the message file is "D:\MESSAGE\AUTOMSG.MSG". 
  1062. The third message within the message file contains the string "%1 Error at 
  1063. Station %2". The application calls DosGetMessage to convert this message into 
  1064. the string "Automation Failure Error at Station 69B". 
  1065.  
  1066.     #define INCL_DOSMISC   /* Miscellaneous values */
  1067.     #include <os2.h>
  1068.     #include <stdio.h>
  1069.  
  1070.     UCHAR   *IvTable[2];    /* Table of variables to insert       */
  1071.     ULONG    IvCount;       /* Number of variables                */
  1072.     UCHAR    DataArea[80];  /* Message buffer (returned)          */
  1073.     ULONG    DataLength;    /* Length of buffer                   */
  1074.     ULONG    MsgNumber;     /* Number of the message              */
  1075.     UCHAR    FileName[40];  /* Message file path-name string      */
  1076.     ULONG    MsgLength;     /* Length of message (returned)       */
  1077.     UCHAR    Field1[20];    /* String to substitute into variable */
  1078.                             /* field %1 of the message            */
  1079.     UCHAR    Field2[20];    /* String to substitute into variable */
  1080.                             /* field %2 of the message            */
  1081.     APIRET   rc;            /* Return code                        */
  1082.  
  1083.     strcpy(Field1,"Automation Failure");   /* Define the field with which to  */
  1084.                                            /* perform the first substitution  */
  1085.  
  1086.     strcpy(Field2,"69B");        /* Define the field with which to            */
  1087.                                  /* perform the second substitution           */
  1088.  
  1089.     IvTable[0] = Field1;         /* Set up the array of pointers to           */
  1090.     IvTable[1] = Field2;         /* substitute strings                        */
  1091.  
  1092.     IvCount = 2;                 /* Two variable message fields in message    */
  1093.  
  1094.     DataLength = 80;             /* Data buffer that will receive the         */
  1095.                                  /* complete message is 80 bytes in size      */
  1096.  
  1097.     MsgNumber = 3;               /* Specify the third message in the          */
  1098.                                  /* message file                              */
  1099.  
  1100.     strcpy(FileName,"D:\\MESSAGE\\AUTOMSG.MSG");   /* Path name of the        */
  1101.                                                    /* message file            */
  1102.  
  1103.     rc = DosGetMessage(IvTable, IvCount, DataArea, DataLength,
  1104.                        MsgNumber, FileName, &MsgLength);
  1105.  
  1106.     if (rc != 0) {
  1107.         printf("DosGetMessage error: return code = %ld", rc);
  1108.         return;
  1109.     }
  1110.  
  1111. On successful return, the DataArea buffer contains the complete message (with 
  1112. the two variable fields appropriately updated), and the MsgLength variable 
  1113. contains the length of the message that was placed into the DataArea buffer. 
  1114.  
  1115. If an error occurs (that is, if the return code does not equal 0), a message 
  1116. that is related to the error will be placed in the message buffer. See the 
  1117. DosGetMessage API reference in Control Program Programming Reference for a 
  1118. description of the default messages that can be placed into the user's buffer 
  1119. if an error occurs during the processing of these requests. 
  1120.  
  1121.  
  1122. ΓòÉΓòÉΓòÉ 2.2.2. Text String Substitution in Memory ΓòÉΓòÉΓòÉ
  1123.  
  1124. DosInsertMessage inserts variable text-string information into a message that 
  1125. resides within program memory. 
  1126.  
  1127. In the following code fragment, the message resides in a program string 
  1128. variable named Message. The message is the string "%1 Error at Station %2". The 
  1129. application calls DosInsertMessage to convert this message into the string 
  1130. "Automation Failure Error at Station 69B". 
  1131.  
  1132.     #define INCL_DOSMISC   /* Miscellaneous values */
  1133.     #include <os2.h>
  1134.     #include <stdio.h>
  1135.  
  1136.     UCHAR   *IvTable[2];               /* Table of variables to insert         */
  1137.     ULONG    IvCount;                  /* Number of variables                  */
  1138.     UCHAR    MsgInput[40] = "%1 Error at Station %2";     /* The input message */
  1139.     ULONG    MsgInLength;              /* Length of input message              */
  1140.     UCHAR    DataArea[80];             /* Message buffer (returned)            */
  1141.     ULONG    DataLength;               /* Length of updated message buffer     */
  1142.     ULONG    MsgLength;                /* Length of updated message (returned) */
  1143.     UCHAR    Field1[20];               /* String to substitute into variable   */
  1144.                                        /* field %1 of the message              */
  1145.     UCHAR    Field2[20];               /* String to substitute into variable   */
  1146.                                        /* field %2 of the message              */
  1147.     APIRET   rc;                       /* Return code                          */
  1148.  
  1149.     strcpy(Field1,"Automation Failure");    /* Define the field with which to  */
  1150.                                             /* perform the first substitution  */
  1151.  
  1152.     strcpy(Field2,"69B");                   /* Define the field with which to  */
  1153.                                             /* perform the second substitution */
  1154.  
  1155.     IvTable[0] = Field1;                    /* Set up the array of pointers to */
  1156.     IvTable[1] = Field2;                    /* substitute strings              */
  1157.  
  1158.     IvCount = 2;                            /* Two variable message fields in  */
  1159.                                             /* message                         */
  1160.  
  1161.     MsgInLength = strlen(MsgInput);         /* Length of input message         */
  1162.  
  1163.     DataLength = 80;                        /* Data buffer that will receive   */
  1164.                                             /* the complete message is 80      */
  1165.                                             /* bytes in size                   */
  1166.  
  1167.     rc = DosInsertMessage(IvTable, IvCount, MsgInput, MsgInLength,
  1168.                           DataArea, DataLength, &MsgLength);
  1169.  
  1170.     if (rc != 0) {
  1171.         printf("DosInsertMessage error: return code = %ld", rc);
  1172.         return;
  1173.     }
  1174.  
  1175. On successful return, the DataArea buffer contains the complete message (with 
  1176. the two variable fields appropriately updated), and the MsgLength variable 
  1177. contains the length of the message that was placed into the DataArea buffer. 
  1178.  
  1179. If an error occurs (that is, if the return code does not equal 0), a message 
  1180. that is related to the error will be placed in the message buffer. See the 
  1181. DosGetMessage API reference in Control Program Programming Reference for a 
  1182. description of the default messages that can be placed into the user's buffer 
  1183. if an error occurs during the processing of these requests. 
  1184.  
  1185.  
  1186. ΓòÉΓòÉΓòÉ 2.2.3. Writing Messages ΓòÉΓòÉΓòÉ
  1187.  
  1188. DosPutMessage is used to write the message to the screen or to a file on a 
  1189. disk. 
  1190.  
  1191. The following code fragment writes the message string contained in 
  1192. MessageBuffer to the file specified by FileHandle. The message string has 
  1193. already been placed in MessageBuffer using either DosGetMessage or 
  1194. DosInsertMessage. MsgLength was set to the length of the message string by the 
  1195. same call that put the message into MessageBuffer. 
  1196.  
  1197.     #define INCL_DOSMISC   /* Miscellaneous values */
  1198.     #include <os2.h>
  1199.     #include <stdio.h>
  1200.  
  1201.  
  1202.     HFILE   FileHandle;           /* Handle of output file or device */
  1203.     ULONG   MsgLength;            /* Length of message buffer        */
  1204.     UCHAR   MessageBuffer[80];    /* Message buffer                  */
  1205.     APIRET  rc;                   /* Return code                     */
  1206.  
  1207.     rc = DosPutMessage(FileHandle, MsgLength, MessageBuffer);
  1208.  
  1209.     if (rc != 0) {
  1210.         printf("DosPutMessage error: return code = %ld", rc);
  1211.         return;
  1212.     }
  1213.  
  1214. To write a message to the screen, use the standard output file handle. 
  1215.  
  1216.  
  1217. ΓòÉΓòÉΓòÉ 2.2.4. Code Page Information Associated with Message Files ΓòÉΓòÉΓòÉ
  1218.  
  1219. DosQueryMessageCP obtains a list of code page identifiers and language 
  1220. identifiers that are associated with a specified message file. 
  1221.  
  1222. In the following code fragment code page and language identifiers associated 
  1223. with the message file "D:\MESSAGE\AUTOMSG.MSG" are retrieved. 
  1224.  
  1225.     #define INCL_DOSMISC   /* Miscellaneous values */
  1226.     #include <os2.h>
  1227.     #include <stdio.h>
  1228.  
  1229.     UCHAR    BufferArea[20];  /* Buffer for the returned list  */
  1230.     ULONG    BufferLength;    /* Length of the buffer area     */
  1231.     UCHAR    FileName[40];    /* Message file path-name string */
  1232.     ULONG    DataLength;      /* Length of the returned data   */
  1233.     APIRET   rc;              /* Return code                   */
  1234.  
  1235.     strcpy(FileName, "D:\\MESSAGE\\AUTOMSG.MSG");  /* Path name of message file */
  1236.  
  1237.     BufferLength = 20;                             /* Length of buffer area     */
  1238.  
  1239.     rc = DosQueryMessageCp(BufferArea, BufferLength, FileName,
  1240.                            &DataLength);
  1241.  
  1242.     if (rc != 0) {
  1243.         printf("DosQueryMessageCp error: return code = %ld", rc);
  1244.         return;
  1245.     }
  1246.  
  1247. On successful return, the BufferArea buffer contains a set of information 
  1248. concerning the code page identifiers and language identifiers that are 
  1249. associated with the message file. 
  1250.  
  1251.  
  1252. ΓòÉΓòÉΓòÉ 3. National Language Support ΓòÉΓòÉΓòÉ
  1253.  
  1254. Many applications need to be independent of a particular language. Rather than 
  1255. being hard-coded in English, they want to support, for example, an English 
  1256. version of the application, and a French version, and a German version; 
  1257. preferably without having to change the program code for each version. Meeting 
  1258. this requirement is simplified through the use of such resources as string 
  1259. tables, menu templates, dialog templates, accelerator tables, and through the 
  1260. use of code pages. 
  1261.  
  1262. This chapter describes the functions an application uses to be NLS enabled, or 
  1263. language independent. 
  1264.  
  1265. The following topic is related to the information in this chapter: 
  1266.  
  1267.    o  Message Management 
  1268.  
  1269.  
  1270. ΓòÉΓòÉΓòÉ 3.1. About National Language Support ΓòÉΓòÉΓòÉ
  1271.  
  1272. The support of national languages by applications requires the following 
  1273. considerations: 
  1274.  
  1275.    o  Displayed text must be translated into the appropriate language. 
  1276.  
  1277.    o  Symbols or icons might not convey the same meaning in all countries. 
  1278.       Alternative designs for different countries might be necessary. 
  1279.  
  1280.    o  Translation changes the length of text strings. 
  1281.  
  1282.    o  Different languages often have different text characters. 
  1283.  
  1284.  The use of national language resource files can help with the first three 
  1285.  items, and the ability of the application to receive input and display output 
  1286.  in any ASCII code page can help with the last item. 
  1287.  
  1288.  The use of ASCII code page 850 avoids many of the problems in this area, since 
  1289.  it contains most of the characters required for Latin-1 languages, which 
  1290.  include much of Western Europe and North and South America. However, older 
  1291.  programs use code page 437 for U.S. English, and code pages 860, 863, and 865 
  1292.  for various languages. The code page applies to both input and output data. 
  1293.  
  1294.  Note:  Code page 850 was used for translating Presentation Manager text. Use 
  1295.         code page 850 whenever possible for all Presentation Manager 
  1296.         applications that might require translation. 
  1297.  
  1298.  
  1299. ΓòÉΓòÉΓòÉ 3.1.1. National Language Resource Files ΓòÉΓòÉΓòÉ
  1300.  
  1301. When creating an application, define national language dependencies in 
  1302. resources that are held in resource files separate from the program code.  That 
  1303. is: 
  1304.  
  1305.    o  Keep pure text strings in string tables. 
  1306.    o  Keep menus in menu templates. 
  1307.    o  Keep dialog boxes in dialog templates. 
  1308.    o  Keep accelerators in accelerator tables. 
  1309.  
  1310.  The language displayed by the application can then be changed by translating 
  1311.  the resources, in most cases without changing the application. 
  1312.  
  1313.  However, when translating from one language to another, the length of a text 
  1314.  string can change substantially. For example, when translating from English to 
  1315.  German, the length of a text string can double in length. 
  1316.  
  1317.  The following table furnishes a general idea of the amount of expansion that 
  1318.  can be expected during translation. 
  1319.  
  1320.  Translation Expansion 
  1321.  
  1322.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1323.   ΓöéFor English Phrases           ΓöéTranslation Expansion Factors Γöé
  1324.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1325.   ΓöéUp to 10 characters           Γöé101 - 200%                    Γöé
  1326.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1327.   Γöé11 - 20 characters            Γöé81 - 100%                     Γöé
  1328.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1329.   Γöé21 - 30 characters            Γöé61 - 80%                      Γöé
  1330.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1331.   Γöé31 - 50 characters            Γöé41 - 60%                      Γöé
  1332.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1333.   Γöé51 - 70 characters            Γöé31 - 40%                      Γöé
  1334.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1335.   ΓöéOver 70 characters            Γöé30%                           Γöé
  1336.   ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  1337.  
  1338.  When designing your dialog boxes and text string messages, add white space to 
  1339.  allow for the expansion that will occur when the text is translated. You might 
  1340.  have to adapt the application program to allow for the change in the length of 
  1341.  text strings after they are translated. For example, a change in the length of 
  1342.  a text string can cause it to become misaligned with other displayed objects. 
  1343.  
  1344.  You can also use the Dialog Box Editor to adjust for misalignments, or to 
  1345.  change the size of the dialog box. This would enable you to leave your 
  1346.  application program unchanged. 
  1347.  
  1348.  Text strings explicitly displayed by the application program are more of a 
  1349.  problem. You will have to include program code that can handle text strings of 
  1350.  varying length and format them at runtime according to their size. 
  1351.  
  1352.  
  1353. ΓòÉΓòÉΓòÉ 3.1.2. Language-Specific Versions of NLS-Enabled Applications ΓòÉΓòÉΓòÉ
  1354.  
  1355. There are two methods of creating a specific national language version of a 
  1356. program designed to handle more than one national language. The choice of the 
  1357. method depends on the amount of available disk space and whether the user wants 
  1358. to change between different languages once the program is installed. The two 
  1359. methods are: 
  1360.  
  1361.    o  Statically link the resources to the application's .EXE files. The 
  1362.       executable files are then language-specific and cannot be changed to 
  1363.       another national language. The specific .EXE files are then sent to the 
  1364.       user. 
  1365.  
  1366.    o  Place the resources into a language-specific, dynamic link library. 
  1367.       Designate one library file for each national language. Selecting a 
  1368.       particular library file for use with the application gives the desired 
  1369.       version of the program. Using this method, all national languages can be 
  1370.       shipped with the product; selection of the national language occurs 
  1371.       during installation (for example, by naming a specific .DLL file). It is 
  1372.       possible to change the national language setting while the program is 
  1373.       operating. 
  1374.  
  1375.  
  1376. ΓòÉΓòÉΓòÉ 3.2. About Code Page Management ΓòÉΓòÉΓòÉ
  1377.  
  1378. A code page is a table that defines how the characters in a language or group 
  1379. of languages are encoded. A specific value is given to each character in the 
  1380. code page. For example, in code page 850 the letter "╨┤" (lowercase) is encoded 
  1381. as hex A4 (decimal 164), and the letter "╨╡" (uppercase) is encoded as hex A5 
  1382. (decimal 165). 
  1383.  
  1384. Code page management enables a user to select a code page for keyboard input, 
  1385. and screen and printer output before starting an application, a system command, 
  1386. or a utility program in the OS/2 multitasking environment. 
  1387.  
  1388. This means that a user in a particular country, such as England (code page 
  1389. 850), Norway (code page 865), or a language region such as Canadian French 
  1390. (code page 863) can use a code page that defines an ASCII-based character set 
  1391. containing characters used by that particular country or language. 
  1392.  
  1393. Installable code page files include keyboard translate tables, display 
  1394. character sets, printer character sets, and country/language information for 
  1395. each code page supported. 
  1396.  
  1397. Of particular interest are two code pages: 
  1398.  
  1399.    o  Code Page 850 
  1400.    o  Code Page 437 
  1401.  
  1402.  Code Page 850 (CP850) 
  1403.  Code Page 850 is also called the Latin-1, multilingual code page. This code 
  1404.  page supports the alphabetic characters of the Latin-1-based languages. It 
  1405.  contains characters required by 13 languages used in approximately 40 
  1406.  countries. 
  1407.  
  1408.  CP850 also provides the flexibility to develop new applications based on 
  1409.  non-Latin-based or special industry-based code pages. 
  1410.  
  1411.  Code Page 850 supports countries using the following languages: 
  1412.  
  1413.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1414.   ΓöéBelgian French                ΓöéCanadian French               Γöé
  1415.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1416.   ΓöéDanish                        ΓöéDutch                         Γöé
  1417.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1418.   ΓöéFinnish                       ΓöéFlemish                       Γöé
  1419.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1420.   ΓöéFrench                        ΓöéGerman                        Γöé
  1421.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1422.   ΓöéItalian                       ΓöéNorwegian                     Γöé
  1423.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1424.   ΓöéPortuguese                    ΓöéSpanish                       Γöé
  1425.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1426.   ΓöéLAD Spanish                   ΓöéSwedish                       Γöé
  1427.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1428.   ΓöéSwiss French                  ΓöéSwiss German                  Γöé
  1429.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1430.   ΓöéU.K. English                  ΓöéU.S. English                  Γöé
  1431.   ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  1432.  
  1433.  Code Page 437 (CP437) 
  1434.  Code Page 437 is the standard personal computer code page. 
  1435.  
  1436.  The lower 128 characters are based on the 7-bit ASCII code. The upper 128 
  1437.  characters contain characters from several European languages (including part 
  1438.  of the Greek alphabet) and various graphic characters. However, some of the 
  1439.  accented characters, such as those used in the Nordic countries, are not 
  1440.  represented. The missing characters are available in other code pages (code 
  1441.  page 850 will usually contain the desired characters). 
  1442.  
  1443.  Note:  Some of the 256 symbols that can be displayed are printer control 
  1444.         characters, and are not printed. 
  1445.  
  1446.  
  1447. ΓòÉΓòÉΓòÉ 3.2.1. ASCII and EBCDIC Code Page Support ΓòÉΓòÉΓòÉ
  1448.  
  1449. The two leading character-coding systems are ASCII and EBCDIC. Presentation 
  1450. Manager applications can use an EBCDIC code page instead of an ASCII code page. 
  1451. Code pages based on both systems are supported by the OS/2 operating system. 
  1452.  
  1453. Any code page that either is defined in the CONFIG.SYS file, or is one of the 
  1454. EBCDIC code pages supported, can be selected. 
  1455.  
  1456.  
  1457. ΓòÉΓòÉΓòÉ 3.2.2. Code Page Preparation ΓòÉΓòÉΓòÉ
  1458.  
  1459. During system initialization, the code pages specified in the CODEPAGE 
  1460. statement are prepared to enable run-time code page switching of the display, 
  1461. the keyboard, the printer, and the country information. The display, keyboard, 
  1462. and printer must be defined in a DEVINFO statement in order to be prepared. 
  1463. Country information is prepared for the system country code specified in the 
  1464. COUNTRY statement. 
  1465.  
  1466. If a resource cannot be prepared for the selected code page during system 
  1467. initialization, it is prepared for a default code page. The following are the 
  1468. defaults: 
  1469.  
  1470.    o  A keyboard layout defaults to the code page of the translate table 
  1471.       designated as the default layout in the KEYBOARD.DCP file. The default 
  1472.       layout is based on the national code page of its associated country. You 
  1473.       must explicitly specify KEYBOARD.DCP in the DEVINFO statement for the 
  1474.       keyboard in CONFIG.SYS. 
  1475.  
  1476.    o  The display defaults to the code page of ROM_0 for the device. 
  1477.  
  1478.       (ROM_0 means a device default code page that is the device native code 
  1479.       page or the lowest addressed ROM code page.) 
  1480.  
  1481.    o  The printer defaults to the code page of ROM_0 for the device. 
  1482.  
  1483.       (ROM_0 means a device default code page that is the device native code 
  1484.       page or the lowest addressed ROM code page.) 
  1485.  
  1486.    o  The country information defaults to the code page of the first entry 
  1487.       found in the COUNTRY.SYS file for the country code. Each entry is the 
  1488.       same information for a given country code, but is encoded in a different 
  1489.       code page. The first entry is based on the preferred country code page. 
  1490.  
  1491.  If country information cannot be prepared at system initialization because it 
  1492.  is not found in the COUNTRY.SYS file, for a code page selected with the 
  1493.  CODEPAGE statement, then it is prepared (maintained for run-time code page 
  1494.  switching in memory) in the default code page. Similarly, a keyboard layout is 
  1495.  prepared in its default code page if it cannot be prepared in the selected 
  1496.  code page, because it is not found in the KEYBOARD.DCP file. 
  1497.  
  1498.  COUNTRY.SYS contains one default entry per country code, and KEYBOARD.DCP 
  1499.  contains one default entry per keyboard layout based on these assignments. 
  1500.  
  1501.  
  1502. ΓòÉΓòÉΓòÉ 3.2.3. Code Page Functions ΓòÉΓòÉΓòÉ
  1503.  
  1504. At the system level, the operating system switches the code pages of supported 
  1505. displays and printers to agree with the code page of the process sending the 
  1506. output. At the application level, OS/2 functions enable a process to control 
  1507. code page assignments. 
  1508.  
  1509.  
  1510. ΓòÉΓòÉΓòÉ 3.3. Using Code Pages ΓòÉΓòÉΓòÉ
  1511.  
  1512. The OS/2 operating system provides applications with several functions to 
  1513. obtain information about and manipulate code pages. These functions enable 
  1514. applications to determine and set the current code page. 
  1515.  
  1516. OS/2 code page management functions enable applications to read keyboard input 
  1517. and write display and printer output for multiple processes using ASCII-based 
  1518. data encoded in different code pages. 
  1519.  
  1520. The system switches to the required code page, for a code-page-supported 
  1521. device, before input or output. 
  1522.  
  1523. Note:  In the example code fragments that follow, error checking was left out 
  1524.        to conserve space. Applications should always check the return code that 
  1525.        the functions return. Control Program functions return an APIRET value. 
  1526.        A return code of 0 indicates success. If a non-zero value is returned, 
  1527.        an error occurred. 
  1528.  
  1529.  
  1530. ΓòÉΓòÉΓòÉ 3.3.1. Querying Code Page Support and the Current Code Page ΓòÉΓòÉΓòÉ
  1531.  
  1532. DosQueryCp is used to determine the code page of the current process and the 
  1533. prepared system code pages. The following code fragment shows how to get the 
  1534. current code page, and then up to three other prepared pages: 
  1535.  
  1536.     #define INCL_DOSNLS   /* National Language Support values */
  1537.     #include <os2.h>
  1538.  
  1539.     ULONG  CpList[8];
  1540.     ULONG  CpSize;
  1541.     APIRET rc;    /* Return code */
  1542.  
  1543.     rc = DosQueryCp(sizeof(CpList),    /* Length of list          */
  1544.                     CpList,            /* List                    */
  1545.                     &CpSize);          /* Length of returned list */
  1546.  
  1547. The required code page is the current code page of the process at the time it 
  1548. opens a device, or a specific code page selected by the process with a 
  1549. set-code-page function. A character set can also be specified for some devices, 
  1550. for example, for some printers. 
  1551.  
  1552. The country functions retrieve country- and language-dependent information in 
  1553. the current code page of the calling process, or in a code page selected by the 
  1554. process. 
  1555.  
  1556.  
  1557. ΓòÉΓòÉΓòÉ 3.3.2. Setting the Code Page for Text Characters ΓòÉΓòÉΓòÉ
  1558.  
  1559. Each process has a code page tag maintained by the operating system. A code 
  1560. page tag is the identifier of the current code page for the process. 
  1561.  
  1562. A child process inherits the code page tag of its parent. The default code page 
  1563. for the first process in a session is the same as the session code page. The 
  1564. default code page for a new session is the primary code page specified in the 
  1565. CODEPAGE configuration statement. 
  1566.  
  1567. To change the code page tag of a process, call DosSetProcessCp. This will not 
  1568. change the process code page tag of its parent or any child process. 
  1569.  
  1570.  
  1571. ΓòÉΓòÉΓòÉ 3.3.3. Obtaining the Case Map String ΓòÉΓòÉΓòÉ
  1572.  
  1573. DosMapCase performs case mapping on a string of binary values that represent 
  1574. ASCII characters. 
  1575.  
  1576. The case map that is used is the one in the country file that corresponds to 
  1577. the system country code or selected country code, and to the process code page 
  1578. or selected code page. The default name of the country file is COUNTRY.SYS. 
  1579.  
  1580.  
  1581. ΓòÉΓòÉΓòÉ 3.3.4. Obtaining the DBCS Environment Vector ΓòÉΓòÉΓòÉ
  1582.  
  1583. DosQueryDBCSEnv obtains a double-byte character set (DBCS) environment vector 
  1584. that resides in the country file. The default name of the country file is 
  1585. COUNTRY.SYS. 
  1586.  
  1587. The vector corresponds to the system country code or selected country code, and 
  1588. to the process code page or selected code page. 
  1589.  
  1590. The following code fragment shows how to use DosQueryDBCSEnv: 
  1591.  
  1592.     #define INCL_DOSNLS   /* National Language Support values */
  1593.     #include <os2.h>
  1594.     #include <stdio.h>
  1595.  
  1596.     ULONG         Length;             /* Length of data area provided         */
  1597.     COUNTRYCODE   Structure;          /* Input data structure                 */
  1598.     UCHAR         MemoryBuffer[12];   /* DBCS environmental vector (returned) */
  1599.     APIRET        rc;                 /* Return code                          */
  1600.  
  1601.     Length = 12;                      /* A length of 12 bytes is sufficient   */
  1602.                                       /* to contain the DBCS data returned    */
  1603.  
  1604.     Structure.country = 0;            /* Use the default system country code  */
  1605.  
  1606.     Structure.codepage = 0;           /* Return DBSC information for the      */
  1607.                                       /* caller's current process code page   */
  1608.  
  1609.     rc = DosQueryDBCSEnv(Length, &Structure, MemoryBuffer);
  1610.  
  1611.     if (rc != 0) {
  1612.         printf("DosQueryDBCSEnv error: return code = %ld", rc);
  1613.         return;
  1614.     }
  1615.  
  1616. On successful return, the buffer MemoryBuffer will contain the country 
  1617. dependent information for the DBCS environmental vector. 
  1618.  
  1619. Instead of the single-byte character set (SBCS) representation used for Latin 
  1620. text, some Asian countries use code pages that consist of double-byte character 
  1621. set characters, in which each character is represented by a two-byte code. The 
  1622. DBCS code pages enable single-byte data, double-byte data, or mixed 
  1623. (single-byte and double-byte) data. 
  1624.  
  1625.  
  1626. ΓòÉΓòÉΓòÉ 3.3.5. Obtaining Formatting Information ΓòÉΓòÉΓòÉ
  1627.  
  1628. DosQueryCtryInfo obtains country dependent formatting information that resides 
  1629. in the country file. The default name of the country file is COUNTRY.SYS. 
  1630.  
  1631. The information corresponds to the system country code or selected country 
  1632. code, and to the process code page or selected code page. 
  1633.  
  1634.  
  1635. ΓòÉΓòÉΓòÉ 3.3.6. Obtaining Collating Information for SORT ΓòÉΓòÉΓòÉ
  1636.  
  1637. DosQueryCollate obtains a collating sequence table (for characters 00H through 
  1638. FFH) from the country file. The default name of the country file is 
  1639. COUNTRY.SYS. The SORT utility program uses this table to sort text according to 
  1640. the collating sequence. 
  1641.  
  1642. The collating table returned corresponds to the system country code or selected 
  1643. country code, and to the process code page or selected code page. 
  1644.  
  1645.  
  1646. ΓòÉΓòÉΓòÉ 4. Pipes ΓòÉΓòÉΓòÉ
  1647.  
  1648. Communication between processes is valuable in a multitasking operating system 
  1649. to enable concurrent processes to work together. Pipes are one of three forms 
  1650. of interprocess communication (IPC), the other forms of IPC being semaphores 
  1651. and queues. 
  1652.  
  1653. This chapter describes how to create, manage, and use pipes. Pipes enable two 
  1654. or more processes to communicate as if they were reading from and writing to a 
  1655. file. 
  1656.  
  1657. The following topics are related to the information in this chapter: 
  1658.  
  1659.    o  Memory (Shared Memory) 
  1660.    o  Program Execution and Control 
  1661.    o  Semaphores 
  1662.    o  Queues 
  1663.  
  1664.  
  1665. ΓòÉΓòÉΓòÉ 4.1. About Pipes ΓòÉΓòÉΓòÉ
  1666.  
  1667. A pipe is a named or unnamed buffer used to pass data between processes. A 
  1668. process writes to or reads from a pipe as if the pipe were standard input or 
  1669. standard output. A parent process can use pipes to control the input that a 
  1670. child process receives and to receive the output that the child process 
  1671. produces. 
  1672.  
  1673. There are two types of pipes-named and unnamed. 
  1674.  
  1675.  
  1676. ΓòÉΓòÉΓòÉ 4.1.1. Unnamed Pipes ΓòÉΓòÉΓòÉ
  1677.  
  1678. An unnamed pipe is a circular buffer in memory. The buffer has in and out 
  1679. pointers that are maintained by the system. 
  1680.  
  1681. An unnamed pipe can transfer information only between related processes. A 
  1682. child process started by a parent process with DosExecPgm inherits the handles 
  1683. to any unnamed pipes created by its parent. This inheritance enables the parent 
  1684. process and the child process to use the unnamed pipe to communicate with one 
  1685. another. This type of pipe is typically used to redirect the standard input and 
  1686. standard output of a child process. 
  1687.  
  1688. To do this, a process opens a pipe and duplicates the read and write handles of 
  1689. the pipe as the standard input and standard output files for the child process. 
  1690. Once the handles are duplicated, the parent process can use DosExecPgm to start 
  1691. the child process. When the child process reads and writes to its standard 
  1692. input and standard output handles, it is reading and writing to the pipe. The 
  1693. parent process can also communicate with the child process through the pipe. 
  1694.  
  1695. Using an unnamed pipe, a text editor could run another program, such as a 
  1696. compiler or assembler, and display the output of the compiler or assembler 
  1697. within the editor. 
  1698.  
  1699. DosCreatePipe creates an unnamed pipe. This function returns two file handles 
  1700. for the pipe, one for writing to the pipe and another for reading from the 
  1701. pipe. A process can then write to the pipe by using DosWrite and read from the 
  1702. pipe by using DosRead. 
  1703.  
  1704. A pipe exists until both handles are closed. The order in which the handles are 
  1705. closed is sometimes important. For example, DosWrite might wait for data to be 
  1706. read from the pipe before completing its operation. In this case, the read 
  1707. handle is closed before the write handle is closed, writing to the pipe 
  1708. generates an error. 
  1709.  
  1710. No control or permission mechanisms or checks are performed on operations to 
  1711. unnamed pipes. 
  1712.  
  1713.  
  1714. ΓòÉΓòÉΓòÉ 4.1.2. Named Pipes ΓòÉΓòÉΓòÉ
  1715.  
  1716. Named pipes enable related or unrelated processes on either the same computer 
  1717. system or different systems to communicate with each other. Any process that 
  1718. knows the name of a pipe can open and use a named pipe. In addition, named pipe 
  1719. data can be transparently redirected across a network, such as a local area 
  1720. network (LAN). (Unnamed pipes, by contrast, can be used only by related 
  1721. processes that are on the same computer system.) 
  1722.  
  1723. One process (the server process) creates the pipe and connects to one end of 
  1724. it. Other processes that access the named pipe are called client processes; 
  1725. they connect to the other end of the pipe. The server and client processes can 
  1726. then pass data back and forth by reading from and writing to the pipe. The 
  1727. server process controls access to the named pipe. 
  1728.  
  1729. The client process can be either local or remote. A local client process is one 
  1730. that runs on the same computer system as the server process. A remote client 
  1731. process runs on a different system and communicates with the server process 
  1732. across a local area network (LAN). 
  1733.  
  1734. When the server process creates a named pipe with DosCreateNPipe, it must 
  1735. specify the direction that data will flow through the pipe. The process 
  1736. specifies an inbound pipe if it intends to read data from the client process, 
  1737. an outbound pipe if it intends to write data to the client process, or a duplex 
  1738. pipe if it intends to read from and write to the client process. 
  1739.  
  1740. The server process also specifies whether data passes through the pipe as bytes 
  1741. or messages. A message is a block of data, with a system-supplied header, that 
  1742. is read or written as a single unit. The server and client processes define the 
  1743. size and format of a message. 
  1744.  
  1745. The server process also specifies whether child processes will inherit the 
  1746. named pipe and how information will be read from and written to the pipe. If 
  1747. the server specifies wait mode, DosRead will be blocked (it will not return to 
  1748. the process) until data is available in the pipe, and DosWrite will be blocked 
  1749. until there is enough room in the pipe to contain the entire data buffer. If 
  1750. the server specifies no-wait mode, reading from an empty pipe or writing to a 
  1751. full pipe immediately returns an error value. 
  1752.  
  1753. A named pipe consists of two pipe buffers, one for each direction of 
  1754. communication. However, each end of the pipe has only one handle associated 
  1755. with it. The server receives the handle for its end when it creates the pipe 
  1756. with DosCreateNPipe. The client receives the handle for its end when it opens 
  1757. the pipe with DosOpen. 
  1758.  
  1759. The server and the client use their respective handles both to read from the 
  1760. pipe and to write to it. (This is in contrast to unnamed pipes, for which both 
  1761. the server and the client read from one handle and write to another.) In other 
  1762. words, data that is written by the process at one end of the pipe is read by 
  1763. the process at the other end. 
  1764.  
  1765. A named pipe can have multiple instances, up to the number specified when the 
  1766. pipe is first created. Pipe instances are actually separate pipes-that is, 
  1767. unique sets of pipe buffers with unique handles-that share the same name. The 
  1768. ability to create multiple pipe instances enables the server to communicate 
  1769. with multiple client processes at the same time. 
  1770.  
  1771.  
  1772. ΓòÉΓòÉΓòÉ 4.1.2.1. Server-Client Communications Using Named Pipes ΓòÉΓòÉΓòÉ
  1773.  
  1774. A server process initiates a connection to a client process by using 
  1775. DosConnectNPipe. Once the pipe has been connected by the server process, the 
  1776. client process must open the pipe by using DosOpen to complete the connection. 
  1777. If no client process has opened the pipe when the server process calls 
  1778. DosConnectNPipe, the function either waits until a client opens the pipe or 
  1779. returns ERROR_PIPE_NOT_CONNECTED, depending on whether the server process 
  1780. created the pipe to wait for data. 
  1781.  
  1782. Each client process requires a separate instance of a pipe. For example, if a 
  1783. server process creates a named pipe and specifies that four instances of the 
  1784. pipe can be created, the process can then create three more instances of the 
  1785. named pipe (for a total of four pipes, including the original). Each instance 
  1786. has the same name, but each has a unique pipe handle. The process can then 
  1787. connect each pipe to the server. (Each instance must be connected by an 
  1788. explicit use of DosConnectNPipe.) In this example, the server must use each 
  1789. function four times to create and connect four separate instances of the named 
  1790. pipe. Each pipe is then available to a separate client process. 
  1791.  
  1792. If a client process receives the ERROR_PIPE_BUSY return value from DosOpen, no 
  1793. instances of the given pipe are available. The process can use DosWaitNPipe to 
  1794. wait for an instance to become available. The function waits until an instance 
  1795. is free or until the specified time interval elapses. When an instance becomes 
  1796. free, the process can open the pipe. If several processes are waiting for an 
  1797. instance to become available, the system gives the named pipe to the process 
  1798. that has been waiting the longest. 
  1799.  
  1800. The server process can disconnect a client process from a pipe by using 
  1801. DosDisConnectNPipe. Ideally, the client process closes the pipe by using 
  1802. DosClose before the server process disconnects the pipe. If the client process 
  1803. has not closed the pipe when the server process disconnects it, the server 
  1804. process forces the pipe closed and the client process subsequently receives 
  1805. errors if it attempts to access the pipe. Note that forcing the closure of the 
  1806. pipe might discard data in the pipe before the client process has had an 
  1807. opportunity to read it. 
  1808.  
  1809. A process can read and write bytes to a named pipe by using DosRead and 
  1810. DosWrite. A process can read or write messages by using DosTransactNPipe. 
  1811. Depending on the access mode, DosTransactNPipe writes a message to the pipe, 
  1812. reads a message from the pipe, or both. If a named pipe contains unread data or 
  1813. is not a message pipe, DosTransactNPipe fails. If it is reading from the pipe, 
  1814. DosTransactNPipe does not return until a complete message is read, even if the 
  1815. server process specified no-wait mode when the pipe was created. 
  1816.  
  1817. A process can also read data from a named pipe without removing the data from 
  1818. the pipe by using DosPeekNPipe. This function copies the specified number of 
  1819. bytes from the pipe and returns the number of bytes of data left in the pipe 
  1820. and the number of bytes left in the current message, if any. 
  1821.  
  1822. DosPeekNPipe also returns the state of the pipe. A named pipe can be in one of 
  1823. the following states: 
  1824.  
  1825. Named Pipe States 
  1826.  
  1827. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1828. ΓöéState          ΓöéDescription                                  Γöé
  1829. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1830. ΓöéConnected      ΓöéThe pipe has been created and connected by   Γöé
  1831. Γöé               Γöéthe server process and has been opened by a  Γöé
  1832. Γöé               Γöéclient process.  Only connected pipes can be Γöé
  1833. Γöé               Γöéwritten to or read from.                     Γöé
  1834. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1835. ΓöéClosing        ΓöéThe pipe has been closed by the client       Γöé
  1836. Γöé               Γöéprocess but has not yet been disconnected by Γöé
  1837. Γöé               Γöéthe server process.                          Γöé
  1838. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1839. ΓöéDisconnected   ΓöéThe pipe has been created by the server      Γöé
  1840. Γöé               Γöéprocess but not connected, or has been       Γöé
  1841. Γöé               Γöéexplicitly disconnected and not yet          Γöé
  1842. Γöé               Γöéreconnected. A disconnected pipe cannot      Γöé
  1843. Γöé               Γöéaccept a DosOpen request.                    Γöé
  1844. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1845. ΓöéListening      ΓöéThe pipe has been created and connected by   Γöé
  1846. Γöé               Γöéthe server process but has not yet been      Γöé
  1847. Γöé               Γöéopened by a client process. A listening pipe Γöé
  1848. Γöé               Γöéis ready to accept a request to open. If the Γöé
  1849. Γöé               Γöépipe is not in a listening state, DosOpen    Γöé
  1850. Γöé               Γöéreturns ERROR_PIPE_BUSY.                     Γöé
  1851. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  1852. DosCallNPipe is used to open, write to, read from, and close a named 
  1853. message-format pipe. This function is equivalent to calling DosOpen, 
  1854. DosTransactNPipe, and DosClose If no instances of the pipe are available, 
  1855. DosCallNPipe waits for an instance or returns without opening the pipe if the 
  1856. specified interval of time elapses. 
  1857.  
  1858. A process can retrieve information about the handle state of a named pipe by 
  1859. using DosQueryNPHState. The handle state is a combination of the instance 
  1860. count, the access mode, and the pipe type (byte or message). DosQueryNPHState 
  1861. also specifies whether the process owning the handle is a server or client and 
  1862. whether the pipe waits if reading and writing cannot proceed. 
  1863.  
  1864. A process can modify the handle state of a named pipe by using DosSetNPHState. 
  1865. For example, the process can change the reading mode for the pipe, enabling a 
  1866. process to read bytes from the pipe instead of messages. 
  1867.  
  1868.  
  1869. ΓòÉΓòÉΓòÉ 4.1.2.2. Steps in Managing Server-Client Transactions ΓòÉΓòÉΓòÉ
  1870.  
  1871. The following sequence summarizes the typical steps in the management of a 
  1872. named pipe: 
  1873.  
  1874.    1. The server process creates the pipe by calling DosCreateNPipe. 
  1875.       DosCreateNPipe returns a handle for the server end of the pipe. (Note 
  1876.       that the server uses the same handle to both read from and write to the 
  1877.       pipe.) The pipe is now in the disconnected state and cannot be opened by 
  1878.       a client process. The server process calls DosConnectNPipe to put the 
  1879.       pipe into a listening state. 
  1880.  
  1881.    2. The pipe can now be opened by a client process. 
  1882.  
  1883.    3. A client process supplies the name of the pipe in a call to DosOpen and 
  1884.       receives a pipe handle in return. (The client uses the same handle to 
  1885.       both read from and write to the pipe.) The pipe is now in the connected 
  1886.       state and can be read from or written to by the client. 
  1887.  
  1888.    4. The server and client processes communicate by calling DosRead and 
  1889.       DosWrite. DosResetBuffer can be used to synchronize read and write 
  1890.       dialogs. A server process that supports a large number of clients for a 
  1891.       local named pipe can use DosSetNPipeSem and DosQueryNPipeSemState to 
  1892.       coordinate access to the pipe. Server and client processes can also use 
  1893.       DosTransactNPipe and DosCallNPipe to facilitate their communication. 
  1894.  
  1895.    5. After completing its transactions, the client process calls DosClose to 
  1896.       close its end of the pipe. The pipe is now in the closing state and 
  1897.       cannot be accessed by another client. 
  1898.  
  1899.    6. The server process calls DosDisConnectNPipe to acknowledge that the 
  1900.       client has closed its end of the pipe.  The pipe is now in the 
  1901.       disconnected state again. 
  1902.  
  1903.    7. To enable another client process to open the pipe, the server must call 
  1904.       DosConnectNPipe again. This puts the pipe back into the listening state. 
  1905.       To end its access to the pipe, the server calls DosClose. When all of the 
  1906.       handles for both ends of the pipe have been closed, the pipe is 
  1907.       deallocated by the system. 
  1908.  
  1909.  
  1910. ΓòÉΓòÉΓòÉ 4.1.2.3. Preparing a Named Pipe for a Client ΓòÉΓòÉΓòÉ
  1911.  
  1912. A server process uses DosConnectNPipe to put a newly created named pipe into 
  1913. the listening state. The pipe must be in the listening state in order for a 
  1914. client process to gain access to the pipe by calling DosOpen. 
  1915.  
  1916. After successfully opening the pipe and finishing its transactions, the client 
  1917. process calls DosClose to end its access to the pipe. The server process must 
  1918. acknowledge the close by calling DosDisConnectNPipe. It can then call 
  1919. DosConnectNPipe again to put the pipe into the listening state for the next 
  1920. client. 
  1921.  
  1922. Together, DosConnectNPipe and DosDisConnectNPipe enable a server to create a 
  1923. named pipe and to reuse it for communication with different clients. Without 
  1924. these functions, the server would have to delete and re-create the pipe for 
  1925. each client. 
  1926.  
  1927. Note:  If multiple instances of a named pipe have been created, then each 
  1928.        instance of the pipe must be put into the listening state before it can 
  1929.        be opened by a client. 
  1930.  
  1931.  
  1932. ΓòÉΓòÉΓòÉ 4.1.2.4. Facilitating Transaction Processing ΓòÉΓòÉΓòÉ
  1933.  
  1934. DosTransactNPipe and DosCallNPipe facilitate the use of named pipes by 
  1935. combining other named pipe functions. Compared to calling the other functions 
  1936. separately, DosTransactNPipe and DosCallNPipe provide significant performance 
  1937. gains for applications that operate in a networked environment.  They can also 
  1938. be used by local processes. However, both of these functions can be used only 
  1939. with duplex message pipes. 
  1940.  
  1941.    o  DosTransactNPipe performs a transaction (a DosWrite followed by DosRead) 
  1942.       on a duplex message pipe. 
  1943.  
  1944.    o  DosCallNPipe has the combined effect of DosOpen, DosTransactNPipe, and 
  1945.       DosClose, and is referred to as a procedure call. It provides an 
  1946.       efficient means of implementing local and remote procedure call 
  1947.       interfaces between processes. 
  1948.  
  1949.  
  1950. ΓòÉΓòÉΓòÉ 4.1.2.5. Coordinating Access to a Local Named Pipe with Semaphores ΓòÉΓòÉΓòÉ
  1951.  
  1952. When a process writes to a named pipe, the process at the other end (or handle) 
  1953. of the pipe might require notification that data is available to be read. 
  1954. Similarly, when a process reads from a named pipe, the process at the other end 
  1955. might require notification that write space has become available. As long as 
  1956. the communicating processes are on the same computer system, shared event 
  1957. semaphores and muxwait semaphores can be used to provide this notification. 
  1958. Using shared semaphores for this purpose is more efficient than dedicating a 
  1959. thread to periodically poll each pipe, particularly when a server process is 
  1960. communicating with a large number of client processes. The server or client 
  1961. (whichever is writing to the pipe) can post a semaphore whenever data is 
  1962. available in the pipe. This means that the reading process can use 
  1963. DosWaitEventSem or DosWaitMuxWaitSem to wait for data to arrive, rather than 
  1964. devote a thread to periodically polling the pipe. 
  1965.  
  1966. A process associates a semaphore with a named pipe by using DosSetNPipeSem. 
  1967. First, create an event semaphore with DosCreateEventSem, specifying the initial 
  1968. state of the semaphore as reset. Then call DosSetNPipeSem to attach the event 
  1969. semaphore to a particular named-pipe handle. Up to two event semaphores can be 
  1970. attached to each named pipe, one for the server process and one for the client 
  1971. process. If there is already a semaphore associated with one end of the pipe, 
  1972. that semaphore is replaced. A process can check the state of the semaphores by 
  1973. using DosQueryNPipeSemState. 
  1974.  
  1975. The server or client process must then call DosWaitEventSem. The particular 
  1976. thread that calls this function will block until data is either read from or 
  1977. written to the pipe. At that time, the system posts the event semaphore, 
  1978. enabling the blocked thread to resume its execution. 
  1979.  
  1980. If a process requires notification whenever any one of multiple named pipes has 
  1981. been written to or read from, it can either attach the same event semaphore to 
  1982. multiple pipes, or it can create a muxwait semaphore: 
  1983.  
  1984.    o  If the same event semaphore is attached to multiple pipes, then the 
  1985.       KeyHandle parameter of DosSetNPipeSem is used to assign a unique value to 
  1986.       each pipe. After the event semaphore has been posted, the process calls 
  1987.       DosQueryNPipeSemState. This function returns information about each of 
  1988.       the named pipes that are attached to the semaphore, including key-handle 
  1989.       values. The calling process can use this information to determine which 
  1990.       one of the named pipes has either data or write space available. 
  1991.  
  1992.    o  To use a muxwait semaphore, a process first creates an event semaphore 
  1993.       for each of the pipes that it wants to monitor. Each semaphore must then 
  1994.       be attached to a pipe by calling DosSetNPipeSem. Again, a unique 
  1995.       key-handle value must be assigned to each pipe. 
  1996.  
  1997.       Next, the process calls DosCreateMuxWaitSem to create the muxwait 
  1998.       semaphore, specifying DCMW_WAIT_ANY as one of the flAttr flags. The 
  1999.       muxwait semaphore will consist of a linked list of the previously created 
  2000.       event semaphores. 
  2001.  
  2002.       The process calls DosWaitMuxWaitSem so that it will be notified the next 
  2003.       time data is read from or written to any of the pipes. However, it must 
  2004.       call DosQueryNPipeSemState to determine which one of the pipes is ready 
  2005.       to be read from or written to. 
  2006.  
  2007.  
  2008. ΓòÉΓòÉΓòÉ 4.2. Using Unnamed Pipes ΓòÉΓòÉΓòÉ
  2009.  
  2010. Unnamed pipes are useful in applications that transfer data between related 
  2011. processes. They are commonly used to control the input and output of child 
  2012. processes by redirecting the standard input and output of the child process to 
  2013. a pipe controlled by the parent process. 
  2014.  
  2015. Note:  In the example code fragments that follow, error checking was left out 
  2016.        to conserve space. Applications should always check the return code that 
  2017.        the functions return. Control Program functions return an APIRET value. 
  2018.        A return code of 0 indicates success. If a non-zero value is returned, 
  2019.        an error occurred. 
  2020.  
  2021.  
  2022. ΓòÉΓòÉΓòÉ 4.2.1. Creating Unnamed Pipes ΓòÉΓòÉΓòÉ
  2023.  
  2024. DosCreatePipe creates an unnamed pipe. Two handles are returned: one for read 
  2025. access to the pipe and one for write access. The pipe size specified is 
  2026. advisory; its actual size is dependent on the amount of available memory. If 
  2027. the size parameter is 0, the pipe is created with the default size, which is 
  2028. 512 bytes. 
  2029.  
  2030. This example creates an unnamed pipe. The current process can use the unnamed 
  2031. pipe for communication between itself and a child process. 
  2032.  
  2033.     #define INCL_DOSQUEUES   /* Queue values */
  2034.     #include <os2.h>
  2035.     #include <stdio.h>
  2036.  
  2037.     HFILE    ReadHandle;    /* Pointer to the read handle      */
  2038.     HFILE    WriteHandle;   /* Pointer to the write handle     */
  2039.     ULONG    PipeSize;      /* Pipe size                       */
  2040.     APIRET   rc;            /* Return code                     */
  2041.  
  2042.     PipeSize = 4096;        /* Ask for 4KB of internal storage */
  2043.                             /* for the pipe                    */
  2044.  
  2045.     rc = DosCreatePipe(&ReadHandle, &WriteHandle, PipeSize);
  2046.  
  2047.     if (rc != 0) {
  2048.         printf("DosCreatePipe error: return code = %ld", rc);
  2049.         return;
  2050.     }
  2051.  
  2052. On successful return, the ReadHandle variable contains the read handle for the 
  2053. pipe, and the WriteHandle variable contains the write handle for the pipe. 
  2054.  
  2055. After a process creates a pipe, any child process started with DosExecPgm 
  2056. inherits the pipe handles. Using shared memory, the parent process can pass one 
  2057. of the pipe handles to the child process; thus, one process can store data in 
  2058. the pipe and the other can retrieve it. 
  2059.  
  2060.  
  2061. ΓòÉΓòÉΓòÉ 4.2.2. Reading from and Writing to Unnamed Pipes ΓòÉΓòÉΓòÉ
  2062.  
  2063. Applications use the OS/2 file system functions to read from and write to 
  2064. unnamed pipes. 
  2065.  
  2066. The handles returned by DosCreatePipe are used as file handles to DosRead and 
  2067. DosWrite. 
  2068.  
  2069. To write (or add data) to an unnamed pipe, call DosWrite, specifying the write 
  2070. handle of the pipe in DosWrite's file handle parameter. DosWrite requests to a 
  2071. pipe are processed in the order in which they are made. Multiple calls to 
  2072. DosWrite can be made before data is read (or removed) from the pipe. When the 
  2073. pipe becomes full, write requests are blocked until space is freed by read 
  2074. requests. 
  2075.  
  2076. To read from a pipe, call DosRead, specifying the read handle of the pipe in 
  2077. DosRead's file handle parameter. Subsequent calls to DosRead can empty the pipe 
  2078. if no further calls to DosWrite are made in the meantime. 
  2079.  
  2080. If the process reading the pipe ends, the next DosWrite request for that pipe 
  2081. returns ERROR_BROKEN_PIPE. 
  2082.  
  2083. Calling DosClose terminates access to an unnamed pipe. However, the pipe is not 
  2084. deleted from memory until all handles to the pipe have been closed, including 
  2085. any handles that were defined with DosDupHandle. 
  2086.  
  2087.  
  2088. ΓòÉΓòÉΓòÉ 4.2.3. Redirecting Standard I/O for Child Processes ΓòÉΓòÉΓòÉ
  2089.  
  2090. An application can use unnamed pipes to redirect the standard input and the 
  2091. standard output for a child process. 
  2092.  
  2093. A typical use of an unnamed pipe is to read the output of a child process. An 
  2094. application creates a pipe and then duplicates the standard output handle. When 
  2095. the child process is started, its standard output will be written into the 
  2096. pipe, where the application can read and display it. The following code 
  2097. fragment shows how to do this: 
  2098.  
  2099.     #define INCL_DOSQUEUES   /* Queue values */
  2100.     #include <os2.h>
  2101.  
  2102.     #define PIPESIZE 256
  2103.     #define HF_STDOUT 1      /* Standard output handle */
  2104.  
  2105.     HPIPE hpR, hpW;
  2106.     RESULTCODES resc;
  2107.     ULONG cbRead, cbWritten;
  2108.     CHAR achBuf[PIPESIZE], szFailName[CCHMAXPATH];
  2109.  
  2110.     HFILE hfSave = -1,
  2111.           hfNew = HF_STDOUT;
  2112.  
  2113.     DosDupHandle(HF_STDOUT, &hfSave);    /* Saves standard output handle      */
  2114.  
  2115.     DosCreatePipe(&hpR, &hpW, PIPESIZE); /* Creates pipe                      */
  2116.  
  2117.     DosDupHandle(hpW, &hfNew);           /* Duplicates standard output handle */
  2118.  
  2119.     DosExecPgm(szFailName, sizeof(szFailName),   /* Starts child process      */
  2120.                EXEC_ASYNC, (PSZ) NULL, (PSZ) NULL, &resc,
  2121.                "DUMMY.EXE");
  2122.  
  2123.     DosClose(hpW);                       /* Closes write handle to ensure     */
  2124.                                          /* Notification at child termination */
  2125.  
  2126.     DosDupHandle(hfSave, &hfNew);        /* Brings stdout back                */
  2127.  
  2128.     /*
  2129.      * Read from the pipe and write to the screen
  2130.      * as long as there are bytes to read.
  2131.      */
  2132.  
  2133.     do {
  2134.         DosRead(hpR, achBuf, sizeof(achBuf), &cbRead);
  2135.         DosWrite(HF_STDOUT, achBuf, cbRead, &cbWritten);
  2136.     } while(cbRead);
  2137.  
  2138. A parent process can also use unnamed pipes to communicate with a child process 
  2139. by redirecting both the standard input and the standard output for the child 
  2140. process. To do this, the parent process: 
  2141.  
  2142.    1. Uses DosDupHandle to redefine the read handle of one pipe as standard 
  2143.       input (0000), and the write handle of the other pipe as standard output 
  2144.       (0001). 
  2145.    2. Starts the child process with DosExecPgm. 
  2146.    3. Uses the remaining pipe handles to read and write to the pipes. 
  2147.  
  2148.  The parent process controls the meanings for standard I/O for the child 
  2149.  process. Thus, when the child process uses standard I/O handles with DosRead 
  2150.  and DosWrite, it reads from and writes to the pipes of its parent instead of 
  2151.  reading from the keyboard and writing to the display. 
  2152.  
  2153.  
  2154. ΓòÉΓòÉΓòÉ 4.3. Using Named Pipes ΓòÉΓòÉΓòÉ
  2155.  
  2156. Named pipes are useful in applications that transfer data between processes. 
  2157. The processes using named pipes can be related, unrelated, or even on different 
  2158. computers. 
  2159.  
  2160.  
  2161. ΓòÉΓòÉΓòÉ 4.3.1. Creating Named Pipes ΓòÉΓòÉΓòÉ
  2162.  
  2163. The server process creates a named pipe by using DosCreateNPipe. 
  2164.  
  2165. You must specify the name of the pipe, the access modes, the type of pipe (byte 
  2166. or message), and the sizes of the input and output buffers. DosCreateNPipe 
  2167. returns a pipe handle that can be used in subsequent pipe operations. 
  2168.  
  2169. Each named pipe must have a unique name of the following form: 
  2170.  
  2171.     \PIPE\PipeName
  2172.  
  2173. The "\PIPE\" in the name above is required, but need not be uppercase.  It is 
  2174. not the name of a subdirectory. 
  2175.  
  2176. To open a pipe on a remote computer, the client process must specify the name 
  2177. of the server process that opened the pipe as part of the pipe name, as 
  2178. follows: 
  2179.  
  2180.     \\Server\PIPE\PipeName
  2181.  
  2182. "\\Server" in the name above is the name of the remote computer; again, 
  2183. "\PIPE\" is required. 
  2184.  
  2185. The name parameter must conform to the rules for OS/2 file names, but no actual 
  2186. file is created for the pipe. 
  2187.  
  2188. In the following code fragment, DosCreateNPipe creates a pipe named \pipe\pipe1 
  2189. and supplies a unique handle identifying the pipe. OpenMode is set to 
  2190. NP_ACCESS_DUPLEX. This activates full duplex access to the named pipe. There 
  2191. will be no inheritance to child process, and no write-through (write-through 
  2192. only affects remote pipes). PipeMode is set to "NP_WMESG | NP_RMESG | 0x01". 
  2193. This specifies that the pipe should be read as a message stream for both 
  2194. reading and writing and an instance count of 1 (only one instance of the named 
  2195. pipe can be created at a time). The pipe will block on Read/Write if no data is 
  2196. available. 
  2197.  
  2198.     #define INCL_DOSNMPIPES   /* Named-pipe values */
  2199.     #include <os2.h>
  2200.     #include <stdio.h>
  2201.  
  2202.     UCHAR   FileName[40];  /* Pipe name              */
  2203.     HPIPE   PipeHandle;    /* Pipe handle (returned) */
  2204.     ULONG   OpenMode;      /* Open-mode parameters   */
  2205.     ULONG   PipeMode;      /* Pipe-mode parameters   */
  2206.     ULONG   OutBufSize;    /* Size of the out-buffer */
  2207.     ULONG   InBufSize;     /* Size of the in-buffer  */
  2208.     ULONG   TimeOut;       /* Default value for DosWaitNPipe time-out parameter */
  2209.     APIRET  rc;            /* Return code            */
  2210.  
  2211.     strcpy(FileName,"\\PIPE\\PIPE1");
  2212.  
  2213.     OpenMode = NP_ACCESS_DUPLEX;            /* Full duplex, no inheritance,     */
  2214.                                             /* no write-through                 */
  2215.  
  2216.     PipeMode = NP_WMESG | NP_RMESG | 0x01;  /* Block on read and write, message */
  2217.                                             /* stream, instance count of 1      */
  2218.  
  2219.     OutBufSize = 4096;   /* The outgoing buffer must be 4KB in size             */
  2220.  
  2221.     InBufSize = 2048;    /* The incoming buffer must be 2KB in size             */
  2222.  
  2223.     TimeOut = 10000;     /* Time-out is 10 seconds (units are in milliseconds)  */
  2224.  
  2225.     rc = DosCreateNPipe(FileName, &PipeHandle, OpenMode,
  2226.                         PipeMode, OutBufSize, InBufSize,
  2227.                         TimeOut);
  2228.  
  2229.     if (rc != 0) {
  2230.         printf("DosCreateNPipe error: return code = %ld", rc);
  2231.         return;
  2232.     }
  2233.  
  2234. Once the named pipe is created, the application can call DosConnectNPipe to 
  2235. connect a client process to the pipe. 
  2236.  
  2237. Once a client process connects to the pipe, the process can read from and write 
  2238. to the pipe. The preceding example creates a byte pipe, so the process can use 
  2239. DosRead and DosWrite to read from and write to the pipe. 
  2240.  
  2241. After the client process finishes using the pipe, the server process can 
  2242. disconnect the pipe by using DosDisConnectNPipe. The server process can either 
  2243. connect again or close the named pipe by using DosClose. 
  2244.  
  2245. When a server process creates a named pipe, it defines the pipe to the system 
  2246. by specifying the file write-through mode, the inheritance mode, the access and 
  2247. blocking modes, the pipe type, the read mode, the size of the in and out 
  2248. buffers, and the instance count.  The following list describes these modes, 
  2249. types, and buffers. 
  2250.  
  2251.    o  The file write-through mode has significance only for communication with 
  2252.       remote client processes. When the file write-through bit is set, data is 
  2253.       sent across the network as soon as it is written; otherwise, the 
  2254.       operating system will in some cases hold data briefly in a local buffer 
  2255.       before sending it across the network. 
  2256.  
  2257.    o  The inheritance mode specifies whether or not the pipe handle will be 
  2258.       inherited by a child process. 
  2259.  
  2260.    o  The access mode specifies the direction in which data will flow through 
  2261.       the pipe. The server creates an inbound pipe (a pipe with inbound access 
  2262.       mode) if it intends to read data from the client process, an outbound 
  2263.       pipe if it intends to write data to the client process, or a duplex pipe 
  2264.       if it intends to both read from and write to the client process. 
  2265.  
  2266.    o  The blocking mode specifies whether or not DosRead and DosWrite will 
  2267.       block when no data is available to read, or there is no room to write 
  2268.       data. 
  2269.  
  2270.    o  The pipe type is the form in which a stream of data is written to the 
  2271.       pipe. If the pipe is a byte pipe, the server and client processes write 
  2272.       data as an undifferentiated stream of bytes. If the pipe is a message 
  2273.       pipe, the processes write data as a stream of messages;  messages are 
  2274.       blocks of data, each with a system-supplied header, that are written as 
  2275.       single units. The server and client processes define the size and format 
  2276.       of a message. 
  2277.  
  2278.    o  The read mode is the form in which data is read from the pipe. The data 
  2279.       in a pipe that was created as a byte pipe can only be read as bytes; 
  2280.       therefore, a byte pipe will always be in byte-read mode. The data in a 
  2281.       message pipe, however, can be read either as messages or as bytes.  (If 
  2282.       it is to be read as bytes, DosRead skips over the message headers). 
  2283.       Therefore, message pipes can be in either message-read mode or byte-read 
  2284.       mode. 
  2285.  
  2286.       Note:  The terms "byte pipe" and "message pipe" always refer to the pipe 
  2287.              type-the form in which data is written to the pipe. When the read 
  2288.              mode of a pipe is being referred to, it is always explicitly 
  2289.              identified as either message-read mode or byte-read mode. 
  2290.  
  2291.    o  The in and out buffers can be up to 64KB in size. If the pipe will be 
  2292.       read in message-read mode, and if the message size is known, the server 
  2293.       can control how many messages the buffer will hold at one time by 
  2294.       specifying the appropriate buffer size. 
  2295.  
  2296.    o  The instance count is the maximum number of instances of the named pipe 
  2297.       that can be created. A pipe instance is actually a separate pipe-that is, 
  2298.       a unique set of pipe buffers with unique handles. However, the term "pipe 
  2299.       instance" is used to distinguish pipes that share the same name from 
  2300.       pipes with different names. Because a client process uses only the name 
  2301.       of the pipe when opening it, the existence of multiple pipe instances is 
  2302.       transparent to a client process. 
  2303.  
  2304.  Creating Multiple Instances of a Named Pipe 
  2305.  Although each named pipe must have a unique name, a server process can create 
  2306.  multiple instances of a pipe, all of which have the same name. A pipe instance 
  2307.  is actually a separate pipe-that is, a unique set of pipe buffers with unique 
  2308.  handles. 
  2309.  
  2310.  The ability to create multiple pipe instances enables the server to 
  2311.  communicate with multiple client processes at the same time. Because a client 
  2312.  process uses only the name of the pipe when opening it, the existence of 
  2313.  multiple pipe instances is transparent to a client process. 
  2314.  
  2315.  The ICount parameter of DosCreateNPipe specifies the maximum number of named 
  2316.  pipe instances that can be created. (An unlimited number can also be 
  2317.  specified.) This parameter is specified only when the first instance of a 
  2318.  named pipe is created; any subsequent attempt to redefine the instance count 
  2319.  will be ignored. 
  2320.  
  2321.  If the instance count is greater than 1, the server process can create 
  2322.  additional pipe instances by specifying the same pipe name in subsequent calls 
  2323.  to DosCreateNPipe. Generally, the attributes of the subsequent pipe instances 
  2324.  are defined to be the same as those of the original pipe instance, because a 
  2325.  client process that requests the pipe has no way of controlling which pipe 
  2326.  instance will be assigned to it. 
  2327.  
  2328.  After an additional pipe instance has been created, it is used in the same 
  2329.  manner as the original pipe instance.  That is, the same sequence of named 
  2330.  pipe functions is used in the control or management of all named pipe 
  2331.  instances. (See Steps in Managing Server-Client Transactions for more 
  2332.  information.) 
  2333.  
  2334.  Note:  If all of the instances of a named pipe are in use when a client calls 
  2335.         DosOpen, ERROR_PIPE_BUSY is returned. However, the client can wait for 
  2336.         an instance of that pipe to become available by calling DosWaitNPipe. 
  2337.  
  2338.  Multiple instances of a named pipe can be created by different processes. That 
  2339.  is, multiple server processes can create and use instances of the same named 
  2340.  pipe to communicate with their clients. 
  2341.  
  2342.  
  2343. ΓòÉΓòÉΓòÉ 4.3.2. Opening Named Pipes ΓòÉΓòÉΓòÉ
  2344.  
  2345. A client process can open the client end of a named pipe by using DosOpen. 
  2346. DosOpen opens the client end of a pipe by name and returns a handle. The 
  2347. application must use the appropriate pipe name and access modes to open the 
  2348. pipe for reading, writing, or both. (To open a pipe on a remote computer, the 
  2349. client process must also specify the name of the computer system as part of the 
  2350. pipe name, as follows: 
  2351.  
  2352.     \\ComputerName\PIPE\PipeName.)
  2353.  
  2354. If a pipe name includes a remote LAN server name, DosOpen attempts to open the 
  2355. pipe on a remote computer. The server process can then read input from the 
  2356. client process through the pipe. 
  2357.  
  2358. The following code fragment opens a remote pipe, reads from the standard input 
  2359. (usually the keyboard), and sends the information to the server process through 
  2360. the pipe: 
  2361.  
  2362.     #define INCL_DOSQUEUES   /* Queue values          */
  2363.     #include <os2.h>
  2364.  
  2365.     #define PIPESIZE 256
  2366.     #define SERVER_PIPE_NAME "\\\\myserver\\pipe\\mypipe"
  2367.     #define HF_STDIN 0       /* Standard input handle */
  2368.  
  2369.     HPIPE   hp;
  2370.     BYTE    abBuf[PIPESIZE];
  2371.     ULONG   ulAction, cbRead, cbWritten;
  2372.     APIRET  rc;
  2373.  
  2374.     rc = DosOpen(SERVER_PIPE_NAME, &hp, &ulAction, 0,
  2375.                  FILE_NORMAL, FILE_OPEN,
  2376.                  OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE,
  2377.                  (PEAOP) NULL);
  2378.  
  2379.     if (rc)
  2380.         DosExit(EXIT_PROCESS, 0);                    /* Open pipe failed      */
  2381.  
  2382.     do {                                             /* Open pipe succeeded   */
  2383.         DosRead(HF_STDIN, abBuf, sizeof(abBuf), &cbRead);
  2384.         DosWrite(hp, abBuf, cbRead, &cbWritten);     /* Writes to the pipe    */
  2385.     } while (cbRead > 2);                            /* Stop on a blank line  */
  2386.  
  2387.     DosClose(hp);
  2388.  
  2389. The client process checks the return value from DosOpen to verify that the pipe 
  2390. was actually opened. If the server process has not yet created the pipe, 
  2391. DosOpen returns an error. When the client process finishes using the pipe, it 
  2392. closes the pipe by using DosClose. 
  2393.  
  2394. When a named pipe is opened, its initial state is set by the system to block 
  2395. read and write operations (blocking mode), and to read data as a byte stream 
  2396. (byte-read mode). However, the client can change these modes by calling 
  2397. DosSetNPHState. A call to DosOpen fails if all instances of the named pipe are 
  2398. already open. 
  2399.  
  2400. The open also fails if the pipe has been closed by a client, but the server has 
  2401. not called DosDisConnectNPipe (to acknowledge the client's close), followed by 
  2402. DosConnectNPipe (to prepare the pipe for the next client). In both of these 
  2403. situations, ERROR_PIPE_BUSY is returned. 
  2404.  
  2405. If all instances of a named pipe are busy, a client process can call 
  2406. DosWaitNPipe to wait for an instance to become available before it calls 
  2407. DosOpen again. 
  2408.  
  2409. After a pipe instance has been opened by a client, that same instance cannot be 
  2410. opened by another client at the same time.  However, the opening process can 
  2411. duplicate the handle as many times as desired by calling DosDupHandle. This 
  2412. enables child processes to share access to a pipe instance with a parent 
  2413. process. 
  2414.  
  2415. The access-mode and sharing-mode fields that are specified for DosOpen must be 
  2416. the same as those that were specified by the server when it created the pipe 
  2417. with DosCreateNPipe. 
  2418.  
  2419.  
  2420. ΓòÉΓòÉΓòÉ 4.3.3. Reading from Named Pipes ΓòÉΓòÉΓòÉ
  2421.  
  2422. Both the server and the client processes read data from a pipe by calling 
  2423. DosRead. The server reads from the handle that was returned when it created the 
  2424. pipe with DosCreateNPipe, and the client reads from the handle that was 
  2425. returned to it by DosOpen. 
  2426.  
  2427. When a pipe is created, the PipeMode parameter is used to specify both the pipe 
  2428. type and the read mode for the server end of the pipe: 
  2429.  
  2430.    o  A byte pipe can be read-only in byte-read mode. (DosCreateNPipe and 
  2431.       DosSetNPHState return ERROR_INVALID_PARAMETER if message-read mode is 
  2432.       specified for a byte pipe.) In byte-read mode, all currently available 
  2433.       data is returned, up to the buffer size specified by DosRead. 
  2434.  
  2435.    o  A message pipe can be read in either byte-read mode or message-read mode, 
  2436.       as follows: 
  2437.  
  2438.         -  When a message pipe is read in byte-read mode, the message headers 
  2439.            are skipped, and the pipe is read as if it were a byte pipe. 
  2440.  
  2441.         -  When a message pipe is read in message-read mode, each message is 
  2442.            read either in its entirety, or not at all, depending on the size of 
  2443.            the message and the buffer length: 
  2444.  
  2445.              o  If the buffer length that was specified for DosRead is larger 
  2446.                 than the next available message, then only that message is 
  2447.                 read, and the Bytes-Read parameter indicates the size of the 
  2448.                 message. 
  2449.  
  2450.              o  If the buffer length for DosRead is smaller than the next 
  2451.                 available message, DosRead returns the number of bytes 
  2452.                 requested and ERROR_MORE_DATA. Subsequent calls to DosRead are 
  2453.                 blocked until the rest of the message can be transferred. 
  2454.                 (DosPeekNPipe can be used to find out how many bytes are left 
  2455.                 in the message.) 
  2456.  
  2457.  The PipeMode parameter of DosCreateNPipe also specifies the blocking mode for 
  2458.  the server end of the pipe: 
  2459.  
  2460.    o  If nonblocking mode was specified, DosRead returns immediately with 0 in 
  2461.       the Bytes-Read parameter if no data is available. 
  2462.  
  2463.    o  If blocking mode was specified, DosRead blocks until data is available; 
  2464.       the only time it will return with 0 in the Bytes-Read parameter is if it 
  2465.       reaches end-of-file. 
  2466.  
  2467.  DosRead works the same for both ends of the pipe. However, the read mode and 
  2468.  blocking mode are not necessarily the same for the client end of the pipe as 
  2469.  they are for the server end, because DosOpen always opens the CLIENT end in 
  2470.  byte-read mode and blocking mode. 
  2471.  
  2472.  The read mode and blocking mode for either end of the pipe can be changed by 
  2473.  calling DosSetNPHState. The pipe type, however, is always the same for both 
  2474.  the server and client ends of the pipe, and it cannot be changed. 
  2475.  
  2476.  
  2477. ΓòÉΓòÉΓòÉ 4.3.4. Writing to Named Pipes ΓòÉΓòÉΓòÉ
  2478.  
  2479. Both the server and the client processes write to a pipe by calling DosWrite. 
  2480. The server writes to the handle that was returned to it by DosCreateNPipe, and 
  2481. the client writes to the handle that was returned to it by DosOpen. 
  2482.  
  2483. Either bytes or messages can be written, depending on whether the pipe was 
  2484. created as a byte pipe or as a message pipe. 
  2485.  
  2486. When a process writes to a message pipe, the buffer-length parameter for 
  2487. DosWrite holds the size of the message that the process is writing. Because 
  2488. DosWrite automatically encodes message lengths in the pipe, applications do not 
  2489. have to encode this information in the data buffers. 
  2490.  
  2491. The action taken by DosWrite depends on the blocking mode of the pipe, which is 
  2492. not necessarily the same for the server and client ends of the pipe. For the 
  2493. server process, the blocking mode of the pipe is specified when the pipe is 
  2494. created. For a client process, the blocking mode is automatically set to 
  2495. blocking when the pipe is opened. The blocking mode can also be reset by 
  2496. calling DosSetNPHState. 
  2497.  
  2498. If the end of the message pipe that is being written to is in blocking mode, 
  2499. DosWrite does not return until all of the requested bytes have been written. 
  2500. (It might have to wait for the first part of the message to be read before it 
  2501. can write the rest of the message.) 
  2502.  
  2503. If the message pipe is in nonblocking mode, DosWrite takes the following 
  2504. action: 
  2505.  
  2506.    o  If the message is larger than the pipe buffer, DosWrite blocks until the 
  2507.       entire message has been written. (Again, it might have to wait for the 
  2508.       first part of the message to be read before it can write the rest of the 
  2509.       message.) 
  2510.  
  2511.    o  If the message is smaller than the pipe buffer, but there is currently 
  2512.       not enough room in the buffer, DosWrite returns with a value of 0 in the 
  2513.       Bytes-Written parameter. 
  2514.  
  2515.  If a byte pipe is in nonblocking mode, and if there is more data to be written 
  2516.  than will fit in the pipe buffer, then DosWrite writes as many bytes as will 
  2517.  fit in the buffer and returns the number of bytes that were actually written. 
  2518.  
  2519.  If a process tries to write to a pipe whose other end is closed, 
  2520.  ERROR_BROKEN_PIPE is returned. 
  2521.  
  2522.  
  2523. ΓòÉΓòÉΓòÉ 4.3.5. Synchronizing Named Pipe Dialogs ΓòÉΓòÉΓòÉ
  2524.  
  2525. Communicating processes can synchronize their named pipe dialogs by calling 
  2526. DosResetBuffer after each call to DosWrite. 
  2527.  
  2528. When used with external files, DosResetBuffer flushes the buffer cache of the 
  2529. requesting process to disk. When used with named pipes, this function blocks 
  2530. the calling process at one end of the pipe until the data the calling process 
  2531. has written to the pipe has been successfully read at the other end of the 
  2532. pipe. 
  2533.  
  2534.  
  2535. ΓòÉΓòÉΓòÉ 4.3.6. Determining Pipe Status ΓòÉΓòÉΓòÉ
  2536.  
  2537. DosQueryNPHState and DosQueryNPipeInfo can be used to obtain information about 
  2538. named pipes. 
  2539.  
  2540. DosQueryNPHState 
  2541. A client process can read data from the pipe, write data to the pipe, or both, 
  2542. depending on the access mode specified when the pipe was created. To check the 
  2543. current access mode, the client process can call DosQueryNPHState. 
  2544.  
  2545. The following code fragment shows how to use DosQueryNPHState to obtain 
  2546. information about a named pipe: 
  2547.  
  2548.     #define INCL_DOSNMPIPES   /* Named-pipe values */
  2549.     #include <os2.h>
  2550.     #include <stdio.h>
  2551.  
  2552.     HPIPE    Handle;            /* Pipe handle       */
  2553.     ULONG    PipeHandleState;   /* Pipe-handle state */
  2554.     APIRET   rc;                /* Return code       */
  2555.  
  2556.     rc = DosQueryNPHState(Handle, &PipeHandleState);
  2557.  
  2558.     if (rc != 0) {
  2559.         printf("DosQueryNPHState error: return code = %ld", rc);
  2560.         return;
  2561.     }
  2562.  
  2563. On successful return, PipeHandleState will contain information that describes 
  2564. the nature of the named pipe. 
  2565.  
  2566. DosQueryNPHState returns the following information about the pipe handle and 
  2567. the attributes of the pipe: 
  2568.  
  2569.    o  The end of the pipe that the handle is for (server or client end) 
  2570.  
  2571.    o  The pipe type (byte pipe or message pipe) 
  2572.  
  2573.    o  The instance count 
  2574.  
  2575.    o  The blocking mode (blocking or nonblocking) 
  2576.  
  2577.    o  The read mode (byte-read mode or message-read mode) 
  2578.  
  2579.  The values for pipe type and instance count cannot be changed, so they are 
  2580.  always the same as those that were specified when the pipe was created with 
  2581.  DosCreateNPipe. The information returned for blocking mode and read mode, 
  2582.  however, can come from different sources: 
  2583.  
  2584.    o  If the handle is for the server end of the pipe, then the blocking mode 
  2585.       and the read mode were set with DosCreateNPipe, but could have been reset 
  2586.       with DosSetNPHState. 
  2587.  
  2588.    o  If the handle is for the client end of the pipe, then the blocking mode 
  2589.       and the read mode were set to "blocking" and "byte-read" by the system 
  2590.       when the client called DosOpen. However, again, they could have been 
  2591.       reset with DosSetNPHState. 
  2592.  
  2593.  The pipe attributes are described in more detail in Creating Named Pipes. 
  2594.  
  2595.  An application can use DosSetNPHState to change the wait mode and the read 
  2596.  mode. The pipe cannot be changed to no-wait mode when another thread is 
  2597.  blocked on a read or write operation to the same end of the pipe. 
  2598.  
  2599.  DosQueryNPipeInfo 
  2600.  More detailed information about a named pipe can be obtained by using 
  2601.  DosQueryNPipeInfo. This function returns information in a PIPEINFO data 
  2602.  structure that includes the name of the pipe, the current and maximum instance 
  2603.  counts (the current number of pipes and the maximum number of times the pipe 
  2604.  can be created), the size of the input and output buffers for the pipe, and 
  2605.  the pipe identifier of the client process. 
  2606.  
  2607.  The following code fragment shows how to use DosQueryNPipeInfo: 
  2608.  
  2609.       #define INCL_DOSNMPIPES   /* Named-pipe values */
  2610.       #include <os2.h>
  2611.       #include <stdio.h>
  2612.  
  2613.       HPIPE    Handle;          /* Pipe handle                     */
  2614.       ULONG    InfoLevel;       /* Pipe data required              */
  2615.       PIPEINFO InfoBuf;         /* Pipe information data structure */
  2616.       ULONG    InfoBufSize;     /* Pipe data-buffer size           */
  2617.       APIRET   rc;              /* Return code                     */
  2618.  
  2619.       InfoLevel = 1;                    /* Ask for standard level of pipe info */
  2620.  
  2621.       InfoBufSize = sizeof(PIPEINFO);   /* Length of pipe info data structure  */
  2622.  
  2623.       rc = DosQueryNPipeInfo(Handle, InfoLevel, &InfoBuf, InfoBufSize);
  2624.  
  2625.       if (rc != 0) {
  2626.           printf("DosQueryNPipeInfo error: return code = %ld", rc);
  2627.           return;
  2628.       }
  2629.  
  2630.  On successful return, the pipe information data structure contains a set of 
  2631.  information describing the nature and the current state of the named pipe. 
  2632.  
  2633.  DosQueryNPipeInfo returns level 1 or level 2 file information for the pipe. 
  2634.  Level 1 information includes the following: 
  2635.  
  2636.    o  The actual sizes of the in-buffer and out-buffer 
  2637.    o  The maximum number of pipe instances permitted 
  2638.    o  The current number of pipe instances 
  2639.    o  The length of the pipe name 
  2640.    o  The ASCIIZ name of the pipe, including \\ComputerName if the pipe is in a 
  2641.       remote computer system. 
  2642.  
  2643.       Level 2 information consists of a unique 2-byte identifier for each of 
  2644.       the pipe's client processes. 
  2645.  
  2646.  
  2647. ΓòÉΓòÉΓòÉ 4.3.7. Examining the Contents of Named Pipes ΓòÉΓòÉΓòÉ
  2648.  
  2649. DosPeekNPipe examines the current contents of a named pipe. It is similar to 
  2650. DosRead, except that DosPeekNPipe does not remove data from the pipe. In 
  2651. addition, DosPeekNPipe never blocks, even if the pipe is in blocking mode; if 
  2652. the pipe cannot be accessed immediately, ERROR_PIPE_BUSY is returned. 
  2653.  
  2654. Because DosPeekNPipe does not block, it returns only what is currently in the 
  2655. pipe. Thus, if a message pipe is being examined, only a portion of a message 
  2656. might be returned, even though the specified buffer length could accommodate 
  2657. the entire message. 
  2658.  
  2659. DosPeekNPipe also returns the state of the pipe. A named pipe can be in any of 
  2660. the following states: Connected, Disconnected, Listening, Closing. 
  2661.  
  2662. The following code fragment shows how to use DosPeekNPipe: 
  2663.  
  2664.     #define INCL_DOSNMPIPES   /* Named-pipe values */
  2665.     #include <os2.h>
  2666.     #include <stdio.h>
  2667.  
  2668.     HPIPE              Handle;      /* Pipe handle                */
  2669.     UCHAR              Buffer[200]; /* Address of user buffer     */
  2670.     ULONG              BufferLen;   /* Buffer length              */
  2671.     ULONG              BytesRead;   /* Bytes read (returned)      */
  2672.     struct _AVAILDATA  BytesAvail;  /* Bytes available (returned) */
  2673.     ULONG              PipeState;   /* Pipe state (returned)      */
  2674.     APIRET             rc;          /* Return code                */
  2675.  
  2676.     BufferLen = 200;  /* Length of the read buffer */
  2677.  
  2678.     rc = DosPeekNPipe(Handle, Buffer, BufferLen,
  2679.                       &BytesRead, &BytesAvail, &PipeState);
  2680.  
  2681.     if (rc != 0) {
  2682.         printf("DosPeekNPipe error: return code = %ld", rc);
  2683.         return;
  2684.     }
  2685.  
  2686. On successful return, the input buffer Buffer will contain up to the first 200 
  2687. bytes from the named pipe, BytesRead will contain the number of bytes read into 
  2688. Buffer, BytesAvail will contain the total number of bytes that were available 
  2689. in the pipe, and PipeState will contain a value indicating the state of the 
  2690. named pipe. 
  2691.  
  2692.  
  2693. ΓòÉΓòÉΓòÉ 4.3.8. Closing Named Pipes ΓòÉΓòÉΓòÉ
  2694.  
  2695. DosClose closes the specified pipe handle. When all of the handles that access 
  2696. one end of a pipe have been closed, the pipe is referred to as a broken pipe. 
  2697.  
  2698. If the client end of the pipe closes, no other process can reopen the pipe 
  2699. until the server calls DosDisConnectNPipe (to acknowledge the client's close) 
  2700. followed by DosConnectNPipe (to prepare the pipe for a new client). Until it 
  2701. calls DosDisConnectNPipe, the server will receive ERROR_EOF if it tries to read 
  2702. from the pipe, and ERROR_BROKEN_PIPE if it tries to write to it. Clients that 
  2703. attempt to open the pipe receive ERROR_PIPE_BUSY. 
  2704.  
  2705. If the server end closes when the client end is already closed, the pipe is 
  2706. deallocated immediately; otherwise, the pipe is not deallocated until the last 
  2707. client handle is closed. 
  2708.  
  2709. The following code fragment shows how to close a named pipe.  Assume that a 
  2710. previous call to DosOpen provided the named pipe handle that is contained in 
  2711. Handle. 
  2712.  
  2713.     #define INCL_DOSNMPIPES   /* Named-pipe values */
  2714.     #include <os2.h>
  2715.     #include <stdio.h>
  2716.  
  2717.     HPIPE   Handle;      /* Pipe handle */
  2718.     APIRET  rc;          /* Return code */
  2719.  
  2720.     rc = DosDisConnectNPipe(Handle);
  2721.  
  2722.     if (rc != 0) {
  2723.         printf("DosDisConnectNPipe error: return code = %ld", rc);
  2724.         return;
  2725.     }
  2726.  
  2727.  
  2728. ΓòÉΓòÉΓòÉ 5. Program Execution Control ΓòÉΓòÉΓòÉ
  2729.  
  2730. Multitasking is the ability of the operating system to manage the execution of 
  2731. more than one application at a time. A multitasking operating system, such as 
  2732. OS/2, enables users to run many applications simultaneously. 
  2733.  
  2734. For the programmer, the OS/2 operating system supports two types of 
  2735. multitasking. An application can start other programs, in separate processes, 
  2736. that will execute concurrently with the application. These programs can be a 
  2737. new copy of the application, a related program that is designed to work with 
  2738. the application, or an unrelated program. Running multiple processes is the 
  2739. first type of multitasking provided for programmers. 
  2740.  
  2741. Running multiple threads is the second type of multitasking supported by the 
  2742. OS/2 operating system. The OS/2 operating system enables applications to run 
  2743. multiple threads of execution within the same process; separate activities can 
  2744. be multitasked within the application. An example of multiple-thread 
  2745. multitasking would be for the application to dispatch a separate subroutine to 
  2746. load a file from the disk, and have the subroutine execute at the same time the 
  2747. main program continues to monitor and respond to user input. 
  2748.  
  2749. This chapter describes processes, threads, and sessions, and the OS/2 functions 
  2750. used to create and manage them. Additionally, there is a section describing CPU 
  2751. scheduling. 
  2752.  
  2753. The following topics are related to the information in this chapter: 
  2754.  
  2755.    o  Memory 
  2756.    o  Semaphores 
  2757.    o  Queues 
  2758.    o  Pipes 
  2759.    o  Exception Handling 
  2760.    o  Debugging 
  2761.  
  2762.  
  2763. ΓòÉΓòÉΓòÉ 5.1. About Program Execution Control-Thread, Processes, and Sessions ΓòÉΓòÉΓòÉ
  2764.  
  2765. To successfully use multitasking-multiple processes and multiple threads-in 
  2766. your programs, you need to understand the difference between a thread, a 
  2767. process, and a session. 
  2768.  
  2769. A thread is a dispatchable unit of execution that consists of a set of 
  2770. instructions, related CPU register values, and a stack. Each process has at 
  2771. least one thread, called the main thread or thread 1, and can have many threads 
  2772. running simultaneously. The application runs when the operating system gives 
  2773. control to a thread in the process. The thread is the basic unit of execution 
  2774. scheduling. 
  2775.  
  2776. A process is the code, data, and other resources-such as file handles, 
  2777. semaphores, pipes, queues, and so on-of an application in memory. The OS/2 
  2778. operating system considers every application it loads to be a process. System 
  2779. resources are allocated on a per-process basis. 
  2780.  
  2781. A session is one (or more) processes with their own virtual console. (A virtual 
  2782. console is a virtual screen-either a character-based, full screen or a 
  2783. Presentation Manager window-and buffers for keyboard and mouse input.) 
  2784.  
  2785. The OS/2 operating system supports up to 255 concurrent sessions and up to 4095 
  2786. processes. The operating system supports a system-wide maximum of 4095 threads, 
  2787. but the number of threads available in a single process will be lower, and will 
  2788. vary, because of resource usage within the process. 
  2789.  
  2790.  
  2791. ΓòÉΓòÉΓòÉ 5.1.1. Threads ΓòÉΓòÉΓòÉ
  2792.  
  2793. Applications always have at least one thread of execution-thread 1. Using 
  2794. multiple threads of execution, an application can do several things at the same 
  2795. time. 
  2796.  
  2797. For example, a simple Presentation Manager application consists of a single 
  2798. process with two threads: 
  2799.  
  2800.    o  A user interface thread that listens and responds to user requests, and 
  2801.       that queues work for the second thread 
  2802.  
  2803.    o  A processing thread that handles lengthy processing 
  2804.  
  2805.  The operating system creates the first thread of execution for a process when 
  2806.  it starts the executable file. To create another thread of execution, a thread 
  2807.  calls DosCreateThread, specifying the address within the program module where 
  2808.  the thread begins asynchronous execution. Although a thread can execute any 
  2809.  part of the application, including a part being executed by another thread, 
  2810.  threads typically are used to execute separate sections of the application. By 
  2811.  using several threads, the system can distribute the available CPU time and 
  2812.  enable an application to carry out several tasks simultaneously. For example, 
  2813.  an application can load a file and prompt the user for input at the same time. 
  2814.  
  2815.  Each thread in a process has a unique stack and register context. Threads 
  2816.  shares the resources of the process with the other threads in the process. For 
  2817.  example, threads in the same process have access to the memory spaces of other 
  2818.  threads within the process. However, threads of one process do not have access 
  2819.  to the data spaces of other processes. 
  2820.  
  2821.  Each thread has a priority, that determines the amount of CPU time the thread 
  2822.  is allocated. Threads inherit the priority of the thread that creates them. 
  2823.  The priority of a thread can be changed by the application; see Changing the 
  2824.  Priority of a Thread for details. 
  2825.  
  2826.  An application can use DosSuspendThread and DosResumeThread to suspend and 
  2827.  resume the execution of a given thread. When an application suspends a thread, 
  2828.  the thread remains suspended until the application calls DosResumeThread. 
  2829.  
  2830.  When an application has more than one thread, it might be necessary to ensure 
  2831.  that one thread is finished executing before another thread uses a shared 
  2832.  resource, such as a disk file. DosWaitThread causes the application to wait 
  2833.  until a specific thread has finished. DosWaitThread can also be used to 
  2834.  determine the state of a thread; the function can return immediately with an 
  2835.  error value if the identified thread is still running. 
  2836.  
  2837.  A thread ends when it calls DosExit. 
  2838.  
  2839.  
  2840. ΓòÉΓòÉΓòÉ 5.1.2. Processes ΓòÉΓòÉΓòÉ
  2841.  
  2842. An OS/2 application that has been loaded into memory and prepared for execution 
  2843. is called a process. As mentioned earlier, a process consists of the code, 
  2844. data, and other resources (for example, open file handles) that belong to the 
  2845. application. Each process has at least one thread, called the main thread or 
  2846. thread 1. 
  2847.  
  2848. When the operating system executes an application, it confirms that the process 
  2849. code and data are in memory and that the main thread's registers and stack are 
  2850. set before starting the application. Each application has access to all 
  2851. resources of the computer, such as memory, disk drives, screen, keyboard, and 
  2852. the CPU itself. The system carefully manages these resources so that 
  2853. applications can access them without conflict. 
  2854.  
  2855. A process can have more than one thread. The operating system creates the first 
  2856. thread of execution for a process when it starts the executable file. More 
  2857. threads can be created with DosCreateThread. Each thread runs independently, 
  2858. with its own stack and register values. Unless the application changes a 
  2859. thread's priority, each thread gets a slice of the CPU in a round-robin 
  2860. strategy. All the threads in a process share the application's globally defined 
  2861. variables and other resources (open file handles, and so on). 
  2862.  
  2863. A process or thread ends when it calls DosExit. The operating system 
  2864. automatically closes any files or other resources left open by the process when 
  2865. the process ends. When a thread ends, however, any open resources remain open 
  2866. until another thread closes them or the process ends. A process can direct the 
  2867. operating system to carry out other actions when the process ends, by using 
  2868. DosExitList to create a list of termination functions. The operating system 
  2869. calls the termination functions, in the order given, when the process is about 
  2870. to end. If the thread has registered any exception handlers, the exception 
  2871. handlers will also be called before the thread terminates. 
  2872.  
  2873.  
  2874. ΓòÉΓòÉΓòÉ 5.1.2.1. Creating Processes ΓòÉΓòÉΓòÉ
  2875.  
  2876. An application can load and execute other applications by using DosExecPgm. The 
  2877. new application, once loaded, is called a child process. The process that 
  2878. starts the new application is called the parent process. 
  2879.  
  2880. A child process is like any other process. It has its own code, data, and 
  2881. threads. The child process inherits the resources-such as file handles, pipes, 
  2882. and queues-that belong to the parent process at the time the child process is 
  2883. created, although not necessarily with the same access rights. The parent 
  2884. process can place restrictions on the access of the child process to these 
  2885. resources: 
  2886.  
  2887.    o  Files are inherited except for files that were opened with no inheritance 
  2888.       indicated. 
  2889.  
  2890.    o  Pipes are inherited. 
  2891.  
  2892.  Assuming that the parent process gives the child process appropriate access 
  2893.  rights, the child process can use the inherited resources without preparing 
  2894.  them. For example, if the parent process opens a file for reading and then 
  2895.  starts a child process, the child process can read from the file immediately; 
  2896.  it does not have to open the file. However, once the child process is created 
  2897.  additional resources that the parent process creates are not available to the 
  2898.  child process. Similarly, resources the child process creates are not 
  2899.  available to the parent process. 
  2900.  
  2901.  The parent process also has control over the meanings of standard input, 
  2902.  output, and error for the child process. For example, the parent can write a 
  2903.  series of records to a file, open the file as standard input, open a listing 
  2904.  file as standard output, and then execute a sort program that takes its input 
  2905.  from standard input and writes to standard output. 
  2906.  
  2907.  Note that memory is not included in the list of things that a child process 
  2908.  can inherit from its parent process. The child process is created with its own 
  2909.  process address space that is separate and distinct from the memory of the 
  2910.  parent process. A new linear address space is built for the new process. The 
  2911.  only way for a parent process and a child process to access the same memory is 
  2912.  to set up a shared memory area. 
  2913.  
  2914.  The executable file of the child process can be started either synchronously 
  2915.  or asynchronously to the parent process. If the parent process starts the 
  2916.  child process running synchronously, the parent process is suspended and waits 
  2917.  until the child process ends before continuing. A child process running 
  2918.  asynchronously executes independently of the parent process (that is, both run 
  2919.  at the same time). The parent process specifies how the child process is to 
  2920.  run by setting a parameter in the call to DosExecPgm. 
  2921.  
  2922.  The OS/2 command processor, CMD.EXE, starts most child processes 
  2923.  synchronously. The parent process waits for each child process to end before 
  2924.  it prompts the user for the next command. The command processor also enables 
  2925.  the user to start asynchronous applications by using the DETACH command. When 
  2926.  the user detaches an application, the command processor starts the application 
  2927.  asynchronously, in the background, and continues to prompt for input. 
  2928.  
  2929.  
  2930. ΓòÉΓòÉΓòÉ 5.1.2.2. Process Termination ΓòÉΓòÉΓòÉ
  2931.  
  2932. A parent process can use DosWaitChild to determine the termination status of a 
  2933. child process that is running independently. The parent process can have one of 
  2934. its threads call DosWaitChild to wait for completion of the child process while 
  2935. other threads of the parent continue processing. 
  2936.  
  2937. If the child has started another process, DosWaitChild waits for the completion 
  2938. of any grandchild processes before returning, but does not report their status. 
  2939. If the specified child process has multiple threads, DosWaitChild returns the 
  2940. result code of the last DosExit request. 
  2941.  
  2942. If there are no child processes, either active or ended with a return code, 
  2943. DosWaitChild returns with an error code. If no child processes have terminated, 
  2944. DosWaitChild can optionally wait until one terminates before returning to the 
  2945. parent. 
  2946.  
  2947.  
  2948. ΓòÉΓòÉΓòÉ 5.1.2.3. Process Exit Lists ΓòÉΓòÉΓòÉ
  2949.  
  2950. Because any process can terminate any other process for which it has a process 
  2951. identifier, applications might lose information if a process terminates the 
  2952. application before it can save its work. To prevent this loss of data, you can 
  2953. create a list of functions to clean up data and files before the operating 
  2954. system terminates the process. This list is called an exit list. The operating 
  2955. system maintains an exit list for each process and calls these functions 
  2956. whenever the application is terminated, whether by another process or by 
  2957. itself. 
  2958.  
  2959. You call DosExitList to add to the exit list a routine that is to be given 
  2960. control when a process is terminated (or finishes its execution). Multiple 
  2961. routines can be added to the list. When the process is terminating, the 
  2962. operating system transfers control to each address on the list. 
  2963.  
  2964. Exit-list functions perform clean-up operations on resources. For example, an 
  2965. exit-list function can be used in a dynamic link library module to free 
  2966. resources or clear flags and semaphores when a client program has ended. 
  2967.  
  2968.  
  2969. ΓòÉΓòÉΓòÉ 5.1.3. Multitasking with Threads and Multitasking with Processes ΓòÉΓòÉΓòÉ
  2970.  
  2971. The creation and termination of a process is relatively slow compared to the 
  2972. creation and termination of a thread, and is more costly in terms of system 
  2973. resources. 
  2974.  
  2975. For example, sharing data and resources between processes requires shared 
  2976. memory and the mechanisms of interprocess communication; threads, on the other 
  2977. hand, have full access to the memory and other resources that belong to the 
  2978. process the threads are part of and can be coordinated using semaphores. For 
  2979. these reasons, thread-to-thread task context switches are faster than 
  2980. process-to-process context switches. 
  2981.  
  2982. Because the operating system can create and execute threads more quickly than 
  2983. processes, the preferred multitasking method for applications is to distribute 
  2984. tasks among threads in the same process instead of among processes. 
  2985.  
  2986.  
  2987. ΓòÉΓòÉΓòÉ 5.1.4. Sessions ΓòÉΓòÉΓòÉ
  2988.  
  2989. The OS/2 operating system uses sessions to help the user move from one 
  2990. application to the next without disrupting the screen display of an 
  2991. application. 
  2992.  
  2993. A session consists of at least one process and a virtual console-buffers for 
  2994. keyboard and mouse input and either a character-based, full screen or a 
  2995. Presentation Manager window. When the system creates a session, the process in 
  2996. the session displays output in the screen or window. The user can view the 
  2997. output and supply input by moving to the session. The user moves to a session 
  2998. by pressing the Alt+Esc key combination, by selecting the title of the session 
  2999. from the Window List, or, for windowed sessions, by clicking the mouse in the 
  3000. session window. 
  3001.  
  3002. A child session is under the control of the session that creates it. The 
  3003. session that starts the child session is called the parent session. Any process 
  3004. in the parent session can exercise control over a child session. 
  3005.  
  3006. An unrelated session is not under the control of the session that started it. 
  3007. The process that creates the unrelated session cannot select it, make it 
  3008. nonselectable, bind it, or terminate it, nor can any other session. 
  3009. DosStartSession does not even return a session identifier when an unrelated 
  3010. session is started. Unrelated sessions are controlled entirely by the user. 
  3011. When the operating system starts new sessions, it starts them as unrelated 
  3012. sessions. 
  3013.  
  3014.  
  3015. ΓòÉΓòÉΓòÉ 5.1.4.1. Creating Sessions ΓòÉΓòÉΓòÉ
  3016.  
  3017. A process creates a new session by using DosStartSession. DosStartSession 
  3018. enables an application to start another session and to specify the name of the 
  3019. application to be started in that session. 
  3020.  
  3021. DosStartSession also specifies which of the five session types is to be 
  3022. started: 
  3023.  
  3024.    o  Full screen, protect mode 
  3025.    o  Text windowed, protect mode 
  3026.    o  Presentation Manager (PM) 
  3027.    o  Full screen DOS Session 
  3028.    o  Windowed DOS Session 
  3029.  Protect mode applications run in full screen and text windowed sessions, PM 
  3030.  and AVIO applications run in PM windows, and DOS applications run in full 
  3031.  screen DOS Sessions and windowed DOS Sessions. 
  3032.  
  3033.  OS/2 applications running in any of the OS/2 session types-full screen, text 
  3034.  windowed, and PM-can start sessions of any other type, including DOS Sessions. 
  3035.  DOS Session applications cannot start other sessions. 
  3036.  
  3037.  An application can start another process in a separate session when the 
  3038.  application will not manage any I/O done by the process. For example, an 
  3039.  application that starts an unrelated application could start it in a separate 
  3040.  session. 
  3041.  
  3042.  A session can be started as a related or an unrelated session. A related 
  3043.  session is called a child session, and the session starting the child session 
  3044.  is called the parent session. An application can control its child sessions by 
  3045.  using the session identifier returned by DosStartSession with the 
  3046.  DosSetSession, DosSelectSession, and DosStopSession. If an application starts 
  3047.  an unrelated session, the new session cannot be controlled by the application. 
  3048.  The Related field in the STARTDATA structure specifies whether the new session 
  3049.  is related to the session calling DosStartSession. 
  3050.  
  3051.  After a process has started a child session, no other process in its session 
  3052.  can start a child session until all dependent sessions started by this process 
  3053.  have ended. 
  3054.  
  3055.  When a session is created, the title specified in the function call (or the 
  3056.  application name if no title is specified) is added to the Window List. 
  3057.  
  3058.  DosStartSession can be used to start either a foreground or a background 
  3059.  session, but a new session can be started in the foreground only when the 
  3060.  caller's session, or one of the caller's descendant sessions, is currently 
  3061.  executing in the foreground. The foreground session for windowed applications 
  3062.  is the session of the application that owns the window focus. 
  3063.  
  3064.  Termination Queues 
  3065.  The parent session must create a termination queue prior to specifying the 
  3066.  queue name in a call to DosStartSession. The operating system will continue to 
  3067.  notify the parent session through the specified queue as long as the session 
  3068.  calling DosStartSession remains a parent session. In other words, when all the 
  3069.  child sessions for a particular parent session terminate, the termination 
  3070.  queue is closed by the operating system. An existing queue name must be 
  3071.  specified on the next DosStartSession call if the caller wants to continue 
  3072.  receiving termination notification messages. 
  3073.  
  3074.  The operating system writes a data element to the specified queue when any 
  3075.  child session terminates. The queue is posted regardless or who terminates the 
  3076.  child session (the child, the parent, or the user) and whether the termination 
  3077.  is normal or abnormal. 
  3078.  
  3079.  A parent session calls DosReadQueue to receive notification when a child 
  3080.  session has terminated. The word that contains the request parameter, returned 
  3081.  by DosReadQueue, will be 0. The data element has the following format: 
  3082.  
  3083.  Termination Queue Element Format 
  3084.  
  3085.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  3086.   ΓöéSize      ΓöéDescription                                       Γöé
  3087.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3088.   ΓöéWORD      ΓöéSession ID of the child session that terminated   Γöé
  3089.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3090.   ΓöéWORD      ΓöéResult code                                       Γöé
  3091.   ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  3092.  
  3093.  The process that originally called the DosStartSession request should call 
  3094.  DosReadQueue, with the NOWAIT parameter set to 0. This is the only process 
  3095.  that has addressability to the notification data element. After reading and 
  3096.  processing the data element, the caller must free the segment containing the 
  3097.  data element by calling DosFreeMem. 
  3098.  
  3099.  When a child session terminates, the result code returned in the termination 
  3100.  queue's data element is the result code of the program specified in the 
  3101.  DosStartSession call, providing 
  3102.  
  3103.    o  the program was executed directly, with no intermediate secondary command 
  3104.       processor, or 
  3105.    o  the program is executed indirectly through a secondary command processor, 
  3106.       and the /C parameter is specified. 
  3107.  
  3108.  When a child session is running in the foreground at the time it terminates, 
  3109.  the parent session becomes the new foreground session. When a parent session 
  3110.  terminates, any child sessions are terminated. When an unrelated session 
  3111.  terminates in the foreground, the operating system selects the next foreground 
  3112.  session. 
  3113.  
  3114.  
  3115. ΓòÉΓòÉΓòÉ 5.1.4.2. Child Session Control ΓòÉΓòÉΓòÉ
  3116.  
  3117. A session can be either a child session or an unrelated session. A child 
  3118. session is under the control of the processes in the session that creates it 
  3119. (the parent session). A process can select, set, or stop a child session by 
  3120. using DosSelectSession, DosSetSession, or DosStopSession, respectively. 
  3121. DosStartSession returns a unique session identifier for the child session for 
  3122. use in these functions. 
  3123.  
  3124. A session can run in either the foreground or background. A process can create 
  3125. a foreground session only if the creating process or one of its descendant 
  3126. sessions is executing in the current foreground session. A process can move a 
  3127. child session to the foreground by selecting the child session using the 
  3128. session identifier and calling DosSelectSession. A process can make a child 
  3129. session nonselectable by using DosSetSession to change the SelectInd field in 
  3130. the STATUSDATA structure. This prevents the user from selecting the session 
  3131. from the Window List but does not prevent a process from selecting the child 
  3132. session by using DosSelectSession. 
  3133.  
  3134. A process can bind a child session to its own session by using DosSetSession. 
  3135. Binding a session causes that session to move to the foreground whenever the 
  3136. user selects the parent session from the Window List. 
  3137.  
  3138. A parent session can use a session identifier with the DosSetSession function 
  3139. only if the parent session created the child session associated with that 
  3140. identifier. It cannot use identifiers for child sessions created by other 
  3141. parent processes. This is true for all session management functions. 
  3142.  
  3143. Although a child session is related to the session that started it, the 
  3144. processes in the child and original sessions are not related. This means that 
  3145. even though DosStartSession supplies the process identifier of the process in 
  3146. the child session, the process identifier cannot be used with OS/2 functions 
  3147. such as DosSetPriority. 
  3148.  
  3149.  
  3150. ΓòÉΓòÉΓòÉ 5.1.4.3. Child Session Termination ΓòÉΓòÉΓòÉ
  3151.  
  3152. A parent session can stop a child session by using DosStopSession. Stopping the 
  3153. child session terminates the processes in that session. It also stops any 
  3154. sessions related to the child session. If a child session is in the foreground 
  3155. when it is stopped, the parent session becomes the foreground session. 
  3156. DosStopSession breaks any bond that exists between the parent session and the 
  3157. specified child session. 
  3158.  
  3159. A process running in the session specified in the call to DosStopSession can 
  3160. ignore the request to terminate. If this happens, DosStopSession still returns 
  3161. 0 (indicating success). The only way to be certain that the child session has 
  3162. terminated is to wait for notification through the termination queue specified 
  3163. in the call to DosStartSession. The operating system writes a data element into 
  3164. the specified queue when the child session terminates. The process in the 
  3165. parent session must call DosReadQueue to retrieve this data element, which 
  3166. contains the session identifier for the child session and the return value for 
  3167. the process in the child session. Only the process that created the child 
  3168. session can read the data element. 
  3169.  
  3170.  
  3171. ΓòÉΓòÉΓòÉ 5.2. About CPU Scheduling ΓòÉΓòÉΓòÉ
  3172.  
  3173. The OS/2 operating system performs prioritized, preemptive, multitasking. 
  3174. Prioritized means that the operating system does not divide CPU time equally 
  3175. among all threads. All programs do not get equal access to the CPU. A 
  3176. prioritizing, time-slicing strategy is used to allocate access to the CPU among 
  3177. competing threads. Each thread has a priority and the operating system runs the 
  3178. highest priority thread that is ready to run. Programs with higher priorities 
  3179. (a real-time robotic application, for example), are given access to the CPU 
  3180. before programs with lower priorities. If a thread with a higher priority than 
  3181. the currently running thread becomes ready to run, the current thread is 
  3182. stopped immediately, or preempted, and the higher priority thread is given the 
  3183. CPU. The lower priority thread does not get to complete its time slice. Threads 
  3184. of equal priority are given CPU time in a round-robin manner. 
  3185.  
  3186. Preemptive means that the multitasking activity needs no cooperation from the 
  3187. executing programs. The operating system maintains control over executing 
  3188. programs, and stops, or preempts, them when their time slice with the CPU is 
  3189. over or when a higher priority program is ready to run. 
  3190.  
  3191. CPU scheduling is based on four priority classes-Time Critical, Fixed-High, 
  3192. Regular, and Idle-Time. Each class has 32 levels of execution ordering. 
  3193. Scheduling parameters are user-selectable at the time the system is started or 
  3194. can be varied dynamically based on system load. 
  3195.  
  3196. Depending on a thread's priority class and level, the operating system 
  3197. periodically gives each thread in each process a small slice of CPU time. 
  3198. Threads with higher priorities always run before threads having lower 
  3199. priorities. A thread runs until its time is up or until a thread with a higher 
  3200. priority is ready to run. At that time, the operating system preempts the 
  3201. thread and starts another thread. Threads can also voluntarily relinquish the 
  3202. CPU (for example, by calling DosSleep). 
  3203.  
  3204. The amount of time in each time slice is defined by the TIMESLICE command in 
  3205. the CONFIG.SYS file. The TIMESLICE command can be used by the user to customize 
  3206. the size of the time slices that a thread gets. The default is for the 
  3207. operating system to dynamically vary the size of the time slice based on the 
  3208. activity of the thread and the overall system load. 
  3209.  
  3210. When a thread is created (using DosCreateThread), it inherits the priority of 
  3211. the thread that started it. DosSetPriority enables threads to change their 
  3212. priority classes and levels in response to changes in their execution 
  3213. environments. DosSetPriority enables a thread to change its own priority, or 
  3214. the priority of any thread within its process. DosSetPriority also enables 
  3215. changing priorities for the entire process and for descendant processes. Within 
  3216. each class, the priority level of a thread can vary because of a DosSetPriorty 
  3217. request or, if dynamic priority variation is being used, because of action 
  3218. taken by the operating system. 
  3219.  
  3220.  
  3221. ΓòÉΓòÉΓòÉ 5.2.1. Priority Classes ΓòÉΓòÉΓòÉ
  3222.  
  3223. The operating system uses four priority classes to determine when a thread 
  3224. receives a time slice: 
  3225.  
  3226. Priority Classes 
  3227.  
  3228. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  3229. ΓöéPriority                      ΓöéDescription                   Γöé
  3230. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3231. ΓöéTime-critical                 ΓöéHighest priority.  For use    Γöé
  3232. Γöé                              Γöéwhen response time is         Γöé
  3233. Γöé                              Γöécritical.                     Γöé
  3234. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3235. ΓöéFixed-high                    ΓöéUsed by threads that provide  Γöé
  3236. Γöé                              Γöéservice to other threads. ThisΓöé
  3237. Γöé                              Γöépriority class is to be used  Γöé
  3238. Γöé                              Γöéwhen it is desirable that the Γöé
  3239. Γöé                              Γöéthread not be too sensitive toΓöé
  3240. Γöé                              Γöéthe foreground/background     Γöé
  3241. Γöé                              Γöéboost provided by dynamic     Γöé
  3242. Γöé                              Γöépriority variation. It is     Γöé
  3243. Γöé                              Γöémeant for programs that need  Γöé
  3244. Γöé                              Γöéto execute before regular     Γöé
  3245. Γöé                              Γöéprograms, but without the     Γöé
  3246. Γöé                              Γöéimmediate response time       Γöé
  3247. Γöé                              Γöérequirement called for by     Γöé
  3248. Γöé                              Γöétime-critical threads.        Γöé
  3249. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3250. ΓöéRegular                       ΓöéDefault priority.  Most       Γöé
  3251. Γöé                              Γöéthreads belong in this class. Γöé
  3252. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3253. ΓöéIdle-time                     ΓöéLowest priority.  This        Γöé
  3254. Γöé                              Γöépriority only gets CPU time   Γöé
  3255. Γöé                              Γöéwhen there is no other work toΓöé
  3256. Γöé                              Γöédo.                           Γöé
  3257. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  3258.  
  3259. A time-critical thread always receives a time slice before a fixed-high thread, 
  3260. a fixed-high thread always receives a time slice before a regular thread, and a 
  3261. regular thread always receives a time slice before an idle-time thread. 
  3262.  
  3263. Time-Critical Threads 
  3264. Time-critical threads have the highest priority class and execute before any 
  3265. fixed-high, regular, or idle-time threads. 
  3266.  
  3267. The time-critical class is for threads that must react to events outside the 
  3268. system. For example, in a communications application, a thread responsible for 
  3269. reading data from the communications device needs enough time to read all 
  3270. incoming data. Because more than a regular time slice might be needed, a 
  3271. time-critical classification ensures that the thread gets all the time 
  3272. required. 
  3273.  
  3274. Time-critical threads have a static priority that is not varied by the 
  3275. operating system. They are scheduled among themselves in priority level order, 
  3276. with round-robin scheduling of threads of equal priority. 
  3277.  
  3278. Time-critical threads must be executed quickly, then free the CPU for other 
  3279. work until another time-critical event occurs. This is important to maintain 
  3280. good interactive responsiveness to the user and enable communications and other 
  3281. time  critical applications to run concurrently. The time-critical activity 
  3282. should, when possible, be in a thread separate from the rest of the 
  3283. application, to isolate and minimize the time spent processing at the 
  3284. time-critical level. A good rule of thumb is that a time-critical thread should 
  3285. consist of no more than about 20,000 assembly language instructions. 
  3286.  
  3287. Fixed-High Threads 
  3288. A fixed-high thread has a priority class that is lower than time-critical but 
  3289. executes before any regular or idle-time threads. This class of threads should 
  3290. be used to provide service for other threads where it is desirable that the 
  3291. thread not be too sensitive to the foreground/background boost provided by 
  3292. dynamic priority variation. A messaging thread, would be a good example of this 
  3293. type of thread. 
  3294.  
  3295. The operating system varies the priority of a fixed-high thread around a base 
  3296. value according to the activity of the thread and the system at any point in 
  3297. time. The base value can be set by the thread itself. 
  3298.  
  3299. Regular Threads 
  3300. A regular thread is the class that the majority of threads fall into. No 
  3301. explicit action is necessary by the application to run at this priority, it is 
  3302. the default. 
  3303.  
  3304. The operating system varies the priority level of a regular thread around a 
  3305. base value according to the activity of the thread and the system at any point 
  3306. in time. The base value can be set by the thread itself. 
  3307.  
  3308. Idle-Time Threads 
  3309. An idle-time thread is one with very low priority that executes only when there 
  3310. are no regular, fixed-high, or time-critical threads to execute. Idle-time 
  3311. threads get CPU time only when there is no other work to do. The idle-time 
  3312. class is for threads that need very little CPU time. 
  3313.  
  3314. Idle-time threads have a static priority that is not varied by the operating 
  3315. system. 
  3316.  
  3317.  
  3318. ΓòÉΓòÉΓòÉ 5.2.2. Priority Levels ΓòÉΓòÉΓòÉ
  3319.  
  3320. Within each class, the operating system maintains a priority level for a 
  3321. thread. For each of the four priority classes, there are 32 priority levels-0 
  3322. to 31. A thread with priority level 31 always receives a time slice before a 
  3323. thread with priority level 30, and so on. 
  3324.  
  3325. If two or more threads have the same priority level, the operating system 
  3326. distributes the CPU time equally by using a round-robin scheme; that is, the 
  3327. operating system gives a time slice to first one, then another, and so on, and 
  3328. then goes back to the first. A thread can use DosSetPriority to change its own 
  3329. priority or the priority of any other thread within its process. 
  3330.  
  3331. Although an application can set the priority level of a thread at any time, 
  3332. only applications that use more than one thread or process should do so. The 
  3333. best use of priority is to speed up threads or processes on which other threads 
  3334. or processes depend. For example, an application might temporarily raise the 
  3335. priority of a thread loading a file if another thread is waiting for that file 
  3336. to be loaded. Because the priority of a thread is relative to all other threads 
  3337. in the system, raising the priority of the threads in an application merely to 
  3338. get the extra CPU time adversely affects the overall operation of the system. 
  3339.  
  3340. There are other ways to affect the amount of CPU time a thread is given. A 
  3341. thread can define a critical section of code by using DosEnterCritSec and 
  3342. DosExitCritSec. While inside the critical section of code, a thread cannot be 
  3343. preempted by any other thread within its process (threads in other processes 
  3344. are still given their time slices). Using critical sections enables threads to 
  3345. get more CPU time, while not unduly affecting the rest of the system. 
  3346.  
  3347. The priority class and priority level are set using DosSetPriority. The 
  3348. priority class is changed by passing the new priority class to the function. 
  3349. The priority level, however, is changed by passing a value, called the 
  3350. priority-delta, that is added to the existing priority level to produce the new 
  3351. priority level; changes to the priority level are relative to the current 
  3352. priority level. Specifying a positive priority-delta increases the priority 
  3353. level, enabling the thread to obtain more CPU time than it normally would. A 
  3354. negative priority-delta decreases the priority level, giving the thread less 
  3355. CPU time than it would normally receive. The value is restricted to the valid 
  3356. range, based upon the current priority class of the process. 
  3357.  
  3358. If you change the priority level without changing the priority class, the 
  3359. priority-delta is relative to the current priority level. However, if you 
  3360. change the priority class at the same time that you change the priority level, 
  3361. the priority-delta value is relative to 0. Whenever DosSetPriority is called 
  3362. with a class specification, but no value is specified for priority-delta, the 
  3363. base priority level defaults to 0. 
  3364.  
  3365. The process identifier parameter of DosSetPriority specifies which process is 
  3366. affected by the call. A process can change the priority of itself, of any 
  3367. process that is a descendant of itself, or of one of its threads. 
  3368.  
  3369. A thread can change the priority of any thread within its current process. When 
  3370. a thread changes the priority of threads in a descendant process, however, only 
  3371. those threads running at the default priority will be changed. You cannot 
  3372. change the priority of a thread in a child process that has already changed its 
  3373. priority from the default. 
  3374.  
  3375. The initial thread of execution for an application is given a regular class 
  3376. priority that varies by the system. When a thread is created, it is initially 
  3377. dispatched in the same class and priority as the thread that started it. A 
  3378. child process inherits the priority of the thread in the parent process that 
  3379. creates it. 
  3380.  
  3381.  
  3382. ΓòÉΓòÉΓòÉ 5.2.3. Priority Guidelines ΓòÉΓòÉΓòÉ
  3383.  
  3384. Within the two most common priority classes-time-critical and regular-there are 
  3385. certain broad guidelines recommended for choosing the priority level for a 
  3386. program. 
  3387.  
  3388.    o  TIME-CRITICAL CLASS 
  3389.  
  3390.       The guidelines for level within the time critical class are set to 
  3391.       maximize the number of different applications that can successfully 
  3392.       multitask in an OS/2 system. The guidelines are described in the 
  3393.       following table. 
  3394.  
  3395.       Recommended Priority Levels for Time-Critical Threads 
  3396.  
  3397.             ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  3398.             ΓöéActivity     ΓöéRange of    ΓöéJustification/Comments        Γöé
  3399.             Γöé             ΓöéRecommended Γöé                              Γöé
  3400.             Γöé             ΓöéPriority    Γöé                              Γöé
  3401.             Γöé             ΓöéLevels      Γöé                              Γöé
  3402.             Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3403.             ΓöéRobotics/RealΓöé20-31       ΓöéOS/2 systems can be used on   Γöé
  3404.             Γöétime process Γöé            Γöémanufacturing lines to controlΓöé
  3405.             Γöécontrol      Γöé            Γöéequipment or in other real    Γöé
  3406.             Γöé             Γöé            Γöétime process control          Γöé
  3407.             Γöé             Γöé            Γöéapplications. In this case a  Γöé
  3408.             Γöé             Γöé            Γöéslow response from the PC     Γöé
  3409.             Γöé             Γöé            Γöécould cause expensive damage  Γöé
  3410.             Γöé             Γöé            Γöéto equipment or even human    Γöé
  3411.             Γöé             Γöé            Γöéinjury. Therefore the highest Γöé
  3412.             Γöé             Γöé            Γöépriority levels should be     Γöé
  3413.             Γöé             Γöé            Γöéreserved for these            Γöé
  3414.             Γöé             Γöé            Γöéapplications.                 Γöé
  3415.             Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3416.             ΓöéCommunicationΓöé10-19       ΓöéIn communications, the        Γöé
  3417.             Γöé             Γöé            Γöéinability to get the processorΓöé
  3418.             Γöé             Γöé            Γöécould cause a loss of data or Γöé
  3419.             Γöé             Γöé            Γöécommunications sessions.      Γöé
  3420.             Γöé             Γöé            ΓöéTherefore this class of       Γöé
  3421.             Γöé             Γöé            Γöéapplications is next highest. Γöé
  3422.             Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3423.             ΓöéOther        Γöé0-09        ΓöéOther threads might need to   Γöé
  3424.             Γöé             Γöé            Γöépreempt the foreground in     Γöé
  3425.             Γöé             Γöé            Γöéspecial cases (for example,   Γöé
  3426.             Γöé             Γöé            ΓöéControl-Break). These should  Γöé
  3427.             Γöé             Γöé            Γöébe set below the other 2      Γöé
  3428.             Γöé             Γöé            Γöéclasses.                      Γöé
  3429.             ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  3430.  
  3431.       In general, application performance is not a good reason to make a thread 
  3432.       time critical. 
  3433.  
  3434.    o  REGULAR CLASS 
  3435.  
  3436.       In cases where explicit priority levels are set, they should follow the 
  3437.       guidelines listed below. 
  3438.  
  3439.       Recommended Priority Levels for Regular Priority Threads 
  3440.  
  3441.             ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  3442.             ΓöéActivity     ΓöéRange of    ΓöéJustification                 Γöé
  3443.             Γöé             ΓöéRecommended Γöé                              Γöé
  3444.             Γöé             ΓöéPriority    Γöé                              Γöé
  3445.             Γöé             ΓöéLevel       Γöé                              Γöé
  3446.             Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3447.             ΓöéCommunicationΓöé26-31       ΓöéCommunications should take    Γöé
  3448.             Γöé             Γöé            Γöépriority over other backgroundΓöé
  3449.             Γöé             Γöé            Γöéprocessing to increase overlapΓöé
  3450.             Γöé             Γöé            Γöéwith transmission and         Γöé
  3451.             Γöé             Γöé            Γöéprocessing on the partner PC  Γöé
  3452.             Γöé             Γöé            Γöéor host.  This gives the best Γöé
  3453.             Γöé             Γöé            Γöésystem performance.           Γöé
  3454.             Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3455.             ΓöéOther        Γöé0-25.       ΓöéIf an application has multipleΓöé
  3456.             Γöé             Γöé            Γöéthreads it might be necessary Γöé
  3457.             Γöé             Γöé            Γöéto set them to several        Γöé
  3458.             Γöé             Γöé            Γöédifferent priorities to       Γöé
  3459.             Γöé             Γöé            Γöéoptimize the order in which   Γöé
  3460.             Γöé             Γöé            Γöéthey run. A range of priority Γöé
  3461.             Γöé             Γöé            Γöélevels is provided to         Γöé
  3462.             Γöé             Γöé            Γöéfacilitate this. (The default Γöé
  3463.             Γöé             Γöé            Γöépriority is regular class,    Γöé
  3464.             Γöé             Γöé            Γöélevel = 0.)                   Γöé
  3465.             ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  3466.  
  3467.  
  3468. ΓòÉΓòÉΓòÉ 5.2.4. Dynamic Priority Alteration ΓòÉΓòÉΓòÉ
  3469.  
  3470. The operating system can be configured to dynamically alter the priority of a 
  3471. process. The PRIORITY statement in CONFIG.SYS can be set to either ABSOLUTE or 
  3472. DYNAMIC. If PRIORITY specifies the ABSOLUTE option, all processes receive CPU 
  3473. time based on the priority established by calls to DosSetPriority. If the 
  3474. PRIORITY command in the CONFIG.SYS file specifies the DYNAMIC option, the 
  3475. operating system adjusts process priorities based on system load and process 
  3476. activity, and on whether the process is in the foreground. DYNAMIC is the 
  3477. default setting; if the PRIORITY command is not specified, the system uses 
  3478. DYNAMIC priority. DYNAMIC is designed to gives the best overall system 
  3479. performance under most conditions. 
  3480.  
  3481. When dynamic priority variation is enabled, the operating system grants higher 
  3482. priority to the foreground process than to background processes. System load 
  3483. and process activity are also taken into consideration. The priority of the 
  3484. process consists of a computed priority value that is based upon the display 
  3485. status of the process (foreground or background), and its recent I/O and CPU 
  3486. time usage history. When dynamic priority variation is enabled, I/O priority 
  3487. boosts are generated for keyboard input, window, foreground, processor 
  3488. starvation, device I/O, and DOS Session interrupts. This ensures that the 
  3489. foreground process-the process most likely to be in use-receives enough CPU 
  3490. time to provide quick response to user input. 
  3491.  
  3492. There are times when dynamic priority variation can interfere with a 
  3493. multi-threaded application's execution.  For example, if you are doing a lot of 
  3494. keyboard input on a thread, its priority will get boosted and other threads may 
  3495. not get enough CPU time.  A communication thread is an example of a time 
  3496. sensitive background thread which would be one case.  The solution is to either 
  3497. set PRIORITY = ABSOLUTE or to call DosSetPriority on a regular basis to keep 
  3498. the threads priority at the desired level. 
  3499.  
  3500.  
  3501. ΓòÉΓòÉΓòÉ 5.2.5. Altering the Size of the Time Slice ΓòÉΓòÉΓòÉ
  3502.  
  3503. The TIMESLICE command in CONFIG.SYS sets the minimum and maximum amount of 
  3504. processor time allocated to processes and programs for both OS/2 and DOS 
  3505. sessions. 
  3506.  
  3507. The first parameter selects the minimum TIMESLICE value in milliseconds. This 
  3508. value is the minimum amount of time a thread is to be processed before yielding 
  3509. the processor to a thread of the same priority level. This value must be an 
  3510. integer greater than or equal to 32. 
  3511.  
  3512. The second parameter selects the maximum TIMESLICE value in milliseconds. The 
  3513. value of this parameter is the maximum amount of time a thread can be processed 
  3514. before yielding processor time. This value must be an integer greater than or 
  3515. equal to the minimum value, and less than 65536. 
  3516.  
  3517. The default is dynamic time slicing, which varies the size of the time slice 
  3518. depending on system load and paging activity. Dynamic time slicing is designed 
  3519. to give the best performance in most situations. 
  3520.  
  3521.  
  3522. ΓòÉΓòÉΓòÉ 5.3. Using Processes ΓòÉΓòÉΓòÉ
  3523.  
  3524. An OS/2 application that has been loaded into memory and prepared for execution 
  3525. is called a process. A process is the code, data, and other resources of the 
  3526. application, such as the open file handles, semaphores, pipes, queues and so 
  3527. on. The OS/2 operating system considers every application it loads to be a 
  3528. process. 
  3529.  
  3530. Each process has at least one thread, called the main thread or thread 1. The 
  3531. application runs when the system scheduler gives control to a thread in the 
  3532. process. For more on thread management, see Using Threads. 
  3533.  
  3534. Note:  In the example code fragments that follow, error checking was left out 
  3535.        to conserve space. Applications should always check the return code that 
  3536.        the functions return. Control Program functions return an APIRET value. 
  3537.        A return code of 0 indicates success. If a non-zero value is returned, 
  3538.        an error occurred. 
  3539.  
  3540.  
  3541. ΓòÉΓòÉΓòÉ 5.3.1. Starting a Child Process ΓòÉΓòÉΓòÉ
  3542.  
  3543. You start a process by calling DosExecPgm. The process you start is a child of 
  3544. the calling, or parent, process and inherits many of the resources owned by the 
  3545. parent process, such as file handles. 
  3546.  
  3547. DosExecPgm creates a process environment from an executable file. The target 
  3548. program is loaded into storage, and it begins execution. 
  3549.  
  3550. The following code fragment starts an application named ABC: 
  3551.  
  3552.     #define INCL_DOSPROCESS       /* Process and thread values */
  3553.     #include <os2.h>
  3554.  
  3555.     CHAR szFailName[CCHMAXPATH];
  3556.     RESULTCODES resc;
  3557.  
  3558.     DosExecPgm(szFailName,           /* Object-name buffer  */
  3559.                sizeof(szFailName),   /* Length of buffer    */
  3560.                EXEC_SYNC,            /* Sync flag           */
  3561.                (PSZ) NULL,           /* Argument string     */
  3562.                (PSZ) NULL,           /* Environment string  */
  3563.                &resc,                /* Address for result  */
  3564.                "ABC.EXE");           /* Name of application */
  3565.  
  3566. In this example, ABC runs synchronously (as specified by EXEC_SYNC). This means 
  3567. the parent process temporarily stops while the child process runs. The parent 
  3568. process does not continue until the child process ends. 
  3569.  
  3570.  
  3571. ΓòÉΓòÉΓòÉ 5.3.1.1. Starting an Asynchronous Child Process ΓòÉΓòÉΓòÉ
  3572.  
  3573. To start a child process and enable it to run asynchronously (that is, without 
  3574. suspending the parent process until the child process ends), you use the 
  3575. EXEC_ASYNC constant in a call to DosExecPgm. If you start a process in this 
  3576. way, the function copies the process identifier of the child process to the 
  3577. codeTerminate field of the RESULTCODES structure that is returned by 
  3578. DosExecPgm. You can use this process identifier to check the progress of the 
  3579. child process or to terminate the process. 
  3580.  
  3581. You can also run a child process asynchronously by using DosExecPgm with the 
  3582. EXEC_ASYNCRESULT constant. In addition to causing DosExecPgm to return to the 
  3583. parent process immediately, this constant also directs the operating system to 
  3584. save a copy of the termination status when the child process terminates. This 
  3585. status specifies the reason the child process stopped. The parent process can 
  3586. retrieve the termination status by using DosWaitChild. 
  3587.  
  3588. The following code fragment starts the program SIMPLE.EXE, and then waits for 
  3589. it to finish. It then prints the termination code and the return code. 
  3590.  
  3591.     #define INCL_DOSPROCESS       /* Process and thread values */
  3592.     #include <os2.h>
  3593.     #include <stdio.h>
  3594.  
  3595.     #define START_PROGRAM "SIMPLE.EXE"
  3596.  
  3597.     CHAR         LoadError[100];
  3598.     PSZ          Args;
  3599.     PSZ          Envs;
  3600.     RESULTCODES  ReturnCodes;
  3601.     APIRET       rc;
  3602.  
  3603.     rc = DosExecPgm(LoadError,           /* Object name buffer           */
  3604.                     sizeof(LoadError),   /* Length of object name buffer */
  3605.                     EXEC_SYNC,           /* Asynchronous/Trace flags     */
  3606.                     Args,                /* Argument string              */
  3607.                     Envs,                /* Environment string           */
  3608.                     &ReturnCodes,        /* Termination codes            */
  3609.                     START_PROGRAM);      /* Program file name            */
  3610.  
  3611.     printf("Termination Code %d  Return Code %d \n",
  3612.            ReturnCodes.codeTerminate,
  3613.            ReturnCodes.codeResult);
  3614.  
  3615. ----------------SIMPLE.EXE------------------
  3616.  
  3617.     #define INCL_DOSPROCESS       /* Process and thread values */
  3618.     #include <os2.h>
  3619.     #include <stdio.h>
  3620.  
  3621.     #define RETURN_CODE 0
  3622.  
  3623.     main()
  3624.     {
  3625.         printf("Hello!\n");
  3626.         DosExit(EXIT_PROCESS,     /* End the thread or process */
  3627.                 RETURN_CODE);     /* Result code               */
  3628.     }
  3629.  
  3630.  
  3631. ΓòÉΓòÉΓòÉ 5.3.1.2. Starting a Background Process ΓòÉΓòÉΓòÉ
  3632.  
  3633. You can start a child process in the background by specifying the 
  3634. EXEC_BACKGROUND constant in DosExecPgm. A background process runs independently 
  3635. of the parent process and is called a detached process. A detached process 
  3636. should not require any input from the keyboard or output to the video screen, 
  3637. but it can use interprocess communication, such as pipes, queues, and shared 
  3638. memory. 
  3639.  
  3640. The following code fragment starts the program BATCH.EXE in the background. 
  3641.  
  3642.     #define INCL_DOSPROCESS       /* Process and thread values */
  3643.     #include <os2.h>
  3644.     #include <stdio.h>
  3645.  
  3646.     #define START_PROGRAM "BATCH.EXE"
  3647.  
  3648.     CHAR         LoadError[100];
  3649.     PSZ          Args;
  3650.     PSZ          Envs;
  3651.     RESULTCODES  ReturnCodes;
  3652.     APIRET       rc;
  3653.  
  3654.     rc = DosExecPgm(LoadError,           /* Object name buffer           */
  3655.                     sizeof(LoadError),   /* Length of object name buffer */
  3656.                     EXEC_BACKGROUND,     /* Asynchronous/Trace flags     */
  3657.                     Args,                /* Argument string              */
  3658.                     Envs,                /* Environment string           */
  3659.                     &ReturnCodes,        /* Termination codes            */
  3660.                     START_PROGRAM);      /* Program file name            */
  3661.  
  3662.     if (rc != 0) {
  3663.         printf("DosExecPgm error: return code = %ld", rc);
  3664.         return;
  3665.     }
  3666.  
  3667.  
  3668. ΓòÉΓòÉΓòÉ 5.3.1.3. Setting the Command Line and Environment for a Child Process ΓòÉΓòÉΓòÉ
  3669.  
  3670. When you start a process, it inherits many of the resources of the parent. This 
  3671. includes file handles, such as the standard input and standard output files. A 
  3672. child process also inherits the resources of the screen group, such as the 
  3673. mouse and video modes, and the environment variables of the parent process. 
  3674.  
  3675. The call to DosExecPgm determines the command line and environment that the 
  3676. child process receives. The fourth and fifth parameters of the function are 
  3677. pointers to the command line and the environment, respectively. If these 
  3678. pointers are NULL, the child process receives nothing for a command line and 
  3679. only an exact duplicate of the environment of the parent process. The parent 
  3680. process can modify this information by creating a string (ending with two NULL 
  3681. characters) and passing the address of the string to the function. The command 
  3682. line string must include the name of the application, followed by a NULL 
  3683. character, and the command line arguments, followed by two NULL characters. Any 
  3684. number of arguments can be passed to the child process, as long as the argument 
  3685. string ends with two NULL characters. 
  3686.  
  3687. The following code fragment passes to the child process the string "test 
  3688. -option1 -option2" as its command line: 
  3689.  
  3690.     #define INCL_DOSPROCESS    /* Process and thread values */
  3691.     #include <os2.h>
  3692.  
  3693.     RESULTCODES resc;
  3694.     CHAR szFailName[CCHMAXPATH];
  3695.  
  3696.     CHAR szCommandLine[] = "test\0-option1 -option2\0";
  3697.  
  3698.     DosExecPgm(szFailName,          /* Object-name buffer  */
  3699.                sizeof(szFailName),  /* Length of buffer    */
  3700.                EXEC_SYNC,           /* Sync flag           */
  3701.                szCommandLine,       /* Argument string     */
  3702.                (PSZ) NULL,          /* Environment string  */
  3703.                &resc,               /* Address of result   */
  3704.                "test.exe");         /* Name of application */
  3705.  
  3706.  
  3707. ΓòÉΓòÉΓòÉ 5.3.2. Changing the Priority of a Process ΓòÉΓòÉΓòÉ
  3708.  
  3709. Changing the priority of a process is simply a matter of changing the priority 
  3710. of every thread executing in the process. For the details see the section on 
  3711. changing thread priorities, Changing the Priority of a Thread. 
  3712.  
  3713.  
  3714. ΓòÉΓòÉΓòÉ 5.3.3. Obtaining Information about Child Processes ΓòÉΓòÉΓòÉ
  3715.  
  3716. The operating system creates and maintains a Process Information Block for 
  3717. every process. An application can use DosGetInfoBlocks to access the Process 
  3718. Information Block. This function returns a pointer to a PIB data structure, 
  3719. which contains the information from the Process Information Block. 
  3720.  
  3721. The following code fragment returns the address of the Process Information 
  3722. Block of the current process. The calling thread can subsequently browse either 
  3723. the PIB block. 
  3724.  
  3725.     #define INCL_DOSPROCESS     /* Process and thread values */
  3726.     #include <os2.h>
  3727.  
  3728.     PTIB     ptib;      /* Address of pointer to Thread Information Block  */
  3729.     PPIB     ppib;      /* Address of pointer to Process Information Block */
  3730.     APIRET  rc;         /* Return code                                     */
  3731.  
  3732.     rc = DosGetInfoBlocks(&ptib, &ppib);
  3733.  
  3734. DosGetInfoBlocks also returns the address of the Thread Information Block of 
  3735. the current thread. 
  3736.  
  3737.  
  3738. ΓòÉΓòÉΓòÉ 5.3.4. Waiting for a Child Process to Terminate ΓòÉΓòÉΓòÉ
  3739.  
  3740. You can synchronize the execution of a process with the execution of one of its 
  3741. child processes by calling DosWaitChild. DosWaitChild does not return until the 
  3742. specified child process terminates. This can be useful, for example, if the 
  3743. parent process needs to ensure that the child process has completed its task 
  3744. before the parent process continues with its own task. 
  3745.  
  3746. In the following code fragment, the parent process starts a child process and 
  3747. then waits for the child process to finish: 
  3748.  
  3749.     #define INCL_DOSPROCESS     /* Process and thread values */
  3750.     #include <os2.h>
  3751.  
  3752.     RESULTCODES resc;
  3753.     PID pidEnded;
  3754.     CHAR szFailName[CCHMAXPATH];
  3755.  
  3756.     CHAR szCommandLine[] = "APP\0test\0";
  3757.  
  3758.     DosExecPgm(szFailName,              /* Failed-name buffer     */
  3759.                sizeof(szFailName),      /* Length of buffer       */
  3760.                EXEC_ASYNC,              /* Sync flag              */
  3761.                szCommandLine,           /* Argument string        */
  3762.                (PSZ) NULL,              /* Environment string     */
  3763.                &resc,                   /* Address of result      */
  3764.                "APP.EXE");              /* Name of application    */
  3765.  
  3766.     DosWaitChild(DCWA_PROCESS,          /* Only the process       */
  3767.                  DCWW_WAIT,             /* Waits until it is done */
  3768.                  &resc,                 /* Puts the result here   */
  3769.                  &pidEnded,             /* PID of ended process   */
  3770.                  resc.codeTerminate);   /* Child to wait for      */
  3771.  
  3772. You can cause a process to wait for all its child processes to end by using the 
  3773. DCWA_PROCESSTREE constant in the call to DosWaitChild. 
  3774.  
  3775.  
  3776. ΓòÉΓòÉΓòÉ 5.3.5. Ending the Current Process ΓòÉΓòÉΓòÉ
  3777.  
  3778. You terminate the current process by calling DosExit. When you exit, the system 
  3779. stops the process and frees any existing resources the process owns. 
  3780.  
  3781. In the following code fragment, DosExit is used to terminate the process if the 
  3782. given file does not exist: 
  3783.  
  3784.     #define INCL_DOSPROCESS     /* Process and thread values */
  3785.     #include <os2.h>
  3786.  
  3787.     #define HF_STDERR 2         /* Standard error handle     */
  3788.  
  3789.     HFILE   hf;
  3790.     ULONG   ulAction, cbWritten;
  3791.     APIRET  rc;
  3792.  
  3793.     rc = DosOpen("SAMPLE.TXT", &hf, &ulAction, 0, FILE_NORMAL,
  3794.          FILE_OPEN, OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYWRITE, (PEAOP2) NULL);
  3795.  
  3796.     if (rc) {
  3797.         DosWrite(HF_STDERR, "Cannot open file\r\n", 18, &cbWritten);
  3798.         DosExit(EXIT_PROCESS, rc);
  3799.     }
  3800.  
  3801. EXIT_PROCESS directs DosExit to terminate all the threads in a process 
  3802. including the calling thread, thus terminating the process. DosExit includes an 
  3803. error value that is returned to the parent process through the RESULTCODES 
  3804. structure specified in the DosExecPgm call that started the process. If you 
  3805. started the application from the command line, the command processor, CMD.EXE, 
  3806. makes this value available through the ERRORLEVEL variable. If another process 
  3807. started the application, that process can call DosWaitChild to determine the 
  3808. error value. 
  3809.  
  3810. If you want to exit only from a given thread, you can call DosExit with the 
  3811. EXIT_THREAD constant. This will terminate only the calling thread;  other 
  3812. threads in the process are not affected. If the thread you terminate is the 
  3813. last thread in the process, the process also terminates. If the thread consists 
  3814. of a function, the thread terminates when the function returns. 
  3815.  
  3816.  
  3817. ΓòÉΓòÉΓòÉ 5.3.6. Terminating a Process ΓòÉΓòÉΓòÉ
  3818.  
  3819. A process can terminate the execution of a descendant process by calling 
  3820. DosKillProcess. This causes the operating system to send a XCPT_SIGNAL_KILLPROC 
  3821. exception to the target process. The child processes of the target process can 
  3822. also be terminated. 
  3823.  
  3824. The following code fragment terminates the specified process and all child 
  3825. processes belonging to that process: 
  3826.  
  3827.     #define INCL_DOSPROCESS       /* Process and thread values */
  3828.     #include <os2.h>
  3829.  
  3830.     PID pidProcess;
  3831.  
  3832.     DosKillProcess(DKP_PROCESSTREE, pidProcess);
  3833.  
  3834. In this example, the pidProcess parameter specifies which descendant process to 
  3835. terminate. The process identifier is returned by DosExecPgm in the 
  3836. codeTerminate field of the RESULTCODES structure when you start the child 
  3837. process. 
  3838.  
  3839. The parameter DKP_PROCESSTREE in the example indicates that the specified 
  3840. process, pidProcess, and all of its descendant processes are to be terminated. 
  3841.  
  3842. If you specify DKP_PROCESS in a call to DosKillProcess, only the specified 
  3843. process is terminated. Its child processes, if any, continue to run. 
  3844.  
  3845. The process to be terminated must either be the current process, or it must 
  3846. have been directly created by the current process with DosExecPgm for 
  3847. asynchronous execution. That is, a process can terminate itself and its 
  3848. descendants. 
  3849.  
  3850. The process to be terminated need not still be executing. If it has started its 
  3851. own child processes, but has stopped executing, its children can still be 
  3852. flagged for termination. 
  3853.  
  3854. Obtaining the Termination Status of a Child Process 
  3855.  
  3856. The operating system saves the termination status for a process if the process 
  3857. was started by using the EXEC_ASYNCRESULT constant in the call to DosExecPgm. 
  3858. You can retrieve the termination status of the most recently terminated process 
  3859. by using the DCWW_NOWAIT constant with DosWaitChild and setting the child 
  3860. process identification parameter to 0. The DCWW_NOWAIT constant directs the 
  3861. function to return immediately, without waiting for a process to end. Instead, 
  3862. the function retrieves the termination status from the process that most 
  3863. recently ended. If you specify a child process identification with DCWW_NOWAIT, 
  3864. DosWaitChild returns ERROR_CHILD_NOT_COMPLETE if the child process has not 
  3865. terminated. Once the specified process has ended, DosWaitChild returns its 
  3866. termination code. 
  3867.  
  3868. The following code fragment starts a child session (the program SIMPLE.EXE), 
  3869. and then retrieves the termination status from the process that most recently 
  3870. ended. 
  3871.  
  3872.     #define INCL_DOSPROCESS         /* Process and thread values */
  3873.     #include <os2.h>
  3874.     #include <stdio.h>
  3875.  
  3876.     #define START_PROGRAM "SIMPLE.EXE"
  3877.  
  3878.     CHAR         LoadError[100];
  3879.     PSZ          Args;
  3880.     PSZ          Envs;
  3881.     RESULTCODES  ReturnCodes;
  3882.     ULONG        Pid;           /* Process ID (returned)             */
  3883.     ULONG        Target;        /* Process ID of process to wait for */
  3884.     APIRET       rc;            /* Return code                       */
  3885.  
  3886.     strcpy(Args, "-a2 -l");     /* Pass arguments "-a2" and "-l"     */
  3887.  
  3888.     Target = 0;       /* Process ID for the most recently terminated process   */
  3889.  
  3890.     rc = DosExecPgm(LoadError,            /* Object name buffer                */
  3891.                     sizeof(LoadError),    /* Length of object name buffer      */
  3892.                     EXEC_ASYNCRESULT,     /* Asynchronous/Trace flags          */
  3893.                     Args,                 /* Argument string                   */
  3894.                     Envs,                 /* Environment string                */
  3895.                     &ReturnCodes,         /* Termination codes                 */
  3896.                     START_PROGRAM);       /* Program file name                 */
  3897.  
  3898.     if (rc != 0) {
  3899.         printf("DosExecPgm error: return code = %ld", rc);
  3900.         return;
  3901.     }
  3902.  
  3903.     rc = DosWaitChild(DCWA_PROCESS,       /* Execution options                 */
  3904.                       DCWW_NOWAIT,        /* Wait options                      */
  3905.                       &ReturnCodes,       /* Termination codes                 */
  3906.                       &Pid,               /* Process ID (returned)             */
  3907.                       Target);            /* Process ID of process to wait for */
  3908.     if (rc != 0) {
  3909.         printf("DosWaitChild error: return code = %ld", rc);
  3910.         return;
  3911.     }
  3912.  
  3913.  
  3914. ΓòÉΓòÉΓòÉ 5.3.7. Creating an Exit List ΓòÉΓòÉΓòÉ
  3915.  
  3916. You call DosExitList to add to the exit list a routine that is to be given 
  3917. control when a process is terminated (or finishes its execution). Multiple 
  3918. routines can be added to the list. When the process is terminating, the 
  3919. operating system transfers control to each address on the list. 
  3920.  
  3921. If there are multiple addresses on the list, each function gets control in 
  3922. numerical order (with 0 being first and 0FFH being last), based on a value 
  3923. supplied by the application when it calls DosExitList. In case of duplicate 
  3924. entries for this parameter, the routines will be executed in LIFO (last in, 
  3925. first out) order. 
  3926.  
  3927. DosExitList requires a function code that specifies an action and a pointer to 
  3928. the function that is to receive control upon termination. 
  3929.  
  3930. The following code fragment adds the locally defined function SaveFiles to the 
  3931. exit list: 
  3932.  
  3933.     #define INCL_DOSPROCESS         /* Process and thread values */
  3934.     #include <os2.h>
  3935.  
  3936.     #define HF_STDOUT 1             /* Standard output handle    */
  3937.  
  3938.     VOID main(VOID)
  3939.     {
  3940.         .
  3941.         .
  3942.         .
  3943.         DosExitList(EXLST_ADD, (PFNEXITLIST) SaveFiles);
  3944.         .
  3945.         .
  3946.         .
  3947.         DosExit(EXIT_PROCESS, 0);
  3948.     }
  3949.  
  3950.     VOID APIENTRY SaveFiles(ULONG ulTermCode)
  3951.     {
  3952.         ULONG cbWritten;
  3953.  
  3954.         switch (ulTermCode) {
  3955.             case TC_EXIT:
  3956.             case TC_KILLPROCESS:
  3957.                  DosWrite(HF_STDOUT, "Goodbye\r\n", 10, &cbWritten);
  3958.                  break;
  3959.  
  3960.             case TC_HARDERROR:
  3961.             case TC_TRAP:
  3962.                  break;
  3963.  
  3964.         }
  3965.         DosExitList(EXLST_EXIT, 0);
  3966.     }
  3967.  
  3968. Any function that you add to the list must take one parameter. The function can 
  3969. carry out any task, as shown in the preceding example, but as its last action 
  3970. it must call DosExitList, specifying the EXLST_EXIT constant. An exit-list 
  3971. function must not have a return value and must not call DosExit to terminate. 
  3972.  
  3973. When an exit-list routine receives control, the parameter (located at ESP+4 on 
  3974. the stack) contains an indicator of why the process ended. The values returned 
  3975. are the same as those for termination codes returned by DosWaitChild or 
  3976. DosExecPgm requests. These values are: 
  3977.  
  3978.  TC_EXIT (0)           Normal exit 
  3979.  TC_HARDERROR (1)      Hard-error halt 
  3980.  TC_TRAP (2)           Trap operation for a 16-bit child process 
  3981.  TC_KILLPROCESS (3)    Unintercepted DosKillProcess 
  3982.  TC_EXCEPTION (4)      Exception operation for a 32-bit child process 
  3983.  
  3984.  To execute the exit-list functions, the operating system reassigns thread 1 
  3985.  after terminating all other threads in the process. If thread 1 has already 
  3986.  exited (for example, if it called DosExit without terminating other threads in 
  3987.  the process), the exit-list functions cannot be executed. In general, it is 
  3988.  poor practice to terminate thread 1 without terminating all other threads. 
  3989.  
  3990.  Before transferring control to the termination routines, the operating system 
  3991.  resets the stack to its initial value. Transfer is by way of an assembly 
  3992.  language JMP instruction. The routine must be in the address space of the 
  3993.  terminating process. The termination routine at that address takes the 
  3994.  necessary steps and then calls DosExitList with FunctionOrder=EXLST_EXIT. 
  3995.  Control is then transferred to the next address in the invocation order of the 
  3996.  exit list. When all such addresses have been processed, the process completes 
  3997.  exiting. If a routine on the list does not call DosExitList at the completion 
  3998.  of its processing, the process waits, and the operating system prevents 
  3999.  termination. 
  4000.  
  4001.  During DosExitList processing, the process is in a state of partial 
  4002.  termination. All threads of the process are terminated, except for the one 
  4003.  executing the exit-list routines. To ensure good response to a user request to 
  4004.  end a program, there should be minimal delay in completing termination. 
  4005.  Termination routines should be short and fail-safe. 
  4006.  
  4007.  You can use DosExitList with the EXLST_REMOVE constant to remove a function 
  4008.  from the list. 
  4009.  
  4010.  The designer of an exit-list routine must carefully consider which functions 
  4011.  will be used by the routine. In general, calls to most OS/2 functions are 
  4012.  valid in a DosExitList routine, but certain functions, such as DosCreateThread 
  4013.  and DosExecPgm, are not. 
  4014.  
  4015.  
  4016. ΓòÉΓòÉΓòÉ 5.4. Using Threads ΓòÉΓòÉΓòÉ
  4017.  
  4018. A thread is a dispatchable unit of execution that consists of a set of 
  4019. instructions, related CPU register values, and a stack. Every process has at 
  4020. least one thread and can have many threads running at the same time. The 
  4021. application runs when the operating system gives control to a thread in the 
  4022. process. The thread is the basic unit of execution scheduling. 
  4023.  
  4024. Every process has at least one thread, called the main thread or thread 1. To 
  4025. execute different parts of an application simultaneously, you can start several 
  4026. threads. 
  4027.  
  4028. A new thread inherits all the resources currently owned by the process. This 
  4029. means that if you opened a file before creating the thread, the file is 
  4030. available to the thread. Similarly, if the new thread creates or opens a 
  4031. resource, such as another file, that resource is available to the other threads 
  4032. in the process. 
  4033.  
  4034.  
  4035. ΓòÉΓòÉΓòÉ 5.4.1. Creating a Thread ΓòÉΓòÉΓòÉ
  4036.  
  4037. You use DosCreateThread to create a new thread for a process. 
  4038.  
  4039. DosCreateThread requires the address of the code to execute and a variable to 
  4040. receive the identifier of the thread. The address of the code is typically the 
  4041. address of a function that is defined within the application. 
  4042.  
  4043. You can pass one ULONG parameter to the thread when you start it. To pass more 
  4044. information to the thread, pass the address of a data structure. 
  4045.  
  4046. You specify how you want the thread to run when you call DosCreateThread. If 
  4047. bit 1 of the flag parameter in the function call is 0, the thread starts 
  4048. immediately. If bit 1 of the flag parameter is 1, the thread starts suspended 
  4049. and will not run until the application calls DosResumeThread. 
  4050.  
  4051. Each thread maintains its own stack. You specify the size of the stack when you 
  4052. call DosCreateThread. The amount of space needed depends on a number of 
  4053. factors, including the number of function calls the thread makes and the number 
  4054. of parameters and local variables used by each function. If you plan to call 
  4055. OS/2 functions, a reasonable stack size is 8192 bytes (8KB); 4096 bytes (4KB) 
  4056. should be the absolute minimum. If bit 1 of the flag parameter is 0, the 
  4057. operating system uses the default method for initializing the thread's stack. 
  4058. If bit 1 of the flag parameter is 1, memory for the thread's entire stack is 
  4059. pre-committed. 
  4060.  
  4061. The following code fragment creates a thread: 
  4062.  
  4063.     #define INCL_DOSPROCESS         /* Process and thread values */
  4064.     #include <os2.h>
  4065.  
  4066.     #define HF_STDOUT 1             /* Standard output handle    */
  4067.  
  4068.     VOID main(VOID)
  4069.     {
  4070.         ULONG ulBeepLen;
  4071.         TID   tidThread;
  4072.  
  4073.         ulBeepLen = 1000;
  4074.         .
  4075.         DosCreateThread(&tidThread,   /* Thread ID returned by DosCreateThread */
  4076.                         ThreadFunc,   /* Address of the thread function        */
  4077.                         ulBeepLen,    /* Parameter passed to thread            */
  4078.                         0,            /* Immediate execution, default stack    */
  4079.                                       /* initialization                        */
  4080.                         4096);        /* Stack size                            */
  4081.         .
  4082.         .
  4083.         .
  4084.         DosExit(EXIT_PROCESS, 0);
  4085.     }
  4086.  
  4087.     VOID ThreadFunc(ULONG ulBeepLen)
  4088.     {
  4089.         DosBeep(750, ulBeepLen);
  4090.  
  4091.         DosWrite(HF_STDOUT, "Message from new thread\r\n", 25, 0);
  4092.     }
  4093.  
  4094. A thread continues to run until it calls DosExit, returns control to the 
  4095. operating system, or is terminated by a DosKillThread call. 
  4096.  
  4097. In the preceding example, the thread exits when the function implicitly returns 
  4098. control at the end of the function. 
  4099.  
  4100.  
  4101. ΓòÉΓòÉΓòÉ 5.4.2. Obtaining Information about a Thread ΓòÉΓòÉΓòÉ
  4102.  
  4103. The operating system creates and maintains a Thread Information Block for each 
  4104. thread. An application can use DosGetInfoBlocks to access the Thread 
  4105. Information Block. This function returns a pointer to a TIB data structure. 
  4106.  
  4107. The following code fragment returns the address of the Thread Information Block 
  4108. of the current thread. The calling thread can subsequently browse the TIB 
  4109. control block. 
  4110.  
  4111.     #define INCL_DOSPROCESS     /* Process and thread values */
  4112.     #include <os2.h>
  4113.  
  4114.     PTIB     ptib;      /* Address of pointer to Thread Information Block  */
  4115.     PPIB     ppib;      /* Address of pointer to Process Information Block */
  4116.     APIRET  rc;         /* Return code                                     */
  4117.  
  4118.     rc = DosGetInfoBlocks(&ptib, &ppib);
  4119.  
  4120. DosGetInfoBlocks also returns the address of the Process Information Block of 
  4121. the current process. 
  4122.  
  4123.  
  4124. ΓòÉΓòÉΓòÉ 5.4.3. Changing the Priority of a Thread ΓòÉΓòÉΓòÉ
  4125.  
  4126. You can use DosSetPriority to change the execution priority of threads in a 
  4127. process. The execution priority defines when or how often a thread receives an 
  4128. execution time slice. Threads with higher priorities receive time slices before 
  4129. those with lower priorities. When a thread that is higher in priority than the 
  4130. currently running thread becomes ready to run, it immediately preempts the 
  4131. lower priority thread (the lower priority thread does not get to complete its 
  4132. time slice). Threads with equal priority receive time slices in a round-robin 
  4133. order. If you raise the priority of a thread, the thread is executed more 
  4134. frequently. 
  4135.  
  4136. You can use DosSetPriority to set the priority for one thread in a process, for 
  4137. all threads in a process (and thus the process itself), or for threads in a 
  4138. child process. 
  4139.  
  4140. A process can change the priority of any thread within itself. When a process 
  4141. changes the priority of threads in a descendant process, however, only those 
  4142. with default priorities are changed. The priority of any thread in a descendant 
  4143. process that has already explicitly changed its priority from the default with 
  4144. DosSetPriority is not changed. 
  4145.  
  4146. In the following code fragment, DosSetPriority lowers the priority of a process 
  4147. to be used as a background process: 
  4148.  
  4149.     #define INCL_DOSPROCESS       /* Process and thread values */
  4150.     #include <os2.h>
  4151.  
  4152.     PTIB ptib;    /* Thread Information Block  */
  4153.     PPIB ppib;    /* Process Information Block */
  4154.  
  4155.     DosGetInfoBlocks(&ptib, &ppib);
  4156.  
  4157.     DosSetPriority(PRTYS_PROCESSTREE, PRTYC_IDLETIME, 0, ppib->pib_ulpid);
  4158.  
  4159. DosGetInfoBlocks retrieves the Process Information Blocks and Thread 
  4160. Information Blocks. DosSetPriority then uses the process identifier to change 
  4161. the priority to idle time (idle-time processes receive the least attention by 
  4162. the operating system). 
  4163.  
  4164. If you specify PRTYS_PROCESS when calling DosSetPriority, only the priority of 
  4165. the specified process changes. The priorities of all child processes remain 
  4166. unchanged. 
  4167.  
  4168. If you specify PRTYS_THREAD in the call to DosSetPriority, you must specify a 
  4169. thread identifier as the last parameter.  The priority of the specified thread 
  4170. changes, but the priorities of all other threads in the process remain 
  4171. unchanged. 
  4172.  
  4173. Whenever DosSetPriority is called with a class specification, but no value is 
  4174. specified for priority-delta, the base priority level defaults to 0. 
  4175.  
  4176.  
  4177. ΓòÉΓòÉΓòÉ 5.4.4. Suspending the Current Thread ΓòÉΓòÉΓòÉ
  4178.  
  4179. You can temporarily suspend the execution of the current thread for a set 
  4180. amount of time by using DosSleep. This function suspends execution of the 
  4181. thread for the specified number of milliseconds. DosSleep is useful when you 
  4182. need to delay the execution of a task. For example, you can use DosSleep to 
  4183. delay a response when the user presses a DIRECTION key. The delay provides the 
  4184. user with enough time to observe the results and release the key. 
  4185.  
  4186. The following code fragment uses DosSleep to suspend execution of a thread for 
  4187. 1000 milliseconds (1 second): 
  4188.  
  4189.     #define INCL_DOSPROCESS       /* Process and thread values */
  4190.     #include <os2.h>
  4191.  
  4192.     DosSleep(1000);
  4193.  
  4194.  
  4195. ΓòÉΓòÉΓòÉ 5.4.5. Suspending and Resuming Execution of a Thread ΓòÉΓòÉΓòÉ
  4196.  
  4197. DosSuspendThread and DosResumeThread are used to temporarily suspend the 
  4198. execution of a thread when it is not needed and resume execution when the 
  4199. thread is needed. 
  4200.  
  4201. These functions are best used when it is necessary for a process to temporarily 
  4202. suspend execution of a thread that is in the middle of a task. For example, 
  4203. consider a thread that opens and reads files from a disk. If other threads in 
  4204. the process do not require input from these files, the process can suspend 
  4205. execution of the thread so that the operating system does not needlessly grant 
  4206. control to it. 
  4207.  
  4208. The specified thread might not be suspended immediately if it has some system 
  4209. resources locked that must be freed first. However, the thread is not permitted 
  4210. to execute further application program instructions until a corresponding 
  4211. DosResumeThread is called. 
  4212.  
  4213. A thread can only suspend another thread that is within its process. 
  4214.  
  4215. DosResumeThread is used to enable the suspended thread to resume execution. 
  4216.  
  4217. The following code fragment temporarily suspends the execution of another 
  4218. thread within the same process. A subsequent call to DosResumeThread restarts 
  4219. the suspended thread. Assume that the thread identifier of the target thread 
  4220. has been placed int ThreadID already. 
  4221.  
  4222.     #define INCL_DOSPROCESS     /* Process and thread values */
  4223.     #include <os2.h>
  4224.     #include <stdio.h>
  4225.  
  4226.     TID     ThreadID;     /* Thread identifier */
  4227.     APIRET  rc;           /* Return code       */
  4228.  
  4229.     rc = DosSuspendThread(ThreadID);
  4230.  
  4231.     if (rc != 0) {
  4232.         printf("DosSuspendThread error: return code = %ld", rc);
  4233.         return;
  4234.     }
  4235.  
  4236.     rc = DosResumeThread(ThreadID);
  4237.  
  4238.     if (rc != 0) {
  4239.         printf("DosResumeThread error: return code = %ld", rc);
  4240.         return;
  4241.     }
  4242.  
  4243.  
  4244. ΓòÉΓòÉΓòÉ 5.4.6. Entering Critical Sections ΓòÉΓòÉΓòÉ
  4245.  
  4246. A thread can prevent execution of any of the other threads in its process by 
  4247. calling DosEnterCritSec. 
  4248.  
  4249. This function temporarily prevents a thread from being preempted by other 
  4250. threads within its process. The other threads in the process will not be 
  4251. executed until the current thread calls DosExitCritSec. This enables the 
  4252. calling thread to access a time-critical resource of the process. 
  4253.  
  4254. The following code fragment enters a section that will not be preempted, 
  4255. performs a simple task, and then exits quickly. 
  4256.  
  4257.     #define INCL_DOSPROCESS     /* Process and thread values */
  4258.     #include <os2.h>
  4259.     #include <stdio.h>
  4260.  
  4261.     BOOL    flag;         /* Program control flag */
  4262.     APIRET  rc;           /* Return code          */
  4263.  
  4264.     rc = DosEnterCritSec();
  4265.  
  4266.     if (rc != 0) {
  4267.         printf("DosEnterCritSec error: return code = %ld", rc);
  4268.         return;
  4269.     }
  4270.  
  4271.     flag = TRUE;           /* Set the flag */
  4272.  
  4273.     rc = DosExitCritSec();
  4274.  
  4275.     if (rc != 0) {
  4276.         printf("DosExitCritSec error: return code = %ld", rc);
  4277.         return;
  4278.     }
  4279.  
  4280. A count is maintained of the outstanding DosEnterCritSec requests. The count is 
  4281. incremented when a DosEnterCritSec request is made, and decremented when a 
  4282. DosExitCritSec request is made. A DosExitCritSec request will not cause normal 
  4283. thread dispatching to be restored while the count is greater than 0. 
  4284.  
  4285. This count is maintained in a WORD-sized variable. If overflow occurs, the 
  4286. count is set to its maximum value, and an error is returned. The operation is 
  4287. not performed when this occurs. 
  4288.  
  4289. Threads that call DosEnterCritSec must not must not make dynamic link calls 
  4290. within these critical sections. The dynamic link procedure could be using 
  4291. semaphores to serialize a resource. If a thread entering the critical section 
  4292. blocks another thread that already owns the resource which the dynamic link 
  4293. function is about to request, a deadlock occurs. 
  4294.  
  4295. For example, threads of an application are serializing their access to a queue 
  4296. by means of a semaphore. A thread enters a critical section and makes a request 
  4297. to read the queue while another thread already has the semaphore that controls 
  4298. access to the queue. The thread that has the semaphore is now effectively 
  4299. blocked by DosEnterCritSec, and the thread that has requested the queue waits 
  4300. forever to access it. 
  4301.  
  4302. Note:  Thread 1 is the initial thread of execution. It handles all signals 
  4303.        (Ctrl+C, Ctrl+Break, and KillProcess). If a signal occurs while 
  4304.        DosEnterCritSec is active, thread 1 can begin execution to process the 
  4305.        signal. Thread 1 must not access the critical resource that is being 
  4306.        protected by the use of DosEnterCritSec. 
  4307.  
  4308.  
  4309. ΓòÉΓòÉΓòÉ 5.4.7. Waiting for a Thread to Terminate ΓòÉΓòÉΓòÉ
  4310.  
  4311. An application might need to ensure that one thread has finished executing 
  4312. before another thread continues with its own task. For example, one thread 
  4313. might have to finish reading a disk file into memory before another thread can 
  4314. use the information. You can use DosWaitThread to suspend a thread until 
  4315. another thread has terminated. 
  4316.  
  4317. DosWaitThread places the current thread into a wait state until another thread 
  4318. in the current process has terminated. It then returns the thread identifier of 
  4319. the terminating thread. 
  4320.  
  4321. The following code fragment creates three threads. The thread identifier for 
  4322. each thread is returned by DosCreateThread in the atid array. Using &atid[0] as 
  4323. a parameter in the call to DosWaitThread causes the operating system to wait 
  4324. until the thread with that identifier (the thread running Thread2Func) 
  4325. terminates. 
  4326.  
  4327.     #define INCL_DOSPROCESS       /* Process and thread values */
  4328.     #include <os2.h>
  4329.  
  4330.     #define HF_STDOUT 1           /* Standard output handle    */
  4331.  
  4332.     TID atid[3];
  4333.     ULONG cbWritten;
  4334.  
  4335.     DosCreateThread(&atid[0], Thread2Func, 0, 0, 4096);
  4336.     DosCreateThread(&atid[1], Thread3Func, 0, 0, 4096);
  4337.     DosCreateThread(&atid[2], Thread4Func, 0, 0, 4096);
  4338.     DosWaitThread(&atid[0], DCWW_WAIT);
  4339.     DosWrite(HF_STDOUT, "The thread has terminated\r\n", 27, &cbWritten);
  4340.  
  4341. If you set the tid parameter to 0 in the call to DosWaitThread, the operating 
  4342. system waits only until the next thread (any thread in the process) terminates. 
  4343. The identifier for the terminated thread is then returned in the tid parameter. 
  4344.  
  4345. After the threads are created as in the preceding example, the following code 
  4346. fragment waits until one of the threads terminates, and then returns its thread 
  4347. identifier: 
  4348.  
  4349.     #define INCL_DOSPROCESS       /* Process and thread values */
  4350.     #include <os2.h>
  4351.  
  4352.     TID tid;
  4353.  
  4354.     tid = 0;
  4355.  
  4356.     DosWaitThread(&tid, DCWW_WAIT);
  4357.  
  4358. The thread identifier of the next thread to terminate after the DosWaitThread 
  4359. call is returned in the tid parameter. 
  4360.  
  4361. You can use DosWaitThread so that you can recover thread resources when the 
  4362. thread terminates, or to synchronize the execution of a thread with the 
  4363. execution of other threads. 
  4364.  
  4365.  
  4366. ΓòÉΓòÉΓòÉ 5.4.8. Ending the Current Thread ΓòÉΓòÉΓòÉ
  4367.  
  4368. To end the execution of the current thread, call DosExit, specifying the action 
  4369. code as 0. It is good practice to end each thread in the application 
  4370. individually. 
  4371.  
  4372. If the thread that is ending is the last thread in the process, or if the 
  4373. request is to terminate all threads in the process, then the process also 
  4374. terminates.  All threads except one are terminated, and that thread executes 
  4375. any routines in the list specified by DosExitList. When this is complete, the 
  4376. resources of the process are released, and the result code that was specified 
  4377. in the DosExit call is passed to any thread that calls DosWaitChild for this 
  4378. process. 
  4379.  
  4380. In the following code fragment, the main routine starts another program, 
  4381. SIMPLE.EXE, and then expects a return code of 3 to be returned. SIMPLE.EXE sets 
  4382. the return code with DosExit. 
  4383.  
  4384.     #define INCL_DOSPROCESS           /* Process and thread values */
  4385.     #include <os2.h>
  4386.     #include <stdio.h>
  4387.  
  4388.     #define START_PROGRAM "SIMPLE.EXE"
  4389.     #define RETURN_OK 3
  4390.  
  4391.     CHAR        LoadError[100];
  4392.     PSZ         Args;
  4393.     PSZ         Envs;
  4394.     RESULTCODES ReturnCodes;
  4395.     APIRET      rc;
  4396.  
  4397.     rc = DosExecPgm(LoadError,                /* Object name buffer           */
  4398.                     sizeof(LoadError),        /* Length of object name buffer */
  4399.                     EXEC_SYNC,                /* Asynchronous/Trace flags     */
  4400.                     Args,                     /* Argument string              */
  4401.                     Envs,                     /* Environment string           */
  4402.                     &ReturnCodes,             /* Termination codes            */
  4403.                     START_PROGRAM);           /* Program file name            */
  4404.  
  4405.     if (ReturnCodes.codeResult == RETURN_OK)  /* Check result code            */
  4406.         printf("Things are ok...");
  4407.     else
  4408.         printf("Something is wrong...");
  4409.  
  4410. ----------------SIMPLE.EXE------------------
  4411.  
  4412.     #define INCL_DOSPROCESS          /* Process and thread values */
  4413.     #include <os2.h>
  4414.     #include <stdio.h>
  4415.  
  4416.     #define RETURN_CODE 3
  4417.  
  4418.     main()
  4419.     {
  4420.         printf("Hello!\n");
  4421.         DosExit(EXIT_THREAD,         /* End thread/process */
  4422.                 RETURN_CODE);        /* Result code        */
  4423.     }
  4424.  
  4425. When you specify DosExit for thread 1 (the initial thread of execution started 
  4426. by the operating system for this process), all of the threads in the process 
  4427. are terminated, and the process is ended. 
  4428.  
  4429.  
  4430. ΓòÉΓòÉΓòÉ 5.4.9. Terminating a Thread ΓòÉΓòÉΓòÉ
  4431.  
  4432. DosKillThread terminates a thread in the current process. DosKillThread enables 
  4433. a thread in a process to terminate any other thread in the process. 
  4434.  
  4435. DosKillThread is used to force a thread within the current process to terminate 
  4436. without causing the entire process to be terminated. 
  4437.  
  4438.     #define INCL_DOSPROCESS       /* Process and thread values */
  4439.     #include <os2.h>
  4440.  
  4441.     TID tidThread;    /* ThreadID of the thread to be terminated */
  4442.  
  4443.     DosCreateThread(&tidThread, ThreadFunction, 0, 0, 4096);
  4444.     .
  4445.     .
  4446.     .
  4447.     DosKillThread(tidThread);
  4448.  
  4449. DosKillThread returns to the requestor without waiting for the target thread to 
  4450. complete its termination processing. 
  4451.  
  4452. It is an invalid operation to use DosKillThread to kill the current thread. 
  4453.  
  4454. Terminating thread 1 will cause the entire process to terminate similar to 
  4455. executing DosExit on thread 1. DosKillThread will not terminate a thread that 
  4456. is suspended. Instead the suspended thread will be terminated when it resumes 
  4457. execution. For this reason, you should not kill the main thread of an 
  4458. application if there are any secondary threads that are suspended. 
  4459.  
  4460. If the target thread is executing 16-bit code or was created by a 16-bit 
  4461. requester, ERROR_BUSY is returned. 
  4462.  
  4463.  
  4464. ΓòÉΓòÉΓòÉ 5.5. Using Sessions ΓòÉΓòÉΓòÉ
  4465.  
  4466. A session consists of at least one process and a virtual console (either full 
  4467. screen, or Presentation Manager window, and buffers for keyboard and mouse 
  4468. input). An application can manage its own child sessions by using 
  4469. DosStartSession, DosStopSession, DosSelectSession, and DosSetSession. 
  4470.  
  4471.  
  4472. ΓòÉΓòÉΓòÉ 5.5.1. Starting a Session ΓòÉΓòÉΓòÉ
  4473.  
  4474. DosStartSession is used to start new sessions and to specify the name of the 
  4475. application to be started in the new session. 
  4476.  
  4477. There are five types of sessions that you can start: full screen, text window, 
  4478. Presentation Manager (PM), full screen DOS Session, and windowed DOS Session. 
  4479. OS/2 applications running in any of the OS/2 session types-full screen, text 
  4480. window, and PM-can start a session for any other application type, including 
  4481. DOS Sessions. Applications running in DOS Sessions cannot start sessions. 
  4482.  
  4483. DosStartSession can be used to start either a foreground or a background 
  4484. session, but a new session can be started in the foreground only when the 
  4485. session of the caller, or one of the descendant sessions of the caller, is 
  4486. currently executing in the foreground. 
  4487.  
  4488. A session can be started as an unrelated session or as a child session. 
  4489.  
  4490. In the following code fragment, an unrelated, foreground session is created, 
  4491. and the application, SIMON.EXE, is started in the new session: 
  4492.  
  4493.     #define INCL_DOSPROCESS       /* Process and thread values */
  4494.     #define INCL_DOSSESMGR
  4495.     #include <os2.h>
  4496.  
  4497.     #define HF_STDOUT 1      /* Standard output handle */
  4498.  
  4499.     STARTDATA  sd;
  4500.     PID        pidProcess;
  4501.     CHAR       szBuf[CCHMAXPATH];
  4502.     ULONG      ulSessionID, cbWritten;
  4503.     APIRET     rc;
  4504.     CHAR       szPgmName[] = "SIMON.EXE";
  4505.  
  4506.     sd.Length = sizeof(sd);                    /* Length of the structure */
  4507.     sd.Related = SSF_RELATED_INDEPENDENT;      /* Unrelated session       */
  4508.     sd.FgBg = SSF_FGBG_FORE;                   /* In the foreground       */
  4509.     sd.TraceOpt = SSF_TRACEOPT_NONE;           /* No tracing              */
  4510.     sd.PgmTitle = (PSZ) NULL;                  /* Title is PgmName        */
  4511.     sd.PgmName = szPgmName;                    /* Address of szPgmName    */
  4512.     sd.PgmInputs = (PBYTE) NULL;               /* No command line args    */
  4513.     sd.TermQ = (PBYTE) NULL;                   /* No terminal queue       */
  4514.     sd.Environment = (PBYTE) NULL;             /* Inherits environment    */
  4515.     sd.InheritOpt = SSF_INHERTOPT_PARENT;      /* Uses parent environment */
  4516.     sd.SessionType = SSF_TYPE_PM;              /* PM session              */
  4517.     sd.IconFile = (PSZ) NULL;                  /* Uses default icon       */
  4518.     sd.PgmHandle = 0;                          /* Used by Win calls       */
  4519.     sd.PgmControl = SSF_CONTROL_MAXIMIZE;      /* Starts app maximized    */
  4520.     sd.InitXPos = 0;                           /* Lower left corner       */
  4521.     sd.InitYPos = 0;                           /* Lower left corner       */
  4522.     sd.InitXSize = 0;                          /* Ignored for maximized   */
  4523.     sd.InitYSize = 0;                          /* Ignored for maximized   */
  4524.     sd.ObjectBuffer = szBuf;                   /* Fail-name buffer        */
  4525.     sd.ObjectBuffLen = sizeof(szBuf);          /* Buffer length           */
  4526.  
  4527.     rc = DosStartSession(&sd, &ulSessionID, &pidProcess);
  4528.  
  4529.     if (rc) {
  4530.         DosBeep(750,250);
  4531.         DosWrite(HF_STDOUT, "error starting new session\r\n", 28, &cbWritten);
  4532.         DosExit(EXIT_PROCESS, rc);
  4533.     }
  4534.  
  4535. Before calling DosStartSession, you must create a STARTDATA data structure that 
  4536. defines the session to be started. Different lengths for the data structure are 
  4537. supported to provide compatibility and various levels of application control. 
  4538.  
  4539. DosStartSession uses the STARTDATA structure to specify the details of the new 
  4540. session, such as the name of the application to start in the session, whether 
  4541. the new session should be started in the foreground or background, and whether 
  4542. the new session is unrelated or is a child session of the session calling 
  4543. DosStartSession. 
  4544.  
  4545. When a session is created, the title specified in STARTDATA, (or the 
  4546. application title if no title is specified in STARTDATA) is added to the Window 
  4547. List. 
  4548.  
  4549. The Related field in the STARTDATA structure specifies whether the new session 
  4550. is related to the session calling DosStartSession. 
  4551.  
  4552. If the InheritOpt field in the STARTDATA data structure is set to 1, the new 
  4553. session inherits the environment and open file handles of the calling process. 
  4554. This applies for both unrelated and related sessions. 
  4555.  
  4556.  
  4557. ΓòÉΓòÉΓòÉ 5.5.2. Controlling the Execution of Child Sessions ΓòÉΓòÉΓòÉ
  4558.  
  4559. Once a process has started a child session, it can use DosSelectSession to 
  4560. control the child session. 
  4561.  
  4562. A process calls DosSetSession to set the selectability and bonding of a child 
  4563. session. 
  4564.  
  4565.  
  4566. ΓòÉΓòÉΓòÉ 5.5.2.1. Setting User Selectability of a Child Session ΓòÉΓòÉΓòÉ
  4567.  
  4568. A process calls DosSetSession to set the selectability of a child session. 
  4569. When a child session is selectable, the user can select it from the Window List 
  4570. or by using Alt+Esc. When a child session is nonselectable, the user cannot 
  4571. select the session from the Window List or move to it by using the Alt+Esc 
  4572. keys. 
  4573.  
  4574. In the following code fragment, DosSetSession makes a child session 
  4575. nonselectable: 
  4576.  
  4577.     #define INCL_DOSPROCESS       /* Process and thread values */
  4578.     #define INCL_DOSSESMGR
  4579.     #include <os2.h>
  4580.  
  4581.     ULONG ulSessionID;
  4582.     STATUSDATA stsdata;
  4583.  
  4584.     stsdata.Length = sizeof(stsdata);
  4585.     stsdata.SelectInd = SET_SESSION_NON_SELECTABLE;  /* Non-selectable         */
  4586.     stsdata.BondInd = SET_SESSION_UNCHANGED;         /* Leaves session bonding */
  4587.                                                      /* index unchanged        */
  4588.  
  4589.     DosSetSession(ulSessionID, &stsdata);
  4590.  
  4591. Once a child session is made nonselectable, the user cannot select the session 
  4592. from the Window List or move to it by using the Alt+Esc keys. However, the 
  4593. parent session can still bring the child session to the foreground by using 
  4594. DosSelectSession. If the session contains a Presentation Manager application or 
  4595. is a windowed session, the user will still be able to select it with a mouse. 
  4596.  
  4597. The parent session can make a nonselectable child session selectable by setting 
  4598. the SelectInd field to SET_SESSION_SELECTABLE in the STATUSDATA structure. 
  4599. DosSetSession can be called only by a parent session and only for a child 
  4600. session. That is, the calling process must be the process that started the 
  4601. child session using DosStartSession. Neither the parent session itself nor any 
  4602. grandchild, nor any other descendant session beyond a child session can be the 
  4603. target of this call. 
  4604.  
  4605. Additionally, DosSetSession cannot be used to change the status of a session 
  4606. that was started as an unrelated session. The Related field in the STARTDATA 
  4607. structure must have been set to 1 when the session was started. 
  4608.  
  4609.  
  4610. ΓòÉΓòÉΓòÉ 5.5.2.2. Binding Child Sessions to Parent Sessions ΓòÉΓòÉΓòÉ
  4611.  
  4612. An application can use DosSetSession to establish a bond between a parent 
  4613. session and one of its child sessions. When the two sessions are bound, the 
  4614. operating system brings the child session to the foreground when the user 
  4615. selects the parent session. 
  4616.  
  4617. In the following code fragment, a parent session is bound to the child session 
  4618. specified by the ulSessionID parameter: 
  4619.  
  4620.     #define INCL_DOSPROCESS       /* Process and thread values */
  4621.     #define INCL_DOSSESMGR
  4622.     #include <os2.h>
  4623.  
  4624.     ULONG ulSessionID;
  4625.     STATUSDATA stsdata;
  4626.  
  4627.     stsdata.Length = sizeof(stsdata);
  4628.     stsdata.SelectInd = SET_SESSION_UNCHANGED;   /* Leaves select setting alone */
  4629.     stsdata.BondInd = SET_SESSION_BOND;          /* Binds parent and child      */
  4630.  
  4631.     DosSetSession(ulSessionID, &stsdata);
  4632.  
  4633. When the application uses DosSetSession to establish a parent-child bond, any 
  4634. bond the parent has with another child session is broken. The application can 
  4635. remove the parent-child bond by calling DosSetSession with the BondInd field 
  4636. (in the STATUSDATA structure) set to SET_SESSION_NO_BOND. 
  4637.  
  4638. A parent session can be executing in either the foreground or the background 
  4639. when it calls DosSetSession. 
  4640.  
  4641.  
  4642. ΓòÉΓòÉΓòÉ 5.5.2.3. Switching a Session to the Foreground ΓòÉΓòÉΓòÉ
  4643.  
  4644. An application can bring a session to the foreground, or select the session, by 
  4645. calling DosSelectSession. 
  4646.  
  4647. DosSelectSession can only be used to select the current session or one of the 
  4648. current session's child sessions. It cannot be used to select a grandchild 
  4649. session, or any other descendant session beyond a child session, or any 
  4650. sessions that were started as unrelated sessions. 
  4651.  
  4652. The session making the call, or one of its child sessions, must be executing in 
  4653. the foreground at the time the function is called. A process can call 
  4654. DosSelectSession with its own session identifier to switch itself to the 
  4655. foreground when one of its descendants is executing in the foreground. 
  4656.  
  4657. The following code fragment uses DosSelectSession to switch the child session 
  4658. specified by the ulSessionID parameter to the foreground for five seconds. The 
  4659. application then switches the parent session back to the foreground: 
  4660.  
  4661.     #define INCL_DOSPROCESS       /* Process and thread values */
  4662.     #include <os2.h>
  4663.  
  4664.     ULONG ulSessionID;
  4665.  
  4666.     DosSelectSession(ulSessionID);   /* Switches child to foreground */
  4667.     DosSleep(5000);                  /* Sleeps for 5 seconds         */
  4668.     DosSelectSession(0);             /* Switches parent back         */
  4669.  
  4670.  
  4671. ΓòÉΓòÉΓòÉ 5.5.3. Terminating a Session ΓòÉΓòÉΓòÉ
  4672.  
  4673. DosStopSession can be used by a parent session to stop one or all of its child 
  4674. sessions. If the child session specified in the call to DosStopSession has 
  4675. related sessions, the related sessions are also terminated. The parent session 
  4676. can be running in the foreground or the background when it calls 
  4677. DosStopSession. If the child session is running in the foreground when it is 
  4678. terminated, the parent session becomes the foreground session. 
  4679.  
  4680. DosStopSession can only be called by a parent session for a child session. 
  4681. Neither the parent session itself, nor any grandchild, nor any other descendant 
  4682. session beyond a child session, nor any unrelated session, can be the target of 
  4683. this call. 
  4684.  
  4685. In the following code fragment, the child session specified by the ulSessionID 
  4686. parameter is terminated: 
  4687.  
  4688.     #define INCL_DOSPROCESS       /* Process and thread values */
  4689.     #define INCL_DOSSESMGR
  4690.     #include <os2.h>
  4691.  
  4692.     ULONG ulSessionID;
  4693.  
  4694.     DosStopSession(STOP_SESSION_SPECIFIED, ulSessionID);
  4695.  
  4696. An application can terminate all its child sessions by setting the first 
  4697. parameter to STOP_SESSION_ALL in the call to DosStopSession. If this is 
  4698. specified, the second parameter is ignored. 
  4699.  
  4700. A process running in a child session can ignore the request to terminate. If 
  4701. the process has set up its own exception handler, it might not terminate 
  4702. immediately after the call to DosStopSession. The only way the parent process 
  4703. can be certain that the child session has terminated is to wait for 
  4704. notification through the termination queue specified in the call to 
  4705. DosStartSession that started the session. When the child session terminates, 
  4706. the operating system writes a data element into the termination queue, 
  4707. specifying the child process identifier and the termination status. 
  4708.  
  4709. If the process in the session specified by DosStopSession has not ended, then 
  4710. DosStopSession still returns a normal return code. You can ensure that a 
  4711. process in a session has ended by waiting for notification from the termination 
  4712. queue specified with DosStartSession. 
  4713.  
  4714.  
  4715. ΓòÉΓòÉΓòÉ 6. Queues ΓòÉΓòÉΓòÉ
  4716.  
  4717. Communication between processes is valuable in a multitasking operating system 
  4718. to enable concurrent processes to work together. Queues are one of three forms 
  4719. of interprocess communication (IPC), the other forms of IPC being semaphores 
  4720. and pipes. 
  4721.  
  4722. This chapter describes how to create and use queues. Queues enable one or more 
  4723. processes to transfer data to a specific target process. 
  4724.  
  4725. Note:  The queues used for interprocess communication should not to be confused 
  4726.        with the message queues used for communication between Presentation 
  4727.        Manager (PM) and PM applications, nor with the printer queues used by 
  4728.        the print spooler in managing print jobs. 
  4729.  
  4730.  The following topics are related to the information in this chapter: 
  4731.  
  4732.    o  Memory (Shared Memory) 
  4733.    o  Program Execution and Control 
  4734.    o  Semaphores 
  4735.    o  Pipes 
  4736.  
  4737.  
  4738. ΓòÉΓòÉΓòÉ 6.1. About Queues ΓòÉΓòÉΓòÉ
  4739.  
  4740. A queue is a named, ordered list of elements that is used to pass information 
  4741. between threads of the same (related) process or between different (unrelated) 
  4742. processes. 
  4743.  
  4744. Processes pass information to a queue in the form of elements. An element is a 
  4745. 32-bit unit of information. Queue elements can be values, flags, pointers to 
  4746. shared memory regions, anything that can fit into 32 bits. The format of a 
  4747. queue element depends entirely on the process that creates the queue (the queue 
  4748. owner). Only the queue owner can read elements from the queue; other processes 
  4749. can only write to the queue. Reading an element automatically removes it from 
  4750. the queue. 
  4751.  
  4752. The process that creates the queue is known as the server process of the queue. 
  4753. The other processes that access the queue are known as client processes. 
  4754.  
  4755. The owner of the queue (the server process) can choose the order in which to 
  4756. read incoming information and can examine queue elements without removing them 
  4757. from the queue. Queue elements can be added and accessed in First-In-First-Out 
  4758. (FIFO), Last-In-First-Out (LIFO), or priority-based order. 
  4759.  
  4760. Any process that has the name of a queue can open the queue and write to it. 
  4761. The processes writing elements to the queue must use the format determined by 
  4762. the queue owner. 
  4763.  
  4764. Queues are very efficient. They pass only 32-bit sized elements, rather than 
  4765. large data structures. However, queues can be used only for one-way 
  4766. communication, because a client process can write to a queue but cannot read 
  4767. from one. 
  4768.  
  4769. Typically, processes use queues to transfer information about the contents of a 
  4770. shared memory. The elements in the queue could contain the address and length 
  4771. of data areas in shared memory objects. The sending process allocates a shared 
  4772. memory object and gives access to the shared memory to the queue owner. The 
  4773. sending process can free the shared memory after writing the elements to the 
  4774. queue because the shared memory will not be deallocated until the queue owner 
  4775. frees it. 
  4776.  
  4777. Any thread in the process that owns the queue can examine queue elements 
  4778. without removing them. This is called peeking at the queue. 
  4779.  
  4780. The operating system supplies the process identifier of the process that writes 
  4781. an element to the queue, so that a process reading from or peeking at the queue 
  4782. can determine the origin of the element. The process identifier is returned as 
  4783. part of a REQUESTDATA data structure. Threads can use the ulData field of the 
  4784. REQUESTDATA data structure to pass additional information about the queue 
  4785. element. 
  4786.  
  4787. If the queue is empty when a process attempts to read from it, the process can 
  4788. either wait for an element to become available or continue executing without 
  4789. reading from the queue. Semaphores can be used to indicate when an element is 
  4790. in the queue. 
  4791.  
  4792.  
  4793. ΓòÉΓòÉΓòÉ 6.1.1. Queues and Semaphores ΓòÉΓòÉΓòÉ
  4794.  
  4795. If a process manages only one queue, it typically waits for an element to 
  4796. become available. However, if a process manages several queues, waiting for one 
  4797. queue means that other queues cannot be read. To avoid wasting time while 
  4798. waiting, a process can supply an event semaphore when it calls DosReadQueue or 
  4799. DosPeekQueue. The process can then continue to execute without actually reading 
  4800. an element from the queue, because DosWriteQueue will post the semaphore only 
  4801. when an element is ready. The semaphore remains posted until someone resets it; 
  4802. usually  the queue owner process resets the semaphore after it reads all the 
  4803. available information from the queue. 
  4804.  
  4805. If a process uses a unique semaphore for each queue, it can use 
  4806. DosWaitMuxWaitSem to wait for the first queue to receive an element. 
  4807.  
  4808. Only one semaphore is permitted per queue. 
  4809.  
  4810.  
  4811. ΓòÉΓòÉΓòÉ 6.1.2. Queue Servers and Clients ΓòÉΓòÉΓòÉ
  4812.  
  4813. The server process and its threads have certain queue-managing privileges. Only 
  4814. the server process and its threads can: 
  4815.  
  4816.    o  Examine queue elements without removing them (DosPeekQueue) 
  4817.    o  Remove elements from the queue (DosReadQueue) 
  4818.    o  Purge all the elements in a queue (DosPurgeQueue) 
  4819.    o  Write to the queue without opening it first (DosWriteQueue) 
  4820.    o  Delete the queue (DosCloseQueue). 
  4821.  Both server and client processes can query the number of elements in the queue 
  4822.  using DosQueryQueue. 
  4823.  
  4824.  Client processes can query the queue (DosQueryQueue) and add elements to it 
  4825.  (DosWriteQueue), but they must first gain access to the queue by calling 
  4826.  DosOpenQueue. When a client process is finished with a queue, it ends its 
  4827.  access to the queue by calling DosCloseQueue. (Note that, unlike the server 
  4828.  process and its threads, a client process cannot use DosCloseQueue to delete a 
  4829.  queue.) 
  4830.  
  4831.  When a queue is opened by a client process, an access count is set to 1. Each 
  4832.  client process has its own access count. The access count is incremented 
  4833.  whenever a thread in a process opens the queue and decremented whenever a 
  4834.  thread in the process closes the queue. Access to the queue by the client 
  4835.  process ends when the access count for the process reaches 0. When the server 
  4836.  process closes the queue, the queue is terminated and removed from the system. 
  4837.  
  4838.  
  4839. ΓòÉΓòÉΓòÉ 6.1.3. Queue Element Order ΓòÉΓòÉΓòÉ
  4840.  
  4841. DosReadQueue reads either a specified element or the first element in the 
  4842. queue. The first element in the queue depends on the queue type, which is 
  4843. specified when the queue is created. A queue can have FIFO, LIFO, or priority 
  4844. ordering. 
  4845.  
  4846. Priority values range from 0 (lowest priority) through 15 (highest priority). 
  4847. The writing process assigns a priority to a queue element when the element is 
  4848. written to the queue. DosReadQueue reads elements from the queue in descending 
  4849. order of priority, regardless of the order in which DosWriteQueue placed the 
  4850. elements in the queue. Elements with equal priority are read in FIFO order. 
  4851.  
  4852.  
  4853. ΓòÉΓòÉΓòÉ 6.1.4. Obtaining Information about Queues and Queue Elements ΓòÉΓòÉΓòÉ
  4854.  
  4855. Any thread in the process that owns the queue can use DosPeekQueue to examine 
  4856. the elements in the queue to determine which one to actually read. Each call to 
  4857. DosPeekQueue returns the identifier of the next element in the queue, so the 
  4858. function can be called repeatedly to move through the queue. The identifier of 
  4859. the desired element can then be supplied to DosReadQueue. 
  4860.  
  4861. Any process that has opened a queue can use DosQueryQueue to determine the 
  4862. number of elements in the queue. This function also returns an error value if 
  4863. the queue owner has closed the queue. 
  4864.  
  4865.  
  4866. ΓòÉΓòÉΓòÉ 6.2. Using Queues ΓòÉΓòÉΓòÉ
  4867.  
  4868. Queues are useful for a process to manage input from other processes. The 
  4869. examples in the following sections show how to create and use queues. 
  4870.  
  4871. Note:  In the example code fragments that follow, error checking was left out 
  4872.        to conserve space. Applications should always check the return code that 
  4873.        the functions return. Control Program functions return an APIRET value. 
  4874.        A return code of 0 indicates success. If a non-zero value is returned, 
  4875.        an error occurred. 
  4876.  
  4877.  
  4878. ΓòÉΓòÉΓòÉ 6.2.1. Creating a Queue ΓòÉΓòÉΓòÉ
  4879.  
  4880. A thread creates a queue by using DosCreateQueue and specifying a queue name 
  4881. and the queue type as arguments. The queue name must be unique and have the 
  4882. following form: 
  4883.  
  4884.     \QUEUES\QueName
  4885.  
  4886. The "\QUEUES\" is required, though it need not be uppercase.  It is not a 
  4887. subdirectory. 
  4888.  
  4889. The QueName parameter must conform to the rules for OS/2 file names, although 
  4890. no actual file is created for the queue. 
  4891.  
  4892. The process that creates the queue is known as the server process of the queue. 
  4893. The other processes that access the queue are known as client processes. 
  4894.  
  4895. The following code fragment creates a FIFO queue named \queues\sample.que: 
  4896.  
  4897.     #define INCL_DOSQUEUES   /* Queue values */
  4898.     #include <os2.h>
  4899.  
  4900.     HQUEUE hq;
  4901.  
  4902.     DosCreateQueue(&hq, QUE_FIFO | QUE_CONVERT_ADDRESS,
  4903.                    "\\queues\\sample.que");
  4904.  
  4905. When the server process creates the queue, it determines whether the ordering 
  4906. of queue elements is based on arrival (FIFO or LIFO) or priority. If the 
  4907. ordering is based on priority, then priority values must be assigned whenever 
  4908. data is added to the queue. 
  4909.  
  4910. The server must also specify whether the operating system is to convert 16-bit 
  4911. addresses of elements placed in the queue by 16-bit processes to 32-bit 
  4912. addresses. 
  4913.  
  4914. After a process has created a queue, any thread in that process can access the 
  4915. queue with equal authority. 
  4916.  
  4917.  
  4918. ΓòÉΓòÉΓòÉ 6.2.2. Allocating Memory for Queue Data ΓòÉΓòÉΓòÉ
  4919.  
  4920. When queues are used only to pass the addresses to data rather than the data 
  4921. itself, processes must allocate shared memory objects for storing queue data. 
  4922. The two most common methods of storing queue data are: 
  4923.  
  4924.    o  Using a named shared memory object - for related processes 
  4925.    o  Using unnamed shared memory objects - for unrelated processes 
  4926.  
  4927.  
  4928. ΓòÉΓòÉΓòÉ 6.2.2.1. Named Shared Memory Objects ΓòÉΓòÉΓòÉ
  4929.  
  4930. Related processes generally use a single named shared memory object for storing 
  4931. queue data.  The server process allocates the memory object by calling 
  4932. DosAllocSharedMem. Care must be taken to ensure that the memory object is large 
  4933. enough to meet application requirements. 
  4934.  
  4935. The name of the shared memory object is established by agreement among the 
  4936. server and the client processes. For simplicity, the name can be the same as 
  4937. the queue name, except that the prefix \SHAREMEM\ must be used instead of 
  4938. \QUEUES\. 
  4939.  
  4940. A client process accesses the named shared memory object by calling 
  4941. DosGetNamedSharedMem. It must then call DosOpenQueue to gain access to the 
  4942. queue of the server. 
  4943.  
  4944. Before the server process ends, it releases the memory object by calling 
  4945. DosFreeMem. 
  4946.  
  4947.  
  4948. ΓòÉΓòÉΓòÉ 6.2.2.2. Unnamed Shared Memory Objects ΓòÉΓòÉΓòÉ
  4949.  
  4950. Unrelated processes generally use unnamed shared memory objects for storing 
  4951. queue data. This makes it possible for a client process to store data in a 
  4952. shared memory object without knowing its name. To use unnamed shared memory 
  4953. objects for storing queue data, the server process must take the following 
  4954. steps whenever it is called by a client: 
  4955.  
  4956.    1. Save the process identification (PID) of the client process. 
  4957.    2. Allocate an unnamed shared memory object for the data of the client 
  4958.       process by calling DosAllocSharedMem. 
  4959.    3. Give the client process the capability of accessing the memory object by 
  4960.       calling DosGiveSharedMem with the client's PID. 
  4961.  The client process must then call DosOpenQueue to gain access to the server's 
  4962.  queue. 
  4963.  
  4964.  After each client completes its queue requests or ends, the server calls 
  4965.  DosFreeMem to release the client's memory object. 
  4966.  
  4967.  
  4968. ΓòÉΓòÉΓòÉ 6.2.3. Opening a Queue ΓòÉΓòÉΓòÉ
  4969.  
  4970. Once the queue is created, the server process of the queue and the threads of 
  4971. the server process have immediate access to the queue and can proceed to access 
  4972. the queue. A client process must request access to a queue by calling 
  4973. DosOpenQueue. Once the queue is open, the client process can add an element to 
  4974. the queue with DosWriteQueue, and it can query the number of elements in the 
  4975. queue with DosQueryQueue. 
  4976.  
  4977. DosOpenQueue retrieves the queue handle and the process identifier of the queue 
  4978. owner. The function also increments the queue's access count. 
  4979.  
  4980. The following code fragment shows how another process would open the queue 
  4981. created with DosCreateQueue. 
  4982.  
  4983.     #define INCL_DOSQUEUES
  4984.     #include<os2.h>
  4985.  
  4986.     #define HF_STDOUT 1    /* Standard output handle */
  4987.  
  4988.     HQUEUE  hq;
  4989.     PID     pidOwner;
  4990.     ULONG   cbWritten;
  4991.     APIRET  rc;
  4992.  
  4993.     rc = DosOpenQueue(&pidOwner, &hq, "\\queues\\sample.que");
  4994.  
  4995.     if (rc) {
  4996.         DosWrite(HF_STDOUT, "\r\n Queue open failed. \r\n", 24, &cbWritten);
  4997.         DosExit(EXIT_PROCESS, 1);
  4998.     }
  4999.     else {
  5000.         DosWrite(HF_STDOUT, "\r\n Queue opened. \r\n", 19, &cbWritten);
  5001.     }
  5002.  
  5003. When it is finished with the queue, a thread in the client process ends its 
  5004. access by calling DosCloseQueue. DosCloseQueue decrements the access count for 
  5005. the process each time it is called. When the access count reaches 0, the 
  5006. connection between the client process and the queue is terminated. 
  5007.  
  5008. After a process has opened a queue, any thread in that process can access the 
  5009. queue with equal authority. 
  5010.  
  5011. Note:  If a queue was created by a call to the 16-bit DosCreateQueue, then it 
  5012.        is not accessible to 32-bit DosOpenQueue requests, and 
  5013.        ERROR_QUE_PROC_NO_ACCESS will be returned. 
  5014.  
  5015.  
  5016. ΓòÉΓòÉΓòÉ 6.2.4. Writing to a Queue ΓòÉΓòÉΓòÉ
  5017.  
  5018. The server process and any of its threads can add an element to a queue simply 
  5019. by calling DosWriteQueue. A client process, however, must first request access 
  5020. to the queue by calling DosOpenQueue. 
  5021.  
  5022. Processes that communicate by passing the addresses of shared memory objects 
  5023. through the queue must have a shared memory object that they each have access 
  5024. to. Once a process opens the queue, it can allocate shared memory by using 
  5025. DosAllocMem with the OBJ_GIVEABLE attribute and then give the shared memory to 
  5026. the queue owner with DosGiveSharedMem. 
  5027.  
  5028. A process that has opened a queue can write to the queue by using 
  5029. DosWriteQueue. The writing process must create elements in a form that the 
  5030. queue owner can read. 
  5031.  
  5032. The following code fragment adds an element to a queue. Assume that the caller 
  5033. has placed the handle of the queue into QueueHandle already. Assume also that 
  5034. DataBuffer has been set to point to a data element in shared memory, and that 
  5035. DataLength has been set to contain the length of the data element in shared 
  5036. memory. 
  5037.  
  5038.     #define INCL_DOSQUEUES   /* Queue values */
  5039.     #include <os2.h>
  5040.     #include <stdio.h>
  5041.  
  5042.     HQUEUE   QueueHandle;   /* Queue handle                         */
  5043.     ULONG    Request;       /* Request-identification data          */
  5044.     ULONG    DataLength;    /* Length of element being added        */
  5045.     PVOID    DataBuffer;    /* Element being added                  */
  5046.     ULONG    ElemPriority;  /* Priority of element being added      */
  5047.     APIRET   rc;            /* Return code                          */
  5048.  
  5049.     Request = 0;            /* Assume that no special data is being */
  5050.                             /* sent along with this write request   */
  5051.  
  5052.     ElemPriority = 0;       /* For priority-based queues: add the   */
  5053.                             /* new queue element at the logical end */
  5054.                             /* of the queue                         */
  5055.  
  5056.     rc = DosWriteQueue(QueueHandle, Request, DataLength,
  5057.                        DataBuffer, ElemPriority);
  5058.  
  5059.     if (rc != 0) {
  5060.         printf("DosWriteQueue error: return code = %ld", rc);
  5061.         return;
  5062.     }
  5063.  
  5064. Once the process has written to the queue, it frees the shared memory. However, 
  5065. the memory will not be freed until the queue owner also frees it. 
  5066.  
  5067. If the queue was created as a priority-based queue (as specified in the 
  5068. QueueFlags parameter of DosCreateQueue), then the priority of the element that 
  5069. is being added must be specified. 
  5070.  
  5071. If the server process has ended, or if it has closed the queue before 
  5072. DosWriteQueue is called, then ERROR_QUE_INVALID_HANDLE is returned. 
  5073.  
  5074.  
  5075. ΓòÉΓòÉΓòÉ 6.2.5. Reading from a Queue ΓòÉΓòÉΓòÉ
  5076.  
  5077. The queue owner (server process) and its threads can read an element from the 
  5078. queue by using DosReadQueue. The owner can read the first element in the queue 
  5079. by specifying 0 as the element number. Alternatively, the owner can read a 
  5080. particular element in the queue by specifying an element code returned from 
  5081. DosPeekQueue. This function is not available to client processes. 
  5082.  
  5083. DosReadQueue can either remove queue elements in the order that was specified 
  5084. when the queue was created (FIFO, LIFO, or priority), or it can use an element 
  5085. identifier from DosPeekQueue as input to remove a previously examined element. 
  5086.  
  5087. The following code fragment reads an element from the queue. Assume that the 
  5088. caller has placed the handle of the queue into QueueHandle already and that the 
  5089. identifier of the process that owns the queue has been placed into OwningPID 
  5090. already. 
  5091.  
  5092.     #define INCL_DOSQUEUES   /* Queue values */
  5093.     #include <os2.h>
  5094.     #include <stdio.h>
  5095.  
  5096.     HQUEUE        QueueHandle;   /* Queue handle                 */
  5097.     REQUESTDATA   Request;       /* Request-identification data  */
  5098.     ULONG         DataLength;    /* Length of element received   */
  5099.     PULONG        DataAddress;   /* Address of element received  */
  5100.     ULONG         ElementCode;   /* Request a particular element */
  5101.     BOOL32        NoWait;        /* No wait if queue is empty    */
  5102.     BYTE          ElemPriority;  /* Priority of element received */
  5103.     HEV           SemHandle;     /* Semaphore handle             */
  5104.     PID           OwningPID;     /* PID of queue owner           */
  5105.     APIRET        rc;            /* Return code                  */
  5106.  
  5107.     Request.pid = OwningPID;     /* Set request data block to indicate  */
  5108.                                  /* queue owner                         */
  5109.  
  5110.     ElementCode = 0;             /* Indicate that the read should start */
  5111.                                  /* at the front of the queue           */
  5112.  
  5113.     NoWait = 0;                  /* Indicate that the read should wait  */
  5114.                                  /* if the queue is currently empty     */
  5115.  
  5116.     SemHandle = 0;               /* Unused since this is a call that    */
  5117.                                  /* waits synchronously                 */
  5118.  
  5119.     rc = DosReadQueue(QueueHandle, &Request, &DataLength,
  5120.                       (PVOID *) &DataAddress, ElementCode, NoWait,
  5121.                       &ElemPriority, SemHandle);
  5122.  
  5123.     if (rc != 0) {
  5124.         printf("DosReadQueue error: return code = %ld", rc);
  5125.         return;
  5126.     }
  5127.  
  5128. On successful return, DataLength contains the size of the element on the queue 
  5129. that is pointed to by the pointer within DataAddress, ElemPriority has been 
  5130. updated to contain the priority of the queue element pointed to by DataAddress, 
  5131. and Request.ulData contains any special data that the DosWriteQueue caller 
  5132. placed into the queue. 
  5133.  
  5134. If the queue is empty and NoWait is set to DCWW_WAIT (0), the calling thread 
  5135. waits until an element is placed in the queue. If the queue is empty and NoWait 
  5136. is set to DCWW_NOWAIT (1), DosReadQueue returns immediately with 
  5137. ERROR_QUE_EMPTY. 
  5138.  
  5139. If NoWait is set to DCWW_NOWAIT, an event semaphore must be provided so that 
  5140. the calling thread can determine when an element has been placed in the queue. 
  5141. The semaphore is created by calling DosCreateEventSem, and its handle is 
  5142. supplied as a DosReadQueue parameter. The first time an event semaphore handle 
  5143. is supplied in a DosReadQueue or DosPeekQueue request for which DCWW_NOWAIT has 
  5144. been specified for a particular queue, the handle is saved by the system. The 
  5145. same handle must be supplied in all subsequent DosReadQueue and DosPeekQueue 
  5146. requests that are called for that queue; if a different handle is supplied, 
  5147. ERROR_INVALID_PARAMETER is returned. 
  5148.  
  5149. When a client process adds an element to the queue, the system automatically 
  5150. opens the semaphore (if necessary) and posts it. The server can either call 
  5151. DosQueryEventSem periodically to determine whether the semaphore has been 
  5152. posted, or it can call DosWaitEventSem. DosWaitEventSem causes the calling 
  5153. thread to block until the semaphore is posted. 
  5154.  
  5155. After the event semaphore has been posted, the calling thread must call 
  5156. DosReadQueue again to remove the newly added queue element. 
  5157.  
  5158. If QUE_CONVERT_ADDRESS is specified in the call to DosCreateQueue, the 
  5159. operating system will automatically convert 16-bit addresses to 32-bit 
  5160. addresses. 
  5161.  
  5162.  
  5163. ΓòÉΓòÉΓòÉ 6.2.6. Peeking at a Queue ΓòÉΓòÉΓòÉ
  5164.  
  5165. The server process and its threads can examine a queue element by calling 
  5166. DosPeekQueue. This function is not available to client processes. 
  5167.  
  5168. Unlike DosReadQueue, DosPeekQueue does not remove the element from the queue. 
  5169.  
  5170. DosPeekQueue can either examine elements in the order that was specified when 
  5171. the queue was created (FIFO, LIFO, or priority), or it can examine the next 
  5172. element in the queue after a previous DosPeekQueue request has been called. By 
  5173. making multiple DosPeekQueue requests, the server process can search through a 
  5174. queue, examining each element in turn. When it locates the element it is 
  5175. searching for, the server process can remove the element from the queue by 
  5176. calling DosReadQueue. 
  5177.  
  5178. If several threads are using the same queue, the process writing to the queue 
  5179. can use the ulData field of the REQUESTDATA data structure to indicate that an 
  5180. element is directed to a particular thread. The thread can peek at the queue 
  5181. whenever data is available and read any elements containing the appropriate 
  5182. value in the ulData field. 
  5183.  
  5184. The following code fragment shows how a thread can use DosPeekQueue to examine 
  5185. the elements in a queue. Assume that a previous call to DosOpenQueue provided 
  5186. the queue handle that is contained in QueueHandle. Assume that the identifier 
  5187. of the process that owns the queue has been placed into OwningPID already. 
  5188.  
  5189.     #define INCL_DOSQUEUES       /* Queue values */
  5190.     #include <os2.h>
  5191.     #include <stdio.h>
  5192.  
  5193.     HQUEUE        QueueHandle;   /* Queue handle                  */
  5194.     REQUESTDATA   Request;       /* Request-identification data   */
  5195.     ULONG         DataLength;    /* Length of examined element    */
  5196.     PVOID         DataAddress;   /* Address of examined element   */
  5197.     ULONG         ElementCode;   /* Indicator of examined element */
  5198.     BOOL32        NoWait;        /* No wait if queue is empty     */
  5199.     BYTE          ElemPriority;  /* Priority of examined element  */
  5200.     HEV           SemHandle;     /* Semaphore handle              */
  5201.     PID           OwningPID;     /* PID of queue owner            */
  5202.     APIRET        rc;            /* Return code                   */
  5203.  
  5204.     Request.pid = OwningPID;     /* Set request data block to indicate   */
  5205.                                  /* queue owner                          */
  5206.  
  5207.     ElementCode = 0;             /* Indicate that the peek should start  */
  5208.                                  /* at the front of the queue            */
  5209.  
  5210.     NoWait = DCWW_WAIT           /* Indicate that the peek call should   */
  5211.                                  /* wait if the queue is currently empty */
  5212.  
  5213.     SemHandle = 0;               /* Unused since this is a call that     */
  5214.                                  /* synchronously waits                  */
  5215.  
  5216.     rc = DosPeekQueue(QueueHandle, &Request, &DataLength,
  5217.                       &DataAddress, &ElementCode, NoWait,
  5218.                       &ElemPriority, SemHandle);
  5219.  
  5220.     if (rc != 0) {
  5221.         printf("DosPeekQueue error: return code = %ld", rc);
  5222.         return;
  5223.     }
  5224.  
  5225. On successful return, DataLength contains the size of the element on the queue 
  5226. that is pointed to by the pointer within DataAddress, ElementCode has been 
  5227. updated to indicate the next queue element, ElemPriority has been updated to 
  5228. contain the priority of the queue element pointed to by DataAddress, and 
  5229. Request.ulData contains any special data that the DosWriteQueue caller placed 
  5230. into the queue. 
  5231.  
  5232. If the queue is empty and NoWait is set to DCWW_WAIT (0), the calling thread 
  5233. waits until an element is placed in the queue. If the queue is empty and NoWait 
  5234. is set to DCWW_NOWAIT (1), DosPeekQueue returns immediately with 
  5235. ERROR_QUE_EMPTY. 
  5236.  
  5237. If NoWait is set to DCWW_NOWAIT, an event semaphore must be provided so that 
  5238. the calling thread can determine when an element has been placed in the queue. 
  5239. The semaphore is created by calling DosCreateEventSem, and its handle is 
  5240. supplied as a DosPeekQueue parameter. The first time an event semaphore handle 
  5241. is supplied in a DosPeekQueue or DosReadQueue request for which DCWW_NOWAIT has 
  5242. been specified for a particular queue, the handle is saved by the system. The 
  5243. same handle must be supplied in all subsequent DosPeekQueue and DosReadQueue 
  5244. requests that are called for that queue; if a different handle is supplied, 
  5245. ERROR_INVALID_PARAMETER is returned. 
  5246.  
  5247. When a client process adds an element to the queue, the system automatically 
  5248. opens the semaphore (if necessary) and posts it. The server can either call 
  5249. DosQueryEventSem periodically to determine whether the semaphore has been 
  5250. posted, or it can call DosWaitEventSem. DosWaitEventSem causes the calling 
  5251. thread to block until the semaphore is posted. 
  5252.  
  5253. After the event semaphore has been posted, the calling thread must call 
  5254. DosPeekQueue again to examine the newly added queue element. 
  5255.  
  5256. If QUE_CONVERT_ADDRESS is specified in the call to DosCreateQueue, the 
  5257. operating system will automatically convert 16-bit addresses to 32-bit 
  5258. addresses. 
  5259.  
  5260.  
  5261. ΓòÉΓòÉΓòÉ 6.2.7. Purging a Queue ΓòÉΓòÉΓòÉ
  5262.  
  5263. The server process or any of its threads can empty a queue of all its elements 
  5264. by calling DosPurgeQueue. This function is not available to client processes. 
  5265.  
  5266. Warning: This is an unconditional purge of all elements in the queue. 
  5267.  
  5268. The following code fragment shows how the owner of a queue can empty the queue 
  5269. of all data elements. Assume that the owner of the queue has saved the queue's 
  5270. handle (obtained in a previous call to DosCreateQueue) in QueueHandle. 
  5271.  
  5272.     #define INCL_DOSQUEUES    /* Queue values */
  5273.     #include <os2.h>
  5274.     #include <stdio.h>
  5275.  
  5276.     HQUEUE   QueueHandle;     /* Queue handle */
  5277.     APIRET   rc;              /* Return code  */
  5278.  
  5279.     rc = DosPurgeQueue(QueueHandle);
  5280.  
  5281.     if (rc != 0) {
  5282.         printf("DosPurgeQueue error: return code = %ld", rc);
  5283.         return;
  5284.     }
  5285.  
  5286.  
  5287. ΓòÉΓòÉΓòÉ 6.2.8. Closing a Queue ΓòÉΓòÉΓòÉ
  5288.  
  5289. DosCloseQueue can be used both to end access to a queue and to delete a queue. 
  5290. The action taken as a result of a DosCloseQueue request depends on: 
  5291.  
  5292.    o  Whether the requesting process is the server process or a client process 
  5293.    o  The value of the access count, which is maintained for each client 
  5294.       process by the operating system. The access count for a client process is 
  5295.       incremented whenever DosOpenQueue is called, and decremented whenever 
  5296.       DosCloseQueue is called. 
  5297.  
  5298.  If the requesting process is a client, and the access count equals 0, 
  5299.  DosCloseQueue ends the client's access to the queue, but the queue itself is 
  5300.  not affected. If the access count does not equal 0, the count is decremented, 
  5301.  but the process retains access to the queue. 
  5302.  
  5303.  If the requesting process is the server, DosCloseQueue purges any outstanding 
  5304.  elements from the queue and deletes the queue regardless of the access count; 
  5305.  client processes that still have the queue open receive 
  5306.  ERROR_QUE_INVALID_HANDLE on their next request. 
  5307.  
  5308.  
  5309. ΓòÉΓòÉΓòÉ 7. Semaphores ΓòÉΓòÉΓòÉ
  5310.  
  5311. Communication between processes is valuable in a multitasking operating system 
  5312. to enable concurrent processes to work together. Semaphores are one of three 
  5313. forms of interprocess communication (IPC), the other forms of IPC being pipes 
  5314. and queues. 
  5315.  
  5316. This chapter describes how to create and use semaphores. Semaphores enable an 
  5317. application to signal the completion of tasks and control access to resources 
  5318. that are shared between more than one thread or process. 
  5319.  
  5320. The following topics are related to the information in this chapter: 
  5321.  
  5322.    o  Memory (Shared Memory) 
  5323.    o  Program Execution and Control 
  5324.    o  Pipes 
  5325.    o  Queues 
  5326.  
  5327.  
  5328. ΓòÉΓòÉΓòÉ 7.1. About Semaphores ΓòÉΓòÉΓòÉ
  5329.  
  5330. Semaphores signal the beginning or ending of an operation and provide mutually 
  5331. exclusive ownership of resources. Typically, semaphores are used to prevent 
  5332. more than one process or thread within a process from accessing a resource, 
  5333. such as shared memory, at the same time. 
  5334.  
  5335. Semaphores are defined by the operating system and reside in an internal memory 
  5336. buffer. They are divided into three types, according to the functionality they 
  5337. provide: 
  5338.  
  5339.    o  Event semaphores enable a thread to notify waiting threads that an event 
  5340.       has occurred. The waiting threads then resume execution, performing 
  5341.       operations that are dependent on the completion of the signaled event. 
  5342.  
  5343.    o  Mutual exclusion (mutex) semaphores enable threads to serialize their 
  5344.       access to shared resources. That is, ownership of a mutex semaphore is 
  5345.       used by cooperating threads as a prerequisite for performing operations 
  5346.       on a resource. (Threads cooperate by using the mutex semaphore functions 
  5347.       to ensure that access to the resource is mutually exclusive.) 
  5348.  
  5349.    o  Multiple Wait (muxwait) semaphores enable threads to wait either for 
  5350.       multiple events to occur, or for multiple resources to become available. 
  5351.       Alternatively, a flag can be set so that a thread waits for any one of 
  5352.       multiple events to occur, or for any one of multiple resources to become 
  5353.       available. 
  5354.  
  5355.  
  5356. ΓòÉΓòÉΓòÉ 7.1.1. Event Semaphores ΓòÉΓòÉΓòÉ
  5357.  
  5358. An event semaphore provides a signaling mechanism among threads or processes, 
  5359. ensuring that events occur in the desired sequence. Event semaphores are used 
  5360. by one thread to signal other threads that an event has occurred. An 
  5361. application can use this type of semaphore to block a thread or process until 
  5362. the event has occurred. 
  5363.  
  5364. An event semaphore has two states, reset and posted. When an event semaphore is 
  5365. in the reset state, the operating system blocks any thread or process that is 
  5366. waiting on the semaphore. When an event semaphore is in the posted state, all 
  5367. threads or processes waiting on the semaphore resume execution. 
  5368.  
  5369. For example, assume thread 1 is allocating a shared memory object and threads 2 
  5370. and 3 must wait for the memory to be allocated before they attempt to examine 
  5371. its contents. Before thread 1 allocates the memory, it creates an event 
  5372. semaphore, specifying the initial state of the semaphore as reset. (If the 
  5373. event semaphore has already been created, thread 1 simply resets the 
  5374. semaphore.) Threads 2 and 3 use DosWaitEventSem to wait for the semaphore to 
  5375. signal that the event, in this case the allocation and preparation of the 
  5376. shared memory object, has been completed. Because the semaphore was reset by 
  5377. thread 1, threads 2 and 3 are blocked when they call DosWaitEventSem. After 
  5378. thread 1 has finished allocating and placing data in the shared memory object, 
  5379. it signals the completion of its task by posting the event semaphore. The 
  5380. posting of the event semaphore unblocks threads 2 and 3, enabling them to 
  5381. resume execution. They can then proceed to examine the contents of the 
  5382. allocated memory. 
  5383.  
  5384. In the example above, one thread controls the resetting and posting of the 
  5385. event semaphore, while other threads merely wait on the semaphore. Another 
  5386. approach could be for an application or thread to reset an event semaphore, 
  5387. then block itself on that semaphore. At a later time, another application or 
  5388. thread would post the event semaphore, unblocking the first thread. 
  5389.  
  5390.  
  5391. ΓòÉΓòÉΓòÉ 7.1.2. Mutual Exclusion (Mutex) Semaphores ΓòÉΓòÉΓòÉ
  5392.  
  5393. A mutual exclusion (mutex) semaphore protects resources (such as files, data in 
  5394. memory, and peripheral devices) from simultaneous access by several processes. 
  5395. Mutex semaphores enable threads to serialize their access to resources. It does 
  5396. so by preventing the processes from concurrently executing the sections of code 
  5397. through which access is made. These sections of code are called critical 
  5398. sections. For example, a mutex semaphore could be used to prevent two or more 
  5399. threads from simultaneously writing to the same file on a disk. 
  5400.  
  5401. Before a thread can execute a mutex-protected critical section, it must request 
  5402. and receive ownership of the mutex semaphore. Only the thread that has gained 
  5403. ownership of the mutex semaphore is permitted to perform operations on the 
  5404. protected resource. Only one thread at a time can own the mutex semaphore, and 
  5405. the owner thread retains ownership  until it finishes executing its critical 
  5406. section. When finished, the owner thread releases the mutex semaphore, enabling 
  5407. another thread to become the owner. 
  5408.  
  5409. When a thread requests ownership of a mutex semaphore that is already owned, 
  5410. the operating system blocks the thread. When more than one thread requests 
  5411. ownership of the same semaphore, the operating system queues the requests and 
  5412. grants subsequent ownership based on the thread's priority and the order in 
  5413. which the requests were received. 
  5414.  
  5415. If more than one thread is blocked on a DosRequestMutexSem request, then 
  5416. ownership is given to the thread that has the highest priority level. If more 
  5417. than one of the waiting threads have the same priority level, then FIFO 
  5418. ordering is used to determine which thread is unblocked and given ownership of 
  5419. the semaphore. 
  5420.  
  5421. For example, both thread 1 and thread 2 must write information to the same disk 
  5422. file. Thread 1 claims ownership of an agreed-upon mutex semaphore and starts 
  5423. writing its information to the file. If thread 2 also requests ownership of the 
  5424. semaphore, it will be blocked. When thread 1 has finished writing to the file, 
  5425. it releases the semaphore. The operating system then unblocks thread 2 and 
  5426. designates it as the new owner of the semaphore so that it can write to the 
  5427. file. 
  5428.  
  5429. During process termination, after delivery of process-termination exceptions 
  5430. and unwind exceptions, if any threads in the process aside from Thread 1 (the 
  5431. main thread) own a mutex semaphore, ownership of the semaphore (and therefore, 
  5432. the shared resource) passes to Thread 1. This gives Thread 1 a last chance to 
  5433. clean up the semaphore and the shared resource before the process ends. If 
  5434. Thread 1 ends without releasing the semaphore, all threads that are currently 
  5435. waiting on ownership of the semaphore will be unblocked with the SEM_OWNER_DIED 
  5436. return code. Any thread that attempts to open it or request ownership of the 
  5437. semaphore will receive a SEM_OWNER_DIED return code. 
  5438.  
  5439. The recommended way to clean up semaphores, and other resources, is for each 
  5440. thread, especially Thread 1, to have an exception handler to handle clean up 
  5441. during process termination (the XCPT_PROCESS_TERMINATE or 
  5442. XCPT_ASYNC_PROCESS_TERMINATE exceptions). When it is not possible to register 
  5443. an exception handler for a thread, (a DLL, for example, must de-register its 
  5444. exception handlers when it returns control to the thread that called it), you 
  5445. should add a clean up routine to the exit list of the process. 
  5446.  
  5447.  
  5448. ΓòÉΓòÉΓòÉ 7.1.3. Multiple Wait (Muxwait) Semaphores ΓòÉΓòÉΓòÉ
  5449.  
  5450. A multiple wait (muxwait) semaphore enables a thread to wait on several event 
  5451. or mutex semaphores simultaneously. A muxwait semaphore is a compound semaphore 
  5452. that consists of a list of up to 64 event semaphores or mutex semaphores (the 
  5453. two types cannot be mixed). 
  5454.  
  5455. A flag is set when the muxwait semaphore is created to enable threads to use 
  5456. the semaphore in either of two ways: 
  5457.  
  5458.    o  Threads can wait for all of the mutex semaphores to be released, or for 
  5459.       all of the event semaphores to be posted. 
  5460.  
  5461.    o  Threads can wait for any one of the mutex semaphores in the list to be 
  5462.       released, or for any one of the event semaphores in the list to be 
  5463.       posted. 
  5464.  
  5465.  Depending on the value of the flag, a muxwait semaphore is said to have 
  5466.  cleared when either any or all of the semaphores in the muxwait list have been 
  5467.  posted or released. 
  5468.  
  5469.  For example, suppose a thread requires access to several regions of shared 
  5470.  memory at the same time. The operating system blocks the thread until the 
  5471.  thread acquires ownership of all the mutex semaphores protecting the shared 
  5472.  regions. The thread can then access all the memory regions. Meanwhile, the 
  5473.  operating system prevents access by other threads. 
  5474.  
  5475.  
  5476. ΓòÉΓòÉΓòÉ 7.1.4. Named and Anonymous Semaphores ΓòÉΓòÉΓòÉ
  5477.  
  5478. A semaphore can be either named or anonymous. A named semaphore is always 
  5479. shared; that is, it is always available to any process that knows the name. An 
  5480. anonymous semaphore can be either private to a process or shared among 
  5481. processes, depending on whether the application includes the DC_SEM_SHARED flag 
  5482. in the function that creates the semaphore. A semaphore intended for use solely 
  5483. among threads of the same process can be anonymous and private. 
  5484.  
  5485. The operating system creates a named semaphore when an application specifies a 
  5486. name in the function that creates the semaphore. The name must have the 
  5487. following form: 
  5488.  
  5489.     \SEM32\SemName
  5490.  
  5491. The "\SEM32\" is required, though it need not be uppercase. The semaphore name 
  5492. must conform to the rules for OS/2 file names, although no actual file is 
  5493. created for the semaphore. If the application does not specify a name in the 
  5494. function that creates the semaphore, the operating system creates an anonymous 
  5495. semaphore. 
  5496.  
  5497. The OS/2 operating system permits a system-wide maximum of 65536 (64K) shared 
  5498. semaphores. In addition, each process can use up to 65536 (64K) private 
  5499. semaphores. 
  5500.  
  5501. A shared muxwait semaphore must contain either all shared event semaphores or 
  5502. all shared mutex semaphores. However, a private muxwait semaphore can contain a 
  5503. combination of shared and private event or mutex semaphores. The operating 
  5504. system generates a unique handle when it creates a semaphore. Processes must 
  5505. obtain this handle before they can access the semaphore. A semaphore's handle 
  5506. is always available to the process that created the semaphore. A process can 
  5507. obtain the handle of a named semaphore created in another process by using the 
  5508. appropriate semaphore-opening function. A process that requires access to an 
  5509. anonymous shared semaphore that was created in another process must obtain the 
  5510. handle of the semaphore through some other form of interprocess communication, 
  5511. such as a pipe or a queue. 
  5512.  
  5513.  
  5514. ΓòÉΓòÉΓòÉ 7.1.5. Semaphore Management ΓòÉΓòÉΓòÉ
  5515.  
  5516. After one process creates a semaphore, threads in other processes must open the 
  5517. semaphore before they can access it. (Creating a semaphore automatically opens 
  5518. it for the creating process.) The open operation ensures that the process is a 
  5519. valid user of the semaphore. The operating system keeps track of the number of 
  5520. open operations that each process performs on a semaphore. A process can have 
  5521. up to 65535 (64K - 1) open operations performed on a semaphore at any one time. 
  5522.  
  5523. If a process finishes using a semaphore and will not use it again, the process 
  5524. should close the semaphore so that the operating system can free the memory the 
  5525. semaphore is using. The operating system returns the ERROR_SEM_BUSY error value 
  5526. if a thread tries to close a semaphore that has another thread in the same 
  5527. process still waiting for it. 
  5528.  
  5529. If a process terminates with open semaphores, the operating system 
  5530. automatically closes the semaphores for that process. 
  5531.  
  5532. Semaphores reside in a memory buffer rather than a disk file. Therefore, when 
  5533. the last process that has a semaphore open exits or closes that semaphore, the 
  5534. operating system frees the associated handle or name. 
  5535.  
  5536. When an application calls a function that causes a thread to wait on a 
  5537. semaphore, the application can specify the amount of time for the thread to 
  5538. wait. When the interval elapses without the semaphore being posted or released, 
  5539. the function returns the ERROR_TIMEOUT error value and the thread continues 
  5540. running. The application can provide a specific time-out value in milliseconds, 
  5541. or it can specify either the SEM_INDEFINITE_WAIT or the SEM_IMMEDIATE_RETURN 
  5542. flag. If a thread is interrupted while it is waiting on a semaphore, the 
  5543. ERROR_INTERRUPT error value is returned to the caller. 
  5544.  
  5545.  
  5546. ΓòÉΓòÉΓòÉ 7.2. Using Event Semaphores ΓòÉΓòÉΓòÉ
  5547.  
  5548. An application can use an event semaphore to trigger execution of other 
  5549. processes. This is useful if, for example, one process provides data to many 
  5550. other processes. Using an event semaphore frees the other process from the 
  5551. trouble of polling to determine when new data is available. 
  5552.  
  5553. Note:  In the example code fragments that follow, error checking was left out 
  5554.        to conserve space. Applications should always check the return code that 
  5555.        the functions return. Control Program functions return an APIRET value. 
  5556.        A return code of 0 indicates success. If a non-zero value is returned, 
  5557.        an error occurred. 
  5558.  
  5559.  
  5560. ΓòÉΓòÉΓòÉ 7.2.1. Creating an Event Semaphore ΓòÉΓòÉΓòÉ
  5561.  
  5562. Processes create an event semaphore by using DosCreateEventSem. The process 
  5563. that controls the event or resource is usually the one that creates the 
  5564. semaphore, but it does not have to be. 
  5565.  
  5566. Threads in the process that creates the semaphore do not have to open the 
  5567. semaphore before using it. DosCreateEventSem obtains access to the semaphore 
  5568. for the calling process and its threads. Threads in other processes must call 
  5569. DosOpenEventSem to open the semaphore before they can use it. 
  5570.  
  5571. Event semaphores can be defined as either private or shared: 
  5572.  
  5573.    o  Private semaphores are always unnamed and are therefore always identified 
  5574.       by their handles. They can be used only by threads within a single 
  5575.       process. 
  5576.  
  5577.    o  Shared semaphores can be either named or unnamed. If named, they can be 
  5578.       opened using either the name or the handle. The handle returned by 
  5579.       DosOpenEventSem is then used to identify the semaphore for all other 
  5580.       functions. Semaphore names must include the prefix \SEM32\ and must 
  5581.       conform to file system naming conventions. Shared semaphores can be used 
  5582.       by threads in multiple processes. 
  5583.  
  5584.  In the following code fragment, the controlling process creates a named event 
  5585.  semaphore and posts the semaphore after writing data to a shared file: 
  5586.  
  5587.       #define INCL_DOSSEMAPHORES   /* Semaphore values */
  5588.       #include <os2.h>
  5589.  
  5590.       HEV hevWriteEvent;
  5591.  
  5592.       DosCreateEventSem("\\sem32\\wrtevent",          /* Named-shared semaphore */
  5593.                          &hevWriteEvent, 0, FALSE);   /* Initially reset        */
  5594.           .
  5595.           .
  5596.           /* Write data to shared file. */
  5597.           .
  5598.           .
  5599.       DosPostEventSem(hevWriteEvent);                 /* Posts the event        */
  5600.           .
  5601.           .    /* Continue execution. */
  5602.           .
  5603.  
  5604.  There is a system-wide limit of 65536 (64K) shared semaphores (including 
  5605.  mutex, event, and muxwait semaphores); in addition, each process can have up 
  5606.  to 65536 (64K) private semaphores. 
  5607.  
  5608.  When an event semaphore is created, a flag is used to specify the initial 
  5609.  state of the event semaphore, either reset or posted. If the initial state is 
  5610.  reset, a thread that calls DosWaitEventSem will be blocked until a process 
  5611.  that has access to the semaphore uses DosPostEventSem to post the event 
  5612.  semaphore. If the initial state is posted, then a thread that calls 
  5613.  DosWaitEventSem will return immediately to continue its execution. If the 
  5614.  thread calling DosWaitEventSem is not in the process that created the 
  5615.  semaphore, the thread must open the semaphore with DosOpenEventSem before 
  5616.  calling DosWaitEventSem. 
  5617.  
  5618.  The operating system maintains a usage count for each semaphore. 
  5619.  DosCreateEventSem initializes the usage count to 1. Thereafter, each call to 
  5620.  DosOpenEventSem increments the count, and each call to DosCloseEventSem 
  5621.  decrements it. 
  5622.  
  5623.  
  5624. ΓòÉΓòÉΓòÉ 7.2.2. Opening an Event Semaphore ΓòÉΓòÉΓòÉ
  5625.  
  5626. When a process creates an event semaphore, all of the threads that belong to 
  5627. the process have immediate access to the semaphore. 
  5628.  
  5629. Threads in other processes must open the semaphore by calling DosOpenEventSem 
  5630. before they can use the semaphore in any other event semaphore function. 
  5631.  
  5632. The following code fragment shows how processes can open an event semaphore 
  5633. that was created in a different process and then wait for the event to be 
  5634. posted: 
  5635.  
  5636.     #define INCL_DOSSEMAPHORES   /* Semaphore values */
  5637.     #include <os2.h>
  5638.  
  5639.     HEV hevEventHandle = 0;                 /* Must be 0 because we are opening */
  5640.                                             /* the semaphore by name            */
  5641.  
  5642.     DosOpenEventSem("\\sem32\\wrtevent", &hevEventHandle);
  5643.  
  5644.     DosWaitEventSem(hevEventHandle,
  5645.                     SEM_INDEFINITE_WAIT);   /* Waits until event is posted      */
  5646.         .
  5647.         .    /* Read from file when event is posted. */
  5648.         .
  5649.  
  5650. Applications can open an event semaphore by name or by handle. If the name is 
  5651. used to open the semaphore, as in the code fragment above, the handle parameter 
  5652. must be 0. If the handle is used to open the semaphore, the name parameter must 
  5653. be NULL. 
  5654.  
  5655. Access to semaphores is on a per-process basis. Therefore, a semaphore that has 
  5656. been opened by one thread in a process is open to all other threads in that 
  5657. process as well. 
  5658.  
  5659. DosOpenEventSem merely provides access to an event semaphore. In order to wait 
  5660. for an event semaphore to be posted, a thread must call DosWaitEventSem. In 
  5661. order to post or reset an open event semaphore, a thread uses DosPostEventSem 
  5662. or DosResetEventSem respectively. 
  5663.  
  5664. When a process no longer requires access to an event semaphore, it closes the 
  5665. semaphore by calling DosCloseEventSem. If a process ends without closing an 
  5666. open semaphore, the semaphore is closed by the operating system. 
  5667.  
  5668. Each call to DosOpenEventSem increments the usage count of the semaphore. This 
  5669. count is initialized to 1 when the semaphore is created and is decremented by 
  5670. each call to DosCloseEventSem. When the usage count reaches 0, the semaphore is 
  5671. deleted by the operating system. 
  5672.  
  5673. Calls to DosOpenEventSem and DosCloseEventSem can be nested, but the usage 
  5674. count for a semaphore cannot exceed 65535. If an attempt is made to exceed this 
  5675. number, ERROR_TOO_MANY_OPENS is returned. 
  5676.  
  5677.  
  5678. ΓòÉΓòÉΓòÉ 7.2.3. Closing an Event Semaphore ΓòÉΓòÉΓòÉ
  5679.  
  5680. When a process no longer requires access to an event semaphore, it closes the 
  5681. semaphore by calling DosCloseEventSem. 
  5682.  
  5683. The following code fragment closes an event semaphore. Assume that the handle 
  5684. of the semaphore has been placed into HEV already. 
  5685.  
  5686.     #define INCL_DOSSEMAPHORES   /* Semaphore values */
  5687.     #include <os2.h>
  5688.     #include <stdio.h>
  5689.  
  5690.     HEV     hev;     /* Event semaphore handle */
  5691.     APIRET  rc;      /* Return code            */
  5692.  
  5693.     rc = DosCloseEventSem(hev);
  5694.  
  5695.     if (rc != 0) {
  5696.         printf("DosCloseEventSem error: return code = %ld", rc);
  5697.         return;
  5698.     }
  5699.  
  5700. Calls to DosOpenEventSem and DosCloseEventSem can be nested, but the usage 
  5701. count for a semaphore cannot exceed 65535. If an attempt is made to exceed this 
  5702. number, ERROR_TOO_MANY_OPENS is returned. 
  5703.  
  5704. If a process ends without closing an open semaphore, the semaphore is closed by 
  5705. the operating system. 
  5706.  
  5707. Each call to DosCloseEventSem decrements the usage count of the semaphore. This 
  5708. count is initialized to 1 when the semaphore is created and is incremented by 
  5709. each call to DosOpenEventSem. When the usage count reaches 0, the semaphore is 
  5710. deleted from the operating system. The call to DosCloseEventSem that decrements 
  5711. the usage count to 0 and causes the semaphore to be deleted is referred to as 
  5712. the final close. If a thread attempts to perform the final close for a 
  5713. semaphore while another thread in the same process is still waiting for it, 
  5714. ERROR_SEM_BUSY is returned. 
  5715.  
  5716.  
  5717. ΓòÉΓòÉΓòÉ 7.2.4. Resetting an Event Semaphore ΓòÉΓòÉΓòÉ
  5718.  
  5719. DosResetEventSem resets an event semaphore if it is not already reset, and 
  5720. returns the number of times the semaphore was posted since it was last reset. 
  5721. All threads that subsequently call DosWaitEventSem for this semaphore will be 
  5722. blocked. 
  5723.  
  5724. Any thread belonging to the process that created the event semaphore can change 
  5725. the state of the semaphore to reset by calling DosResetEventSem. Threads in 
  5726. other processes can also call DosResetEventSem, but they must first gain access 
  5727. to the semaphore by calling DosOpenEventSem. 
  5728.  
  5729. When an event semaphore is in the reset state, any thread that calls 
  5730. DosWaitEventSem to wait for the semaphore will be blocked. When the event 
  5731. semaphore is posted, all of the threads that are waiting for the semaphore are 
  5732. released to continue execution. 
  5733.  
  5734. The following code fragment resets an event semaphore. Assume that the handle 
  5735. of the semaphore has been placed into HEV already. 
  5736.  
  5737.     #define INCL_DOSSEMAPHORES   /* Semaphore values */
  5738.     #include <os2.h>
  5739.     #include <stdio.h>
  5740.  
  5741.     HEV     hev;        /* Event semaphore handle                        */
  5742.     ULONG   ulPostCt;   /* Post count for the event semaphore (returned) */
  5743.     APIRET  rc;         /* Return code                                   */
  5744.  
  5745.     rc = DosResetEventSem(hev, &ulPostCt);
  5746.  
  5747.     if (rc != 0) {
  5748.         printf("DosResetEventSem error: return code = %ld", rc);
  5749.         return;
  5750.     }
  5751.  
  5752. DosResetEventSem returns the post count of the event semaphore and resets the 
  5753. post count to 0. The post count is the number of times the semaphore has been 
  5754. posted (using DosPostEventSem) since the last time the semaphore was in the 
  5755. reset state. (An event semaphore can be reset when it is created, as well as by 
  5756. calling DosResetEventSem.) The post count can also be obtained by calling 
  5757. DosQueryEventSem. 
  5758.  
  5759. If the event semaphore is already reset when DosResetEventSem is called, 
  5760. ERROR_ALREADY_RESET is returned, along with a post count of 0. The semaphore is 
  5761. not reset a second time. 
  5762.  
  5763.  
  5764. ΓòÉΓòÉΓòÉ 7.2.5. Posting an Event Semaphore ΓòÉΓòÉΓòÉ
  5765.  
  5766. DosPostEventSem posts the semaphore, if it is not already posted, and 
  5767. increments the post count. All threads that have called DosWaitEventSem for 
  5768. this semaphore are unblocked and resume execution. Threads that call 
  5769. DosWaitEventSem after the event semaphore has been posted and before the next 
  5770. time it is reset, will return immediately from a call to DosWaitEventSem and 
  5771. continue execution. If the semaphore is subsequently reset, threads that call 
  5772. DosWaitEventSem will again be blocked. 
  5773.  
  5774. Any thread in the process that created an event semaphore can post the 
  5775. semaphore by calling DosPostEventSem. Threads in other processes can also call 
  5776. DosPostEventSem, but they must first gain access to the semaphore by calling 
  5777. DosOpenEventSem. 
  5778.  
  5779. The following code fragment posts a system event semaphore. Assume that the 
  5780. handle of the semaphore has been placed into HEV already. 
  5781.  
  5782.     #define INCL_DOSSEMAPHORES   /* Semaphore values */
  5783.     #include <os2.h>
  5784.     #include <stdio.h>
  5785.  
  5786.     HEV     hev;     /* Event semaphore handle */
  5787.     APIRET  rc;      /* Return code            */
  5788.  
  5789.     rc = DosPostEventSem(hev);
  5790.  
  5791.     if (rc != 0) {
  5792.         printf("DosPostEventSem error: return code = %ld", rc);
  5793.         return;
  5794.     }
  5795.  
  5796. The operating system maintains a post count for each event semaphore. The post 
  5797. count is the number of times the semaphore has been posted (with 
  5798. DosPostEventSem) since the last time the semaphore was in the reset state. 
  5799.  
  5800. If the event semaphore is reset when DosPostEventSem is called, the semaphore 
  5801. is posted and the post count is set to 1. If the event semaphore is already 
  5802. posted when DosPostEventSem is called, the post count is incremented, and 
  5803. ERROR_ALREADY_POSTED is returned to the calling thread. 
  5804.  
  5805. The post count is returned as output by DosResetEventSem; it can also be 
  5806. obtained by calling DosQueryEventSem. 
  5807.  
  5808. The maximum number of times an event semaphore can be posted is 65535. The 
  5809. value of the post count cannot exceed 65535. If an attempt is made to exceed 
  5810. this number, DosPostEventSem returns ERROR_TOO_MANY_POSTS. 
  5811.  
  5812.  
  5813. ΓòÉΓòÉΓòÉ 7.2.6. Waiting for an Event Semaphore ΓòÉΓòÉΓòÉ
  5814.  
  5815. Any thread in the process that created an event semaphore can wait for the 
  5816. semaphore to be posted by calling DosWaitEventSem. Threads in other processes 
  5817. can also call DosWaitEventSem, but they must first gain access to the semaphore 
  5818. by calling DosOpenEventSem. 
  5819.  
  5820. If the semaphore is already posted when DosWaitEventSem is called, the function 
  5821. returns immediately, and the thread continues to run. Otherwise, the thread is 
  5822. blocked until the semaphore is posted. 
  5823.  
  5824. The following code fragment causes the calling thread to wait until the 
  5825. specified event semaphore is posted. Assume that the handle of the semaphore 
  5826. has been placed into HEV already. ulTimeout is the number of milliseconds that 
  5827. the calling thread will wait for the event semaphore to be posted. If the 
  5828. specified event semaphore is not posted during this time interval, the request 
  5829. times out. 
  5830.  
  5831.     #define INCL_DOSSEMAPHORES   /* Semaphore values */
  5832.     #include <os2.h>
  5833.     #include <stdio.h>
  5834.  
  5835.     HEV     hev;        /* Event semaphore handle         */
  5836.     ULONG   ulTimeout;  /* Number of milliseconds to wait */
  5837.     APIRET  rc;         /* Return code                    */
  5838.  
  5839.     ulTimeout = 60000;  /* Wait for a maximum of 1 minute */
  5840.  
  5841.     rc = DosWaitEventSem(hev, ulTimeout);
  5842.  
  5843.     if (rc == ERROR_TIMEOUT) {
  5844.         printf("DosWaitEventSem call timed out");
  5845.         return;
  5846.     }
  5847.  
  5848.     if (rc == ERROR_INTERRUPT) {
  5849.         printf("DosWaitEventSem call was interrupted");
  5850.         return;
  5851.     }
  5852.  
  5853.     if (rc != 0) {
  5854.         printf("DosWaitEventSem error: return code = %ld", rc);
  5855.         return;
  5856.     }
  5857.  
  5858. If the time limit specified in ulTimeout is reached before the semaphore is 
  5859. posted, ERROR_TIMEOUT is returned. If the waiting period is interrupted for 
  5860. some reason before the semaphore is posted, ERROR_INTERRUPT is returned. If 
  5861. SEM_IMMEDIATE_RETURN is specified for the time limit, DosWaitEventSem returns 
  5862. to the calling thread immediately. If SEM_INDEFINITE_WAIT is specified for the 
  5863. time limit, the thread waits indefinitely. 
  5864.  
  5865. Unlike multiple event semaphores in a muxwait list, which are level-triggered, 
  5866. single event semaphores are edge-triggered. This means that if an event 
  5867. semaphore is posted and then reset before a waiting thread gets a chance to 
  5868. run, the semaphore is considered to be posted for the rest of that thread's 
  5869. waiting period; the thread does not have to wait for the semaphore to be posted 
  5870. again. 
  5871.  
  5872.  
  5873. ΓòÉΓòÉΓòÉ 7.2.7. Querying an Event Semaphore ΓòÉΓòÉΓòÉ
  5874.  
  5875. DosQueryEventSem returns the current post count of a semaphore. The post count 
  5876. is the number of times that the semaphore has been posted (with 
  5877. DosPostEventSem) since the last time the semaphore was reset. A count of 0 
  5878. indicates that the semaphore is in the reset state; therefore, the operating 
  5879. system will block any threads that call DosWaitEventSem to wait on the 
  5880. semaphore. 
  5881.  
  5882. Any thread in the process that created an event semaphore can obtain the post 
  5883. count for the semaphore by calling DosQueryEventSem. Threads in other processes 
  5884. can also call DosQueryEventSem, but they must first gain access to the 
  5885. semaphore by calling DosOpenEventSem. 
  5886.  
  5887. The following code fragment retrieves the post count for an event semaphore. 
  5888. Assume that the handle of the semaphore has been placed into HEV already. 
  5889.  
  5890.     #define INCL_DOSSEMAPHORES   /* Semaphore values */
  5891.     #include <os2.h>
  5892.     #include <stdio.h>
  5893.  
  5894.     HEV     hev;       /* Event semaphore handle                          */
  5895.     ULONG   ulPostCt;  /* Current post count for the semaphore (returned) */
  5896.     APIRET  rc;        /* Return code                                     */
  5897.  
  5898.     rc = DosQueryEventSem(hev, &ulPostCt);
  5899.  
  5900.     if (rc != 0) {
  5901.         printf("DosQueryEventSem error: return code = %ld", rc);
  5902.         return;
  5903.     }
  5904.  
  5905. If the specified event semaphore does not exist, ERROR_INVALID_HANDLE is 
  5906. returned. 
  5907.  
  5908.  
  5909. ΓòÉΓòÉΓòÉ 7.3. Using Mutex Semaphores ΓòÉΓòÉΓòÉ
  5910.  
  5911. An application can use a mutual exclusion (mutex) semaphore to protect a shared 
  5912. resource from simultaneous access by multiple threads or processes. For 
  5913. example, if several processes must write to the same disk file, the mutex 
  5914. semaphore ensures that only one process at a time writes to the file. 
  5915.  
  5916.  
  5917. ΓòÉΓòÉΓòÉ 7.3.1. Creating a Mutex Semaphore ΓòÉΓòÉΓòÉ
  5918.  
  5919. Mutex semaphores are created by calling DosCreateMutexSem. This function also 
  5920. opens the semaphore for the calling process and its threads. 
  5921.  
  5922. When a mutex semaphore is created, a flag is set to specify the initial state 
  5923. of the semaphore, owned or unowned. If the semaphore is owned by a thread, 
  5924. other threads requesting the semaphore are blocked. If the semaphore is 
  5925. unowned-not owned by any thread- then any thread requesting ownership will be 
  5926. granted ownership immediately. 
  5927.  
  5928. If the calling thread sets the initial state to owned, it owns the semaphore as 
  5929. soon as the operating system creates the semaphore and can proceed to access 
  5930. the resource that the semaphore was created to protect. 
  5931.  
  5932. If the semaphore is unowned, any thread in the creating process can 
  5933. subsequently request ownership of the semaphore by calling DosRequestMutexSem. 
  5934. Threads in other processes can gain ownership of the semaphore, but they must 
  5935. call DosOpenMutexSem to acquire access to the semaphore before they can call 
  5936. DosRequestMutexSem. 
  5937.  
  5938. Mutex semaphores can be defined as either private or shared. 
  5939.  
  5940.    o  Private semaphores are always unnamed and are therefore identified by 
  5941.       their handles. They can be used only by threads within a single process. 
  5942.  
  5943.    o  Shared semaphores can be either named or unnamed. If named, they can be 
  5944.       opened using either the name or the handle. The handle returned by 
  5945.       DosOpenMutexSem is then used to identify the semaphore for all other 
  5946.       functions. Semaphore names must include the prefix \SEM32\ and must 
  5947.       conform to file system naming conventions. Shared semaphores can be used 
  5948.       by threads in multiple processes. 
  5949.  
  5950.  The following code fragment creates a mutex semaphore: 
  5951.  
  5952.       #define INCL_DOSSEMAPHORES   /* Semaphore values */
  5953.       #include <os2.h>
  5954.  
  5955.       HMTX hmtxProtFile;
  5956.  
  5957.       DosCreateMutexSem("\\sem32\\ProtFile",          /* Named-shared semaphore */
  5958.                         &hmtxProtFile, 0, FALSE);     /* Initially unowned      */
  5959.           .
  5960.           .    /* Get data to write to shared file. */
  5961.           .
  5962.  
  5963.  There is a system-wide limit of 65536 shared semaphores (including mutex, 
  5964.  event, and muxwait semaphores); in addition, each process can have up to 65536 
  5965.  private semaphores. 
  5966.  
  5967.  The operating system maintains a usage count for each semaphore. 
  5968.  DosCreateMutexSem initializes the usage count to 1. Thereafter, each call to 
  5969.  DosOpenMutexSem increments the count, and each call to DosCloseMutexSem 
  5970.  decrements it. 
  5971.  
  5972.  
  5973. ΓòÉΓòÉΓòÉ 7.3.2. Opening a Mutex Semaphore ΓòÉΓòÉΓòÉ
  5974.  
  5975. All of the threads belonging to the process that creates a mutex semaphore have 
  5976. immediate access to the semaphore. Threads in other processes must request 
  5977. access to the semaphore by calling DosOpenMutexSem before they can use the 
  5978. semaphore in other mutex semaphore functions. 
  5979.  
  5980. Access to system resources is granted on a per-process basis. Therefore, a 
  5981. semaphore that has been opened by one thread in a process is open to all other 
  5982. threads in that process as well. 
  5983.  
  5984. DosOpenMutexSem merely provides access to a mutex semaphore. To request 
  5985. ownership of a mutex semaphore, a thread must call DosRequestMutexSem. 
  5986.  
  5987. When a process no longer requires access to a mutex semaphore, it should close 
  5988. the semaphore by calling DosCloseMutexSem. However, if a process ends without 
  5989. closing an open semaphore, the semaphore is closed by the operating system. 
  5990.  
  5991. Each call to DosOpenMutexSem. increments the usage count of the semaphore. This 
  5992. count is initialized to 1 when the semaphore is created and is decremented by 
  5993. each call to DosCloseMutexSem. When the usage count reaches 0, the semaphore is 
  5994. deleted by the system. 
  5995.  
  5996. Calls to DosOpenMutexSem and DosCloseMutexSem. can be nested, but the usage 
  5997. count for a semaphore cannot exceed 65535. If an attempt is made to exceed this 
  5998. number, ERROR_TOO_MANY_OPENS is returned. 
  5999.  
  6000. If a process ends without releasing a mutex semaphore that it owns, any other 
  6001. thread that subsequently tries to open the semaphore will receive 
  6002. ERROR_SEM_OWNER_DIED. This return code indicates that the owning process ended 
  6003. abnormally, leaving the protected resource in an indeterminate state. However, 
  6004. the semaphore is still opened for the calling thread, enabling the thread to 
  6005. call DosQueryMutexSem to find out which process ended without releasing the 
  6006. semaphore. The thread can then take appropriate action concerning the semaphore 
  6007. and the protected resource. 
  6008.  
  6009.  
  6010. ΓòÉΓòÉΓòÉ 7.3.3. Requesting a Mutex Semaphore ΓòÉΓòÉΓòÉ
  6011.  
  6012. In order to access a shared resource, a process must own the mutex semaphore 
  6013. that is protecting the shared resource. Ownership is obtained by first opening 
  6014. the mutex semaphore with DosOpenMutexSem, then using DosRequestMutexSem to 
  6015. request ownership of the semaphore. If another process already owns the 
  6016. semaphore, the requesting process is blocked. If the semaphore is not owned, 
  6017. the operating system grants ownership to the requesting process and the process 
  6018. can access the shared resource. When the process is finished using the shared 
  6019. resource, it uses DosReleaseMutexSem to relinquish its ownership of the 
  6020. semaphore, thereby enabling another process to gain ownership. 
  6021.  
  6022. A process can gain ownership of a mutex semaphore in three ways: 
  6023.  
  6024.    1. The thread that creates a mutex semaphore can designate itself as the 
  6025.       owner by setting a flag when it calls DosCreateMutexSem. 
  6026.  
  6027.    2. Any thread in the process that created the semaphore can request 
  6028.       ownership by calling DosRequestMutexSem. 
  6029.  
  6030.    3. A thread in another process must request access to the semaphore with 
  6031.       DosOpenMutexSem before it can call DosRequestMutexSem. 
  6032.  
  6033.  Note that ownership of a mutex semaphore is given only to the requesting 
  6034.  thread; it is not shared by other threads in the same process. 
  6035.  
  6036.  If a mutex semaphore is unowned, DosRequestMutexSem sets it as owned and 
  6037.  returns immediately to the caller. If the semaphore is already owned, the 
  6038.  calling thread is blocked until either the owning thread calls 
  6039.  DosReleaseMutexSem to release the semaphore, or a specified time limit is 
  6040.  reached. 
  6041.  
  6042.  The following code fragment shows how a process opens a mutex semaphore, 
  6043.  requests it, and, after writing to the shared file, releases and closes the 
  6044.  semaphore: 
  6045.  
  6046.       #define INCL_DOSSEMAPHORES   /* Semaphore values */
  6047.       #include <os2.h>
  6048.  
  6049.       HMTX hmtxProtFile;
  6050.  
  6051.       DosOpenMutexSem("\\sem32\\ProtFile",
  6052.                       &hmtxProtFile);           /* Opens for this process    */
  6053.  
  6054.       DosRequestMutexSem(hmtxProtFile, 5000);   /* Returns in 5 seconds if   */
  6055.           .                                     /* Ownership not obtained    */
  6056.           .    /* Write data to shared file. */
  6057.           .
  6058.       DosReleaseMutexSem(hmtxProtFile);         /* Releases ownership        */
  6059.           .
  6060.           .    /* Continue execution. */
  6061.           .
  6062.       DosCloseMutexSem(hmtxProtFile);           /* Finished with shared file */
  6063.  
  6064.  If more than one thread is blocked on a DosRequestMutexSem request, the thread 
  6065.  with the highest priority level is the first to be unblocked and given 
  6066.  ownership of the semaphore. If more than 1 of the waiting threads have the 
  6067.  same priority level, then FIFO ordering is used to determine which thread is 
  6068.  unblocked and given ownership. 
  6069.  
  6070.  The time-out parameter (5000 milliseconds in the example above) places a limit 
  6071.  on the amount of time a thread blocks on a DosRequestMutexSem request. If the 
  6072.  time limit is reached before the thread gains ownership of the semaphore, 
  6073.  ERROR_TIMEOUT is returned. If SEM_IMMEDIATE_RETURN is specified for the time 
  6074.  limit, DosRequestMutexSem returns without blocking the thread. The thread can 
  6075.  then perform other operations and call DosRequestMutexSem again later if it 
  6076.  still requires access to the protected resource. If SEM_INDEFINITE_WAIT is 
  6077.  specified for the time limit, the thread waits indefinitely. If the thread is 
  6078.  unblocked by an external event while it is waiting for the mutex semaphore (as 
  6079.  when a No Wait I/O request has just been completed), ERROR_INTERRUPT is 
  6080.  returned to the caller. 
  6081.  
  6082.  In addition to the usage count that the operating system maintains for all 
  6083.  semaphores, the operating system maintains a request count for each mutex 
  6084.  semaphore. Each call to DosRequestMutexSem increments the count, and each call 
  6085.  to DosReleaseMutexSem decrements it. 
  6086.  
  6087.  Calls to DosRequestMutexSem and DosReleaseMutexSem can be nested, but the 
  6088.  request count for a semaphore cannot exceed 65535. If an attempt is made to 
  6089.  exceed this number, ERROR_TOO_MANY_SEM_REQUESTS is returned. When calls to 
  6090.  DosRequestMutexSem and DosReleaseMutexSem are nested, a call to 
  6091.  DosReleaseMutexSem merely decrements the request count for the semaphore; the 
  6092.  semaphore is not actually released to another thread until its request count 
  6093.  is 0. If a process ends while it owns a mutex semaphore, all of the currently 
  6094.  blocked DosRequestMutexSem requests, as well as any future requests for the 
  6095.  semaphore, return ERROR_SEM_OWNER_DIED. This return code indicates that the 
  6096.  owning process ended abnormally, leaving the protected resource in an 
  6097.  indeterminate state. An application that receives this error should close the 
  6098.  mutex semaphore (so that it can be deleted from the operating system), because 
  6099.  it is no longer valid. Appropriate action should also be taken concerning the 
  6100.  protected resource. 
  6101.  
  6102.  
  6103. ΓòÉΓòÉΓòÉ 7.3.4. Releasing a Mutex Semaphore ΓòÉΓòÉΓòÉ
  6104.  
  6105. A thread can release ownership of a mutex semaphore by calling 
  6106. DosReleaseMutexSem. Each call to DosReleaseMutexSem decrements the request 
  6107. count that is maintained for the semaphore by the operating system. Each call 
  6108. to DosRequestMutexSem increments the count. 
  6109.  
  6110. The following code fragment relinquishes ownership of a mutex semaphore. Assume 
  6111. that the handle of the semaphore has been placed into hmtx already. 
  6112.  
  6113.     #define INCL_DOSSEMAPHORES   /* Semaphore values */
  6114.     #include <os2.h>
  6115.     #include <stdio.h>
  6116.  
  6117.     HMTX    hmtx;    /* Mutex semaphore handle */
  6118.     APIRET  rc;      /* Return code            */
  6119.  
  6120.     rc = DosReleaseMutexSem(hmtx);
  6121.  
  6122.     if (rc != 0) {
  6123.         printf("DosReleaseMutexSem error: return code = %ld", rc);
  6124.         return;
  6125.     }
  6126.  
  6127. Calls to DosRequestMutexSem and DosReleaseMutexSem can be nested, but the 
  6128. request count cannot exceed 65535. If an attempt is made to exceed this number, 
  6129. ERROR_TOO_MANY_SEM_REQUESTS is returned. When calls to DosRequestMutexSem and 
  6130. DosReleaseMutexSem are nested, a call to DosReleaseMutexSem merely decrements 
  6131. the request count for the semaphore; the semaphore is not actually released to 
  6132. another thread until its request count is 0. 
  6133.  
  6134.  
  6135. ΓòÉΓòÉΓòÉ 7.3.5. Closing a Mutex Semaphore ΓòÉΓòÉΓòÉ
  6136.  
  6137. When a process no longer requires access to a mutex semaphore, it can close the 
  6138. semaphore by calling DosCloseMutexSem. However, if a process ends without 
  6139. closing an open semaphore, the semaphore is closed by the operating system. 
  6140.  
  6141. The following code fragment closes a mutex semaphore. Assume that the handle of 
  6142. the semaphore has been placed into hmtx already. 
  6143.  
  6144.     #define INCL_DOSSEMAPHORES   /* Semaphore values */
  6145.     #include <os2.h>
  6146.     #include <stdio.h>
  6147.  
  6148.     HMTX    hmtx;    /* Mutex semaphore handle */
  6149.     APIRET  rc;      /* Return code            */
  6150.  
  6151.     rc = DosCloseMutexSem(hmtx);
  6152.  
  6153.     if (rc != 0) {
  6154.         printf("DosCloseMutexSem error: return code = %ld", rc);
  6155.         return;
  6156.     }
  6157.  
  6158. Each call to DosCloseMutexSem decrements the usage count of the semaphore. This 
  6159. count is initialized to 1 when the semaphore is created and is incremented by 
  6160. each call to DosOpenMutexSem. When the usage count reaches 0, the semaphore is 
  6161. deleted by the operating system. 
  6162.  
  6163. The call to DosCloseMutexSem that decrements the usage count to 0 and causes 
  6164. the semaphore to be deleted is referred to as the final close. The final close 
  6165. will not succeed if either of the following conditions exists: 
  6166.  
  6167.    o  The semaphore is owned by another thread in the same process. 
  6168.  
  6169.    o  Another thread in the same process is still blocked on a 
  6170.       DosRequestMutexSem request for the semaphore. 
  6171.  
  6172.  For both conditions, ERROR_SEM_BUSY is returned. 
  6173.  
  6174.  ERROR_SEM_BUSY is also returned if a thread tries to close a mutex semaphore 
  6175.  that it still owns. The thread must first relinquish ownership of the 
  6176.  semaphore by calling DosReleaseMutexSem. 
  6177.  
  6178.  Calls to DosOpenMutexSem and DosCloseMutexSem can be nested, but the usage 
  6179.  count for a semaphore cannot exceed 65535. If an attempt is made to exceed 
  6180.  this number, ERROR_TOO_MANY_OPENS is returned. 
  6181.  
  6182.  
  6183. ΓòÉΓòÉΓòÉ 7.3.6. Querying a Mutex Semaphore ΓòÉΓòÉΓòÉ
  6184.  
  6185. An application can use DosQueryMutexSem to determine the current owner of a 
  6186. mutex semaphore and to obtain a count of the number of requests on it. If the 
  6187. mutex semaphore is not owned, the request count is 0. 
  6188.  
  6189. Any thread in the process that created a mutex semaphore can obtain information 
  6190. about the semaphore by calling DosQueryMutexSem. Threads in other processes can 
  6191. also call DosQueryMutexSem, but they must first gain access to the semaphore by 
  6192. calling DosOpenMutexSem. 
  6193.  
  6194. If the mutex semaphore exists and is owned, DosQueryMutexSem returns the 
  6195. process and thread identifications of the owner, as well as the request count 
  6196. for the semaphore. The request count is the number of DosRequestMutexSem calls 
  6197. minus the number of DosReleaseMutexSem calls that have been made for the 
  6198. semaphore by the owning thread. 
  6199.  
  6200. If DosQueryMutexSem returns a request count of 0, the mutex semaphore is 
  6201. unowned. 
  6202.  
  6203. If the owning process ended without calling DosCloseMutexSem, then 
  6204. ERROR_SEM_OWNER_DIED is returned, and the output parameters contain information 
  6205. about the ended owning process. 
  6206.  
  6207.  
  6208. ΓòÉΓòÉΓòÉ 7.4. Using Muxwait Semaphores ΓòÉΓòÉΓòÉ
  6209.  
  6210. A process that requires exclusive use of several shared resources at once can 
  6211. use a multiple wait (muxwait) semaphore to obtain ownership of all the mutex 
  6212. semaphores protecting the shared resources. A process can also use a muxwait 
  6213. semaphore to wait on a group of event semaphores so that the process continues 
  6214. running whenever events of interest occur. 
  6215.  
  6216. A muxwait semaphore can refer to up to 64 event or mutex semaphores. An 
  6217. application cannot refer to event and mutex semaphores in a single muxwait 
  6218. semaphore, or include a muxwait semaphore in another muxwait semaphore. 
  6219.  
  6220.  
  6221. ΓòÉΓòÉΓòÉ 7.4.1. Creating a Muxwait Semaphore ΓòÉΓòÉΓòÉ
  6222.  
  6223. DosCreateMuxWaitSem is used to create muxwait semaphores. This function also 
  6224. opens (obtains access to) the semaphore for the calling process and its 
  6225. threads. Threads in other processes must call DosOpenMuxWaitSem to open the 
  6226. semaphore before they can use it in any other muxwait semaphore function. 
  6227.  
  6228. All the semaphores in the muxwait list must be created and opened before the 
  6229. muxwait list can be created. 
  6230.  
  6231. The following code fragment creates five event semaphores and a corresponding 
  6232. array of semaphore records. The array is used to specify the semaphores 
  6233. included in the muxwait semaphore in the subsequent call to 
  6234. DosCreateMuxWaitSem. 
  6235.  
  6236.     #define INCL_DOSSEMAPHORES   /* Semaphore values */
  6237.     #include <os2.h>
  6238.  
  6239.     ULONG ulLoop, ulSem;
  6240.     HMUX hmuxHandAny;
  6241.     SEMRECORD apsr[5];
  6242.  
  6243.     /* Create event semaphores and fill semaphore-record array. */
  6244.  
  6245.     for (ulLoop = 0; ulLoop < 5; ulLoop++) {   /* Create 5 private events       */
  6246.         DosCreateEventSem((PSZ) NULL,
  6247.                           (PHEV) &apsr[ulLoop].hsemCur,
  6248.                           0,
  6249.                           FALSE);
  6250.         apsr[ulLoop].ulUser = ulLoop;          /* User-assigned data            */
  6251.     }
  6252.         .
  6253.         .
  6254.         .
  6255.  
  6256.     DosCreateMuxWaitSem((PSZ) NULL,
  6257.                         &hmuxHandAny,          /* Creates the muxwait semaphore */
  6258.                         sizeof(apsr),
  6259.                         apsr,                  /* Specifies semrecord array     */
  6260.                         DCMW_WAIT_ANY);
  6261.  
  6262.     DosWaitMuxWaitSem(hmuxHandAny,             /* Waits until one is posted     */
  6263.                       SEM_INDEFINITE_WAIT, &ulSem);
  6264.         .
  6265.         . /* Execution will continue when any event is posted. */
  6266.         .
  6267.  
  6268. Muxwait semaphores can be defined as either private or shared: 
  6269.  
  6270.    o  Private semaphores are always unnamed and are therefore always identified 
  6271.       by their handles. They can be used only by threads within a single 
  6272.       process. 
  6273.  
  6274.    o  Shared semaphores can be either named or unnamed. If named, they can be 
  6275.       opened using either the name or the handle. The handle returned by 
  6276.       DosOpenMuxWaitSem is then used to identify the semaphore for all other 
  6277.       functions. Semaphore names must include the prefix \SEM32\ and must 
  6278.       conform to file system naming conventions. Shared semaphores can be used 
  6279.       by threads in multiple processes. 
  6280.  
  6281.  There is a system-wide limit of 65536 (64K) shared semaphores (including 
  6282.  mutex, event, and muxwait semaphores); in addition, each process can have up 
  6283.  to 65536 (64K) private semaphores. 
  6284.  
  6285.  The following conditions apply to the kinds of semaphores that can be included 
  6286.  in a muxwait-semaphore list: 
  6287.  
  6288.    o  The list must contain either mutex semaphores or event semaphores. It 
  6289.       cannot contain both at the same time and it cannot contain other muxwait 
  6290.       semaphores. 
  6291.  
  6292.    o  If the muxwait semaphore is shared, then all the semaphores in the list 
  6293.       must also be shared. 
  6294.  
  6295.    o  If the muxwait semaphore is private, then the semaphores in its list can 
  6296.       be either private or shared. 
  6297.  
  6298.  If any of these conditions is violated, ERROR_WRONG_TYPE is returned. 
  6299.  
  6300.  The muxwait list can contain a maximum of 64 event semaphores or mutex 
  6301.  semaphores. If an attempt is made to exceed this maximum, 
  6302.  ERROR_TOO_MANY_SEMAPHORES is returned. 
  6303.  
  6304.  If the owners of any of the mutex semaphores in the muxwait semaphore list 
  6305.  have ended without releasing them, ERROR_SEM_OWNER_DIED is returned. The 
  6306.  thread should call DosQueryMutexSem for each mutex semaphore in the 
  6307.  muxwait-semaphore list so that it can determine which semaphores are in the 
  6308.  Owner Died state. 
  6309.  
  6310.  Each mutex semaphore that returns ERROR_SEM_OWNER_DIED from the query should 
  6311.  be closed by calling DosCloseMutexSem. Also, because semaphore handles can be 
  6312.  reused, the mutex semaphores that are closed must be deleted from the 
  6313.  muxwait-semaphore list by calling DosDeleteMuxWaitSem. 
  6314.  
  6315.  The operating system maintains a usage count for each semaphore. 
  6316.  DosCreateMuxWaitSem initializes the usage count to 1. Thereafter, each call to 
  6317.  DosOpenMuxWaitSem increments the count, and each call to DosCloseMuxWaitSem 
  6318.  decrements it. 
  6319.  
  6320.  One parameter of this function is a pointer to an array of SEMRECORD data 
  6321.  structures. Each data structure contains one semaphore record for each of the 
  6322.  semaphores to be included in the muxwait semaphore. A semaphore record 
  6323.  contains the handle and a programmer-defined identifier for that semaphore. 
  6324.  
  6325.  
  6326. ΓòÉΓòÉΓòÉ 7.4.2. Opening a Muxwait Semaphore ΓòÉΓòÉΓòÉ
  6327.  
  6328. Processes other than the semaphore-creating process must use DosOpenMuxWaitSem 
  6329. to gain access to the muxwait semaphore before they can use the semaphore in 
  6330. any other muxwait semaphore function. All of the threads that belong to the 
  6331. process that creates the muxwait semaphore have immediate access to the 
  6332. semaphore. 
  6333.  
  6334. The following code fragment opens a system muxwait semaphore. 
  6335.  
  6336.     #define INCL_DOSSEMAPHORES   /* Semaphore values */
  6337.     #include <os2.h>
  6338.     #include <stdio.h>
  6339.  
  6340.     UCHAR   Name[40];  /* Semaphore name           */
  6341.     HMUX    hmux;      /* Muxwait semaphore handle */
  6342.     APIRET  rc;        /* Return code              */
  6343.  
  6344.     strcpy(Name, "\\SEM32\\MUXWAIT1");  /* Name of the system muxwait semaphore */
  6345.  
  6346.     rc = DosOpenMuxWaitSem(Name, &hmux);
  6347.  
  6348.     if (rc != 0) {
  6349.         printf("DosOpenMuxWaitSem error: return code = %ld", rc);
  6350.         return;
  6351.     }
  6352.  
  6353. On successful return, hmux contains the handle of the system muxwait semaphore. 
  6354.  
  6355. Opening a muxwait semaphore does not open the semaphores in its muxwait list. A 
  6356. process must open each of the semaphores included in a muxwait semaphore before 
  6357. it opens the muxwait semaphore. Otherwise, DosOpenMuxWaitSem returns the 
  6358. ERROR_INVALID_HANDLE error value to the calling function. 
  6359.  
  6360. Access to semaphores is on a per-process basis. Therefore, a semaphore that has 
  6361. been opened by one thread in a process is open to all other threads in that 
  6362. process as well. 
  6363.  
  6364. Note that DosOpenMuxWaitSem merely provides access to a muxwait semaphore. In 
  6365. order to wait for a muxwait semaphore to clear, a thread must call 
  6366. DosWaitMuxWaitSem. 
  6367.  
  6368. When a process no longer requires access to a muxwait semaphore, it closes the 
  6369. semaphore by calling DosCloseMuxWaitSem. However, if a process ends without 
  6370. closing an open semaphore, the semaphore is closed by the operating system. 
  6371.  
  6372. Each call to DosOpenMuxWaitSem increments the usage count of the semaphore. 
  6373. This count is initialized to 1 when the semaphore is created and is decremented 
  6374. by each call to DosCloseMuxWaitSem. When the usage count reaches 0, the 
  6375. semaphore is deleted by the operating system. 
  6376.  
  6377. Calls to DosOpenMuxWaitSem and DosCloseMuxWaitSem can be nested, but the usage 
  6378. count for a semaphore cannot exceed 65535. If an attempt is made to exceed this 
  6379. number, ERROR_TOO_MANY_OPENS is returned. 
  6380.  
  6381. Even if the owner of a mutex semaphore in a muxwait-semaphore list has ended 
  6382. without releasing the semaphore, the muxwait semaphore is still opened. 
  6383. Subsequent calls to the muxwait semaphore will return ERROR_SEM_OWNER_DIED. But 
  6384. because the process has opened the semaphore, it can then call 
  6385. DosQueryMuxWaitSem to identify all the mutex semaphores in the muxwait list. 
  6386. Next, the process can call DosQueryMutexSem for each mutex semaphore in the 
  6387. list to find out which ones are in the Owner Died state. Each mutex semaphore 
  6388. that returns ERROR_SEM_OWNER_DIED from the query should be closed by calling 
  6389. DosCloseMutexSem. Also, because semaphore handles can be reused, the mutex 
  6390. semaphores that are closed should be deleted from the muxwait-semaphore list by 
  6391. calling DosDeleteMuxWaitSem. 
  6392.  
  6393.  
  6394. ΓòÉΓòÉΓòÉ 7.4.3. Closing a Muxwait Semaphore ΓòÉΓòÉΓòÉ
  6395.  
  6396. When a process no longer requires access to a muxwait semaphore, it closes the 
  6397. semaphore by calling DosCloseMuxWaitSem. However, if a process ends without 
  6398. closing an open semaphore, the semaphore is closed by the operating system. 
  6399.  
  6400. Each call to DosCloseMuxWaitSem decrements the usage count of the semaphore. 
  6401. This count is initialized to 1 when the semaphore is created and is incremented 
  6402. by each call to DosOpenMuxWaitSem. When the usage count reaches 0, the 
  6403. semaphore is deleted by the operating system. 
  6404.  
  6405. The call to DosCloseMuxWaitSem that decrements the usage count to 0 and causes 
  6406. the semaphore to be deleted is referred to as the final close. If a thread 
  6407. attempts to perform the final close for a semaphore while another thread in the 
  6408. same process is still waiting for it, ERROR_SEM_BUSY is returned. 
  6409.  
  6410. Calls to DosOpenMuxWaitSem and DosCloseMuxWaitSem can be nested, but the usage 
  6411. count for a semaphore cannot exceed 65535. If an attempt is made to exceed this 
  6412. number, ERROR_TOO_MANY_OPENS is returned. 
  6413.  
  6414.  
  6415. ΓòÉΓòÉΓòÉ 7.4.4. Waiting for a Muxwait Semaphore ΓòÉΓòÉΓòÉ
  6416.  
  6417. A thread can wait on a muxwait semaphore by using DosWaitMuxWaitSem. 
  6418.  
  6419. Any thread in the process that created a muxwait semaphore can wait for the 
  6420. semaphore to clear by calling DosWaitMuxWaitSem. Threads in other processes can 
  6421. also call DosWaitMuxWaitSem, but they must first gain access to the semaphore 
  6422. by calling DosOpenMuxWaitSem. 
  6423.  
  6424. The following code fragment waits for a muxwait semaphore to clear. Assume that 
  6425. the handle of the semaphore has been placed into hmux already. ulTimeout is the 
  6426. number of milliseconds that the calling thread will wait for the muxwait 
  6427. semaphore to clear. If the specified muxwait semaphore is not cleared during 
  6428. this time interval, the request times out. 
  6429.  
  6430.     #define INCL_DOSSEMAPHORES   /* Semaphore values */
  6431.     #include <os2.h>
  6432.     #include <stdio.h>
  6433.  
  6434.     HMUX     hmux;      /* Muxwait semaphore handle              */
  6435.     ULONG    ulTimeout; /* Number of milliseconds to wait        */
  6436.     ULONG    ulUser;    /* User field for the semaphore that was */
  6437.                         /* posted or released (returned)         */
  6438.     APIRET   rc;        /* Return code                           */
  6439.  
  6440.     ulTimeout = 60000;  /* Wait for a maximum of 1 minute        */
  6441.  
  6442.     rc = DosWaitMuxWaitSem(hmux, ulTimeout, &ulUser);
  6443.  
  6444.     if (rc == ERROR_TIMEOUT) {
  6445.         printf("DosWaitMuxWaitSem call timed out");
  6446.         return;
  6447.     }
  6448.  
  6449.     if (rc == ERROR_INTERRUPT) {
  6450.         printf("DosWaitMuxWaitSem call was interrupted");
  6451.         return;
  6452.     }
  6453.  
  6454.     if (rc != 0) {
  6455.         printf("DosWaitMuxWaitSem error: return code = %ld", rc);
  6456.         return;
  6457.     }
  6458.  
  6459. On successful return, the ulUser variable contains the user identifier of the 
  6460. semaphore that caused the wait to terminate. If the caller had to wait for all 
  6461. the semaphores within the muxwait semaphore to clear, then the value 
  6462. corresponds to the last semaphore within the muxwait semaphore to clear. If the 
  6463. caller had to wait for any semaphore with the muxwait semaphore to clear, then 
  6464. the value corresponds to that semaphore. 
  6465.  
  6466. An application can use the DCMW_WAIT_ANY flag in DosCreateMuxWaitSem to block a 
  6467. thread until any one of the event or mutex semaphores included in the muxwait 
  6468. semaphore is posted or released. If the muxwait semaphore refers to mutex 
  6469. semaphores, the thread only gains ownership of the one mutex semaphore that was 
  6470. released. 
  6471.  
  6472. An application can use the DCMW_WAIT_ALL flag in DosCreateMuxWaitSem to block a 
  6473. thread until all of the event or mutex semaphores included in the muxwait 
  6474. semaphore are posted or released. If the muxwait semaphore refers to mutex 
  6475. semaphores, the thread does not gain ownership of any of the mutex semaphores 
  6476. until they are all released. When all are released, the thread becomes owner of 
  6477. all the mutex semaphores included in the muxwait semaphore. If the muxwait 
  6478. semaphore refers to event semaphores, the thread will not run until all of the 
  6479. event semaphores are in the posted state at the same time. This is because 
  6480. event semaphores in a muxwait list are level-triggered, unlike individual event 
  6481. semaphores, which are edge-triggered. 
  6482.  
  6483. For example, suppose that a thread is waiting for five event semaphores in a 
  6484. muxwait list to be posted. The first semaphore is posted and then reset. Next, 
  6485. the remaining semaphores are all posted, and they remain in the posted state. 
  6486. The thread that is waiting for the muxwait semaphore will not run until the 
  6487. first semaphore is posted again. 
  6488.  
  6489. If an application specifies the DCMW_WAIT_ANY flag when the semaphore is 
  6490. created, DosWaitMuxWaitSem returns the programmer-defined identifier of the 
  6491. semaphore that is subsequently posted or released. If an application specifies 
  6492. the DCMW_WAIT_ALL flag, DosWaitMuxWaitSem returns the programmer-defined 
  6493. identifier of the last semaphore that was posted or released. 
  6494.  
  6495. The ulTimeout parameter places a limit on the amount of time a thread blocks on 
  6496. a DosWaitMuxWaitSem request. If the time limit is reached before the semaphore 
  6497. has cleared, ERROR_TIMEOUT is returned. If SEM_IMMEDIATE_RETURN is specified as 
  6498. the time limit, DosWaitMuxWaitSem returns without blocking the thread. The 
  6499. thread can then go on to perform other operations and call DosWaitMuxWaitSem 
  6500. again later to wait for the event or mutex semaphores in the muxwait list to be 
  6501. posted or released. If a time limit of SEM_INDEFINITE_WAIT is specified, the 
  6502. thread waits (is blocked) indefinitely. If the thread is unblocked by an 
  6503. external event while it is waiting for the muxwait semaphore (as when a "no 
  6504. wait" I/O request has just been completed), DosWaitMuxWaitSem returns 
  6505. ERROR_INTERRUPT. 
  6506.  
  6507. When a thread is waiting for any one of the semaphores in a muxwait list to be 
  6508. posted or released, the semaphores are checked in the order in which they are 
  6509. defined in the list. 
  6510.  
  6511. Waiting for Multiple Event Semaphores 
  6512. The following information pertains only to muxwait semaphores that consist of 
  6513. multiple event semaphores: 
  6514.  
  6515. Unlike individual event semaphores, which are edge-triggered, event semaphores 
  6516. in a muxwait list are level-triggered. This means that if a thread is waiting 
  6517. for all of the event semaphores in the muxwait list, it will not run until all 
  6518. of the event semaphores are in the posted state at the same time. 
  6519.  
  6520. For example, a thread is waiting for five event semaphores in a muxwait list to 
  6521. be posted. The first semaphore is posted and then reset. Next, the remaining 
  6522. semaphores are all posted, and they remain in the posted state. The thread that 
  6523. is waiting for the muxwait semaphore will not run until the first semaphore is 
  6524. posted again. 
  6525.  
  6526. Waiting for Multiple Mutex Semaphores 
  6527. The following information pertains only to muxwait semaphores that consist of 
  6528. multiple mutex semaphores: 
  6529.  
  6530.    o  If a thread is waiting for all of the mutex semaphores in a muxwait list 
  6531.       to be released, it does not receive ownership of any of the semaphores 
  6532.       until all of the semaphores have been released. 
  6533.  
  6534.    o  If a thread is waiting for any one of the mutex semaphores in a muxwait 
  6535.       list, then the thread gains ownership only of the first mutex semaphore 
  6536.       that is released. The ownership of all other mutex semaphores in the 
  6537.       muxwait list remains unchanged. 
  6538.  
  6539.    o  If two threads have the same priority, then a thread that is waiting for 
  6540.       a mutex semaphore in a muxwait list takes precedence over a thread that 
  6541.       has requested ownership of only the individual semaphore, provided all 
  6542.       other mutex semaphores in the muxwait list have been released. For 
  6543.       example, a mutex semaphore that is part of a muxwait semaphore is 
  6544.       released. One thread has requested ownership of that single mutex 
  6545.       semaphore, and another thread with the same priority is waiting for the 
  6546.       muxwait semaphore that contains the same mutex semaphore. If all of the 
  6547.       other mutex semaphores in the muxwait list are unowned and ready to be 
  6548.       given to the muxwait semaphore, then the thread that is waiting for the 
  6549.       muxwait semaphore will run first. 
  6550.  
  6551.    o  If the owners of any of the mutex semaphores in the muxwait semaphore 
  6552.       list have ended without releasing them, ERROR_SEM_OWNER_DIED is returned. 
  6553.       The thread must then call DosQueryMuxWaitSem to obtain the records of all 
  6554.       the semaphores in the muxwait list. Next, the thread must call 
  6555.       DosQueryMutexSem for each mutex semaphore in the muxwait-semaphore list 
  6556.       so that it can determine which semaphores are in the Owner Died state. 
  6557.  
  6558.       Each mutex semaphore that returns ERROR_SEM_OWNER_DIED from the query 
  6559.       should be closed by calling DosCloseMutexSem. Also, because semaphore 
  6560.       handles can be reused, the mutex semaphores that are closed should be 
  6561.       deleted from the muxwait-semaphore list by calling DosDeleteMuxWaitSem. 
  6562.  
  6563.    o  If any of the mutex semaphores in the muxwait list are owned by the 
  6564.       calling thread, ERROR_MUTEX_OWNED is returned. 
  6565.  
  6566.  
  6567. ΓòÉΓòÉΓòÉ 7.4.5. Adding a Semaphore to a Muxwait List ΓòÉΓòÉΓòÉ
  6568.  
  6569. An application uses DosAddMuxWaitSem to add semaphores to a muxwait semaphore 
  6570. that has already been created, even while threads are waiting on the muxwait 
  6571. semaphore. 
  6572.  
  6573. Any thread in the process that created a muxwait semaphore can add a mutex 
  6574. semaphore or an event semaphore to the muxwait list by calling 
  6575. DosAddMuxWaitSem. Threads in other processes can also use this function, but 
  6576. they must first gain access to the semaphore by calling DosOpenMuxWaitSem. 
  6577.  
  6578. A maximum of 64 semaphores can be included in a muxwait-semaphore list. If an 
  6579. attempt is made to exceed this maximum, ERROR_TOO_MANY_SEMAPHORES is returned. 
  6580.  
  6581. All of the semaphores in a muxwait-semaphore list must be of the same type. 
  6582. That is, if a mutex semaphore is being added, then the other semaphores in the 
  6583. list must be mutex semaphores. If an event semaphore is being added, then the 
  6584. other semaphores in the list must be event semaphores. A shared muxwait 
  6585. semaphore can contain only shared semaphores in its list. A private muxwait 
  6586. semaphore can contain both private and shared semaphores. If any of these 
  6587. conditions is violated, ERROR_WRONG_TYPE is returned. 
  6588.  
  6589. If the semaphore is successfully added to the muxwait list, DosAddMuxWaitSem 
  6590. checks to see whether each thread that is waiting for the muxwait semaphore has 
  6591. the newly added semaphore open in its process. The muxwait semaphore is invalid 
  6592. for any waiting threads that do not have the newly added semaphore open in 
  6593. their process; these threads are unblocked with a return code of 
  6594. ERROR_INVALID_HANDLE. Any processes that opened the muxwait semaphore before 
  6595. the add operation and that do not have the new semaphore open, will have to 
  6596. open the new semaphore before making any further use of the muxwait semaphore. 
  6597. Any future calls concerning the muxwait semaphore by processes that do not have 
  6598. the new semaphore open will have ERROR_INVALID_HANDLE returned until the new 
  6599. semaphore is opened. 
  6600.  
  6601. A thread that receives a return code of ERROR_INVALID_HANDLE can take the 
  6602. following corrective action: 
  6603.  
  6604.    1. First, the thread can obtain the records of all the semaphores in the 
  6605.       muxwait list by calling DosQueryMuxWaitSem. 
  6606.  
  6607.    2. Next, it can query each semaphore in the muxwait list, using 
  6608.       DosQueryMutexSem or DosQueryEventSem, to find out which semaphore is not 
  6609.       open to its process. 
  6610.  
  6611.    3. Finally, it can open the semaphores that are not open by calling 
  6612.       DosOpenMutexSem or DosOpenEventSem. 
  6613.  
  6614.  As soon as this semaphore is opened, the muxwait semaphore becomes valid again 
  6615.  for the process, as long as no other changes have been made to the muxwait 
  6616.  list to make it invalid. However, in order to successfully wait for the 
  6617.  muxwait semaphore, the process must call DosWaitMuxWaitSem again. 
  6618.  
  6619.  A semaphore must be open for a process before the process can add that 
  6620.  semaphore to a muxwait semaphore. If it is not open and a thread is waiting on 
  6621.  the muxwait semaphore, DosAddMuxWaitSem returns ERROR_INVALID_HANDLE to the 
  6622.  process adding the new semaphore, and the waiting thread continues waiting. 
  6623.  
  6624.  
  6625. ΓòÉΓòÉΓòÉ 7.4.6. Deleting a Semaphore from a Muxwait List ΓòÉΓòÉΓòÉ
  6626.  
  6627. An application can delete semaphores from a muxwait semaphore by using 
  6628. DosDeleteMuxWaitSem. 
  6629.  
  6630. Any thread in the process that created a muxwait semaphore can delete a mutex 
  6631. or event semaphore from the muxwait list by calling DosDeleteMuxWaitSem. 
  6632. Threads in other processes can also use this function, but they must first gain 
  6633. access to the semaphore by calling DosOpenMuxWaitSem. 
  6634.  
  6635. Semaphores can be deleted from the muxwait list even while threads are 
  6636. currently waiting for the semaphore. If the deleted semaphore is the only one 
  6637. in the muxwait list that has not yet been posted or released, then threads that 
  6638. are waiting for the muxwait semaphore are unblocked. Also, if the deleted 
  6639. semaphore happens to be the last one that a particular thread was waiting for, 
  6640. that thread is unblocked. Also, if the deleted semaphore is the last one in the 
  6641. muxwait list (that is, if the list is now empty), then all the threads that are 
  6642. waiting for the muxwait semaphore are unblocked. 
  6643.  
  6644.  
  6645. ΓòÉΓòÉΓòÉ 7.4.7. Querying a Muxwait Semaphore ΓòÉΓòÉΓòÉ
  6646.  
  6647. Processes use DosQueryMuxWaitSem to obtain the semaph ore records for each of 
  6648. the semaphores included in the muxwait semaphore. 
  6649.  
  6650. Any thread in the process that created a muxwait semaphore can obtain 
  6651. information about the semaphores in the muxwait list by calling 
  6652. DosQueryMuxWaitSem. Threads in other processes can also use this function, but 
  6653. they must first gain access to the semaphore by calling DosOpenMuxWaitSem. 
  6654.  
  6655. An application must provide this function with an array in which to store the 
  6656. semaphore records. If the array is not large enough to hold all of the 
  6657. semaphore records that are in the muxwait list, then ERROR_PARAM_TOO_SMALL is 
  6658. returned, and the record-counting parameter of DosQueryMuxWaitSem will contain 
  6659. the number of semaphore records that are in the muxwait list. The calling 
  6660. thread can then allocate the correct amount of space and call 
  6661. DosQueryMuxWaitSem again with the correct amount of space for the list of 
  6662. records. 
  6663.  
  6664. If the owner of any mutex semaphore in the muxwait-semaphore list has ended 
  6665. without releasing the semaphore, the records of all the semaphores in the list 
  6666. are still returned, but DosQueryMuxWaitSem also returns ERROR_SEM_OWNER_DIED. 
  6667. The calling thread can call DosQueryMutexSem for each mutex semaphore in the 
  6668. muxwait-semaphore list so that it can determine which semaphores are in the 
  6669. Owner Died state. The process can then close the unowned mutex semaphores. 
  6670.  
  6671. Each mutex semaphore that returns ERROR_SEM_OWNER_DIED from the query should be 
  6672. closed by calling DosCloseMutexSem. Also, because semaphore handles can be 
  6673. reused, the mutex semaphores that are closed should be deleted from the 
  6674. muxwait-semaphore list by calling DosDeleteMuxWaitSem. 
  6675.  
  6676. If the specified muxwait semaphore does not exist, ERROR_INVALID_HANDLE is 
  6677. returned. 
  6678.  
  6679.  
  6680. ΓòÉΓòÉΓòÉ 8. Glossary ΓòÉΓòÉΓòÉ
  6681.  
  6682. This glossary defines many of the terms used in this book. It includes terms 
  6683. and definitions from the IBM Dictionary of Computing, as well as terms specific 
  6684. to the OS/2 operating system and the Presentation Manager. It is not a complete 
  6685. glossary for the entire OS/2 operating system; nor is it a complete dictionary 
  6686. of computer terms. 
  6687.  
  6688. Other primary sources for these definitions are: 
  6689.  
  6690.    o  The American National Standard Dictionary for Information Systems, ANSI 
  6691.       X3.172-1990, copyrighted 1990 by the American National Standards 
  6692.       Institute, 11 West 42nd Street, New York, New York 10036. These 
  6693.       definitions are identified by the symbol (A) after the definition. 
  6694.  
  6695.    o  The Information Technology Vocabulary, developed by Subcommittee 1, Joint 
  6696.       Technical Committee 1, of the International Organization for 
  6697.       Standardization and the International Electrotechnical Commission 
  6698.       (ISO/IEC JTC1/SC1). Definitions of published parts of this vocabulary are 
  6699.       identified by the symbol (I) after the definition; definitions taken from 
  6700.       draft international standards, committee drafts, and working papers being 
  6701.       developed by ISO/IEC JTC1/SC1 are identified by the symbol (T) after the 
  6702.       definition, indicating that final agreement has not yet been reached 
  6703.       among the participating National Bodies of SC1. 
  6704.  
  6705.  
  6706. ΓòÉΓòÉΓòÉ 8.1. Glossary Listing ΓòÉΓòÉΓòÉ
  6707.  
  6708. Select a starting letter of glossary terms: 
  6709.  
  6710.  A    N 
  6711.  B    O 
  6712.  C    P 
  6713.  D    Q 
  6714.  E    R 
  6715.  F    S 
  6716.  G    T 
  6717.  H    U 
  6718.  I    V 
  6719.  J    W 
  6720.  K    X 
  6721.  L    Y 
  6722.  M    Z 
  6723.  
  6724.  
  6725. ΓòÉΓòÉΓòÉ <hidden> Glossary - A ΓòÉΓòÉΓòÉ
  6726.  
  6727.  accelerator - In SAA Common User Access architecture, a key or combination of 
  6728.    keys that invokes an application-defined function. 
  6729.  
  6730.  accelerator table - A table used to define which key strokes are treated as 
  6731.    accelerators and the commands they are translated into. 
  6732.  
  6733.  access mode - The manner in which an application gains access to a file it has 
  6734.    opened. Examples of access modes are read-only, write-only, and read/write. 
  6735.  
  6736.  access permission - All access rights that a user has regarding an object. (I)
  6737.  
  6738.  action - One of a set of defined tasks that a computer performs. Users request 
  6739.    the application to perform an action in several ways, such as typing a 
  6740.    command, pressing a function key, or selecting the action name from an 
  6741.    action bar or menu. 
  6742.  
  6743.  action bar - In SAA Common User Access architecture, the area at the top of a 
  6744.    window that contains choices that give a user access to actions available in 
  6745.    that window. 
  6746.  
  6747.  action point - The current position on the screen at which the pointer is 
  6748.    pointing. Contrast with hot spot and input focus. 
  6749.  
  6750.  active program - A program currently running on the computer.  An active 
  6751.    program can be interactive (running and receiving input from the user) or 
  6752.    noninteractive (running but not receiving input from the user). See also 
  6753.    interactive program and noninteractive program. 
  6754.  
  6755.  active window - The window with which the user is currently interacting. 
  6756.  
  6757.  address space - (1) The range of addresses available to a program. (A)  (2) 
  6758.    The area of virtual storage available for a particular job. 
  6759.  
  6760.  alphanumeric video output - Output to the logical video buffer when the video 
  6761.    adapter is in text mode and the logical video buffer is addressed by an 
  6762.    application as a rectangular array of character cells. 
  6763.  
  6764.  American National Standard Code for Information Interchange - The standard 
  6765.    code, using a coded character set consisting of 7-bit coded characters (8 
  6766.    bits including parity check), that is used for information interchange among 
  6767.    data processing systems, data communication systems, and associated 
  6768.    equipment. The ASCII set consists of control characters and graphic 
  6769.    characters. (A) 
  6770.  
  6771.    Note:  IBM has defined an extension to ASCII code (characters 128-255). 
  6772.  
  6773.  anchor - A window procedure that handles Presentation Manager* message 
  6774.    conversions between an icon procedure and an application. 
  6775.  
  6776.  anchor block - An area of Presentation-Manager-internal resources to allocated 
  6777.    process or thread that calls WinInitialize. 
  6778.  
  6779.  anchor point - A point in a window used by a program designer or by a window 
  6780.    manager to position a subsequently appearing window. 
  6781.  
  6782.  ANSI - American National Standards Institute. 
  6783.  
  6784.  APA - All points addressable. 
  6785.  
  6786.  API - Application programming interface. 
  6787.  
  6788.  application - A collection of software components used to perform specific 
  6789.    types of work on a computer; for example, a payroll application, an airline 
  6790.    reservation application, a network application. 
  6791.  
  6792.  application object - In SAA Advanced Common User Access architecture, a form 
  6793.    that an application provides for a user; for example, a spreadsheet form. 
  6794.    Contrast with user object. 
  6795.  
  6796.  application programming interface (API) - A functional interface supplied by 
  6797.    the operating system or by a separately orderable licensed program that 
  6798.    allows an application program written in a high-level language to use 
  6799.    specific data or functions of the operating system or the licensed program. 
  6800.  
  6801.  application-modal - Pertaining to a message box or dialog box for which 
  6802.    processing must be completed before further interaction with any other 
  6803.    window owned by the same application may take place. 
  6804.  
  6805.  area - In computer graphics, a filled shape such as a solid rectangle. 
  6806.  
  6807.  ASCII - American National Standard Code for Information Interchange. 
  6808.  
  6809.  ASCIIZ - A string of ASCII characters that is terminated with a byte 
  6810.    containing the value 0. 
  6811.  
  6812.  aspect ratio - In computer graphics, the width-to-height ratio of an area, 
  6813.    symbol, or shape. 
  6814.  
  6815.  asynchronous (ASYNC) - (1) Pertaining to two or more processes that do not 
  6816.    depend upon the occurrence of specific events such as common timing 
  6817.    signals. (T)  (2) Without regular time relationship;  unexpected or 
  6818.    unpredictable with respect to the execution of program instructions. See 
  6819.    also synchronous. 
  6820.  
  6821.  atom - A constant that represents a string. As soon as a string has been 
  6822.    defined as an atom, the atom can be used in place of the string to save 
  6823.    space. Strings are associated with their respective atoms in an atom table. 
  6824.    See also integer atom. 
  6825.  
  6826.  atom table - A table used to relate atoms with the strings that they 
  6827.    represent. Also in the table is the mechanism by which the presence of a 
  6828.    string can be checked. 
  6829.  
  6830.  atomic operation - An operation that completes its work on an object before 
  6831.    another operation can be performed on the same object. 
  6832.  
  6833.  attribute - A characteristic or property that can be controlled, usually to 
  6834.    obtain a required appearance;  for example, the color of a line. See also 
  6835.    graphics attributes and segment attributes. 
  6836.  
  6837.  automatic link - In Information Presentation Facility (IPF), a link that 
  6838.    begins a chain reaction at the primary window. When the user selects the 
  6839.    primary window, an automatic link is activated to display secondary windows. 
  6840.  
  6841.  AVIO - Advanced Video Input/Output. 
  6842.  
  6843.  
  6844. ΓòÉΓòÉΓòÉ <hidden> Glossary - B ΓòÉΓòÉΓòÉ
  6845.  
  6846.  B╨Æzier curve - (1) A mathematical technique of specifying smooth continous 
  6847.    lines and surfaces, which require a starting point and a finishing point 
  6848.    with several intermediate points that influence or control the path of the 
  6849.    linking curve. Named after Dr. P. B╨Æzier. (2) (D of C) In the AIX Graphics 
  6850.    Library, a cubic spline approximation to a set of four control points that 
  6851.    passes through the first and fourth control points and that has a continuous 
  6852.    slope where two spline segments meet. Named after Dr. P. B╨Æzier. 
  6853.  
  6854.  background - (1) In multiprogramming, the conditions under which low-priority 
  6855.    programs are executed. Contrast with foreground. (2) An active session that 
  6856.    is not currently displayed on the screen. 
  6857.  
  6858.  background color - The color in which the background of a graphic primitive is 
  6859.    drawn. 
  6860.  
  6861.  background mix - An attribute that determines how the background of a graphic 
  6862.    primitive is combined with the existing color of the graphics presentation 
  6863.    space. Contrast with mix. 
  6864.  
  6865.  background program - In multiprogramming, a program that executes with a low 
  6866.    priority. Contrast with foreground program. 
  6867.  
  6868.  bit map - A representation in memory of the data displayed on an APA device, 
  6869.    usually the screen. 
  6870.  
  6871.  block - (1) A string of data elements recorded or transmitted as a unit. The 
  6872.    elements may be characters, words, or logical records. (T)  (2) To record 
  6873.    data in a block. (3) A collection of contiguous records recorded as a unit. 
  6874.    Blocks are separated by interblock gaps and each block may contain one or 
  6875.    more records. (A)
  6876.  
  6877.  block device - A storage device that performs I/O operations on blocks of data 
  6878.    called sectors. Data on block devices can be randomly accessed. Block 
  6879.    devices are designated by a drive letter (for example, C:). 
  6880.  
  6881.  blocking mode - A condition set by an application that determines when its 
  6882.    threads might block. For example, an application might set the Pipemode 
  6883.    parameter for the DosCreateNPipe function so that its threads perform I/O 
  6884.    operations to the named pipe block when no data is available. 
  6885.  
  6886.  border - A visual indication (for example, a separator line or a background 
  6887.    color) of the boundaries of a window. 
  6888.  
  6889.  boundary determination - An operation used to compute the size of the smallest 
  6890.    rectangle that encloses a graphics object on the screen. 
  6891.  
  6892.  breakpoint - (1) A point in a computer program where execution may be halted. 
  6893.    A breakpoint is usually at the beginning of an instruction where halts, 
  6894.    caused by external intervention, are convenient for resuming 
  6895.    execution. (T)  (2) A place in a program, specified by a command or a 
  6896.    condition, where the system halts execution and gives control to the 
  6897.    workstation user or to a specified program. 
  6898.  
  6899.  broken pipe - When all of the handles that access one end of a pipe have been 
  6900.    closed. 
  6901.  
  6902.  bucket - One or more fields in which the result of an operation is kept. 
  6903.  
  6904.  buffer - (1) A portion of storage used to hold input or output data 
  6905.    temporarily. (2) To allocate and schedule the use of buffers. (A)
  6906.  
  6907.  button - A mechanism used to request or initiate an action. See also barrel 
  6908.    buttons, bezel buttons, mouse button, push button, and radio button. 
  6909.  
  6910.  byte pipe - Pipes that handle data as byte streams. All unnamed pipes are byte 
  6911.    pipes. Named pipes can be byte pipes or message pipes. See byte stream. 
  6912.  
  6913.  byte stream - Data that consists of an unbroken stream of bytes. 
  6914.  
  6915.  
  6916. ΓòÉΓòÉΓòÉ <hidden> Glossary - C ΓòÉΓòÉΓòÉ
  6917.  
  6918.  cache - A high-speed buffer storage that contains frequently accessed 
  6919.    instructions and data; it is used to reduce access time. 
  6920.  
  6921.  cached micro presentation space - A presentation space from a 
  6922.    Presentation-Manager-owned store of micro presentation spaces. It can be 
  6923.    used for drawing to a window only, and must be returned to the store when 
  6924.    the task is complete. 
  6925.  
  6926.  CAD - Computer-Aided Design. 
  6927.  
  6928.  call - (1) The action of bringing a computer program, a routine, or a 
  6929.    subroutine into effect, usually by specifying the entry conditions and 
  6930.    jumping to an entry point. (I)  (A)  (2) To transfer control to a procedure, 
  6931.    program, routine, or subroutine. 
  6932.  
  6933.  calling sequence - A sequence of instructions together with any associated 
  6934.    data necessary to execute a call. (T)
  6935.  
  6936.  Cancel - An action that removes the current window or menu without processing 
  6937.    it, and returns the previous window. 
  6938.  
  6939.  cascaded menu - In the OS/2 operating system, a menu that appears when the 
  6940.    arrow to the right of a cascading choice is selected. It contains a set of 
  6941.    choices that are related to the cascading choice. Cascaded menus are used to 
  6942.    reduce the length of a menu. See also cascading choice. 
  6943.  
  6944.  cascading choice - In SAA Common User Access architecture, a choice in a menu 
  6945.    that, when selected, produces a cascaded menu containing other choices.  An 
  6946.    arrow () appears to the right of the cascading choice. 
  6947.  
  6948.  CASE statement - In PM programming, provides the body of a window procedure. 
  6949.    There is usually one CASE statement for each message type supported by an 
  6950.    application. 
  6951.  
  6952.  CGA - Color graphics adapter. 
  6953.  
  6954.  chained list - A list in which the data elements may be dispersed but in which 
  6955.    each data element contains information for locating the 
  6956.    next. (T)Synonymous with linked list. 
  6957.  
  6958.  character - A letter, digit, or other symbol. 
  6959.  
  6960.  character box - In computer graphics, the boundary that defines, in world 
  6961.    coordinates, the horizontal and vertical space occupied by a single 
  6962.    character from a character set. See also character mode. Contrast with 
  6963.    character cell. 
  6964.  
  6965.  character cell - The physical, rectangular space in which any single character 
  6966.    is displayed on a screen or printer device. Position is addressed by row and 
  6967.    column coordinates. Contrast with character box. 
  6968.  
  6969.  character code - The means of addressing a character in a character set, 
  6970.    sometimes called code point. 
  6971.  
  6972.  character device - A device that performs I/O operations on one character at a 
  6973.    time. Because character devices view data as a stream of bytes, 
  6974.    character-device data cannot be randomly accessed. Character devices include 
  6975.    the keyboard, mouse, and printer, and are referred to by name. 
  6976.  
  6977.  character mode - A mode that, in conjunction with the font type, determines 
  6978.    the extent to which graphics characters are affected by the character box, 
  6979.    shear, and angle attributes. 
  6980.  
  6981.  character set - (1) An ordered set of unique representations called 
  6982.    characters; for example, the 26 letters of English alphabet, Boolean 0 and 
  6983.    1, the set of symbols in the Morse code, and the 128 ASCII 
  6984.    characters. (A)  (2) All the valid characters for a programming language or 
  6985.    for a computer system. (3) A group of characters used for a specific reason; 
  6986.    for example, the set of characters a printer can print. 
  6987.  
  6988.  check box - In SAA Advanced Common User Access architecture, a square box with 
  6989.    associated text that represents a choice. When a user selects a choice, an X 
  6990.    appears in the check box to indicate that the choice is in effect. The user 
  6991.    can clear the check box by selecting the choice again. Contrast with radio 
  6992.    button. 
  6993.  
  6994.  check mark -  (1) (D of C) In SAA Advanced Common User Access architecture, a 
  6995.    symbol that shows that a choice is currently in effect. (2) The symbol that 
  6996.    is used to indicate a selected item on a pull-down menu. 
  6997.  
  6998.  child process - In the OS/2 operating system, a process started by another 
  6999.    process, which is called the parent process. Contrast with parent process. 
  7000.  
  7001.  child window - A window that appears within the border of its parent window 
  7002.    (either a primary window or another child window). When the parent window is 
  7003.    resized, moved, or destroyed, the child window also is resized, moved, or 
  7004.    destroyed; however, the child window can be moved or resized independently 
  7005.    from the parent window, within the boundaries of the parent window. Contrast 
  7006.    with parent window. 
  7007.  
  7008.  choice - (1) An option that can be selected. The choice can be presented as 
  7009.    text, as a symbol (number or letter), or as an icon (a pictorial symbol). 
  7010.    (2) (D of C) In SAA Common User Access architecture, an item that a user can 
  7011.    select. 
  7012.  
  7013.  chord - (1) To press more than one button on a pointing device while the 
  7014.    pointer is within the limits that the user has specified for the operating 
  7015.    environment. (2) (D of C) In graphics, a short line segment whose end points 
  7016.    lie on a circle. Chords are a means for producing a circular image from 
  7017.    straight lines. The higher the number of chords per circle, the smoother the 
  7018.    circular image. 
  7019.  
  7020.  class - In object-oriented design or programming, a group of objects that 
  7021.    share a common definition and that therefore share common properties, 
  7022.    operations, and behavior. Members of the group are called instances of the 
  7023.    class. 
  7024.  
  7025.  class method - In System Object Model, an action that can be performed on a 
  7026.    class object. Synonymous with factory method. 
  7027.  
  7028.  class object - In System Object Model, the run-time implementation of a class. 
  7029.  
  7030.  class style - The set of properties that apply to every window in a window 
  7031.    class. 
  7032.  
  7033.  client - (1) A functional unit that receives shared services from a 
  7034.    server. (T)  (2) A user, as in a client process that uses a named pipe or 
  7035.    queue that is created and owned by a server process. 
  7036.  
  7037.  client area - The part of the window, inside the border, that is below the 
  7038.    menu bar. It is the user's work space, where a user types information and 
  7039.    selects choices from selection fields.  In primary windows, it is where an 
  7040.    application programmer presents the objects that a user works on. 
  7041.  
  7042.  client program - An application that creates and manipulates instances of 
  7043.    classes. 
  7044.  
  7045.  client window - The window in which the application displays output and 
  7046.    receives input. This window is located inside the frame window, under the 
  7047.    window title bar and any menu bar, and within any scroll bars. 
  7048.  
  7049.  clip limits - The area of the paper that can be reached by a printer or 
  7050.    plotter. 
  7051.  
  7052.  clipboard - In SAA Common User Access architecture, an area of computer 
  7053.    memory, or storage, that temporarily holds data. Data in the clipboard is 
  7054.    available to other applications. 
  7055.  
  7056.  clipping - In computer graphics, removing those parts of a display image that 
  7057.    lie outside a given boundary. (I)  (A)
  7058.  
  7059.  clipping area - The area in which the window can paint. 
  7060.  
  7061.  clipping path - A clipping boundary in world-coordinate space. 
  7062.  
  7063.  clock tick - The minimum unit of time that the system tracks. If the system 
  7064.    timer currently counts at a rate of X Hz, the system tracks the time every 
  7065.    1/X of a second. Also known as time tick. 
  7066.  
  7067.  CLOCK$ - Character-device name reserved for the system clock. 
  7068.  
  7069.  code page - An assignment of graphic characters and control-function meanings 
  7070.    to all code points. 
  7071.  
  7072.  code point - (1) Synonym for character code. (2) (D of C) A 1-byte code 
  7073.    representing one of 256 potential characters. 
  7074.  
  7075.  code segment - An executable section of programming code within a load module. 
  7076.  
  7077.  color dithering - See dithering. 
  7078.  
  7079.  color graphics adapter (CGA) - An adapter that simultaneously provides four 
  7080.    colors and is supported by all IBM Personal Computer and Personal System/2 
  7081.    models. 
  7082.  
  7083.  command - The name and parameters associated with an action that a program can 
  7084.    perform. 
  7085.  
  7086.  command area - An area composed of a command field prompt and a command entry 
  7087.    field. 
  7088.  
  7089.  command entry field - An entry field in which users type commands. 
  7090.  
  7091.  command line - On a display screen, a display line, sometimes at the bottom of 
  7092.    the screen, in which only commands can be entered. 
  7093.  
  7094.  command mode - A state of a system or device in which the user can enter 
  7095.    commands. 
  7096.  
  7097.  command prompt - A field prompt showing the location of the command entry 
  7098.    field in a panel. 
  7099.  
  7100.  Common Programming Interface (CPI) - Definitions of those application 
  7101.    development languages and services that have, or are intended to have, 
  7102.    implementations on and a high degree of commonality across the SAA 
  7103.    environments. One of the three SAA architectural areas. See also Common User 
  7104.    Access architecture. 
  7105.  
  7106.  Common User Access (CUA) architecture -  Guidelines for the dialog between a 
  7107.    human and a workstation or terminal. One of the three SAA architectural 
  7108.    areas. See also Common Programming Interface. 
  7109.  
  7110.  compile - To translate a program written in a higher-level programming 
  7111.    language into a machine language program. 
  7112.  
  7113.  composite window - A window composed of other windows (such as a frame window, 
  7114.    frame-control windows, and a client window) that are kept together as a unit 
  7115.    and that interact with each other. 
  7116.  
  7117.  computer-aided design (CAD) - The use of a computer to design or change a 
  7118.    product, tool, or machine, such as using a computer for drafting or 
  7119.    illustrating. 
  7120.  
  7121.  COM1, COM2, COM3 - Character-device names reserved for serial ports 1 through 
  7122.    3. 
  7123.  
  7124.  CON - Character-device name reserved for the console keyboard and screen. 
  7125.  
  7126.  conditional cascaded menu - A pull-down menu associated with a menu item that 
  7127.    has a cascade mini-push button beside it in an object's pop-up menu. The 
  7128.    conditional cascaded menu is displayed when the user selects the mini-push 
  7129.    button. 
  7130.  
  7131.  container - In SAA Common User Access architecture, an object that holds other 
  7132.    objects. A folder is an example of a container object. See also folder and 
  7133.    object. 
  7134.  
  7135.  contextual help - In SAA Common User Access Architecture, help that gives 
  7136.    specific information about the item the cursor is on. The help is contextual 
  7137.    because it provides information about a specific item as it is currently 
  7138.    being used. Contrast with extended help. 
  7139.  
  7140.  contiguous - Touching or joining at a common edge or boundary, for example, an 
  7141.    unbroken consecutive series of storage locations. 
  7142.  
  7143.  control - In SAA Advanced Common User Access architecture, a component of the 
  7144.    user interface that allows a user to select choices or type information; for 
  7145.    example, a check box, an entry field, a radio button. 
  7146.  
  7147.  control area - A storage area used by a computer program to hold control information. (I)  (A)
  7148.  
  7149.  Control Panel - In the Presentation Manager, a program used to set up user 
  7150.    preferences that act globally across the system. 
  7151.  
  7152.  Control Program - (1) The basic functions of the operating system, including 
  7153.    DOS emulation and the support for keyboard, mouse, and video input/output. 
  7154.    (2) A computer program designed to schedule and to supervise the execution 
  7155.    of programs of a computer system. (I)  (A)
  7156.  
  7157.  control window - A window that is used as part of a composite window to 
  7158.    perform simple input and output tasks. Radio buttons and check boxes are 
  7159.    examples. 
  7160.  
  7161.  control word - An instruction within a document that identifies its parts or 
  7162.    indicates how to format the document. 
  7163.  
  7164.  coordinate space - A two-dimensional set of points used to generate output on 
  7165.    a video display of printer. 
  7166.  
  7167.  Copy - A choice that places onto the clipboard, a copy of what the user has 
  7168.    selected. See also Cut and Paste. 
  7169.  
  7170.  correlation - The action of determining which element or object within a 
  7171.    picture is at a given position on the display. This follows a pick 
  7172.    operation. 
  7173.  
  7174.  coverpage window - A window in which the application's help information is 
  7175.    displayed. 
  7176.  
  7177.  CPI - Common Programming Interface. 
  7178.  
  7179.  critical extended attribute - An extended attribute that is necessary for the 
  7180.    correct operation of the system or a particular application. 
  7181.  
  7182.  critical section - (1) In programming languages, a part of an asynchronous 
  7183.    procedure that cannot be executed simultaneously with a certain part of 
  7184.    another asynchronous procedure. (I)
  7185.  
  7186.    Note:  Part of the other asynchronous procedure also is a critical section. 
  7187.    (2) A section of code that is not reentrant; that is, code that can be 
  7188.    executed by only one thread at a time. 
  7189.  
  7190.  CUA architecture - Common User Access architecture. 
  7191.  
  7192.  current position - In computer graphics, the position, in user coordinates, 
  7193.    that becomes the starting point for the next graphics routine, if that 
  7194.    routine does not explicitly specify a starting point. 
  7195.  
  7196.  cursor - A symbol displayed on the screen and associated with an input device. 
  7197.    The cursor indicates where input from the device will be placed. Types of 
  7198.    cursors include text cursors, graphics cursors, and selection cursors. 
  7199.    Contrast with pointer and input focus. 
  7200.  
  7201.  Cut - In SAA Common User Access architecture, a choice that removes a selected 
  7202.    object, or a part of an object, to the clipboard, usually compressing the 
  7203.    space it occupied in a window. See also Copy and Paste. 
  7204.  
  7205.  
  7206. ΓòÉΓòÉΓòÉ <hidden> Glossary - D ΓòÉΓòÉΓòÉ
  7207.  
  7208.  daisy chain - A method of device interconnection for determining interrupt 
  7209.    priority by connecting the interrupt sources serially. 
  7210.  
  7211.  data segment - A nonexecutable section of a program module; that is, a section 
  7212.    of a program that contains data definitions. 
  7213.  
  7214.  data structure - The syntactic structure of symbolic expressions and their 
  7215.    storage-allocation characteristics. (T)
  7216.  
  7217.  data transfer - The movement of data from one object to another by way of the 
  7218.    clipboard or by direct manipulation. 
  7219.  
  7220.  DBCS - Double-byte character set. 
  7221.  
  7222.  DDE - Dynamic data exchange. 
  7223.  
  7224.  deadlock - (1) Unresolved contention for the use of a resource. (2) An error 
  7225.    condition in which processing cannot continue because each of two elements 
  7226.    of the process is waiting for an action by, or a response from, the other. 
  7227.    (3) An impasse that occurs when multiple processes are waiting for the 
  7228.    availability of a resource that will not become available because it is 
  7229.    being held by another process that is in a similar wait state. 
  7230.  
  7231.  debug - To detect, diagnose, and eliminate errors in programs. (T)
  7232.  
  7233.  decipoint - In printing, one tenth of a point.  There are 72 points in an 
  7234.    inch. 
  7235.  
  7236.  default procedure - A function provided by the Presentation Manager Interface 
  7237.    that may be used to process standard messages from dialogs or windows. 
  7238.  
  7239.  default value - A value assumed when no value has been specified. Synonymous 
  7240.    with assumed value. For example, in the graphics programming interface, the 
  7241.    default line-type is `solid'. 
  7242.  
  7243.  definition list - A type of list that pairs a term and its description. 
  7244.  
  7245.  delta - An application-defined threshold, or number of container items, from 
  7246.    either end of the list. 
  7247.  
  7248.  descendant - See child process. 
  7249.  
  7250.  descriptive text - Text used in addition to a field prompt to give more 
  7251.    information about a field. 
  7252.  
  7253.  Deselect all - A choice that cancels the selection of all of the objects that 
  7254.    have been selected in that window. 
  7255.  
  7256.  Desktop Manager - In the Presentation Manager, a window that displays a list 
  7257.    of groups of programs, each of which can be started or stopped. 
  7258.  
  7259.  desktop window - The window, corresponding to the physical device, against 
  7260.    which all other types of windows are established. 
  7261.  
  7262.  detached process - A background process that runs independent of the parent 
  7263.    process. 
  7264.  
  7265.  detent - A point on a slider that represents an exact value to which a user 
  7266.    can move the slider arm. 
  7267.  
  7268.  device context - A logical description of a data destination such as memory, 
  7269.    metafile, display, printer, or plotter. See also direct device context, 
  7270.    information device context, memory device context, metafile device context, 
  7271.    queued device context, and screen device context. 
  7272.  
  7273.  device driver - A file that contains the code needed to attach and use a 
  7274.    device such as a display, printer, or plotter. 
  7275.  
  7276.  device space - (1) Coordinate space in which graphics are assembled after all 
  7277.    GPI transformations have been applied. Device space is defined in 
  7278.    device-specific units. (2) (D of C) In computer graphics, a space defined by 
  7279.    the complete set of addressable points of a display device. (A)
  7280.  
  7281.  dialog - The interchange of information between a computer and its user 
  7282.    through a sequence of requests by the user and the presentation of responses 
  7283.    by the computer. 
  7284.  
  7285.  dialog box - In SAA Advanced Common User Access architecture, a movable 
  7286.    window, fixed in size, containing controls that a user uses to provide 
  7287.    information required by an application so that it can continue to process a 
  7288.    user request. See also message box, primary window, secondary window. Also 
  7289.    known as a pop-up window. 
  7290.  
  7291.  Dialog Box Editor - A WYSIWYG editor that creates dialog boxes for 
  7292.    communicating with the application user. 
  7293.  
  7294.  dialog item - A component (for example, a menu or a button) of a dialog box. 
  7295.    Dialog items are also used when creating dialog templates. 
  7296.  
  7297.  dialog procedure - A dialog window that is controlled by a window procedure. 
  7298.    It is responsible for responding to all messages sent to the dialog window. 
  7299.  
  7300.  dialog tag language - A markup language used by the DTL compiler to create 
  7301.    dialog objects. 
  7302.  
  7303.  dialog template - The definition of a dialog box, which contains details of 
  7304.    its position, appearance, and window ID, and the window ID of each of its 
  7305.    child windows. 
  7306.  
  7307.  direct device context - A logical description of a data destination that is a 
  7308.    device other than the screen (for example, a printer or plotter), and where 
  7309.    the output is not to go through the spooler. Its purpose is to satisfy 
  7310.    queries. See also device context. 
  7311.  
  7312.  direct manipulation - The user's ability to interact with an object by using 
  7313.    the mouse, typically by dragging an object around on the Desktop and 
  7314.    dropping it on other objects. 
  7315.  
  7316.  direct memory access (DMA) - A technique for moving data directly between main 
  7317.    storage and peripheral equipment without requiring processing of the data by 
  7318.    the processing unit.(T)
  7319.  
  7320.  directory - A type of file containing the names and controlling information 
  7321.    for other files or other directories. 
  7322.  
  7323.  display point - Synonym for pel. 
  7324.  
  7325.  dithering - (1) The process used in color displays whereby every other pel is 
  7326.    set to one color, and the intermediate pels are set to another. Together 
  7327.    they produce the effect of a third color at normal viewing distances. This 
  7328.    process can only be used on solid areas of color; it does not work, for 
  7329.    example, on narrow lines. (2) (D of C ) In computer graphics, a technique of 
  7330.    interleaving dark and light pixels so that the resulting image looks 
  7331.    smoothly shaded when viewed from a distance. 
  7332.  
  7333.  DMA - Direct memory access. 
  7334.  
  7335.  DOS Protect Mode Interface (DPMI) - An interface between protect mode and real 
  7336.    mode programs. 
  7337.  
  7338.  double-byte character set (DBCS) - A set of characters in which each character 
  7339.    is represented by two bytes.  Languages such as Japanese, Chinese, and 
  7340.    Korean, which contain more characters than can be represented by 256 code 
  7341.    points, require double-byte character sets. Since each character requires 
  7342.    two bytes, the entering, displaying, and printing of DBCS characters 
  7343.    requires hardware and software that can support DBCS. 
  7344.  
  7345.  doubleword - A contiguous sequence of bits or characters that comprises two 
  7346.    computer words and is capable of being addressed as a unit. (A)
  7347.  
  7348.  DPMI - DOS Protect Mode Interface. 
  7349.  
  7350.  drag - In SAA Common User Access, to use a pointing device to move an object; 
  7351.    for example, clicking on a window border, and dragging it to make the window 
  7352.    larger. 
  7353.  
  7354.  dragging - (1) In computer graphics, moving an object on the display screen as 
  7355.    if it were attached to the pointer. (2) (D of C) In computer graphics, 
  7356.    moving one or more segments on a display surface by translating. (I)  (A)
  7357.  
  7358.  drawing chain - See segment chain. 
  7359.  
  7360.  drop - To fix the position of an object that is being dragged, by releasing 
  7361.    the select button of the pointing device. 
  7362.  
  7363.  drop - To fix the position of an object that is being dragged, by releasing 
  7364.    the select button of the pointing device. See also drag. 
  7365.  
  7366.  DTL - Dialog tag language. 
  7367.  
  7368.  dual-boot function - A feature of the OS/2 operating system that allows the 
  7369.    user to start DOS from within the operating system, or an OS/2 session from 
  7370.    within DOS. 
  7371.  
  7372.  duplex - Pertaining to communication in which data can be sent and received at 
  7373.    the same time. Synonymous with full duplex. 
  7374.  
  7375.  dynamic data exchange (DDE) - A message protocol used to communicate between 
  7376.    applications that share data. The protocol uses shared memory as the means 
  7377.    of exchanging data between applications. 
  7378.  
  7379.  dynamic data formatting - A formatting procedure that enables you to 
  7380.    incorporate text, bit maps or metafiles in an IPF window at execution time. 
  7381.  
  7382.  dynamic link library - A collection of executable programming code and data 
  7383.    that is bound to an application at load time or run time, rather than during 
  7384.    linking. The programming code and data in a dynamic link library can be 
  7385.    shared by several applications simultaneously. 
  7386.  
  7387.  dynamic linking - The process of resolving external references in a program 
  7388.    module at load time or run time rather than during linking. 
  7389.  
  7390.  dynamic segments - Graphics segments drawn in exclusive-OR mix mode so that 
  7391.    they can be moved from one screen position to another without affecting the 
  7392.    rest of the displayed picture. 
  7393.  
  7394.  dynamic storage - (1) A device that stores data in a manner that permits the 
  7395.    data to move or vary with time such that the specified data is not always 
  7396.    available for recovery. (A)  (2) A storage in which the cells require 
  7397.    repetitive application of control signals in order to retain stored data. 
  7398.    Such repetitive application of the control signals is called a refresh 
  7399.    operation. A dynamic storage may use static addressing or sensing 
  7400.    circuits. (A)  (3) See also static storage. 
  7401.  
  7402.  dynamic time slicing - Varies the size of the time slice depending on system 
  7403.    load and paging activity. 
  7404.  
  7405.  dynamic-link module - A module that is linked at load time or run time. 
  7406.  
  7407.  
  7408. ΓòÉΓòÉΓòÉ <hidden> Glossary - E ΓòÉΓòÉΓòÉ
  7409.  
  7410.  EBCDIC - Extended binary-coded decimal interchange code. A coded character set 
  7411.    consisting of 8-bit coded characters (9 bits including parity check), used 
  7412.    for information interchange among data processing systems, data 
  7413.    communications systems, and associated equipment. 
  7414.  
  7415.  edge-triggered - Pertaining to an event semaphore that is posted then reset 
  7416.    before a waiting thread gets a chance to run. The semaphore is considered to 
  7417.    be posted for the rest of that thread's waiting period; the thread does not 
  7418.    have to wait for the semaphore to be posted again. 
  7419.  
  7420.  EGA - Extended graphics adapter. 
  7421.  
  7422.  element - An entry in a graphics segment that comprises one or more graphics 
  7423.    orders and that is addressed by the element pointer. 
  7424.  
  7425.  EMS - Expanded Memory Specification. 
  7426.  
  7427.  encapsulation - Hiding an object's implementation, that is, its private, 
  7428.    internal data and methods. Private variables and methods are accessible only 
  7429.    to the object that contains them. 
  7430.  
  7431.  entry field - In SAA Common User Access architecture, an area where a user 
  7432.    types information. Its boundaries are usually indicated. See also selection 
  7433.    field. 
  7434.  
  7435.  entry panel - A defined panel type containing one or more entry fields and 
  7436.    protected information such as headings, prompts, and explanatory text. 
  7437.  
  7438.  entry-field control - The component of a user interface that provides the 
  7439.    means by which the application receives data entered by the user in an entry 
  7440.    field. When it has the input focus, the entry field displays a flashing 
  7441.    pointer at the position where the next typed character will go. 
  7442.  
  7443.  environment segment - The list of environment variables and their values for a 
  7444.    process. 
  7445.  
  7446.  environment strings - ASCII text strings that define the value of environment 
  7447.    variables. 
  7448.  
  7449.  environment variables - Variables that describe the execution environment of a 
  7450.    process. These variables are named by the operating system or by the 
  7451.    application. Environment variables named by the operating system are PATH, 
  7452.    DPATH, INCLUDE, INIT, LIB, PROMPT, and TEMP. The values of environment 
  7453.    variables are defined by the user in the CONFIG.SYS file, or by using the 
  7454.    SET command at the OS/2 command prompt. 
  7455.  
  7456.  error message - An indication that an error has been detected. (A)
  7457.  
  7458.  event semaphore - A semaphore that enables a thread to signal a waiting thread 
  7459.    or threads that an event has occurred or that a task has been completed. The 
  7460.    waiting threads can then perform an action that is dependent on the 
  7461.    completion of the signaled event. 
  7462.  
  7463.  exception - An abnormal condition such as an I/O error encountered in 
  7464.    processing a data set or a file. 
  7465.  
  7466.  exclusive system semaphore - A system semaphore that can be modified only by 
  7467.    threads within the same process. 
  7468.  
  7469.  executable file - (1) A file that contains programs or commands that perform 
  7470.    operations or actions to be taken. (2) A collection of related data records 
  7471.    that execute programs. 
  7472.  
  7473.  exit - To execute an instruction within a portion of a computer program in 
  7474.    order to terminate the execution of that portion. Such portions of computer 
  7475.    programs include loops, subroutines, modules, and so on. (T)  Repeated exit 
  7476.    requests return the user to the point from which all functions provided to 
  7477.    the system are accessible. Contrast with cancel. 
  7478.  
  7479.  expanded memory specification (EMS) - Enables DOS applications to access 
  7480.    memory above the 1MB real mode addressing limit. 
  7481.  
  7482.  extended attribute - An additional piece of information about a file object, 
  7483.    such as its data format or category. It consists of a name and a value. A 
  7484.    file object may have more than one extended attribute associated with it. 
  7485.  
  7486.  extended help - In SAA Common User Access architecture, a help action that 
  7487.    provides information about the contents of the application window from which 
  7488.    a user requested help. Contrast with contextual help. 
  7489.  
  7490.  extended-choice selection - A mode that allows the user to select more than 
  7491.    one item from a window. Not all windows allow extended choice selection. 
  7492.    Contrast with multiple-choice selection. 
  7493.  
  7494.  extent - Continuous space on a disk or diskette that is occupied by or 
  7495.    reserved for a particular data set, data space, or file. 
  7496.  
  7497.  external link - In Information Presentation Facility, a link that connects 
  7498.    external online document files. 
  7499.  
  7500.  
  7501. ΓòÉΓòÉΓòÉ <hidden> Glossary - F ΓòÉΓòÉΓòÉ
  7502.  
  7503.  family-mode application - An application program that can run in the OS/2 
  7504.    environment and in the DOS environment; however, it cannot take advantage of 
  7505.    many of the OS/2-mode facilities, such as multitasking, interprocess 
  7506.    communication, and dynamic linking. 
  7507.  
  7508.  FAT - File allocation table. 
  7509.  
  7510.  FEA - Full extended attribute. 
  7511.  
  7512.  field-level help - Information specific to the field on which the cursor is 
  7513.    positioned. This help function is "contextual" because it provides 
  7514.    information about a specific item as it is currently used; the information 
  7515.    is dependent upon the context within the work session. 
  7516.  
  7517.  FIFO - First-in-first-out. (A)
  7518.  
  7519.  file - A named set of records stored or processed as a unit. (T)
  7520.  
  7521.  file allocation table (FAT) - In IBM personal computers, a table used by the 
  7522.    operating system to allocate space on a disk for a file, and to locate and 
  7523.    chain together parts of the file that may be scattered on different sectors 
  7524.    so that the file can be used in a random or sequential manner. 
  7525.  
  7526.  file attribute - Any of the attributes that describe the characteristics of a 
  7527.    file. 
  7528.  
  7529.  File Manager - In the Presentation Manager, a program that displays 
  7530.    directories and files, and allows various actions on them. 
  7531.  
  7532.  file specification - The full identifier for a file, which includes its drive 
  7533.    designation, path, file name, and extension. 
  7534.  
  7535.  file system - The combination of software and hardware that supports storing 
  7536.    information on a storage device. 
  7537.  
  7538.  file system driver (FSD) - A program that manages file I\O and controls the 
  7539.    format of information on the storage media. 
  7540.  
  7541.  fillet - A curve that is tangential to the end points of two adjoining lines. 
  7542.    See also polyfillet. 
  7543.  
  7544.  filtering - An application process that changes the order of data in a queue. 
  7545.  
  7546.  first-in-first-out (FIFO) - A queuing technique in which the next item to be 
  7547.    retrieved is the item that has been in the queue for the longest time. (A)
  7548.  
  7549.  flag - (1) An indicator or parameter that shows the setting of a switch. (2) A 
  7550.    character that signals the occurrence of some condition, such as the end of 
  7551.    a word. (A)  (3) (D of C) A characteristic of a file or directory that 
  7552.    enables it to be used in certain ways. See also archive flag, hidden flag, 
  7553.    and read-only flag. 
  7554.  
  7555.  focus - See input focus. 
  7556.  
  7557.  folder - A container used to organize objects. 
  7558.  
  7559.  font - A particular size and style of typeface that contains definitions of 
  7560.    character sets, marker sets, and pattern sets. 
  7561.  
  7562.  Font Editor - A utility program provided with the IBM Developers Toolkit that 
  7563.    enables the design and creation of new fonts. 
  7564.  
  7565.  foreground program - (1) The program with which the user is currently 
  7566.    interacting. Also known as interactive program. Contrast with background 
  7567.    program. (2) (D of C) In multiprogramming,  a high-priority program. 
  7568.  
  7569.  frame - The part of a window that can contain several different visual 
  7570.    elements specified by the application, but drawn and controlled by the 
  7571.    Presentation Manager. The frame encloses the client area. 
  7572.  
  7573.  frame styles - Standard window layouts provided by the Presentation Manager. 
  7574.  
  7575.  FSD - File system driver. 
  7576.  
  7577.  full-duplex - Synonym for duplex. 
  7578.  
  7579.  full-screen application - An application that has complete control of the 
  7580.    screen. 
  7581.  
  7582.  function - (1) In a programming language, a block, with or without formal 
  7583.    parameters, whose execution is invoked by means of a call. (2) A set of 
  7584.    related control statements that cause one or more programs to be performed. 
  7585.  
  7586.  function key - A key that causes a specified sequence of operations to be 
  7587.    performed when it is pressed, for example, F1 and Alt-K. 
  7588.  
  7589.  function key area - The area at the bottom of a window that contains function 
  7590.    key assignments such as F1=Help. 
  7591.  
  7592.  
  7593. ΓòÉΓòÉΓòÉ <hidden> Glossary - G ΓòÉΓòÉΓòÉ
  7594.  
  7595.  GDT - Global Descriptor Table. 
  7596.  
  7597.  general protection fault - An exception condition that occurs when a process 
  7598.    attempts to use storage or a module that has some level of protection 
  7599.    assigned to it, such as I/O privilege level. See also IOPL code segment. 
  7600.  
  7601.  Global Descriptor Table (GDT) - A table that defines code and data segments 
  7602.    available to all tasks in an application. 
  7603.  
  7604.  global dynamic-link module - A dynamic-link module that can be shared by all 
  7605.    processes in the system that refer to the module name. 
  7606.  
  7607.  global file-name character - Either a question mark (?) or an asterisk (*) 
  7608.    used as a variable in a file name or file name extension when referring to a 
  7609.    particular file or group of files. 
  7610.  
  7611.  glyph - A graphic symbol whose appearance conveys information. 
  7612.  
  7613.  GPI - Graphics programming interface. 
  7614.  
  7615.  graphic primitive - In computer graphics, a basic element, such as an arc or a 
  7616.    line, that is not made up of smaller parts and that is used to create 
  7617.    diagrams and pictures. See also graphics segment. 
  7618.  
  7619.  graphics - (1) A picture defined in terms of graphic primitives and graphics 
  7620.    attributes. (2) (D of C) The making of charts and pictures. (3) Pertaining 
  7621.    to charts, tables, and their creation. (4) See computer graphics, coordinate 
  7622.    graphics, fixed-image graphics, interactive graphics, passive graphics, 
  7623.    raster graphics. 
  7624.  
  7625.  graphics attributes - Attributes that apply to graphic primitives. Examples 
  7626.    are color, line type, and shading-pattern definition. See also segment 
  7627.    attributes. 
  7628.  
  7629.  graphics field - The clipping boundary that defines the visible part of the 
  7630.    presentation-page contents. 
  7631.  
  7632.  graphics mode - One of several states of a display. The mode determines the 
  7633.    resolution and color content of the screen. 
  7634.  
  7635.  graphics model space - The conceptual coordinate space in which a picture is 
  7636.    constructed after any model transforms have been applied. Also known as 
  7637.    model space. 
  7638.  
  7639.  Graphics programming interface - The formally defined programming language 
  7640.    that is between an IBM graphics program and the user of the program. 
  7641.  
  7642.  graphics segment - A sequence of related graphic primitives and graphics 
  7643.    attributes. See also graphic primitive. 
  7644.  
  7645.  graying - The indication that a choice on a pull-down is unavailable. 
  7646.  
  7647.  group - A collection of logically connected controls. For example, the buttons 
  7648.    controlling paper size for a printer could be called a group. See also 
  7649.    program group. 
  7650.  
  7651.  
  7652. ΓòÉΓòÉΓòÉ <hidden> Glossary - H ΓòÉΓòÉΓòÉ
  7653.  
  7654.  handle - (1) An identifier that represents an object, such as a device or 
  7655.    window, to the Presentation Interface. (2) (D of C) In the Advanced DOS and 
  7656.    OS/2 operating systems, a binary value created by the system that identifies 
  7657.    a drive, directory, and file so that the file can be found and opened. 
  7658.  
  7659.  hard error - An error condition on a network that requires either that the 
  7660.    system be reconfigured or that the source of the error be removed before the 
  7661.    system can resume reliable operation. 
  7662.  
  7663.  header - (1) System-defined control information that precedes user data. (2) 
  7664.    The portion of a message that contains control information for the message, 
  7665.    such as one or more destination fields, name of the originating station, 
  7666.    input sequence number, character string indicating the type of message, and 
  7667.    priority level for the message. 
  7668.  
  7669.  heading tags - A document element that enables information to be displayed in 
  7670.    windows, and that controls entries in the contents window controls placement 
  7671.    of push buttons in a window, and defines the shape and size of windows. 
  7672.  
  7673.  heap - An area of free storage available for dynamic allocation by an 
  7674.    application. Its size varies according to the storage requirements of the 
  7675.    application. 
  7676.  
  7677.  help function - (1) A function that provides information about a specific 
  7678.    field, an application panel, or information about the help facility. (2) (D 
  7679.    of C) One or more display images that describe how to use application 
  7680.    software or how to do a system operation. 
  7681.  
  7682.  Help index - In SAA Common User Access architecture, a help action that 
  7683.    provides an index of the help information available for an application. 
  7684.  
  7685.  help panel - A panel with information to assist users that is displayed in 
  7686.    response to a help request from the user. 
  7687.  
  7688.  help window - A Common-User-Access-defined secondary window that displays 
  7689.    information when the user requests help. 
  7690.  
  7691.  hidden file - An operating system file that is not displayed by a directory 
  7692.    listing. 
  7693.  
  7694.  hide button - In the OS/2 operating system, a small, square button located in 
  7695.    the right-hand corner of the title bar of a window that, when selected, 
  7696.    removes from the screen all the windows associated with that window. 
  7697.    Contrast with maximize button. See also restore button. 
  7698.  
  7699.  hierarchical inheritance - The relationship between parent and child classes. 
  7700.    An object that is lower in the inheritance hierarchy than another object, 
  7701.    inherits all the characteristics and behaviors of the objects above it in 
  7702.    the hierarchy. 
  7703.  
  7704.  hierarchy - A tree of segments beginning with the root segment and proceeding 
  7705.    downward to dependent segment types. 
  7706.  
  7707.  high-performance file system (HPFS) - In the OS/2 operating system, an 
  7708.    installable file system that uses high-speed buffer storage, known as a 
  7709.    cache, to provide fast access to large disk volumes. The file system also 
  7710.    supports the coexistence of multiple, active file systems on a single 
  7711.    personal computer, with the capability of multiple and different storage 
  7712.    devices. File names used with the HPFS can have as many as 254 characters. 
  7713.  
  7714.  hit testing - The means of identifying which window is associated with which 
  7715.    input device event. 
  7716.  
  7717.  hook - A point in a system-defined function where an application can supply 
  7718.    additional code that the system processes as though it were part of the 
  7719.    function. 
  7720.  
  7721.  hook chain - A sequence of hook procedures that are "chained" together so that 
  7722.    each event is passed, in turn, to each procedure in the chain. 
  7723.  
  7724.  hot spot - The part of the pointer that must touch an object before it can be 
  7725.    selected. This is usually the tip of the pointer. Contrast with action 
  7726.    point. 
  7727.  
  7728.  HPFS - high-performance file system. 
  7729.  
  7730.  hypergraphic link - A connection between one piece of information and another 
  7731.    through the use of graphics. 
  7732.  
  7733.  hypertext - A way of presenting information online with connections between 
  7734.    one piece of information and another, called hypertext links. See also 
  7735.    hypertext link. 
  7736.  
  7737.  hypertext link - A connection between one piece of information and another. 
  7738.  
  7739.  
  7740. ΓòÉΓòÉΓòÉ <hidden> Glossary - I ΓòÉΓòÉΓòÉ
  7741.  
  7742.  I/O operation - An input operation to, or output operation from a device 
  7743.    attached to a computer. 
  7744.  
  7745.  I-beam pointer - A pointer that indicates an area, such as an entry field in 
  7746.    which text can be edited. 
  7747.  
  7748.  icon - In SAA Advanced Common User Access architecture, a graphical 
  7749.    representation of an object, consisting of an image, image background, and a 
  7750.    label. Icons can represent items (such as a document file) that the user 
  7751.    wants to work on, and actions that the user wants to perform. In the 
  7752.    Presentation Manager, icons are used for data objects, system actions, and 
  7753.    minimized programs. 
  7754.  
  7755.  icon area - In the Presentation Manager, the area at the bottom of the screen 
  7756.    that is normally used to display the icons for minimized programs. 
  7757.  
  7758.  Icon Editor - The Presentation Manager-provided tool for creating icons. 
  7759.  
  7760.  IDL - Interface Definition Language. 
  7761.  
  7762.  image font - A set of symbols, each of which is described in a rectangular 
  7763.    array of pels. Some of the pels in the array are set to produce the image of 
  7764.    one of the symbols. Contrast with outline font. 
  7765.  
  7766.  implied metaclass - Subclassing the metaclass of a parent class without a 
  7767.    separate CSC for the resultant metaclass. 
  7768.  
  7769.  indirect manipulation - Interaction with an object through choices and 
  7770.    controls. 
  7771.  
  7772.  information device context - A logical description of a data destination other 
  7773.    than the screen (for example, a printer or plotter), but where no output 
  7774.    will occur. Its purpose is to satisfy queries. See also device context. 
  7775.  
  7776.  information panel - A defined panel type characterized by a body containing 
  7777.    only protected information. 
  7778.  
  7779.  Information Presentation Facility (IPF) - A facility provided by the OS/2 
  7780.    operating system, by which application developers can produce online 
  7781.    documentation and context-sensitive online help panels for their 
  7782.    applications. 
  7783.  
  7784.  inheritance - The derivation of new (child) classes from existing (parent) 
  7785.    classes. The new class inherits all the data and methods of the parent class 
  7786.    without having to redefine them. 
  7787.  
  7788.  input focus - (1) The area of a window where user interaction is possible 
  7789.    using an input device, such as a mouse or the keyboard. (2) The position in 
  7790.    the active window where a user's normal interaction with the keyboard will 
  7791.    appear. 
  7792.  
  7793.  input router - An internal OS/2 process that removes messages from the system 
  7794.    queue. 
  7795.  
  7796.  input/output control - A device-specific command that requests a function of a 
  7797.    device driver. 
  7798.  
  7799.  installable file system (IFS) - A file system in which software is installed 
  7800.    when the operating system is started. 
  7801.  
  7802.  instance - A single occurrence of an object class that has a particular 
  7803.    behavior. 
  7804.  
  7805.  instruction pointer - In system/38, a pointer that provides addressability for 
  7806.    a machine interface instruction in a program. 
  7807.  
  7808.  integer atom - An atom that represents a predefined system constant and 
  7809.    carries no storage overhead. For example, names of window classes provided 
  7810.    by Presentation Manager are expressed as integer atoms. 
  7811.  
  7812.  interactive graphics - Graphics that can be moved or manipulated by a user at 
  7813.    a terminal. 
  7814.  
  7815.  interactive program - (1) A program that is running (active) and is ready to 
  7816.    receive (or is receiving) input from a user. (2) A running program that can 
  7817.    receive input from the keyboard or another input device. Compare with active 
  7818.    program and contrast with noninteractive program. 
  7819.  
  7820.    Also known as a foreground program. 
  7821.  
  7822.  interchange file - A file containing data that can be sent from one 
  7823.    Presentation Manager interface application to another. 
  7824.  
  7825.  Interface Definition Language (IDL) - Language-neutral interface specification 
  7826.    for a SOM class. 
  7827.  
  7828.  interpreter - A program that translates and executes each instruction of a 
  7829.    high-level programming language before it translates and executes. 
  7830.  
  7831.  interprocess communication (IPC) - In the OS/2 operating system, the exchange 
  7832.    of information between processes or threads through semaphores, pipes, 
  7833.    queues, and shared memory. 
  7834.  
  7835.  interval timer - (1) A timer that provides program interruptions on a 
  7836.    program-controlled basis. (2) An electronic counter that counts intervals of 
  7837.    time under program control. 
  7838.  
  7839.  IOCtl - Input/output control. 
  7840.  
  7841.  IOPL - Input/output privilege level. 
  7842.  
  7843.  IOPL code segment - An IOPL executable section of programming code that 
  7844.    enables an application to directly manipulate hardware interrupts and ports 
  7845.    without replacing the device driver. See also privilege level. 
  7846.  
  7847.  IPC - Interprocess communication. 
  7848.  
  7849.  IPF - Information Presentation Facility. 
  7850.  
  7851.  IPF compiler - A text compiler that interpret tags in a source file and 
  7852.    converts the information into the specified format. 
  7853.  
  7854.  IPF tag language - A markup language that provides the instructions for 
  7855.    displaying online information. 
  7856.  
  7857.  item - A data object that can be passed in a DDE transaction. 
  7858.  
  7859.  
  7860. ΓòÉΓòÉΓòÉ <hidden> Glossary - J ΓòÉΓòÉΓòÉ
  7861.  
  7862.  journal - A special-purpose file that is used to record changes made in the 
  7863.    system. 
  7864.  
  7865.  
  7866. ΓòÉΓòÉΓòÉ <hidden> Glossary - K ΓòÉΓòÉΓòÉ
  7867.  
  7868.  Kanji - A graphic character set used in Japanese ideographic alphabets. 
  7869.  
  7870.  KBD$ - Character-device name reserved for the keyboard. 
  7871.  
  7872.  kernel - The part of an operating system that performs basic functions, such 
  7873.    as allocating hardware resources. 
  7874.  
  7875.  kerning - The design of graphics characters so that their character boxes 
  7876.    overlap. Used to space text proportionally. 
  7877.  
  7878.  keyboard accelerator - A keystroke that generates a command message for an 
  7879.    application. 
  7880.  
  7881.  keyboard augmentation - A function that enables a user to press a keyboard key 
  7882.    while pressing a mouse button. 
  7883.  
  7884.  keyboard focus - A temporary attribute of a window. The window that has a 
  7885.    keyboard focus receives all keyboard input until the focus changes to a 
  7886.    different window. 
  7887.  
  7888.  Keys help - In SAA Common User Access architecture, a help action that 
  7889.    provides a listing of the application keys and their assigned functions. 
  7890.  
  7891.  
  7892. ΓòÉΓòÉΓòÉ <hidden> Glossary - L ΓòÉΓòÉΓòÉ
  7893.  
  7894.  label - In a graphics segment, an identifier of one or more elements that is 
  7895.    used when editing the segment. 
  7896.  
  7897.  LAN - local area network. 
  7898.  
  7899.  language support procedure - A function provided by the Presentation Manager 
  7900.    Interface for applications that do not, or cannot (as in the case of COBOL 
  7901.    and FORTRAN programs), provide their own dialog or window procedures. 
  7902.  
  7903.  lazy drag - See pickup and drop. 
  7904.  
  7905.  lazy drag set - See pickup set. 
  7906.  
  7907.  LDT - In the OS/2 operating system, Local Descriptor Table. 
  7908.  
  7909.  LIFO stack - A stack from which data is retrieved in last-in, first-out order. 
  7910.  
  7911.  linear address - A unique value that identifies the memory object. 
  7912.  
  7913.  linked list - Synonym for chained list. 
  7914.  
  7915.  list box - In SAA Advanced Common User Access architecture, a control that 
  7916.    contains scrollable choices from which a user can select one choice. 
  7917.  
  7918.    Note:  In CUA architecture, this is a programmer term. The end user term is 
  7919.    selection list. 
  7920.  
  7921.  list button - A button labeled with an underlined down-arrow that presents a 
  7922.    list of valid objects or choices that can be selected for that field. 
  7923.  
  7924.  list panel - A defined panel type that displays a list of items from which 
  7925.    users can select one or more choices and then specify one or more actions to 
  7926.    work on those choices. 
  7927.  
  7928.  load time - The point in time at which a program module is loaded into main 
  7929.    storage for execution. 
  7930.  
  7931.  load-on-call - A function of a linkage editor that allows selected segments of 
  7932.    the module to be disk resident while other segments are executing. Disk 
  7933.    resident segments are loaded for execution and given control when any entry 
  7934.    point that they contain is called. 
  7935.  
  7936.  local area network (LAN) - (1) A computer network located on a user's premises 
  7937.    within a limited geographical area. Communication within a local area 
  7938.    network is not subject to external regulations;  however, communication 
  7939.    across the LAN boundary may be subject to some form of regulation. (T)
  7940.  
  7941.    Note:  A LAN does not use store and forward techniques. (2) A network 
  7942.    inwhich a set of devices are connected to one another for communication and 
  7943.    that can be connected to a larger network. 
  7944.  
  7945.  Local Descriptor Table (LDT) - Defines code and data segments specific to a 
  7946.    single task. 
  7947.  
  7948.  lock - A serialization mechanism by means of which a resource is restricted 
  7949.    for use by the holder of the lock. 
  7950.  
  7951.  logical storage device - A device that the user can map to a physical (actual) 
  7952.    device. 
  7953.  
  7954.  LPT1, LPT2, LPT3 - Character-device names reserved for parallel printers 1 
  7955.    through 3. 
  7956.  
  7957.  
  7958. ΓòÉΓòÉΓòÉ <hidden> Glossary - M ΓòÉΓòÉΓòÉ
  7959.  
  7960.  main window - The window that is positioned relative to the desktop window. 
  7961.  
  7962.  manipulation button - The button on a pointing device a user presses to 
  7963.    directly manipulate an object. 
  7964.  
  7965.  map - (1) A set of values having a defined correspondence with the quantities 
  7966.    or values of another set. (I)  (A)  (2) To establish a set of values having 
  7967.    a defined correspondence with the quantities or values of another set. (I)
  7968.  
  7969.  marker box - In computer graphics, the boundary that defines, in world 
  7970.    coordinates, the horizontal and vertical space occupied by a single marker 
  7971.    from a marker set. 
  7972.  
  7973.  marker symbol - A symbol centered on a point. Graphs and charts can use marker 
  7974.    symbols to indicate the plotted points. 
  7975.  
  7976.  marquee box - The rectangle that appears during a selection technique in which 
  7977.    a user selects objects by drawing a box around them with a pointing device. 
  7978.  
  7979.  Master Help Index - In the OS/2 operating system, an alphabetic list of help 
  7980.    topics related to using the operating system. 
  7981.  
  7982.  maximize - To enlarge a window to its largest possible size. 
  7983.  
  7984.  media window - The part of the physical device (display, printer, or plotter) 
  7985.    on which a picture is presented. 
  7986.  
  7987.  memory block - Part memory within a heap. 
  7988.  
  7989.  memory device context - A logical description of a data destination that is a 
  7990.    memory bit map. See also device context. 
  7991.  
  7992.  memory management - A feature of the operating system for allocating, sharing, 
  7993.    and freeing main storage. 
  7994.  
  7995.  memory object - Logical unit of memory requested by an application, which 
  7996.    forms the granular unit of memory manipulation from the application 
  7997.    viewpoint. 
  7998.  
  7999.  menu - In SAA Advanced Common User Access architecture, an extension of the 
  8000.    menu bar that displays a list of choices available for a selected choice in 
  8001.    the menu bar. After a user selects a choice in menu bar, the corresponding 
  8002.    menu appears. Additional pop-up windows can appear from menu choices. 
  8003.  
  8004.  menu bar - In SAA Advanced Common User Access architecture, the area near the 
  8005.    top of a window, below the title bar and above the rest of the window, that 
  8006.    contains choices that provide access to other menus. 
  8007.  
  8008.  menu button - The button on a pointing device that a user presses to view a 
  8009.    pop-up menu associated with an object. 
  8010.  
  8011.  message - (1) In the Presentation Manager, a packet of data used for 
  8012.    communication between the Presentation Manager interface and Presentation 
  8013.    Manager applications (2) In a user interface, information not requested by 
  8014.    users but presented to users by the computer in response to a user action or 
  8015.    internal process. 
  8016.  
  8017.  message box - (1) A dialog window predefined by the system and used as a 
  8018.    simple interface for applications, without the necessity of creating 
  8019.    dialog-template resources or dialog procedures. (2) (D of C) In SAA Advanced 
  8020.    Common User Access architecture, a type of window that shows messages to 
  8021.    users. See also dialog box, primary window, secondary window. 
  8022.  
  8023.  message filter - The means of selecting which messages from a specific window 
  8024.    will be handled by the application. 
  8025.  
  8026.  message queue - A sequenced collection of messages to be read by the 
  8027.    application. 
  8028.  
  8029.  message stream mode - A method of operation in which data is treated as a 
  8030.    stream of messages.  Contrast with  byte stream. 
  8031.  
  8032.  metacharacter - See global file-name character. 
  8033.  
  8034.  metaclass - The conjunction of an object and its class information; that is, 
  8035.    the information pertaining to the class as a whole, rather than to a single 
  8036.    instance of the class. Each class is itself an object, which is an instance 
  8037.    of the metaclass. 
  8038.  
  8039.  metafile - A file containing a series of attributes that set color, shape and 
  8040.    size, usually of a picture or a drawing. Using a program that can interpret 
  8041.    these attributes, a user can view the assembled image. 
  8042.  
  8043.  metafile device context - A logical description of a data destination that is 
  8044.    a metafile, which is used for graphics interchange. See also device context. 
  8045.  
  8046.  metalanguage - A language used to specify another language. For example, data 
  8047.    types can be described using a metalanguage so as to make the descriptions 
  8048.    independent of any one computer language. 
  8049.  
  8050.  method - A function that defines a behavior for a class or object. 
  8051.  
  8052.  method override - The replacement, by a child class, of the implementation of 
  8053.    a method inherited from a parent and an ancestor class. 
  8054.  
  8055.  mickey - A unit of measurement for physical mouse motion whose value depends 
  8056.    on the mouse device driver currently loaded. 
  8057.  
  8058.  micro presentation space - A graphics presentation space in which a restricted 
  8059.    set of the GPI function calls is available. 
  8060.  
  8061.  minimize - To remove from the screen all windows associated with an 
  8062.    application and replace them with an icon that represents the application. 
  8063.  
  8064.  mix - An attribute that determines how the foreground of a graphic primitive 
  8065.    is combined with the existing color of graphics output. Also known as 
  8066.    foreground mix. Contrast with background mix. 
  8067.  
  8068.  mixed character string - A string containing a mixture of one-byte and Kanji 
  8069.    or Hangeul (two-byte) characters. 
  8070.  
  8071.  mnemonic - (1) A method of selecting an item on a pull-down by means of typing 
  8072.    the highlighted letter in the menu item. (2) (D of C) In SAA Advanced Common 
  8073.    User Access architecture, usually a single character, within the text of a 
  8074.    choice, identified by an underscore beneath the character. If all characters 
  8075.    in a choice already serve as mnemonics for other choices, another character, 
  8076.    placed in parentheses immediately following the choice, can be used. When a 
  8077.    user types the mnemonic for a choice, the choice is either selected or the 
  8078.    cursor is moved to that choice. 
  8079.  
  8080.  modal dialog box - In SAA Advanced Common User Access architecture, a type of 
  8081.    movable window, fixed in size, that requires a user to enter information 
  8082.    before continuing to work in the application window from which it was 
  8083.    displayed. Contrast with modeless dialog box. Also known as a serial dialog 
  8084.    box. Contrast with parallel dialog box. 
  8085.  
  8086.    Note:  In CUA architecture, this is a programmer term. The end user term is 
  8087.    pop-up window. 
  8088.  
  8089.  model space - See graphics model space. 
  8090.  
  8091.  modeless dialog box - In SAA Advanced Common User Access architecture, a type 
  8092.    of movable window, fixed in size, that allows users to continue their dialog 
  8093.    with the application without entering information in the dialog box. Also 
  8094.    known as a parallel dialog box. Contrast with modal dialog box. 
  8095.  
  8096.    Note:  In CUA architecture, this is a programmer term. The end user term is 
  8097.    pop-up window. 
  8098.  
  8099.  module definition file - A file that describes the code segments within a load 
  8100.    module. For example, it indicates whether a code segment is loadable before 
  8101.    module execution begins (preload), or loadable only when referred to at run 
  8102.    time (load-on-call). 
  8103.  
  8104.  mouse - In SAA usage, a device that a user moves on a flat surface to position 
  8105.    a pointer on the screen. It allows a user to select a choice o function to 
  8106.    be performed or to perform operations on the screen, such as dragging or 
  8107.    drawing lines from one position to another. 
  8108.  
  8109.  MOUSE$ - Character-device name reserved for a mouse. 
  8110.  
  8111.  multiple-choice selection - In SAA Basic Common User Access architecture, a 
  8112.    type of field from which a user can select one or more choices or select 
  8113.    none. See also check box. Contrast with extended-choice selection. 
  8114.  
  8115.  multiple-line entry field - In SAA Advanced Common User Access architecture, a 
  8116.    control into which a user types more than one line of information. See also 
  8117.    single-line entry field. 
  8118.  
  8119.  multitasking - The concurrent processing of applications or parts of 
  8120.    applications. A running application and its data are protected from other 
  8121.    concurrently running applications. 
  8122.  
  8123.  mutex semaphore - (Mutual exclusion semaphore). A semaphore that enables 
  8124.    threads to serialize their access to resources. Only the thread that 
  8125.    currently owns the mutex semaphore can gain access to the resource, thus 
  8126.    preventing one thread from interrupting operations being performed by 
  8127.    another. 
  8128.  
  8129.  muxwait semaphore - (Multiple wait semaphore). A semaphore that enables a 
  8130.    thread to wait either for multiple event semaphores to be posted or for 
  8131.    multiple mutex semaphores to be released. Alternatively, a muxwait semaphore 
  8132.    can be set to enable a thread to wait for any ONE of the event or mutex 
  8133.    semaphores in the muxwait semaphore's list to be posted or released. 
  8134.  
  8135.  
  8136. ΓòÉΓòÉΓòÉ <hidden> Glossary - N ΓòÉΓòÉΓòÉ
  8137.  
  8138.  named pipe - A named buffer that provides client-to-server, server-to-client, 
  8139.    or full duplex communication between unrelated processes. Contrast with 
  8140.    unnamed pipe. 
  8141.  
  8142.  national language support (NLS) - The modification or conversion of a United 
  8143.    States English product to conform to the requirements of another language or 
  8144.    country. This can include the enabling or retrofitting of a product and the 
  8145.    translation of nomenclature, MRI, or documentation of a product. 
  8146.  
  8147.  nested list - A list that is contained within another list. 
  8148.  
  8149.  NLS - national language support. 
  8150.  
  8151.  non-8.3 file-name format - A file-naming convention in which file names can 
  8152.    consist of up to 255 characters. See also 8.3 file-name format. 
  8153.  
  8154.  noncritical extended attribute - An extended attribute that is not necessary 
  8155.    for the function of an application. 
  8156.  
  8157.  nondestructive read - Reading that does not erase the data in the source 
  8158.    location. (T)
  8159.  
  8160.  noninteractive program - A running program that cannot receive input from the 
  8161.    keyboard or other input device. Compare with active program, and contrast 
  8162.    with interactive program. 
  8163.  
  8164.  nonretained graphics - Graphic primitives that are not remembered by the 
  8165.    Presentation Manager interface when they have been drawn. Contrast with 
  8166.    retained graphics. 
  8167.  
  8168.  null character (NUL) - (1) Character-device name reserved for a nonexistent 
  8169.    (dummy) device. (2) (D of C) A control character that is used to accomplish 
  8170.    media-fill or time-fill and that may be inserted into or removed from a 
  8171.    sequence of characters without affecting the meaning of the sequence; 
  8172.    however, the control of equipment or the format may be affected by this 
  8173.    character. (I)  (A)
  8174.  
  8175.  null-terminated string - A string of (n+1) characters where the (n+1)th 
  8176.    character is the `null' character (0x00) Also known as `zero-terminated' 
  8177.    string and 'ASCIIZ' string. 
  8178.  
  8179.  
  8180. ΓòÉΓòÉΓòÉ <hidden> Glossary - O ΓòÉΓòÉΓòÉ
  8181.  
  8182.  object - A set of data and actions that can be performed on that data. 
  8183.  
  8184.  Object Interface Definition Language (OIDL) - Specification language used in 
  8185.    SOM Version 1 for defining classes. Replaced by Interface Definition 
  8186.    Language (IDL). 
  8187.  
  8188.  object window - A window that does not have a parent but which might have 
  8189.    child windows. An object window cannot be presented on a device. 
  8190.  
  8191.  OIDL - Object Interface Definition Language. 
  8192.  
  8193.  open - To start working with a file, directory, or other object. 
  8194.  
  8195.  ordered list - Vertical arrangements of items, with each item in the list 
  8196.    preceded by a number or letter. 
  8197.  
  8198.  outline font - A set of symbols, each of which is created as a series of lines 
  8199.    and curves.  Synonymous with vector font. Contrast with image font. 
  8200.  
  8201.  output area - An area of storage reserved for output. (A)
  8202.  
  8203.  owner window - A window into which specific events that occur in another 
  8204.    (owned) window are reported. 
  8205.  
  8206.  ownership - The determination of how windows communicate using messages. 
  8207.  
  8208.  owning process - The process that owns the resources that might be shared with 
  8209.    other processes. 
  8210.  
  8211.  
  8212. ΓòÉΓòÉΓòÉ <hidden> Glossary - P ΓòÉΓòÉΓòÉ
  8213.  
  8214.  page - (1) A 4KB segment of contiguous physical memory. (2) (D of C) A defined 
  8215.    unit of space on a storage medium. 
  8216.  
  8217.  page viewport - A boundary in device coordinates that defines the area of the 
  8218.    output device in which graphics are to be displayed. The presentation-page 
  8219.    contents are transformed automatically to the page viewport in device space. 
  8220.  
  8221.  paint - (1) The action of drawing or redrawing the contents of a window. (2) 
  8222.    In computer graphics, to shade an area of a display image;  for example, 
  8223.    with crosshatching or color. 
  8224.  
  8225.  panel - In SAA Basic Common User Access architecture, a particular arrangement 
  8226.    of information that is presented in a window or pop-up. If some of the 
  8227.    information is not visible, a user can scroll through the information. 
  8228.  
  8229.  panel area - An area within a panel that contains related information. The 
  8230.    three major Common User Access-defined panel areas are the action bar, the 
  8231.    function key area, and the panel body. 
  8232.  
  8233.  panel area separator - In SAA Basic Common User Access architecture, a solid, 
  8234.    dashed, or blank line that provides a visual distinction between two 
  8235.    adjacent areas of a panel. 
  8236.  
  8237.  panel body - The portion of a panel not occupied by the action bar, function 
  8238.    key area, title or scroll bars. The panel body can contain protected 
  8239.    information, selection fields, and entry fields. The layout and content of 
  8240.    the panel body determine the panel type. 
  8241.  
  8242.  panel body area - See client area. 
  8243.  
  8244.  panel definition - A description of the contents and characteristics of a 
  8245.    panel. A panel definition is the application developer's mechanism for 
  8246.    predefining the format to be presented to users in a window. 
  8247.  
  8248.  panel ID - In SAA Basic Common User Access architecture, a panel identifier, 
  8249.    located in the upper-left corner of a panel.  A user can choose whether to 
  8250.    display the panel ID. 
  8251.  
  8252.  panel title - In SAA Basic Common User Access architecture, a particular 
  8253.    arrangement of information that is presented in a window or pop-up. If some 
  8254.    of the information is not visible, a user can scroll through the 
  8255.    information. 
  8256.  
  8257.  paper size - The size of paper, defined in either standard U.S. or European 
  8258.    names (for example, A, B, A4), and measured in inches or millimeters 
  8259.    respectively. 
  8260.  
  8261.  parallel dialog box - See modeless dialog box. 
  8262.  
  8263.  parameter list - A list of values that provides a means of associating 
  8264.    addressability of data defined in a called program with data in the calling 
  8265.    program. It contains parameter names and the order in which they are to be 
  8266.    associated in the calling and called program. 
  8267.  
  8268.  parent process - In the OS/2 operating system, a process that creates other 
  8269.    processes. Contrast with child process. 
  8270.  
  8271.  parent window - In the OS/2 operating system, a window that creates a child 
  8272.    window. The child window is drawn within the parent window. If the parent 
  8273.    window is moved, resized, or destroyed, the child window also will be moved, 
  8274.    resized, or destroyed. However, the child window can be moved and resized 
  8275.    independently from the parent window, within the boundaries of the parent 
  8276.    window. Contrast with child window. 
  8277.  
  8278.  partition - (1) A fixed-size division of storage. (2) On an IBM personal 
  8279.    computer fixed disk, one of four possible storage areas of variable size; 
  8280.    one may be accessed by DOS, and each of the others may be assigned to 
  8281.    another operating system. 
  8282.  
  8283.  Paste - A choice in the Edit pull-down that a user selects to move the 
  8284.    contents of the clipboard into a preselected location. See also Copy and 
  8285.    Cut. 
  8286.  
  8287.  path - The route used to locate files; the storage location of a file. A fully 
  8288.    qualified path lists the drive identifier, directory name, subdirectory name 
  8289.    (if any), and file name with the associated extension. 
  8290.  
  8291.  PDD - Physical device driver. 
  8292.  
  8293.  peeking - An action taken by any thread in the process that owns the queue to 
  8294.    examine queue elements without removing them. 
  8295.  
  8296.  pel - (1) The smallest area of a display screen capable of being addressed and 
  8297.    switched between visible and invisible states. Synonym for display point, 
  8298.    pixel, and picture element. (2) (D of C) Picture element. 
  8299.  
  8300.  persistent object - An object whose instance data and state are preserved 
  8301.    between system shutdown and system startup. 
  8302.  
  8303.  physical device driver (PDD) - A system interface that handles hardware 
  8304.    interrupts and supports a set of input and output functions. 
  8305.  
  8306.  pick - To select part of a displayed object using the pointer. 
  8307.  
  8308.  pickup - To add an object or set of objects to the pickup set. 
  8309.  
  8310.  pickup and drop - A drag operation that does not require the direct 
  8311.    manipulation button to be pressed for the duration of the drag. 
  8312.  
  8313.  pickup set - The set of objects that have been picked up as part of a pickup 
  8314.    and drop operation. 
  8315.  
  8316.  picture chain - See segment chain. 
  8317.  
  8318.  picture element - (1) Synonym for pel. (2) (D of C) In computer graphics, the 
  8319.    smallest element of a display surface that can be independently assigned 
  8320.    color and intensity. (T)  . (3) The area of the finest detail that can be 
  8321.    reproduced effectively on the recording medium. 
  8322.  
  8323.  PID - Process identification. 
  8324.  
  8325.  pipe - (1) A named or unnamed buffer used to pass data between processes. A 
  8326.    process reads from or writes to a pipe as if the pipe were a standard-input 
  8327.    or standard-output file. See also named pipe and unnamed pipe. (2) (D of C) 
  8328.    To direct data so that the output from one process becomes the input to 
  8329.    another process. The standard output of one command can be connected to the 
  8330.    standard input of another with the pipe operator (|). 
  8331.  
  8332.  pixel - (1) Synonym for pel. (2) (D of C) Picture element. 
  8333.  
  8334.  plotter - An output unit that directly produces a hardcopy record of data on a 
  8335.    removable medium, in the form of a two-dimensional graphic representation. (T)
  8336.  
  8337.  PM - Presentation Manager. 
  8338.  
  8339.  pointer - (1) The symbol displayed on the screen that is moved by a pointing 
  8340.    device, such as a mouse. The pointer is used to point at items that users 
  8341.    can select. Contrast with cursor. (2) A data element that indicates the 
  8342.    location of another data element. (T)
  8343.  
  8344.  POINTER$ - Character-device name reserved for a pointer device (mouse screen 
  8345.    support). 
  8346.  
  8347.  pointing device - In SAA Advanced Common User Access architecture, an 
  8348.    instrument, such as a mouse, trackball, or joystick, used to move a pointer 
  8349.    on the screen. 
  8350.  
  8351.  pointings - Pairs of x-y coordinates produced by an operator defining 
  8352.    positions on a screen with a pointing device, such as a mouse. 
  8353.  
  8354.  polyfillet - A curve based on a sequence of lines. The curve is tangential to 
  8355.    the end points of the first and last lines, and tangential also to the 
  8356.    midpoints of all other lines. See also fillet. 
  8357.  
  8358.  polygon - One or more closed figures that can be drawn filled, outlined, or 
  8359.    filled and outlined. 
  8360.  
  8361.  polyline - A sequence of adjoining lines. 
  8362.  
  8363.  polymorphism - The ability to have different implementations of the same 
  8364.    method for two or more classes of objects. 
  8365.  
  8366.  pop - To retrieve an item from a last-in-first-out stack of items. Contrast 
  8367.    with push. 
  8368.  
  8369.  pop-up menu - A menu that lists the actions that a user can perform on an 
  8370.    object. The contents of the pop-up menu can vary depending on the context, 
  8371.    or state, of the object. 
  8372.  
  8373.  pop-up window - (1) A window that appears on top of another window in a 
  8374.    dialog. Each pop-up window must be completed before returning to the 
  8375.    underlying window. (2) (D of C) In SAA Advanced Common User Access 
  8376.    architecture, a movable window, fixed in size, in which a user provides 
  8377.    information required by an application so that it can continue to process a 
  8378.    user request. 
  8379.  
  8380.  presentation drivers - Special purpose I/O routines that handle field 
  8381.    device-independent I/O requests from the PM and its applications. 
  8382.  
  8383.  Presentation Manager (PM) - The interface of the OS/2 operating system that 
  8384.    presents, in windows a graphics-based interface to applications and files 
  8385.    installed and running under the OS/2 operating system. 
  8386.  
  8387.  presentation page - The coordinate space in which a picture is assembled for 
  8388.    display. 
  8389.  
  8390.  presentation space (PS) - (1) Contains the device-independent definition of a 
  8391.    picture. (2) (D of C) The display space on a display device. 
  8392.  
  8393.  primary window - In SAA Common User Access architecture, the window in which 
  8394.    the main interaction between the user and the application takes place. In a 
  8395.    multiprogramming environment, each application starts in its own primary 
  8396.    window. The primary window remains for the duration of the application, 
  8397.    although the panel displayed will change as the user's dialog moves forward. 
  8398.    See also secondary window. 
  8399.  
  8400.  primitive - In computer graphics, one of several simple functions for drawing 
  8401.    on the screen, including, for example, the rectangle, line, ellipse, 
  8402.    polygon, and so on. 
  8403.  
  8404.  primitive attribute - A specifiable characteristic of a graphic primitive. See 
  8405.    graphics attributes. 
  8406.  
  8407.  print job - The result of sending a document or picture to be printed. 
  8408.  
  8409.  Print Manager - In the Presentation Manager, the part of the spooler that 
  8410.    manages the spooling process. It also allows users to view print queues and 
  8411.    to manipulate print jobs. 
  8412.  
  8413.  privilege level - A protection level imposed by the hardware architecture of 
  8414.    the IBM personal computer.  There are four privilege levels (number 0 
  8415.    through 3).  Only certain types of programs are allowed to execute at each 
  8416.    privilege level.  See also IOPL code segment. 
  8417.  
  8418.  procedure call - In programming languages, a language construct for invoking 
  8419.    execution of a procedure. 
  8420.  
  8421.  process - An instance of an executing application and the resources it is 
  8422.    using. 
  8423.  
  8424.  program - A sequence of instructions that a computer can interpret and 
  8425.    execute. 
  8426.  
  8427.  program details - Information about a program that is specified in the Program 
  8428.    Manager window and is used when the program is started. 
  8429.  
  8430.  program group - In the Presentation Manager, several programs that can be 
  8431.    acted upon as a single entity. 
  8432.  
  8433.  program name - The full file specification of a program. Contrast with program 
  8434.    title. 
  8435.  
  8436.  program title - The name of a program as it is listed in the Program Manager 
  8437.    window. Contrast with program name. 
  8438.  
  8439.  prompt - A displayed symbol or message that requests input from the user or 
  8440.    gives operational information; for example, on the display screen of an IBM 
  8441.    personal computer, the DOS A> prompt. The user must respond to the prompt in 
  8442.    order to proceed. 
  8443.  
  8444.  protect mode - A method of program operation that limits or prevents access to 
  8445.    certain instructions or areas of storage. Contrast with real mode. 
  8446.  
  8447.  protocol - A set of semantic and syntactic rules that determines the behavior 
  8448.    of functional units in achieving communication. (I)
  8449.  
  8450.  pseudocode - An artificial language used to describe computer program 
  8451.    algorithms without using the syntax of any particular programming language. (A)
  8452.  
  8453.  pull-down - (1) An action bar extension that displays a list of choices 
  8454.    available for a selected action bar choice. After users select an action bar 
  8455.    choice, the pull-down appears with the list of choices. Additional pop-up 
  8456.    windows may appear from pull-down choices to further extend the actions 
  8457.    available to users. (2) (D of C) In SAA Common User Access architecture, 
  8458.    pertaining to a choice in an action bar pull-down. 
  8459.  
  8460.  push - To add an item to a last-in-first-out stack of items. Contrast with 
  8461.    pop. 
  8462.  
  8463.  push button - In SAA Advanced Common User Access architecture, a rectangle 
  8464.    with text inside. Push buttons are used in windows for actions that occur 
  8465.    immediately when the push button is selected. 
  8466.  
  8467.  putback - To remove an object or set of objects from the lazy drag set. This 
  8468.    has the effect of undoing the pickup operation for those objects 
  8469.  
  8470.  putdown - To drop the objects in the lazy drag set on the target object. 
  8471.  
  8472.  
  8473. ΓòÉΓòÉΓòÉ <hidden> Glossary - Q ΓòÉΓòÉΓòÉ
  8474.  
  8475.  queue - (1) A linked list of elements waiting to be processed in FIFO order. 
  8476.    For example, a queue may be a list of print jobs waiting to be printed. (2) 
  8477.    (D of C) A line or list of items waiting to be processed; for example, work 
  8478.    to be performed or messages to be displayed. 
  8479.  
  8480.  queued device context - A logical description of a data destination (for 
  8481.    example, a printer or plotter) where the output is to go through the 
  8482.    spooler. See also device context. 
  8483.  
  8484.  
  8485. ΓòÉΓòÉΓòÉ <hidden> Glossary - R ΓòÉΓòÉΓòÉ
  8486.  
  8487.  radio button - (1) A control window, shaped like a round button on the screen, 
  8488.    that can be in a checked or unchecked state. It is used to select a single 
  8489.    item from a list. Contrast with check box. (2) In SAA Advanced Common User 
  8490.    Access architecture, a circle with text beside it. Radio buttons are 
  8491.    combined to show a user a fixed set of choices from which only one can be 
  8492.    selected. The circle is partially filled when a choice is selected. 
  8493.  
  8494.  RAS - Reliability, availability, and serviceability. 
  8495.  
  8496.  raster - (1) In computer graphics, a predetermined pattern of lines that 
  8497.    provides uniform coverage of a display space. (T)  (2) The coordinate grid 
  8498.    that divides the display area of a display device.  (A)
  8499.  
  8500.  read-only file - A file that can be read from but not written to. 
  8501.  
  8502.  real mode - A method of program operation that does not limit or prevent 
  8503.    access to any instructions or areas of storage.  The operating system loads 
  8504.    the entire program into storage and gives the program access to all system 
  8505.    resources. Contrast with protect mode. 
  8506.  
  8507.  realize - To cause the system to ensure, wherever possible, that the physical 
  8508.    color table of a device is set to the closest possible match in the logical 
  8509.    color table. 
  8510.  
  8511.  recursive routine - A routine that can call itself, or be called by another 
  8512.    routine that was called by the recursive routine. 
  8513.  
  8514.  reentrant - The attribute of a program or routine that allows the same copy of 
  8515.    the program or routine to be used concurrently by two or more tasks. 
  8516.  
  8517.  reference phrase - (1) A word or phrase that is emphasized in a 
  8518.    device-dependent manner to inform the user that additional information for 
  8519.    the word or phrase is available. (2) (D of C) In hypertext, text that is 
  8520.    highlighted and preceded by a single-character input field used to signify 
  8521.    the existence of a hypertext link. 
  8522.  
  8523.  reference phrase help - In SAA Common User Access architecture, highlighted 
  8524.    words or phrases within help information that a user selects to get 
  8525.    additional information. 
  8526.  
  8527.  refresh - To update a window, with changed information, to its current status. 
  8528.  
  8529.  region - A clipping boundary in device space. 
  8530.  
  8531.  register - A part of internal storage having a specified storage capacity and 
  8532.    usually intended for a specific purpose. (T)
  8533.  
  8534.  remote file system - A file-system driver that gains access to a remote system 
  8535.    without a block device driver. 
  8536.  
  8537.  resource - The means of providing extra information used in the definition of 
  8538.    a window. A resource can contain definitions of fonts, templates, 
  8539.    accelerators, and mnemonics; the definitions are held in a resource file. 
  8540.  
  8541.  resource file - A file containing information used in the definition of a 
  8542.    window. Definitions can be of fonts, templates, accelerators, and mnemonics. 
  8543.  
  8544.  restore - To return a window to its original size or position following a 
  8545.    sizing or moving action. 
  8546.  
  8547.  retained graphics - Graphic primitives that are remembered by the Presentation 
  8548.    Manager interface after they have been drawn. Contrast with nonretained 
  8549.    graphics. 
  8550.  
  8551.  return code - (1) A value returned to a program to indicate the results of an 
  8552.    operation requested by that program. (2) A code used to influence the 
  8553.    execution of succeeding instructions.(A) 
  8554.  
  8555.  reverse video - (1) A form of highlighting a character, field, or cursor by 
  8556.    reversing the color of the character, field, or cursor with its background; 
  8557.    for example, changing a red character on a black background to a black 
  8558.    character on a red background. (2) In SAA Basic Common User Access 
  8559.    architecture, a screen emphasis feature that interchanges the foreground and 
  8560.    background colors of an item. 
  8561.  
  8562.  REXX Language - Restructured Extended Executor. A procedural language that 
  8563.    provides batch language functions along with structured programming 
  8564.    constructs such as loops; conditional testing and subroutines. 
  8565.  
  8566.  RGB - (1) Color coding in which the brightness of the additive primary colors 
  8567.    of light, red, green, and blue, are specified as three distinct values of 
  8568.    white light. (2) Pertaining to a color display that accepts signals 
  8569.    representing red, green, and blue. 
  8570.  
  8571.  roman - Relating to a type style with upright characters. 
  8572.  
  8573.  root segment - In a hierarchical database, the highest segment in the tree 
  8574.    structure. 
  8575.  
  8576.  round-robin scheduling - A process that allows each thread to run for a 
  8577.    specified amount of time. 
  8578.  
  8579.  run time - (1) Any instant at which the execution of a particular computer 
  8580.    program takes place. (T)  (2) The amount of time needed for the execution of 
  8581.    a particular computer program. (T)  (3) The time during which an instruction 
  8582.    in an instruction register is decoded and performed. Synonym for execution 
  8583.    time. 
  8584.  
  8585.  
  8586. ΓòÉΓòÉΓòÉ <hidden> Glossary - S ΓòÉΓòÉΓòÉ
  8587.  
  8588.  SAA - Systems Application Architecture. 
  8589.  
  8590.  SBCS - Single-byte character set. 
  8591.  
  8592.  scheduler - A computer program designed to perform functions such as 
  8593.    scheduling, initiation, and termination of jobs. 
  8594.  
  8595.  screen - In SAA Basic Common User Access architecture, the physical surface of 
  8596.    a display device upon which information is shown to a user. 
  8597.  
  8598.  screen device context - A logical description of a data destination that is a 
  8599.    particular window on the screen. See also device context. 
  8600.  
  8601.  SCREEN$ - Character-device name reserved for the display screen. 
  8602.  
  8603.  scroll bar - In SAA Advanced Common User Access architecture, a part of a 
  8604.    window, associated with a scrollable area, that a user interacts with to see 
  8605.    information that is not currently allows visible. 
  8606.  
  8607.  scrollable entry field - An entry field larger than the visible field. 
  8608.  
  8609.  scrollable selection field - A selection field that contains more choices than 
  8610.    are visible. 
  8611.  
  8612.  scrolling - Moving a display image vertically or horizontally in a manner such 
  8613.    that new data appears at one edge, as existing data disappears at the 
  8614.    opposite edge. 
  8615.  
  8616.  secondary window - A window that contains information that is dependent on 
  8617.    information in a primary window and is used to supplement the interaction in 
  8618.    the primary window. 
  8619.  
  8620.  sector - On disk or diskette storage, an addressable subdivision of a track 
  8621.    used to record one block of a program or data. 
  8622.  
  8623.  segment - See graphics segment. 
  8624.  
  8625.  segment attributes - Attributes that apply to the segment as an entity, as 
  8626.    opposed to the individual primitives within the segment. For example, the 
  8627.    visibility or detectability of a segment. 
  8628.  
  8629.  segment chain - All segments in a graphics presentation space that are defined 
  8630.    with the `chained' attribute. Synonym for picture chain. 
  8631.  
  8632.  segment priority - The order in which segments are drawn. 
  8633.  
  8634.  segment store - An area in a normal graphics presentation space where retained 
  8635.    graphics segments are stored. 
  8636.  
  8637.  select - To mark or choose an item. Note that select means to mark or type in 
  8638.    a choice on the screen; enter means to send all selected choices to the 
  8639.    computer for processing. 
  8640.  
  8641.  select button - The button on a pointing device, such as a mouse, that is 
  8642.    pressed to select a menu choice.  Also known as button 1. 
  8643.  
  8644.  selection cursor - In SAA Advanced Common User Access architecture, a visual 
  8645.    indication that a user has selected a choice. It is represented by outlining 
  8646.    the choice with a dotted box. See also text cursor. 
  8647.  
  8648.  selection field - (1) In SAA Advanced Common User Access architecture, a set 
  8649.    of related choices. See also entry field. (2) In SAA Basic Common User 
  8650.    Access architecture, an area of a panel that cannot be scrolled and contains 
  8651.    a fixed number of choices. 
  8652.  
  8653.  semantics - The relationships between symbols and their meanings. 
  8654.  
  8655.  semaphore - An object used by applications for signalling purposes and for 
  8656.    controlling access to serially reusable resources. 
  8657.  
  8658.  separator - In SAA Advanced Common User Access architecture, a line or color 
  8659.    boundary that provides a visual distinction between two adjacent areas. 
  8660.  
  8661.  serial dialog box - See modal dialog box. 
  8662.  
  8663.  serialization - The consecutive ordering of items. 
  8664.  
  8665.  serialize - To ensure that one or more events occur in a specified sequence. 
  8666.  
  8667.  serially reusable resource (SRR) - A logical resource or object that can be 
  8668.    accessed by only one task at a time. 
  8669.  
  8670.  session - (1) A routing mechanism for user interaction via the console; a 
  8671.    complete environment that determines how an application runs and how users 
  8672.    interact with the application. OS/2 can manage more than one session at a 
  8673.    time, and more than one process can run in a session. Each session has its 
  8674.    own set of environment variables that determine where OS/2 looks for 
  8675.    dynamic-link libraries and other important files. (2) (D of C) In the OS/2 
  8676.    operating system, one instance of a started program or command prompt. Each 
  8677.    session is separate from all other sessions that might be running on the 
  8678.    computer. The operating system is responsible for coordinating the resources 
  8679.    that each session uses, such as computer memory, allocation of processor 
  8680.    time, and windows on the screen. 
  8681.  
  8682.  Settings Notebook - A control window that is used to display the settings for 
  8683.    an object and to enable the user to change them. 
  8684.  
  8685.  shadow - An object that refers to another object. A shadow is not a copy of 
  8686.    another object, but is another representation of the object. 
  8687.  
  8688.  shadow box - The area on the screen that follows mouse movements and shows 
  8689.    what shape the window will take if the mouse button is released. 
  8690.  
  8691.  shared data - Data that is used by two or more programs. 
  8692.  
  8693.  shared memory - In the OS/2 operating system, a segment that can be used by 
  8694.    more than one program. 
  8695.  
  8696.  shear - In computer graphics, the forward or backward slant of a graphics 
  8697.    symbol or string of such symbols relative to a line perpendicular to the 
  8698.    baseline of the symbol. 
  8699.  
  8700.  shell - (1) A software interface between a user and the operating system of a 
  8701.    computer. Shell programs interpret commands and user interactions on devices 
  8702.    such as keyboards, pointing devices, and touch-sensitive screens, and 
  8703.    communicate them to the operating system. (2) Software that allows a kernel 
  8704.    program to run under different operating-system environments. 
  8705.  
  8706.  shutdown - The process of ending operation of a system or a subsystem, 
  8707.    following a defined procedure. 
  8708.  
  8709.  sibling processes - Child processes that have the same parent process. 
  8710.  
  8711.  sibling windows - Child windows that have the same parent window. 
  8712.  
  8713.  simple list - A list of like values; for example, a list of user names. 
  8714.    Contrast with mixed list. 
  8715.  
  8716.  single-byte character set (SBCS) - A character set in which each character is 
  8717.    represented by a one-byte code.  Contrast with double-byte character set. 
  8718.  
  8719.  slider box - In SAA Advanced Common User Access architecture: a part of the 
  8720.    scroll bar that shows the position and size of the visible information in a 
  8721.    window relative to the total amount of information available. Also known as 
  8722.    thumb mark. 
  8723.  
  8724.  SOM - System Object Model. 
  8725.  
  8726.  source file - A file that contains source statements for items such as 
  8727.    high-level language programs and data description specifications. 
  8728.  
  8729.  source statement - A statement written in a programming language. 
  8730.  
  8731.  specific dynamic-link module - A dynamic-link module created for the exclusive 
  8732.    use of an application. 
  8733.  
  8734.  spin button - In SAA Advanced Common User Access architecture, a type of entry 
  8735.    field that shows a scrollable ring of choices from which a user can select a 
  8736.    choice. After the last choice is displayed, the first choice is displayed 
  8737.    again.  A user can also type a choice from the scrollable ring into the 
  8738.    entry field without interacting with the spin button. 
  8739.  
  8740.  spline - A sequence of one or more B╨Æzier curves. 
  8741.  
  8742.  spooler - A program that intercepts the data going to printer devices and 
  8743.    writes it to disk. The data is printed or plotted when it is complete and 
  8744.    the required device is available.  The spooler prevents output from 
  8745.    different sources from being intermixed. 
  8746.  
  8747.  stack - A list constructed and maintained so that the next data element to be 
  8748.    retrieved is the most recently stored. This method is characterized as 
  8749.    last-in-first-out (LIFO). 
  8750.  
  8751.  standard window - A collection of window elements that form a panel. The 
  8752.    standard window can include one or more of the following window elements: 
  8753.    sizing borders, system menu icon, title bar, maximize/minimize/restore 
  8754.    icons, action bar and pull-downs, scroll bars, and client area. 
  8755.  
  8756.  static control - The means by which the application presents descriptive 
  8757.    information (for example, headings and descriptors) to the user. The user 
  8758.    cannot change this information. 
  8759.  
  8760.  static storage - (1) A read/write storage unit in which data is retained in 
  8761.    the absence of control signals. (A)  Static storage may use dynamic 
  8762.    addressing or sensing circuits. (2) Storage other than dynamic storage. (A)
  8763.  
  8764.  style - See window style. 
  8765.  
  8766.  subclass - A class that is a child of another class. See also Inheritance. 
  8767.  
  8768.  subdirectory - In an IBM personal computer, a file referred to in a root 
  8769.    directory that contains the names of other files stored on the diskette or 
  8770.    fixed disk. 
  8771.  
  8772.  swapping - (1) A process that interchanges the contents of an area of real 
  8773.    storage with the contents of an area in auxiliary storage. (I)  (A)  (2) In 
  8774.    a system with virtual storage, a paging technique that writes the active 
  8775.    pages of a job to auxiliary storage and reads pages of another job from 
  8776.    auxiliary storage into real storage. (3) The process of temporarily removing 
  8777.    an active job from main storage, saving it on disk, and processing another 
  8778.    job in the area of main storage formerly occupied by the first job. 
  8779.  
  8780.  switch - (1) In SAA usage, to move the cursor from one point of interest to 
  8781.    another;  for example, to move from one screen or window to another or from 
  8782.    a place within a displayed image to another place on the same displayed 
  8783.    image. (2) In a computer program, a conditional instruction and an indicator 
  8784.    to be interrogated by that instruction. (3) A device or programming 
  8785.    technique for making a selection, for example, a toggle, a conditional jump. 
  8786.  
  8787.  switch list - See Task List. 
  8788.  
  8789.  symbolic identifier - A text string that equates to an integer value in an 
  8790.    include file, which is used to identify a programming object. 
  8791.  
  8792.  symbols - In Information Presentation Facility, a document element used to 
  8793.    produce characters that cannot be entered from the keyboard. 
  8794.  
  8795.  synchronous - Pertaining to two or more processes that depend upon the 
  8796.    occurrence of specific events such as common timing signals. (T)  See also 
  8797.    asynchronous. 
  8798.  
  8799.  System Menu - In the Presentation Manager, the pull-down in the top left 
  8800.    corner of a window that allows it to be moved and sized with the keyboard. 
  8801.  
  8802.  System Object Model (SOM) - A mechanism for language-neutral, object-oriented 
  8803.    programming in the OS/2 environment. 
  8804.  
  8805.  system queue - The master queue for all pointer device or keyboard events. 
  8806.  
  8807.  system-defined messages - Messages that control the operations of applications 
  8808.    and provides input an other information for applications to process. 
  8809.  
  8810.  Systems Application Architecture (SAA) - A set of IBM software interfaces, 
  8811.    conventions, and protocols that provide a framework for designing and 
  8812.    developing applications that are consistent across systems. 
  8813.  
  8814.  
  8815. ΓòÉΓòÉΓòÉ <hidden> Glossary - T ΓòÉΓòÉΓòÉ
  8816.  
  8817.  table tags - In Information Presentation Facility, a document element that 
  8818.    formats text in an arrangement of rows and columns. 
  8819.  
  8820.  tag - (1) One or more characters attached to a set of data that contain 
  8821.    information about the set, including its identification. (I)  (A)  (2) In 
  8822.    Generalized Markup Language markup, a name for a type of document or 
  8823.    document element that is entered in the source document to identify it. 
  8824.  
  8825.  target object - An object to which the user is transferring information. 
  8826.  
  8827.  Task List - In the Presentation Manager, the list of programs that are active. 
  8828.    The list can be used to switch to a program and to stop programs. 
  8829.  
  8830.  terminate-and-stay-resident (TSR) - Pertaining to an application that modifies 
  8831.    an operating system interrupt vector to point to its own location (known as 
  8832.    hooking an interrupt). 
  8833.  
  8834.  text - Characters or symbols. 
  8835.  
  8836.  text cursor - A symbol displayed in an entry field that indicates where typed 
  8837.    input will appear. 
  8838.  
  8839.  text window - Also known as the VIO window. 
  8840.  
  8841.  text-windowed application - The environment in which the operating system 
  8842.    performs advanced-video input and output operations. 
  8843.  
  8844.  thread - A unit of execution within a process. It uses the resources of the 
  8845.    process. 
  8846.  
  8847.  thumb mark - The portion of the scroll bar that describes the range and 
  8848.    properties of the data that is currently visible in a window. Also known as 
  8849.    a slider box. 
  8850.  
  8851.  thunk - Term used to describe the process of address conversion, stack and 
  8852.    structure realignment, etc., necessary when passing control between 16-bit 
  8853.    and 32-bit modules. 
  8854.  
  8855.  tilde - A mark used to denote the character that is to be used as a mnemonic 
  8856.    when selecting text items within a menu. 
  8857.  
  8858.  time slice - (1) An interval of time on the processing unit allocated for use 
  8859.    in performing a task. After the interval has expired, processing-unit time 
  8860.    is allocated to another task, so a task cannot monopolize processing-unit 
  8861.    time beyond a fixed limit. (2) In systems with time sharing, a segment of 
  8862.    time allocated to a terminal job. 
  8863.  
  8864.  time-critical process - A process that must be performed within a specified 
  8865.    time after an event has occurred. 
  8866.  
  8867.  timer - A facility provided under the Presentation Manager, whereby 
  8868.    Presentation Manager will dispatch a message of class WM_TIMER to a 
  8869.    particular window at specified intervals. This capability may be used by an 
  8870.    application to perform a specific processing task at predetermined 
  8871.    intervals, without the necessity for the application to explicitly keep 
  8872.    track of the passage of time. 
  8873.  
  8874.  timer tick - See clock tick. 
  8875.  
  8876.  title bar - In SAA Advanced Common User Access architecture, the area at the 
  8877.    top of each window that contains the window title and system menu icon. When 
  8878.    appropriate, it also contains the minimize, maximize, and restore icons. 
  8879.    Contrast with panel title. 
  8880.  
  8881.  TLB - Translation lookaside buffer. 
  8882.  
  8883.  transaction - An exchange between a workstation and another device that 
  8884.    accomplishes a particular action or result. 
  8885.  
  8886.  transform - (1) The action of modifying a picture by scaling, shearing, 
  8887.    reflecting, rotating, or translating. (2) The object that performs or 
  8888.    defines such a modification; also referred to as a transformation. 
  8889.  
  8890.  Translation lookaside buffer (TLB) - A hardware-based address caching 
  8891.    mechanism for paging information. 
  8892.  
  8893.  Tree - In the Presentation Manager, the window in the File Manager that shows 
  8894.    the organization of drives and directories. 
  8895.  
  8896.  truncate - (1) To terminate a computational process in accordance with some 
  8897.    rule (A)  (2) To remove the beginning or ending elements of a string. (3) To 
  8898.    drop data that cannot be printed or displayed in the line width specified or 
  8899.    available. (4) To shorten a field or statement to a specified length. 
  8900.  
  8901.  TSR - Terminate-and-stay-resident. 
  8902.  
  8903.  unnamed pipe - A circular buffer, created in memory, used by related processes 
  8904.    to communicate with one another. Contrast with named pipe. 
  8905.  
  8906.  unordered list - In Information Presentation Facility, a vertical arrangement 
  8907.    of items in a list, with each item in the list preceded by a special 
  8908.    character or bullet. 
  8909.  
  8910.  update region - A system-provided area of dynamic storage containing one or 
  8911.    more (not necessarily contiguous) rectangular areas of a window that are 
  8912.    visually invalid or incorrect, and therefore are in need of repainting. 
  8913.  
  8914.  user interface - Hardware, software, or both that allows a user to interact 
  8915.    with and perform operations on a system, program, or device. 
  8916.  
  8917.  User Shell - A component of OS/2 that uses a graphics-based, windowed 
  8918.    interface to allow the user to manage applications and files installed and 
  8919.    running under OS/2. 
  8920.  
  8921.  utility program - (1) A computer program in general support of computer 
  8922.    processes; for example, a diagnostic program, a trace program, a sort 
  8923.    program. (T)  (2) A program designed to perform an everyday task such as 
  8924.    copying data from one storage device to another. (A)
  8925.  
  8926.  
  8927. ΓòÉΓòÉΓòÉ <hidden> Glossary - U ΓòÉΓòÉΓòÉ
  8928.  
  8929. There are no glossary terms for this starting letter. 
  8930.  
  8931.  
  8932. ΓòÉΓòÉΓòÉ <hidden> Glossary - V ΓòÉΓòÉΓòÉ
  8933.  
  8934.  value set control - A visual component that enables a user to select one 
  8935.    choice from a group of mutually exclusive choices. 
  8936.  
  8937.  vector font - A set of symbols, each of which is created as a series of lines 
  8938.    and curves. Synonymous with outline font. Contrast with image font. 
  8939.  
  8940.  VGA - Video graphics array. 
  8941.  
  8942.  view - A way of looking at an object's information. 
  8943.  
  8944.  viewing pipeline - The series of transformations applied to a graphic object 
  8945.    to map the object to the device on which it is to be presented. 
  8946.  
  8947.  viewing window - A clipping boundary that defines the visible part of model 
  8948.    space. 
  8949.  
  8950.  VIO - Video Input/Output. 
  8951.  
  8952.  virtual memory (VM) - Synonymous with virtual storage. 
  8953.  
  8954.  virtual storage - (1) The storage space that may be regarded as addressable 
  8955.    main storage by the user of a computer system in which virtual addresses are 
  8956.    mapped into real addresses. The size of virtual storage is limited by the 
  8957.    addressing scheme of the computer system and by the amount of auxiliary 
  8958.    storage available, not by the actual number of main storage 
  8959.    locations. (I)  (A)  (2) Addressable space that is apparent to the user as 
  8960.    the processor storage space, from which the instructions and the data are 
  8961.    mapped into the processor storage locations. (3) Synonymous with virtual 
  8962.    memory. 
  8963.  
  8964.  visible region - A window's presentation space, clipped to the boundary of the 
  8965.    window and the boundaries of any overlying window. 
  8966.  
  8967.  volume - (1) A file-system driver that uses a block device driver for input 
  8968.    and output operations to a local or remote device. (I)  (2) A portion of 
  8969.    data, together with its data carrier, that can be handled conveniently as a 
  8970.    unit. 
  8971.  
  8972.  
  8973. ΓòÉΓòÉΓòÉ <hidden> Glossary - W ΓòÉΓòÉΓòÉ
  8974.  
  8975.  wildcard character - Synonymous with global file-name character. 
  8976.  
  8977.  window - (1) A portion of a display surface in which display images pertaining 
  8978.    to a particular application can be presented. Different applications can be 
  8979.    displayed simultaneously in different windows. (A)  (2) An area of the 
  8980.    screen with visible boundaries within which information is displayed. A 
  8981.    window can be smaller than or the same size as the screen. Windows can 
  8982.    appear to overlap on the screen. 
  8983.  
  8984.  window class - The grouping of windows whose processing needs conform to the 
  8985.    services provided by one window procedure. 
  8986.  
  8987.  window coordinates - A set of coordinates by which a window position or size 
  8988.    is defined; measured in device units, or pels. 
  8989.  
  8990.  window handle - Unique identifier of a window, generated by Presentation 
  8991.    Manager when the window is created, and used by applications to direct 
  8992.    messages to the window. 
  8993.  
  8994.  window procedure - Code that is activated in response to a message. The 
  8995.    procedure controls the appearance and behavior of its associated windows. 
  8996.  
  8997.  window rectangle - The means by which the size and position of a window is 
  8998.    described in relation to the desktop window. 
  8999.  
  9000.  window resource - A read-only data segment stored in the .EXE file of an 
  9001.    application o the .DLL file of a dynamic link library. 
  9002.  
  9003.  window style - The set of properties that influence how events related to a 
  9004.    particular window will be processed. 
  9005.  
  9006.  window title - In SAA Advanced Common User Access architecture, the area in 
  9007.    the title bar that contains the name of the application and the OS/2 
  9008.    operating system file name, if applicable. 
  9009.  
  9010.  Workplace Shell - The OS/2 object-oriented, graphical user interface. 
  9011.  
  9012.  workstation - (1) A display screen together with attachments such as a 
  9013.    keyboard, a local copy device, or a tablet. (2) (D of C) One or more 
  9014.    programmable or nonprogrammable devices that allow a user to do work. 
  9015.  
  9016.  world coordinates - A device-independent Cartesian coordinate system used by 
  9017.    the application program for specifying graphical input and output. (I)  (A)
  9018.  
  9019.  world-coordinate space - Coordinate space in which graphics are defined before 
  9020.    transformations are applied. 
  9021.  
  9022.  WYSIWYG - What-You-See-Is-What-You-Get. A capability of a text editor to 
  9023.    continually display pages exactly as they will be printed. 
  9024.  
  9025.  
  9026. ΓòÉΓòÉΓòÉ <hidden> Glossary - X ΓòÉΓòÉΓòÉ
  9027.  
  9028. There are no glossary terms for this starting letter. 
  9029.  
  9030.  
  9031. ΓòÉΓòÉΓòÉ <hidden> Glossary - Y ΓòÉΓòÉΓòÉ
  9032.  
  9033. There are no glossary terms for this starting letter. 
  9034.  
  9035.  
  9036. ΓòÉΓòÉΓòÉ <hidden> Glossary - Z ΓòÉΓòÉΓòÉ
  9037.  
  9038.  z-order - The order in which sibling windows are presented. The topmost 
  9039.    sibling window obscures any portion of the siblings that it overlaps; the 
  9040.    same effect occurs down through the order of lower sibling windows. 
  9041.  
  9042.  zooming - The progressive scaling of an entire display image in order to give 
  9043.    the visual impression of movement of all or part of a display group toward 
  9044.    or away from an observer. (I)  (A)
  9045.  
  9046.  8.3 file-name format - A file-naming convention in which file names are 
  9047.    limited to eight characters before and three characters after a single dot. 
  9048.    Usually pronounced "eight-dot-three." See also non-8.3 file-name format. 
  9049.  
  9050.  
  9051. ΓòÉΓòÉΓòÉ <hidden> IBM Trademark ΓòÉΓòÉΓòÉ
  9052.  
  9053. Trademark of the IBM Corporation. 
  9054.  
  9055.  
  9056. ΓòÉΓòÉΓòÉ <hidden> Trademarks ΓòÉΓòÉΓòÉ
  9057.  
  9058. Trademark of AT&T, Inc. 
  9059.  
  9060.  
  9061. ΓòÉΓòÉΓòÉ <hidden> Trademarks ΓòÉΓòÉΓòÉ
  9062.  
  9063. Trademark of the Intel Corporation. 
  9064.  
  9065.  
  9066. ΓòÉΓòÉΓòÉ <hidden> Trademarks ΓòÉΓòÉΓòÉ
  9067.  
  9068. Trademark of Western Digital Corporation. 
  9069.  
  9070.  
  9071. ΓòÉΓòÉΓòÉ <hidden> Trademarks ΓòÉΓòÉΓòÉ
  9072.  
  9073. Trademark of Orchid Technology, Inc.