home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / contrinf.zip / CP3.INF (.txt) < prev   
OS/2 Help File  |  2001-03-21  |  279KB  |  9,907 lines

  1.  
  2. ΓòÉΓòÉΓòÉ 1. Memory Management ΓòÉΓòÉΓòÉ
  3.  
  4. This chapter describes the memory management features and functions of OS/2. 
  5. The key features of OS/2 memory management are paged virtual memory and a 
  6. 32-bit linear (flat) address space that is mapped through page tables to 
  7. physical memory. An OS/2 application can allocate memory for its own use or to 
  8. be shared with other applications. 
  9.  
  10. The following topics are related to the information in this chapter: 
  11.  
  12.      Exception handling 
  13.      Program execution and control 
  14.      Semaphores 
  15.      Queues 
  16.  
  17.  
  18. ΓòÉΓòÉΓòÉ 1.1. About Memory Management ΓòÉΓòÉΓòÉ
  19.  
  20. OS/2 offers developers a 32-bit, linear (flat) memory address space. OS/2 uses 
  21. a paged memory structure. OS/2 allocates, protects, and manipulates memory in 
  22. 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.      the physical memory in the system 
  50.      the free hard disk space on the hard disk containing the swap file 
  51.      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.      They are not relocatable. 
  60.      They are allocated in units of 4KB. One 4KB unit is called a page. 
  61.      They can be larger than 64KB in size. 
  62.  
  63.  
  64. ΓòÉΓòÉΓòÉ 1.1.3. Memory Pages ΓòÉΓòÉΓòÉ
  65.  
  66. OS/2 allocates and commits memory objects in pages. A memory page is a 4KB 
  67. (4096 bytes) piece of memory. Memory access protection is also done on a 
  68. page-basis, rather than the segment-based protection used in previous versions 
  69. of OS/2. 
  70.  
  71. A page range is a linearly contiguous group of pages within a memory object. A 
  72. page range can be any of the following: 
  73.  
  74.      The entire memory object 
  75.      Part of the memory object 
  76.      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. OS/2 handles memory overcommitment 
  104. by copying memory to the system swap file, SWAPPER.DAT, on the hard disk then 
  105. reusing the memory for another allocation. OS/2 copies as many pages of memory 
  106. as are necessary to make room for the new allocation. The swapped memory can be 
  107. retrieved the next time it is accessed; at that time, some other memory might 
  108. be written to the swap file. 
  109.  
  110. OS/2 selects the memory to swap based on when it was last used. The page that 
  111. is least-recently-used, that is, the page that has gone the longest since its 
  112. 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, OS/2 enables applications to allocate more memory than 
  118. actually exists in the computer, bounded only by the amount of free space on 
  119. 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, OS/2 writes selected memory pages to the 
  129. SWAPPER.DAT file whenever insufficient physical memory exists to satisfy an 
  130. allocation request. This is the default choice. If the MEMMAN command specifies 
  131. NOSWAP, OS/2 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, OS/2 might not even boot. 
  136.  
  137.  The exact amount of memory available to an application depends on the amount 
  138.  of physical memory in the machine and the amount of free disk space on the 
  139.  partition that contains the SWAPPER.DAT file. The location of the SWAPPER.DAT 
  140.  file can be specified by including the SWAPPATH command in the CONFIG.SYS 
  141.  file. With the SWAPPATH command, one can specify the location of the 
  142.  SWAPPER.DAT file, the amount of free disk space to reserve in the partition 
  143.  which will contain SWAPPER.DAT, and the initial size of SWAPPER.DAT. OS/2 
  144.  adjusts the size of SWAPPER.DAT as necessary, leaving other files on the drive 
  145.  and the requested free space untouched. 
  146.  
  147.  
  148. ΓòÉΓòÉΓòÉ 1.1.6. Memory Allocation and Commitment ΓòÉΓòÉΓòÉ
  149.  
  150. When an application asks OS/2 to allocate memory, a linear address range is 
  151. reserved. The range is not backed by physical memory until the memory is 
  152. committed. Commitment assigns physical memory to the linear address range. 
  153.  
  154. A memory object that is allocated, but not committed is called a sparse memory 
  155. object. A sparse memory object must be committed before it can be used. An 
  156. attempt to read from or write to uncommitted memory will cause an access 
  157. violation. 
  158.  
  159. An application can ask OS/2 to commit the memory at the same time it is 
  160. allocated, thus making it immediately usable, or the memory can be committed at 
  161. a later time. If the application commits the memory at the same time the memory 
  162. is allocated, the entire memory object is committed. If the application commits 
  163. the memory at a later time, it can commit the entire sparse memory object or 
  164. only commit a portion of it. 
  165.  
  166. When multiple pages are committed at the same time (a page range), the pages 
  167. will have sequential linear addresses. 
  168.  
  169. Managing Memory Allocation and Commitment 
  170. The recommended way to manage memory is to make a large memory allocation early 
  171. in program execution, then to commit or suballocate memory as the need occurs. 
  172.  
  173. The initial allocation should be for as much space as you expect to use during 
  174. program execution. Allocation without commitment does not actually use any 
  175. physical memory, so there is no waste involved in allocating several megabytes. 
  176.  
  177. After the memory object is allocated, the application uses one of two ways to 
  178. manage the memory object: 
  179.  
  180.      Commit and decommit the memory as it is required 
  181.      Set up the memory object as a heap and suballocate memory from the heap. 
  182.  
  183.  Committing and decommitting memory gives the application more control over the 
  184.  process, but the application will have to keep track of which pages are 
  185.  committed and which pages are not. When suballocating memory from a heap, the 
  186.  application can have OS/2 track commitment and decommitment of physical memory 
  187.  pages, so the application does not have to. If you want DosSubAllocMem to 
  188.  manage the commitment of the pages spanned by the heap, all of the pages 
  189.  spanned by the memory object must be uncommitted initially. 
  190.  
  191.  Remember, no matter how much memory is originally allocated, the amount that 
  192.  an application will ultimately be able to commit and use is limited by the 
  193.  amount of physical memory and free disk space available on the machine. 
  194.  
  195.  Applications are not limited to a single large allocation of memory-other 
  196.  memory allocations can be made as necessary during execution-but large 
  197.  allocations and small commitments or suballocations are the most efficient way 
  198.  to manage memory. 
  199.  
  200.  
  201. ΓòÉΓòÉΓòÉ 1.1.7. Memory Resizing and Reallocation ΓòÉΓòÉΓòÉ
  202.  
  203. In earlier versions of OS/2, an application could increase or decrease the size 
  204. of an allocated memory segment by reallocating the segment. 
  205.  
  206. Memory objects cannot be resized. Instead, an application should allocate a 
  207. sparse memory object of whatever size might be necessary, then commit or 
  208. decommit portions of the object. 
  209.  
  210. If the amount of memory required cannot be determined at the time the memory is 
  211. allocated, the application should allocate a sparse memory object large enough 
  212. to meet the largest memory requirement. The application can then change the 
  213. amount of committed memory as necessary. 
  214.  
  215. For example, if you anticipate your application will use around 512KB of memory 
  216. for most purposes, but might use 5MB under certain circumstances, you might 
  217. take the following steps: 
  218.  
  219.      During program initialization, use DosAllocMem to allocate 5MB. 
  220.  
  221.      Commit the first 512KB (or some part of it) using DosSetMem. 
  222.  
  223.      Proceed with normal processing. 
  224.  
  225.      If extra memory is required occasionally, commit it and decommit it using 
  226.       DosSetMem. 
  227.  
  228.      When the situation arises that the application requires the full 5MB, 
  229.       commit it at that time, using DosSetMem, then decommit it after you are 
  230.       finished with it, also using DosSetMem. 
  231.  
  232.      When the application is finished with the memory, use DosFreeMem to 
  233.       release the memory back to the system. 
  234.  
  235.  
  236. ΓòÉΓòÉΓòÉ 1.1.8. Memory Protection ΓòÉΓòÉΓòÉ
  237.  
  238. When an application allocates a memory object, it can specify the type of 
  239. access to allow to the object. Memory access protection provides a program with 
  240. control over the type of access that its threads have to a page of memory. 
  241.  
  242. Access protection can only be defined for committed pages of memory and is 
  243. initially set at the time the memory is committed. Different pages within the 
  244. same memory object can have different access attributes and access attributes 
  245. can be changed on a page-by-page basis at any time. 
  246.  
  247. An application can request any combination of the following access protection 
  248. attributes: 
  249.  
  250. Memory Access Protection Attributes 
  251.  
  252. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  253. ΓöéAccess              ΓöéDefined Constant    ΓöéDescription         Γöé
  254. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  255. ΓöéRead Access         ΓöéPAG_READ            ΓöéThe object can be   Γöé
  256. Γöé                    Γöé                    Γöéread from, but not  Γöé
  257. Γöé                    Γöé                    Γöéwritten to.         Γöé
  258. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  259. ΓöéWrite Access        ΓöéPAG_WRITE           ΓöéThe object can be   Γöé
  260. Γöé                    Γöé                    Γöéwritten to.  On the Γöé
  261. Γöé                    Γöé                    Γöé80386               Γöé
  262. Γöé                    Γöé                    Γöémicroprocessor,     Γöé
  263. Γöé                    Γöé                    Γöéwrite access impliesΓöé
  264. Γöé                    Γöé                    Γöéboth read and       Γöé
  265. Γöé                    Γöé                    Γöéexecute access.     Γöé
  266. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  267. ΓöéExecute Access      ΓöéPAG_EXECUTE         ΓöéThis is equivalent  Γöé
  268. Γöé                    Γöé                    Γöéto read access on   Γöé
  269. Γöé                    Γöé                    Γöéthe 80386.          Γöé
  270. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  271. ΓöéGuard Page Access   ΓöéPAG_GUARD           ΓöéCauses a            Γöé
  272. Γöé                    Γöé                    Γöéguard-page-entered  Γöé
  273. Γöé                    Γöé                    Γöéexception to be     Γöé
  274. Γöé                    Γöé                    Γöéraised in a process Γöé
  275. Γöé                    Γöé                    Γöéthat attempts to    Γöé
  276. Γöé                    Γöé                    Γöéaccess the memory.  Γöé
  277. Γöé                    Γöé                    ΓöéThis exception can  Γöé
  278. Γöé                    Γöé                    Γöébe ignored or       Γöé
  279. Γöé                    Γöé                    Γöéhandled by the      Γöé
  280. Γöé                    Γöé                    Γöéapplication's       Γöé
  281. Γöé                    Γöé                    Γöéexception handler,  Γöé
  282. Γöé                    Γöé                    Γöéif one is           Γöé
  283. Γöé                    Γöé                    Γöéregistered.         Γöé
  284. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  285.  
  286. The guard page attribute is intended to provide automatic stack growth and 
  287. stack limit checking. An application can also use it in other data structures, 
  288. such as arrays. For example, if an application is using an array of 4096 bytes 
  289. (one page), the application can allocate and commit two pages, one with read 
  290. and write access and one designated as a guard page. If the application tries 
  291. to write past the end of the array a page guard exception will be generated. 
  292.  
  293. Any reference-read, write, or execute-to a guard page causes an access 
  294. violation (page fault) to be generated. This fault causes a Guard Page Entered 
  295. exception to occur for the thread that referred to the guard page. The 
  296. exception can be handled by the exception handler of the process, if one is 
  297. registered. If the process does not have an exception handler registered, 
  298. OS/2's default exception handler will handle the exception. The default action 
  299. by the system exception handler is to convert the page from a guard page to a 
  300. committed page, then try to mark the next page in memory as a guard page. If 
  301. the system is not successful in marking the next page as a guard page, an 
  302. Unable-To-Grow-Stack exception occurs. The thread is allowed to continue 
  303. execution, but must be aware that it has at most 4KB of stack remaining. 
  304.  
  305.  
  306. ΓòÉΓòÉΓòÉ 1.1.9. Obtaining Information about a Page Range ΓòÉΓòÉΓòÉ
  307.  
  308. DosQueryMem is used to obtain information about a range of pages within the 
  309. virtual address space of the current process. 
  310.  
  311. Each page in the virtual address space of a process is either free, private, or 
  312. shared. 
  313.  
  314. Each page within a memory object can be in one of two states, either committed 
  315. or uncommitted. 
  316.  
  317. A committed page has its access controlled by an access protection attribute. 
  318. These protection attributes are read protection (PAG_READ), write protection 
  319. (PAG_WRITE), execute protection (PAG_EXECUTE), and guard page protection 
  320. (PAG_GUARD). 
  321.  
  322.  
  323. ΓòÉΓòÉΓòÉ 1.1.10. Protection Violations ΓòÉΓòÉΓòÉ
  324.  
  325. OS/2 fully utilizes the memory protection capabilities of the 80386 
  326. microprocessor. OS/2 grants an application access to a memory object only if 
  327. the object has been explicitly allocated by the application or made available 
  328. for use by the application. 
  329.  
  330. If an application attempts to access memory that it is not assigned, the system 
  331. interrupts the application and executes the exception handling routine for 
  332. protection violations. Protection violations can be handled by the application 
  333. (in its own exception handling routines) or by OS/2. If the protection 
  334. violation is handled by the operating system, the system exception handling 
  335. routine determines the cause of the exception, displays an error message, and 
  336. then terminates the application. 
  337.  
  338. It is usually not possible for an application to recover from a protection 
  339. violation. Therefore, programmers should ensure that all pointers are valid. 
  340. Because protection violations commonly occur during application debugging, each 
  341. message displayed for a protection violation includes the contents of the 
  342. registers when the violation occurred. If the violation occurred as a result of 
  343. passing an invalid pointer to a memory function, an error code is returned by 
  344. the memory function. 
  345.  
  346. In earlier versions of OS/2, protection violations could be used to find bugs 
  347. when an application accessed memory that was not allocated to the application. 
  348. This approach will no longer work because memory objects can be larger than the 
  349. size requested by the application because the memory objects are allocated on 
  350. 4KB page boundaries. For example, a pointer to the 513th byte of a 512 byte 
  351. memory object is valid and does not cause a protection violation. This means 
  352. that programmers cannot always rely on protection violations to spot memory 
  353. addressing errors. 
  354.  
  355.  
  356. ΓòÉΓòÉΓòÉ 1.1.11. Memory Suballocation and Using Heaps ΓòÉΓòÉΓòÉ
  357.  
  358. There are times when a process requires only small amounts of memory rather 
  359. than an entire memory object. It would be wasteful to allocate an entire page 
  360. of memory when only a few bytes are necessary, so a mechanism is provided for 
  361. applications to allocate a large block of memory and then suballocate portions 
  362. of the memory as necessary to fulfill small requests from an application. This 
  363. is done by creating a heap. 
  364.  
  365. A heap is a region of storage within a memory object from which an application 
  366. can allocate blocks of memory. A memory block is a piece of memory within a 
  367. heap. The size of the memory block is rounded up to the next higher multiple of 
  368. 8 bytes. 
  369.  
  370. Because OS/2 allocates a 4KB page for each memory allocation, using a heap to 
  371. suballocate amounts of memory smaller than 4KB is more efficient than using 
  372. DosAllocMem. 
  373.  
  374. When an application creates a heap, it can have OS/2 track the committing and 
  375. decommitting of memory within the heap. When the application commits and 
  376. decommits memory itself, it has to keep track of the access state of each page 
  377. as they are accessed. 
  378.  
  379. Applications use DosSubSetMem to initialize a memory object for suballocation, 
  380. then use DosSubAllocMem and DosSubFreeMem to allocate and free the memory. 
  381.  
  382. Memory is still committed in pages when an application uses suballocation. If 
  383. the application suballocates 512 bytes, 4096 bytes will be committed. Accessing 
  384. the 513th byte will not cause a protection violation, but you could be 
  385. accessing memory that was suballocated by another thread in the process. 
  386.  
  387.  
  388. ΓòÉΓòÉΓòÉ 1.1.12. Shared Memory ΓòÉΓòÉΓòÉ
  389.  
  390. Shared memory is memory that two or more applications can read from and write 
  391. to. Shared memory is prepared in such a way that any application can receive a 
  392. pointer to the memory and access the data. Applications must explicitly request 
  393. access to shared memory; the shared memory is protected from applications that 
  394. are not granted access. 
  395.  
  396. There are two kinds of shared memory:  named and unnamed. For named shared 
  397. memory, any application that knows the name of the shared memory can access it. 
  398. For unnamed shared memory, a pointer to the shared memory must be passed from 
  399. the process that created the shared memory to the process being given access. 
  400. Access can be granted to any application; it is not necessary that the process 
  401. being granted access be related (parent-child) to the application that created 
  402. the shared memory. 
  403.  
  404. Since memory sharing is done by sharing linear addresses, the linear address 
  405. range of the shared memory object is reserved in all process address spaces. 
  406.  
  407. There are two basic methods of managing shared memory: 
  408.  
  409.      In one method, two or more applications share the same memory at the same 
  410.       time. These applications read from and write to the memory object, 
  411.       usually controlling access to the memory by using a semaphore. 
  412.  
  413.      In the other method of managing shared memory, one application prepares 
  414.       data in memory, then passes that memory to another application for 
  415.       further processing. The first application releases the memory after 
  416.       passing it along, so that only one application accesses the memory at a 
  417.       time. 
  418.  
  419.  
  420. ΓòÉΓòÉΓòÉ 1.1.13. Thread Local Memory ΓòÉΓòÉΓòÉ
  421.  
  422. Thread local memory is a 128-byte region of thread-specific memory that OS/2 
  423. assigns to a thread when the thread is created. Thread local memory for each 
  424. thread is always at the same virtual address, but each thread's local memory 
  425. region is backed by different physical memory, so the memory is specific to 
  426. each thread. This memory region is divided into 32 DWORDS (4 bytes per DWORD), 
  427. and is normally used to store a small number of pointers. 
  428.  
  429. A thread can allocate thread local memory by calling DosAllocThreadLocalMemory. 
  430. Thread local memory is freed by calling DosFreeThreadLocalMemory. 
  431.  
  432. Note that thread local memory should be used sparingly. You should not use the 
  433. entire 128 byte region. 
  434.  
  435.  
  436. ΓòÉΓòÉΓòÉ 1.2. Using Memory Management ΓòÉΓòÉΓòÉ
  437.  
  438. This section describes how to use the OS/2 memory management functions and 
  439. configuration commands to control the use of memory for OS/2 applications. 
  440.  
  441. Note:  In the example code fragments that follow, error checking was left out 
  442.        to conserve space. Applications should always check the return code that 
  443.        the functions return. Control Program functions return an APIRET value. 
  444.        A return code of 0 indicates success. If a non-zero value is returned, 
  445.        an error occurred. 
  446.  
  447.  
  448. ΓòÉΓòÉΓòÉ 1.2.1. Allocating Private Memory ΓòÉΓòÉΓòÉ
  449.  
  450. An application can allocate regions of storage within the virtual address space 
  451. of the process. Such an allocated region is called a memory object. 
  452.  
  453. DosAllocMem is used to allocate a memory object. You specify a variable to 
  454. receive the pointer that will address the new object, the amount of memory 
  455. needed, and the allocation attributes and access protection attributes of the 
  456. new memory object. When choosing the size of the memory object to allocate, 
  457. remember that the maximum size of the memory object is defined when it is 
  458. allocated, and memory objects cannot be resized. 
  459.  
  460. When applications call DosAllocMem, the operating system reserves a range of 
  461. private pages large enough to fulfill the specified allocation request from the 
  462. private virtual address space of the subject process. 
  463.  
  464. DosAllocMem will reserve this linear space and return zero if the allocation 
  465. was successful. If it was unsuccessful, DosAllocMem will return an error code. 
  466. An application should always test the return value before attempting to use the 
  467. memory. 
  468.  
  469. The following code fragment requests an allocation of 512 bytes. Remember that 
  470. 4096 bytes will actually be allocated for this request: 
  471.  
  472.     #define  INCL_DOSMEMMGR   /* Memory Manager values */
  473.     #include <os2.h>
  474.  
  475.     PBYTE   pb;
  476.     APIRET  ulrc;
  477.  
  478.     ulrc = DosAllocMem((PVOID *) &pb,
  479.                        512,
  480.                        fALLOC); /* pb receives the base address of the */
  481.                                 /* 4KB memory object                   */
  482.  
  483.     if (!ulrc) {           /* If the allocation was successful, ulrc == 0 */
  484.         *pb = 3000;        /* Use the allocated memory                    */
  485.     }
  486.  
  487. In this example, DosAllocMem returns a 32-bit pointer to a 4096 byte committed 
  488. memory object and allows the application to write to and read from the memory. 
  489. This pointer is valid only for the 4096 bytes allocated by the system. An 
  490. attempt to use the pointer outside the allocated memory will cause a protection 
  491. violation. 
  492.  
  493.  
  494. ΓòÉΓòÉΓòÉ 1.2.2. Committing and Decommitting Page Ranges ΓòÉΓòÉΓòÉ
  495.  
  496. If an application allocates a sparse memory object, no physical memory location 
  497. is committed for the object. Memory in a sparse object must be committed before 
  498. it can be used. DosSetMem is used to commit or decommit a range of previously 
  499. allocated pages in a private or shared memory object. Applications can make 
  500. specific address ranges within a memory object valid or invalid. Commitment and 
  501. decommitment always take place in multiples of one or more pages. 
  502.  
  503. Applications can also use DosSetMem to change the access protection attributes 
  504. of a range of pages within a memory object. 
  505.  
  506. The following code fragment requests allocation of 2MB of uncommitted memory 
  507. and then commits 4096 bytes of the memory: 
  508.  
  509.     #define  INCL_DOSMEMMGR   /* Memory Manager values */
  510.     #include <os2.h>
  511.  
  512.     APIRET  ulrc;
  513.     PBYTE   pb;
  514.  
  515.     /* Allocate 16KB object */
  516.     ulrc = DosAllocMem((PVOID *) &pb,
  517.                        2097152,
  518.                        PAG_READ |
  519.                        PAG_WRITE);
  520.  
  521.     /* Commit 4KB           */
  522.     ulrc = DosSetMem(pb,
  523.                      4096,
  524.                      PAG_COMMIT |
  525.                      PAG_DEFAULT);
  526.  
  527. An application can also allocate a large committed object and then decommit 
  528. portions of it as they are no longer needed. Decommitment, like commitment, is 
  529. done on page boundaries; an application can decommit no less than a 4096 byte 
  530. page. 
  531.  
  532. The following code fragment allocates 16384 bytes of committed memory and then 
  533. decommits the first 4096 bytes of the memory: 
  534.  
  535.     #define  INCL_DOSMEMMGR   /* Memory Manager values */
  536.     #include <os2.h>
  537.  
  538.     APIRET  ulrc;
  539.     PBYTE   pb;
  540.  
  541.     ulrc = DosAllocMem((PVOID *) &pb,
  542.                        16384,
  543.                        fALLOC);    /* Allocate 16 K object */
  544.  
  545.     ulrc = DosSetMem(pb,
  546.                      4096,
  547.                      PAG_DECOMMIT);            /* Decommit 4KB         */
  548.  
  549. After memory is decommitted, an attempt to access the decommitted memory will 
  550. cause a protection violation. 
  551.  
  552. You cannot pass an argument that crosses multiple memory objects. The function 
  553. will return an error. 
  554.  
  555.  
  556. ΓòÉΓòÉΓòÉ 1.2.3. Establishing Access Protection ΓòÉΓòÉΓòÉ
  557.  
  558. When an OS/2 application commits a memory object, it specifies the types of 
  559. access permitted for the memory object. This can be done at the same time the 
  560. memory object is allocated, with DosAllocMem, or at a later time, using 
  561. DosSetMem. 
  562.  
  563. Any combination of read, write, execute, or guard-page access can be set, but 
  564. at least read or write access must be specified when the memory object is 
  565. committed; it is not possible to commit an object with no access protection 
  566. attributes. 
  567.  
  568. The application can also use DosSetMem to change the access permission of pages 
  569. within a previously committed memory object. An application can permit read 
  570. access to one page of the memory object and write access to the rest. 
  571.  
  572. When using DosSetMem, all the pages in the range being changed must be either 
  573. committed or decommitted. 
  574.  
  575. The following code fragment commits a region of two pages within a previously 
  576. allocated memory object, and sets read-only access rights for the region. 
  577.  
  578.     #define  INCL_DOSMEMMGR   /* Memory Manager values */
  579.     #include <os2.h>
  580.     #include <stdio.h>
  581.  
  582.     PVOID   pBaseAddress;       /* Pointer to the range of pages to be changed */
  583.     ULONG   ulRegionSize;       /* Size, in bytes, of the region to be changed */
  584.     ULONG   ulAttributeFlags;   /* Flag describing the page range              */
  585.     APIRET  ulrc;               /* Return code                                 */
  586.  
  587.     ulRegionSize = 8192;        /* Specify a two-page region                   */
  588.  
  589.     /* Obtain the base address  */
  590.     ulrc = DosAllocMem((PVOID *) &pBaseAddress,
  591.                        ulRegionSize,
  592.                        PAG_WRITE);
  593.  
  594.     ulAttributeFlags = PAG_COMMIT |
  595.                        PAG_READ;
  596.  
  597.     ulrc = DosSetMem(pBaseAddress,
  598.                      ulRegionSize,
  599.                      ulAttributeFlags);
  600.  
  601.     if (ulrc != 0) {
  602.         printf("DosSetMem error: return code = %ld", ulrc);
  603.         return;
  604.     }
  605.  
  606.  
  607. ΓòÉΓòÉΓòÉ 1.2.4. Querying Memory Object Information ΓòÉΓòÉΓòÉ
  608.  
  609. DosQueryMem is used to determine the allocation state and access protection for 
  610. a specified memory object. The application can query an entire memory object or 
  611. a range of pages within an object. 
  612.  
  613. The following code fragment uses DosQueryMem to ensure that memory is committed 
  614. before the application attempts to use the memory: 
  615.  
  616.     #define  INCL_DOSMEMMGR   /* Memory Manager values  */
  617.     #include <os2.h>
  618.     #define HF_STDOUT 1       /* Standard output handle */
  619.  
  620.     PBYTE   pb;         /* Base address of an allocated object */
  621.     ULONG   ulSize,
  622.             ulFlags,
  623.             ulWritten;
  624.     APIRET  ulrc;       /* Return Code                         */
  625.  
  626.     ulSize = 4096;
  627.  
  628.     ulrc = DosAllocMem((PVOID *)&pb,
  629.                        16384,
  630.                        PAG_COMMIT |
  631.                        PAG_WRITE);
  632.  
  633.     ulrc = DosQueryMem(pb,
  634.                        &ulSize,
  635.                        &ulFlags);     /* Queries first 4096 bytes */
  636.  
  637.     if (ulFlags & PAG_COMMIT) {     /* If memory is committed, use it */
  638.         ulrc = DosWrite(HF_STDOUT,
  639.                         "\r\n 4KB is committed.\r\n",
  640.                         21,
  641.                         &ulWritten);
  642.     }
  643.  
  644.  
  645. ΓòÉΓòÉΓòÉ 1.2.5. Freeing Memory ΓòÉΓòÉΓòÉ
  646.  
  647. When memory object is no longer needed, the application uses the DosFreeMem 
  648. function to release the memory. 
  649.  
  650. If applications do not release memory, the operating system either swaps the 
  651. memory to the hard disk (if swapping is enabled) or uses memory that could be 
  652. used by other applications. If OS/2 swaps the memory to the hard disk, the 
  653. SWAPPER.DAT swap file could become very large. Therefore, applications should 
  654. release memory as soon as it is no longer needed. Any memory that is still 
  655. allocated when the application ends is released by OS/2. 
  656.  
  657. DosFreeMem frees a private or shared memory object from the virtual address 
  658. space of the process. The released pages are returned to the system. 
  659.  
  660. The following code fragment allocates 8192 bytes of committed memory and then 
  661. releases the memory: 
  662.  
  663.     #define  INCL_DOSMEMMGR   /* Memory Manager values */
  664.     #include <os2.h>
  665.  
  666.     PBYTE   pb;
  667.     APIRET  ulrc;
  668.  
  669.     ulrc = DosAllocMem((PVOID *) &pb,
  670.                        8192,
  671.                        fALLOC);    /* Allocate 8KB object */
  672.         .
  673.         .
  674.         .
  675.     ulrc = DosFreeMem(pb);         /* Free the object     */
  676.  
  677.  
  678. ΓòÉΓòÉΓòÉ 1.3. Using Suballocation and Heaps ΓòÉΓòÉΓòÉ
  679.  
  680. This section describes how you can use DosAllocMem, DosSubSetMem, 
  681. DosSubAllocMem, DosSubFreeMem, and DosSubUnsetMem to manage a memory heap. 
  682.  
  683.  
  684. ΓòÉΓòÉΓòÉ 1.3.1. Suballocating Memory ΓòÉΓòÉΓòÉ
  685.  
  686. DosAllocMem can be used to create a memory heap. 
  687.  
  688. Before an application can allocate small portions of the heap, it must use the 
  689. DosSubSetMem function to set up the memory for suballocation. The size of the 
  690. heap is rounded up to the next higher multiple of 8 bytes. 
  691.  
  692. Then, the application uses DosSubAllocMem to allocate sections of the heap and 
  693. the DosSubFreeMem function to release the memory. 
  694.  
  695. DosSubAllocMem returns a 32-bit pointer to a block of memory. The pointer can 
  696. be used to access the memory without further modification. 
  697.  
  698. The following code fragment sets up 8192 bytes for suballocation and then 
  699. allocates two small blocks of memory: 
  700.  
  701.     #define  INCL_DOSMEMMGR   /* Memory Manager values */
  702.     #include <os2.h>
  703.  
  704.     APIRET  ulrc;
  705.     PBYTE   pbBase,
  706.             pb1,
  707.             pb2;
  708.  
  709.     ulrc = DosAllocMem((PVOID *) &pbBase,
  710.                        8192,
  711.                        fALLOC);     /* Allocate 8K object    */
  712.  
  713.     ulrc = DosSubSetMem(pbBase,
  714.                         DOSSUB_INIT,
  715.                         8192);      /* Set up object         */
  716.                                     /* for suballocation     */
  717.  
  718.     ulrc = DosSubAllocMem(pbBase,
  719.                           (PVOID *) &pb1,
  720.                           100);     /* Suballocate 100 bytes */
  721.  
  722.     ulrc = DosSubAllocMem(pbBase,
  723.                           (PVOID *) &pb2,
  724.                           500);     /* Suballocate 500 bytes */
  725.  
  726.     ulrc = DosSubFreeMem(pbBase,
  727.                          pb1,
  728.                          100);      /* Free 1st suballocation*/
  729.  
  730.     ulrc = DosSubAllocMem(pbBase,
  731.                           (PVOID *) &pb1,
  732.                           50);      /* Suballocate 50 bytes  */
  733.  
  734.  
  735. ΓòÉΓòÉΓòÉ 1.3.2. Increasing the Size of a Heap ΓòÉΓòÉΓòÉ
  736.  
  737. DosSubSetMem can also be used to increase the size of a previously initialized 
  738. heap. The heap size can be increased up to the size of the memory object that 
  739. contains it. 
  740.  
  741. The size of the heap is rounded up to the next higher multiple of 8 bytes. 
  742.  
  743. The following code fragment increases the size of a heap. Assume that the 
  744. Offset variable was previously loaded with the virtual address of the memory 
  745. object. 
  746.  
  747.     #define  INCL_DOSMEMMGR   /* Memory Manager values */
  748.     #include <os2.h>
  749.     #include <stdio.h>
  750.  
  751.     PVOID   pOffset;    /* Address of the heap to be used for suballocation */
  752.     ULONG   ulFlags;    /* Flags describing the memory object being resized */
  753.     ULONG   ulSize;     /* Size in bytes to increase the size of the heap   */
  754.     APIRET  ulrc;       /* Return code                                      */
  755.  
  756.     ulSize = 20000;     /* Indicate a heap size increase of 20000 bytes     */
  757.  
  758.     /* DOSSUB_INIT set to initialize memory for suballocation */
  759.     ulFlags = DOSSUB_INIT |
  760.               DOSSUB_SPARSE_OBJ;
  761.  
  762.     ulrc = DosSubSetMem(pOffset,
  763.                         ulFlags,
  764.                         ulSize);
  765.  
  766.     if (ulrc != 0) {
  767.         printf("DosSubSetMem error: return code = %ld", ulrc);
  768.         return;
  769.     }
  770.  
  771. In this example, the heap is incremented, and that memory commitment is managed 
  772. internally within subsequent DosSubAllocMem calls. 
  773.  
  774. When using DosSubSetMem to increase the size of the heap, the Flags parameter 
  775. must have the same setting as when the heap was initialized. 
  776.  
  777. Note:  Do not call DosSetMem to change the allocation attribute or access 
  778.        protection attributes of any pages spanned by a memory object that the 
  779.        suballocation functions are managing. Otherwise, unpredictable results 
  780.        could occur. 
  781.  
  782.  Call DosSubUnsetMem when finished with the heap that was set up with 
  783.  DosSubSetMem. This enables the suballocation function to free the resources 
  784.  that it uses to manage the heap. When you are through with the memory object 
  785.  that the heap was part of, use DosFreeMem to free the memory object. 
  786.  
  787.  
  788. ΓòÉΓòÉΓòÉ 1.3.3. Allocating a Block of Memory from a Heap ΓòÉΓòÉΓòÉ
  789.  
  790. DosSubAllocMem allocates a block of memory from a heap that was previously 
  791. initialized by DosSubSetMem. This is used when an application needs an area of 
  792. memory that is smaller than an entire heap. 
  793.  
  794. The size of the memory block is rounded up to the next higher multiple of 8 
  795. bytes. 
  796.  
  797. The following code fragment allocates a block of memory from a heap that was 
  798. previously initialized by DosSubSetMem. Assume that the Offset variable has 
  799. been set to the address of the initialized heap already. 
  800.  
  801.     #define  INCL_DOSMEMMGR   /* Memory Manager values */
  802.     #include <os2.h>
  803.     #include <stdio.h>
  804.  
  805.     PVOID    pOffset;         /* The heap to suballocate from                */
  806.     PPVOID   ppBlockOffset;   /* Pointer to the variable where the offset of */
  807.                               /* the suballocated memory block is returned   */
  808.     ULONG    ulSize;          /* Size in bytes of the memory block requested */
  809.     APIRET   ulrc;            /* Return code                                 */
  810.  
  811.     ulSize = 102;             /* Ask for 102 bytes.  This will be rounded    */
  812.                               /* to 104 bytes (a multiple of 8 bytes).       */
  813.  
  814.     ulrc = DosSubAllocMem(pOffset,
  815.                           &ppBlockOffset,
  816.                           ulSize);
  817.  
  818.     if (ulrc != 0) {
  819.         printf("DosSubAllocMem error: return code = %ld",
  820.                ulrc);
  821.         return;
  822.     }
  823.  
  824. In this example, the address of the allocated block (from the heap) is stored 
  825. in the BlockOffset variable. 
  826.  
  827. Remember to call DosSubFreeMem to free this block of memory when you are 
  828. finished with it. 
  829.  
  830.  
  831. ΓòÉΓòÉΓòÉ 1.3.4. Freeing Memory Blocks ΓòÉΓòÉΓòÉ
  832.  
  833. DosSubFreeMem frees a block of memory that was previously allocated by 
  834. DosSubAllocMem. 
  835.  
  836. Call DosSubFreeMem to free a block of memory in the heap when you are finished 
  837. with that memory block. 
  838.  
  839. The following code fragment frees a block of memory that was previously 
  840. allocated from a heap. DosSubFreeMem returns the block to the heap. Assume that 
  841. the Offset variable has been previously set to the address of the initialized 
  842. heap, and that the BlockOffset variable has been previously set to the address 
  843. of the block to be returned to the heap. 
  844.  
  845.     #define  INCL_DOSMEMMGR   /* Memory Manager values */
  846.     #include <os2.h>
  847.     #include <stdio.h>
  848.  
  849.     PVOID   pOffset;         /* Offset of the heap to which the          */
  850.                              /* block is to be freed                     */
  851.     PVOID   pBlockOffset;    /* Offset of memory block to be freed       */
  852.     ULONG   ulSize;          /* Size in bytes of block to be freed       */
  853.     APIRET  ulrc;            /* Return code                              */
  854.  
  855.     ulSize = 102;            /* Return 102 bytes.  This will be rounded  */
  856.                              /* to 104 bytes (a multiple of 8 bytes).    */
  857.  
  858.     ulrc = DosSubFreeMem(pOffset,
  859.                          pBlockOffset,
  860.                          ulSize);
  861.  
  862.     if (ulrc != 0) {
  863.         printf("DosSubFreeMem error: return code = %ld",
  864.                ulrc);
  865.         return;
  866.     }
  867.  
  868.  
  869. ΓòÉΓòÉΓòÉ 1.3.5. Ending the Use of the Heap ΓòÉΓòÉΓòÉ
  870.  
  871. DosSubUnsetMem terminates the use of a heap within a memory object. All calls 
  872. to DosSubSetMem must eventually be followed by a call to DosSubUnsetMem. This 
  873. enables the suballocation function to free the resources that it uses to manage 
  874. the heap. 
  875.  
  876. The application must call DosSubUnsetMem before it frees the memory object that 
  877. contains this heap (with DosFreeMem). 
  878.  
  879. The following code fragment shows the termination of a heap. Assume that the 
  880. address of the heap was placed into Offset already. 
  881.  
  882.     #define  INCL_DOSMEMMGR   /* Memory Manager values */
  883.     #include <os2.h>
  884.     #include <stdio.h>
  885.  
  886.     PVOID   pOffset;    /* Offset of the heap whose use is being terminated */
  887.     APIRET  ulrc;       /* Return code                                      */
  888.  
  889.     ulrc = DosSubUnsetMem(pOffset);
  890.  
  891.     if (ulrc != 0) {
  892.         printf("DosSubUnsetMem error: return code = %ld",
  893.                ulrc);
  894.         return;
  895.     }
  896.  
  897.  
  898. ΓòÉΓòÉΓòÉ 1.3.6. Allocating and Freeing Thread Local Memory ΓòÉΓòÉΓòÉ
  899.  
  900. Thread local memory is a small region of thread-specific memory assigned to a 
  901. thread when it is started. 
  902.  
  903. A thread can allocate thread local memory by calling DosAllocThreadLocalMemory. 
  904. Thread local memory is freed by calling DosFreeThreadLocalMemory. 
  905.  
  906. The thread local memory region is 32 DWORDS (4 bytes per DWORD) in size, and up 
  907. to 8 DWORDS can be allocated with each call to DosAllocThreadLocalMemory. To 
  908. allocate more than 8 DWORDS, a thread must call DosAllocThreadLocalMemory more 
  909. than once. 
  910.  
  911. Note that thread local memory should be used sparingly. You should not use the 
  912. entire 128 byte region. 
  913.  
  914. The following code fragment allocates six DWORDS in thread local memory and 
  915. then frees these six DWORDS. 
  916.  
  917. #define  INCL_DOSPROCESS
  918. #define  INCL_DOSERRORS
  919. #include <os2.h>
  920. #include <stdio.h>          /* Needed for printf */
  921.  
  922. PULONG   pulMemBlock  = NULL;       /* Pointer to thread DWORDs returned */
  923. APIRET   ulrc         = NO_ERROR;   /* Return code                       */
  924.  
  925.   ulrc = DosAllocThreadLocalMemory(6,
  926.                                    &pulMemBlock );   /* Allocate 6 DWORDs */
  927.  
  928.   if (ulrc != NO_ERROR) {
  929.     printf("DosAllocThreadLocalMemory error: return code = %u\n",
  930.            ulrc);
  931.     return 1;
  932.   }
  933.  
  934.   .
  935.   .
  936.   /* ... Use the thread-local memory block ... */
  937.   .
  938.   .
  939.  
  940.   ulrc = DosFreeThreadLocalMemory(pulMemBlock);       /* Free the memory block */
  941.  
  942.   if (ulrc != NO_ERROR) {
  943.     printf("DosFreeThreadLocalMemory error: return code = %u\n",
  944.            ulrc);
  945.     return 1;
  946.   }
  947.  
  948.  
  949. ΓòÉΓòÉΓòÉ 1.4. Using Shared Memory ΓòÉΓòÉΓòÉ
  950.  
  951. This section describes how you can use DosAllocSharedMem, DosGiveSharedMem, 
  952. DosGetSharedMem, and DosGetNamedSharedMem to use shared memory. 
  953.  
  954. There are three types of shared memory: 
  955.  
  956.      Named, where a process allocates and names shared memory. A second 
  957.       process can use the shared memory by using DosGetNamedSharedMem, 
  958.       specifying the name of the shared memory. 
  959.  
  960.      Unnamed giveable, where a process gives another process access to shared 
  961.       memory with DosGiveSharedMem, using the PID of the second process. 
  962.  
  963.      Unnamed gettable,  where a process knows the address of shared memory 
  964.       they want to use (allocated by another process), gets permission to use 
  965.       that memory with DosGetSharedMem, and then uses the shared memory. 
  966.  
  967.  The difference among these different types of shared memory is not in how the 
  968.  memory is allocated by the original process, but in how the second process 
  969.  gets permission to use and access to the shared memory. All three types of 
  970.  shared memory are allocated with the same call: DosAllocSharedMem, using 
  971.  various parameters. 
  972.  
  973.  
  974. ΓòÉΓòÉΓòÉ 1.4.1. Using Named Shared Memory ΓòÉΓòÉΓòÉ
  975.  
  976. An application uses DosAllocSharedMem to allocate shared memory. When 
  977. allocating the shared memory, an application can assign a unique name to the 
  978. memory. Any application that has the name of the shared memory can use 
  979. DosGetNamedSharedMem to retrieve a pointer to the memory. This makes it 
  980. possible for two or more applications to share memory at the same time. 
  981.  
  982. The name of a shared memory object has the following form: 
  983.  
  984.     \sharemem\name
  985.  
  986. The "\sharemem\" is required. The "name" parameter can be any name that 
  987. conforms to the rules for an OS/2 file name. No file is actually created for 
  988. the memory object. There is no actual "\sharemem\" subdirectory. 
  989.  
  990. The following code fragment allocates 65536 bytes of named shared memory with 
  991. the name "\sharemem\mymem". 
  992.  
  993.     #define  INCL_DOSMEMMGR   /* Memory Manager values */
  994.     #include <os2.h>
  995.  
  996.     APIRET  ulrc;
  997.     CHAR    szMem[] = { "\\sharemem\\mymem" };
  998.     PULONG  pulPb;
  999.  
  1000.     ulrc = DosAllocSharedMem((PVOID *) &pulPb,
  1001.                              szMem,
  1002.                              65536,
  1003.                              fALLOC);
  1004.  
  1005.     *pulPb = 2762;
  1006.  
  1007. Once the named memory is allocated, any other process can retrieve a pointer to 
  1008. the named memory by using DosGetNamedSharedMem. 
  1009.  
  1010. The following code fragment retrieves a pointer to the named memory allocated 
  1011. above: 
  1012.  
  1013.     #define  INCL_DOSMEMMGR   /* Memory Manager values */
  1014.     #include <os2.h>
  1015.     #define HF_STDOUT 1       /* Standard output handle */
  1016.  
  1017.     APIRET  ulrc;
  1018.     CHAR    szMem[] = { "\\sharemem\\mymem" };
  1019.     PULONG  pulPb2;
  1020.     ULONG   ulWritten;
  1021.  
  1022.     ulrc = DosGetNamedSharedMem((PVOID *) &pulPb2,
  1023.                                 szMem,
  1024.                                 PAG_READ |
  1025.                                 PAG_WRITE);
  1026.  
  1027.     if (*pulPb2 == 2762)
  1028.         ulrc = DosWrite(HF_STDOUT, "\r\n Success!\r\n", 13,
  1029.                         &ulWritten);
  1030.  
  1031.  
  1032. ΓòÉΓòÉΓòÉ 1.4.2. Using Unnamed Giveable Shared Memory ΓòÉΓòÉΓòÉ
  1033.  
  1034. A process allocates unnamed giveable shared memory by using DosAllocSharedMem 
  1035. with the object name (pszName parameter) set to NULL and the memory options 
  1036. (flag parameter) set to OBJ_GIVEABLE. The process allocating the memory must 
  1037. pass a pointer to the shared memory to another process. This is typically done 
  1038. by using some form of interprocess communication, such as a queue or a named 
  1039. pipe. 
  1040.  
  1041. If a process allocates shared memory with the OBJ_GIVEABLE option, this process 
  1042. can validate the pointer in another process with DosGiveSharedMem. 
  1043.  
  1044. The following code fragment allocates 24576 bytes (24KB) of unnamed giveable 
  1045. shared memory: 
  1046.  
  1047.     #define  INCL_DOSMEMMGR   /* Memory Manager values */
  1048.     #include <os2.h>
  1049.  
  1050.     APIRET  ulrc;
  1051.     PBYTE   pb;
  1052.  
  1053.     ulrc = DosAllocSharedMem((PVOID *) &pb,
  1054.                              (PSZ) NULL,
  1055.                              24576,        /* amount of memory */
  1056.                              fALLOC |
  1057.                              OBJ_GIVEABLE); /* giveable memory */
  1058.  
  1059. Once the memory is allocated, the allocating process can pass the memory 
  1060. pointer to a second process through interprocess communication. The second 
  1061. process need not use DosGetSharedMem; the second process can just use the 
  1062. shared memory. 
  1063.  
  1064.  
  1065. ΓòÉΓòÉΓòÉ 1.4.3. Using Unnamed Gettable Shared Memory ΓòÉΓòÉΓòÉ
  1066.  
  1067. A process allocates unnamed gettable shared memory by using DosAllocSharedMem 
  1068. with the object name (pszName parameter) set to NULL and the memory options 
  1069. (flag parameter) set to OBJ_GETTABLE. The allocating process must pass a 
  1070. pointer to the shared memory to another process. This is typically done by 
  1071. using some form of interprocess communication, such as a queue or a named pipe. 
  1072.  
  1073. If an application allocates shared memory with the OBJ_GETTABLE option, it 
  1074. passes a pointer to the shared memory to the second process. The second process 
  1075. gets access to the shared memory by using DosGetSharedMem to validate the 
  1076. passed pointer. 
  1077.  
  1078. The following code fragment allocates 24576 bytes (24KB) of unnamed gettable 
  1079. shared memory: 
  1080.  
  1081.     #define  INCL_DOSMEMMGR   /* Memory Manager values */
  1082.     #include <os2.h>
  1083.  
  1084.     APIRET  ulrc;
  1085.     PBYTE   pb;
  1086.  
  1087.     ulrc = DosAllocSharedMem((PVOID *) &pb,
  1088.                              (PSZ) NULL,
  1089.                              24576,
  1090.                              fALLOC |
  1091.                              OBJ_GETTABLE); /* gettable memory */
  1092.  
  1093. Once the memory is allocated, the process can pass the memory pointer to a 
  1094. second process through interprocess communication. Once the second process 
  1095. receives the pointer, it validates the memory with DosGetSharedMem, as shown in 
  1096. the following code: 
  1097.  
  1098.     #define  INCL_DOSMEMMGR   /* Memory Manager values */
  1099.     #include <os2.h>
  1100.  
  1101.     APIRET  ulrc;
  1102.     PBYTE   pb2;
  1103.  
  1104.     ulrc = DosGetSharedMem(pb2,  /* validating the memory allocated by */
  1105.                                  /* the allocating process             */
  1106.                            PAG_READ |
  1107.                            PAG_WRITE);
  1108.  
  1109.  
  1110. ΓòÉΓòÉΓòÉ 2. Message Management ΓòÉΓòÉΓòÉ
  1111.  
  1112. This chapter describes the use of message files to hold an application's text 
  1113. messages to the user. Keeping messages in a message file simplifies changing 
  1114. those messages, for example when maintaining versions of the same application 
  1115. for different countries. 
  1116.  
  1117. The following topic is related to the information in this chapter: 
  1118.  
  1119.      National language support 
  1120.  
  1121.  
  1122. ΓòÉΓòÉΓòÉ 2.1. About Message Management ΓòÉΓòÉΓòÉ
  1123.  
  1124. For full-screen applications, text messages-used by an application to display 
  1125. information to the user-can be held in a message file. 
  1126.  
  1127. To keep and maintain messages in a message file, create a separate message file 
  1128. for each national language you intend to support. Use the MKMSGF utility 
  1129. program to create a binary version of a message file, and the MSGBIND utility 
  1130. program to bind the binary file to the application's executable file. Binding 
  1131. the messages to an application's executable file inserts the messages into the 
  1132. .EXE file. This enables faster access (but, of course, a larger .EXE file). 
  1133.  
  1134. OS/2 provides several functions to assist in message management. Applications 
  1135. can get messages from a message file, substitute variable information into the 
  1136. messages, and write messages to the screen or to a file. 
  1137.  
  1138. Code Page Considerations 
  1139. You can have versions of the message file for each code page you choose to 
  1140. support. When you use MKMSGF to create the message files, the utility will 
  1141. insert the code page information and link together the message files of the 
  1142. different versions. 
  1143.  
  1144. When message files are linked together in this manner, DosGetMessage will 
  1145. search for the appropriate version of the message for the code page that is 
  1146. active at the time the function is called. If there is no version of the 
  1147. message for the current code page, the function will return the first version 
  1148. of the message, no matter which code page it is associated with. 
  1149.  
  1150. Note:  To create portable source code for message files, make sure you 
  1151. specifically set the code page in CONFIG.SYS using the CODEPAGE statement. If 
  1152. you have the wrong code page, or use the default code page, which could be 
  1153. wrong, DosGetMessage returns error code 37 (ERROR_CODE_PAGE_MISMATCHED). 
  1154.  
  1155.  
  1156. ΓòÉΓòÉΓòÉ 2.2. Using Message Management ΓòÉΓòÉΓòÉ
  1157.  
  1158. DosGetMessage retrieves a message from the specified system message file, and 
  1159. inserts variable information into the body of the message. 
  1160.  
  1161. DosInsertMessage inserts variable text-string information into the body of the 
  1162. message, but does not retrieve the message. 
  1163.  
  1164. DosPutMessage sends the message in a buffer, usually to a display screen. 
  1165. DosPutMessage formats the screen buffer to prevent words from being split at 
  1166. the end of a line. 
  1167.  
  1168. DosQueryMessageCP retrieves the message file list of code pages and language 
  1169. identifiers. 
  1170.  
  1171. Note:  In the example code fragments that follow, error checking was left out 
  1172.        to conserve space. Applications should always check the return code that 
  1173.        the functions return. Control Program functions return an APIRET value. 
  1174.        A return code of 0 indicates success. If a non-zero value is returned, 
  1175.        an error occurred. 
  1176.  
  1177.  
  1178. ΓòÉΓòÉΓòÉ 2.2.1. Message Retrieval and String Substitution ΓòÉΓòÉΓòÉ
  1179.  
  1180. DosGetMessage retrieves a message from a system message file, and inserts 
  1181. variable text-string information into the message. 
  1182.  
  1183. In the following code fragment, the message file is "D:\MESSAGE\AUTOMSG.MSG". 
  1184. The third message within the message file contains the string "%1 Error at 
  1185. Station %2". The application calls DosGetMessage to convert this message into 
  1186. the string "Automation Failure Error at Station 69B". 
  1187.  
  1188.     #define INCL_DOSMISC   /* Miscellaneous values */
  1189.     #include <os2.h>
  1190.     #include <stdio.h>
  1191.  
  1192.     UCHAR   *ucIvTable[2];    /* Table of variables to insert       */
  1193.     ULONG    ulIvCount;       /* Number of variables                */
  1194.     UCHAR    ucDataArea[80];  /* Message buffer (returned)          */
  1195.     ULONG    ulDataLength;    /* Length of buffer                   */
  1196.     ULONG    ulMsgNumber;     /* Number of the message              */
  1197.     UCHAR    ucFileName[40];  /* Message file path-name string      */
  1198.     ULONG    ulMsgLength;     /* Length of message (returned)       */
  1199.     UCHAR    ucField1[20];    /* String to substitute into variable */
  1200.                               /* field %1 of the message            */
  1201.     UCHAR    ucField2[20];    /* String to substitute into variable */
  1202.                               /* field %2 of the message            */
  1203.     APIRET   ulrc;            /* Return code                        */
  1204.  
  1205.     strcpy(ucField1,
  1206.            "Automation Failure");   /* Define the field with which to  */
  1207.                                     /* perform the first substitution  */
  1208.  
  1209.     strcpy(ucField2,
  1210.            "69B");                  /* Define the field with which to            */
  1211.                                     /* perform the second substitution           */
  1212.  
  1213.     ucIvTable[0] = ucField1;       /* Set up the array of pointers to           */
  1214.     ucIvTable[1] = ucField2;       /* substitute strings                        */
  1215.  
  1216.     ulIvCount = 2;                 /* Two variable message fields in message    */
  1217.  
  1218.     ulDataLength = 80;             /* Data buffer that will receive the         */
  1219.                                    /* complete message is 80 bytes in size      */
  1220.  
  1221.     ulMsgNumber = 3;               /* Specify the third message in the          */
  1222.                                    /* message file                              */
  1223.  
  1224.     strcpy(ucFileName,
  1225.            "D:\\MESSAGE\\AUTOMSG.MSG");
  1226.            /* Path name of the message file            */
  1227.  
  1228.     ulrc = DosGetMessage(ucIvTable,
  1229.                          ulIvCount,
  1230.                          ucDataArea,
  1231.                          ulDataLength,
  1232.                          ulMsgNumber,
  1233.                          ucFileName,
  1234.                          &ulMsgLength);
  1235.  
  1236.     if (ulrc != 0) {
  1237.         printf("DosGetMessage error: return code = %ld",
  1238.                ulrc);
  1239.         return;
  1240.     }
  1241.  
  1242. On successful return, the DataArea buffer contains the complete message (with 
  1243. the two variable fields appropriately updated), and the MsgLength variable 
  1244. contains the length of the message that was placed into the DataArea buffer. 
  1245.  
  1246. If an error occurs (that is, if the return code does not equal 0), a message 
  1247. that is related to the error will be placed in the message buffer. See the 
  1248. DosGetMessage API reference in Control Program Programming Reference for a 
  1249. description of the default messages that can be placed into the user's buffer 
  1250. if an error occurs during the processing of these requests. 
  1251.  
  1252.  
  1253. ΓòÉΓòÉΓòÉ 2.2.2. Text String Substitution in Memory ΓòÉΓòÉΓòÉ
  1254.  
  1255. DosInsertMessage inserts variable text-string information into a message that 
  1256. resides within program memory. 
  1257.  
  1258. In the following code fragment, the message resides in a program string 
  1259. variable named Message. The message is the string "%1 Error at Station %2". The 
  1260. application calls DosInsertMessage to convert this message into the string 
  1261. "Automation Failure Error at Station 69B". 
  1262.  
  1263.     #define INCL_DOSMISC   /* Miscellaneous values */
  1264.     #include <os2.h>
  1265.     #include <stdio.h>
  1266.  
  1267.     UCHAR   *ucIvTable[2];               /* Table of variables to insert         */
  1268.     ULONG    ulIvCount;                  /* Number of variables                  */
  1269.     UCHAR    ucMsgInput[40] = "%1 Error at Station %2";     /* The input message */
  1270.     ULONG    ulMsgInLength;              /* Length of input message              */
  1271.     UCHAR    ucDataArea[80];             /* Message buffer (returned)            */
  1272.     ULONG    ulDataLength;               /* Length of updated message buffer     */
  1273.     ULONG    ulMsgLength;                /* Length of updated message (returned) */
  1274.     UCHAR    ucField1[20];               /* String to substitute into variable   */
  1275.                                          /* field %1 of the message              */
  1276.     UCHAR    ucField2[20];               /* String to substitute into variable   */
  1277.                                          /* field %2 of the message              */
  1278.     APIRET   ulrc;                       /* Return code                          */
  1279.  
  1280.     strcpy(ucField1,
  1281.            "Automation Failure");        /* Define the field with which to  */
  1282.                                          /* perform the first substitution  */
  1283.  
  1284.     strcpy(ucField2,
  1285.            "69B");                       /* Define the field with which to  */
  1286.                                          /* perform the second substitution */
  1287.  
  1288.     ucIvTable[0] = ucField1;     /* Set up the array of pointers to */
  1289.     ucIvTable[1] = ucField2;     /* substitute strings              */
  1290.  
  1291.     ulIvCount = 2;                          /* Two variable message fields in  */
  1292.                                             /* message                         */
  1293.  
  1294.     ulMsgInLength = strlen(ucMsgInput);     /* Length of input message         */
  1295.  
  1296.     ulDataLength = 80;                      /* Data buffer that will receive   */
  1297.                                             /* the complete message is 80      */
  1298.                                             /* bytes in size                   */
  1299.  
  1300.     ulrc = DosInsertMessage(ucIvTable,
  1301.                             ulIvCount,
  1302.                             ucMsgInput,
  1303.                             ulMsgInLength,
  1304.                             ucDataArea,
  1305.                             ulDataLength,
  1306.                             &ulMsgLength);
  1307.  
  1308.     if (ulrc != 0) {
  1309.         printf("DosInsertMessage error: return code = %ld",
  1310.                ulrc);
  1311.         return;
  1312.     }
  1313.  
  1314. On successful return, the DataArea buffer contains the complete message (with 
  1315. the two variable fields appropriately updated), and the MsgLength variable 
  1316. contains the length of the message that was placed into the DataArea buffer. 
  1317.  
  1318. If an error occurs (that is, if the return code does not equal 0), a message 
  1319. that is related to the error will be placed in the message buffer. See the 
  1320. DosGetMessage API reference in Control Program Programming Reference for a 
  1321. description of the default messages that can be placed into the user's buffer 
  1322. if an error occurs during the processing of these requests. 
  1323.  
  1324.  
  1325. ΓòÉΓòÉΓòÉ 2.2.3. Writing Messages ΓòÉΓòÉΓòÉ
  1326.  
  1327. DosPutMessage is used to write the message to the screen or to a file on a 
  1328. disk. 
  1329.  
  1330. The following code fragment writes the message string contained in 
  1331. MessageBuffer to the file specified by FileHandle. The message string has 
  1332. already been placed in MessageBuffer using either DosGetMessage or 
  1333. DosInsertMessage. MsgLength was set to the length of the message string by the 
  1334. same call that put the message into MessageBuffer. 
  1335.  
  1336.     #define INCL_DOSMISC   /* Miscellaneous values */
  1337.     #include <os2.h>
  1338.     #include <stdio.h>
  1339.  
  1340.  
  1341.     HFILE   hfFileHandle;           /* Handle of output file or device */
  1342.     ULONG   ulMsgLength;            /* Length of message buffer        */
  1343.     UCHAR   ucMessageBuffer[80];    /* Message buffer                  */
  1344.     APIRET  ulrc;                   /* Return code                     */
  1345.  
  1346.     ulrc = DosPutMessage(hfFileHandle,
  1347.                          ulMsgLength,
  1348.                          ucMessageBuffer);
  1349.  
  1350.     if (ulrc != 0) {
  1351.         printf("DosPutMessage error: return code = %ld",
  1352.                ulrc);
  1353.         return;
  1354.     }
  1355.  
  1356. To write a message to the screen, use the standard output file handle. 
  1357.  
  1358.  
  1359. ΓòÉΓòÉΓòÉ 2.2.4. Code Page Information Associated with Message Files ΓòÉΓòÉΓòÉ
  1360.  
  1361. DosQueryMessageCP obtains a list of code page identifiers and language 
  1362. identifiers that are associated with a specified message file. 
  1363.  
  1364. In the following code fragment code page and language identifiers associated 
  1365. with the message file "D:\MESSAGE\AUTOMSG.MSG" are retrieved. 
  1366.  
  1367.     #define INCL_DOSMISC   /* Miscellaneous values */
  1368.     #include <os2.h>
  1369.     #include <stdio.h>
  1370.  
  1371.     UCHAR    ucBufferArea[20];  /* Buffer for the returned list  */
  1372.     ULONG    ulBufferLength;    /* Length of the buffer area     */
  1373.     UCHAR    ucFileName[40];    /* Message file path-name string */
  1374.     ULONG    ulDataLength;      /* Length of the returned data   */
  1375.     APIRET   ulrc;              /* Return code                   */
  1376.  
  1377.     strcpy(ucFileName,
  1378.            "D:\\MESSAGE\\AUTOMSG.MSG");
  1379.            /* Path name of message file */
  1380.  
  1381.     ulBufferLength = 20;                           /* Length of buffer area     */
  1382.  
  1383.     ulrc = DosQueryMessageCp(ucBufferArea,
  1384.                              ulBufferLength,
  1385.                              ucFileName,
  1386.                              &ulDataLength);
  1387.  
  1388.     if (ulrc != 0) {
  1389.         printf("DosQueryMessageCp error: return code = %ld",
  1390.                ulrc);
  1391.         return;
  1392.     }
  1393.  
  1394. On successful return, the BufferArea buffer contains a set of information 
  1395. concerning the code page identifiers and language identifiers that are 
  1396. associated with the message file. 
  1397.  
  1398.  
  1399. ΓòÉΓòÉΓòÉ 3. National Language Support ΓòÉΓòÉΓòÉ
  1400.  
  1401. Many applications need to be independent of a particular language. Rather than 
  1402. being hard-coded in English, they want to support, for example, an English 
  1403. version of the application, and a French version, and a German version; 
  1404. preferably without having to change the program code for each version. Meeting 
  1405. this requirement is simplified through the use of such resources as string 
  1406. tables, menu templates, dialog templates, accelerator tables, and through the 
  1407. use of code pages. 
  1408.  
  1409. This chapter describes the functions an application uses to be NLS enabled, or 
  1410. language independent. 
  1411.  
  1412. The following topic is related to the information in this chapter: 
  1413.  
  1414.      Message management 
  1415.  
  1416.  
  1417. ΓòÉΓòÉΓòÉ 3.1. About National Language Support ΓòÉΓòÉΓòÉ
  1418.  
  1419. The support of national languages by applications requires the following 
  1420. considerations: 
  1421.  
  1422.      Displayed text must be translated into the appropriate language. 
  1423.  
  1424.      Symbols or icons might not convey the same meaning in all countries. 
  1425.       Alternative designs for different countries might be necessary. 
  1426.  
  1427.      Translation changes the length of text strings. 
  1428.  
  1429.      Different languages often have different text characters. 
  1430.  
  1431.  The use of national language resource files can help with the first three 
  1432.  items, and the ability of the application to receive input and display output 
  1433.  in any ASCII code page can help with the last item. 
  1434.  
  1435.  The use of ASCII code page 850 avoids many of the problems in this area, since 
  1436.  it contains most of the characters required for Latin-1 languages, which 
  1437.  include much of Western Europe and North and South America. However, older 
  1438.  programs use code page 437 for U.S. English, and code pages 860, 863, and 865 
  1439.  for various languages. The code page applies to both input and output data. 
  1440.  
  1441.  Note:  Code page 850 was used for translating Presentation Manager text. Use 
  1442.         code page 850 whenever possible for all Presentation Manager 
  1443.         applications that might require translation. 
  1444.  
  1445.  
  1446. ΓòÉΓòÉΓòÉ 3.1.1. National Language Resource Files ΓòÉΓòÉΓòÉ
  1447.  
  1448. When creating an application, define national language dependencies in 
  1449. resources that are held in resource files separate from the program code.  That 
  1450. is: 
  1451.  
  1452.      Keep pure text strings in string tables. 
  1453.      Keep menus in menu templates. 
  1454.      Keep dialog boxes in dialog templates. 
  1455.      Keep accelerators in accelerator tables. 
  1456.  
  1457.  The language displayed by the application can then be changed by translating 
  1458.  the resources, in most cases without changing the application. 
  1459.  
  1460.  However, when translating from one language to another, the length of a text 
  1461.  string can change substantially. For example, when translating from English to 
  1462.  German, the length of a text string can double in length. 
  1463.  
  1464.  The following table furnishes a general idea of the amount of expansion that 
  1465.  can be expected during translation. 
  1466.  
  1467.  Translation Expansion 
  1468.  
  1469.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1470.   ΓöéFor English Phrases           ΓöéTranslation Expansion Factors Γöé
  1471.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1472.   ΓöéUp to 10 characters           Γöé101 - 200%                    Γöé
  1473.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1474.   Γöé11 - 20 characters            Γöé81 - 100%                     Γöé
  1475.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1476.   Γöé21 - 30 characters            Γöé61 - 80%                      Γöé
  1477.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1478.   Γöé31 - 50 characters            Γöé41 - 60%                      Γöé
  1479.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1480.   Γöé51 - 70 characters            Γöé31 - 40%                      Γöé
  1481.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1482.   ΓöéOver 70 characters            Γöé30%                           Γöé
  1483.   ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  1484.  
  1485.  When designing your dialog boxes and text string messages, add white space to 
  1486.  allow for the expansion that will occur when the text is translated. You might 
  1487.  have to adapt the application program to allow for the change in the length of 
  1488.  text strings after they are translated. For example, a change in the length of 
  1489.  a text string can cause it to become misaligned with other displayed objects. 
  1490.  
  1491.  You can also use the Dialog Box Editor to adjust for misalignments, or to 
  1492.  change the size of the dialog box. This would enable you to leave your 
  1493.  application program unchanged. 
  1494.  
  1495.  Text strings explicitly displayed by the application program are more of a 
  1496.  problem. You will have to include program code that can handle text strings of 
  1497.  varying length and format them at runtime according to their size. 
  1498.  
  1499.  
  1500. ΓòÉΓòÉΓòÉ 3.1.2. Language-Specific Versions of NLS-Enabled Applications ΓòÉΓòÉΓòÉ
  1501.  
  1502. There are two methods of creating a specific national language version of a 
  1503. program designed to handle more than one national language. The choice of the 
  1504. method depends on the amount of available disk space and whether the user wants 
  1505. to change between different languages once the program is installed. The two 
  1506. methods are: 
  1507.  
  1508.      Statically link the resources to the application's .EXE files. The 
  1509.       executable files are then language-specific and cannot be changed to 
  1510.       another national language. The specific .EXE files are then sent to the 
  1511.       user. 
  1512.  
  1513.      Place the resources into a language-specific, dynamic link library. 
  1514.       Designate one library file for each national language. Selecting a 
  1515.       particular library file for use with the application gives the desired 
  1516.       version of the program. Using this method, all national languages can be 
  1517.       shipped with the product; selection of the national language occurs 
  1518.       during installation (for example, by naming a specific .DLL file). It is 
  1519.       possible to change the national language setting while the program is 
  1520.       operating. 
  1521.  
  1522.  
  1523. ΓòÉΓòÉΓòÉ 3.2. About Code Page Management ΓòÉΓòÉΓòÉ
  1524.  
  1525. A code page is a table that defines how the characters in a language or group 
  1526. of languages are encoded. A specific value is given to each character in the 
  1527. code page. For example, in code page 850 the letter "╨┤" (lowercase) is encoded 
  1528. as hex A4 (decimal 164), and the letter "╨╡" (uppercase) is encoded as hex A5 
  1529. (decimal 165). 
  1530.  
  1531. Code page management enables a user to select a code page for keyboard input, 
  1532. and screen and printer output before starting an application, a system command, 
  1533. or a utility program in the OS/2 multitasking environment. 
  1534.  
  1535. This means that a user in a particular country, such as England (code page 
  1536. 850), Norway (code page 865), or a language region such as Canadian French 
  1537. (code page 863) can use a code page that defines an ASCII-based character set 
  1538. containing characters used by that particular country or language. 
  1539.  
  1540. Installable code page files include keyboard translate tables, display 
  1541. character sets, printer character sets, and country/language information for 
  1542. each code page supported. 
  1543.  
  1544. Of particular interest are two code pages: 
  1545.  
  1546.      Code Page 850 
  1547.      Code Page 437 
  1548.  
  1549.  Code Page 850 (CP850) 
  1550.  Code Page 850 is also called the Latin-1, multilingual code page. This code 
  1551.  page supports the alphabetic characters of the Latin-1-based languages. It 
  1552.  contains characters required by 13 languages used in approximately 40 
  1553.  countries. 
  1554.  
  1555.  CP850 also provides the flexibility to develop new applications based on 
  1556.  non-Latin-based or special industry-based code pages. 
  1557.  
  1558.  Code Page 850 supports countries using the following languages: 
  1559.  
  1560.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1561.   ΓöéBelgian French                ΓöéCanadian French               Γöé
  1562.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1563.   ΓöéDanish                        ΓöéDutch                         Γöé
  1564.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1565.   ΓöéFinnish                       ΓöéFlemish                       Γöé
  1566.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1567.   ΓöéFrench                        ΓöéGerman                        Γöé
  1568.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1569.   ΓöéItalian                       ΓöéNorwegian                     Γöé
  1570.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1571.   ΓöéPortuguese                    ΓöéSpanish                       Γöé
  1572.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1573.   ΓöéLAD Spanish                   ΓöéSwedish                       Γöé
  1574.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1575.   ΓöéSwiss French                  ΓöéSwiss German                  Γöé
  1576.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1577.   ΓöéU.K. English                  ΓöéU.S. English                  Γöé
  1578.   ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  1579.  
  1580.  Code Page 437 (CP437) 
  1581.  Code Page 437 is the standard personal computer code page. 
  1582.  
  1583.  The lower 128 characters are based on the 7-bit ASCII code. The upper 128 
  1584.  characters contain characters from several European languages (including part 
  1585.  of the Greek alphabet) and various graphic characters. However, some of the 
  1586.  accented characters, such as those used in the Nordic countries, are not 
  1587.  represented. The missing characters are available in other code pages (code 
  1588.  page 850 will usually contain the desired characters). 
  1589.  
  1590.  Note:  Some of the 256 symbols that can be displayed are printer control 
  1591.         characters, and are not printed. 
  1592.  
  1593.  
  1594. ΓòÉΓòÉΓòÉ 3.2.1. ASCII and EBCDIC Code Page Support ΓòÉΓòÉΓòÉ
  1595.  
  1596. The two leading character-coding systems are ASCII and EBCDIC. Presentation 
  1597. Manager applications can use an EBCDIC code page instead of an ASCII code page. 
  1598. Code pages based on both systems are supported by OS/2. 
  1599.  
  1600. Any code page that either is defined in the CONFIG.SYS file, or is one of the 
  1601. EBCDIC code pages supported, can be selected. 
  1602.  
  1603.  
  1604. ΓòÉΓòÉΓòÉ 3.2.2. Code Page Preparation ΓòÉΓòÉΓòÉ
  1605.  
  1606. During system initialization, the code pages specified in the CODEPAGE 
  1607. statement are prepared to enable run-time code page switching of the display, 
  1608. the keyboard, the printer, and the country information. The display, keyboard, 
  1609. and printer must be defined in a DEVINFO statement in order to be prepared. 
  1610. Country information is prepared for the system country code specified in the 
  1611. COUNTRY statement. 
  1612.  
  1613. If a resource cannot be prepared for the selected code page during system 
  1614. initialization, it is prepared for a default code page. The following are the 
  1615. defaults: 
  1616.  
  1617.      A keyboard layout defaults to the code page of the translate table 
  1618.       designated as the default layout in the KEYBOARD.DCP file. The default 
  1619.       layout is based on the national code page of its associated country. You 
  1620.       must explicitly specify KEYBOARD.DCP in the DEVINFO statement for the 
  1621.       keyboard in CONFIG.SYS. 
  1622.  
  1623.      The display defaults to the code page of ROM_0 for the device. 
  1624.  
  1625.       (ROM_0 means a device default code page that is the device native code 
  1626.       page or the lowest addressed ROM code page.) 
  1627.  
  1628.      The printer defaults to the code page of ROM_0 for the device. 
  1629.  
  1630.       (ROM_0 means a device default code page that is the device native code 
  1631.       page or the lowest addressed ROM code page.) 
  1632.  
  1633.      The country information defaults to the code page of the first entry 
  1634.       found in the COUNTRY.SYS file for the country code. Each entry is the 
  1635.       same information for a given country code, but is encoded in a different 
  1636.       code page. The first entry is based on the preferred country code page. 
  1637.  
  1638.  If country information cannot be prepared at system initialization because it 
  1639.  is not found in the COUNTRY.SYS file, for a code page selected with the 
  1640.  CODEPAGE statement, then it is prepared (maintained for run-time code page 
  1641.  switching in memory) in the default code page. Similarly, a keyboard layout is 
  1642.  prepared in its default code page if it cannot be prepared in the selected 
  1643.  code page, because it is not found in the KEYBOARD.DCP file. 
  1644.  
  1645.  COUNTRY.SYS contains one default entry per country code, and KEYBOARD.DCP 
  1646.  contains one default entry per keyboard layout based on these assignments. 
  1647.  
  1648.  
  1649. ΓòÉΓòÉΓòÉ 3.2.3. Code Page Functions ΓòÉΓòÉΓòÉ
  1650.  
  1651. At the system level, OS/2 switches the code pages of supported displays and 
  1652. printers to agree with the code page of the process sending the output. At the 
  1653. application level, OS/2 functions enable a process to control code page 
  1654. assignments. 
  1655.  
  1656.  
  1657. ΓòÉΓòÉΓòÉ 3.3. Using Code Pages ΓòÉΓòÉΓòÉ
  1658.  
  1659. OS/2 provides applications with several functions to obtain information about 
  1660. and manipulate code pages. These functions enable applications to determine and 
  1661. set the current code page. 
  1662.  
  1663. OS/2 code page management functions enable applications to read keyboard input 
  1664. and write display and printer output for multiple processes using ASCII-based 
  1665. data encoded in different code pages. 
  1666.  
  1667. The system switches to the required code page, for a code-page-supported 
  1668. device, before input or output. 
  1669.  
  1670. Note:  In the example code fragments that follow, error checking was left out 
  1671.        to conserve space. Applications should always check the return code that 
  1672.        the functions return. Control Program functions return an APIRET value. 
  1673.        A return code of 0 indicates success. If a non-zero value is returned, 
  1674.        an error occurred. 
  1675.  
  1676.  
  1677. ΓòÉΓòÉΓòÉ 3.3.1. Querying Code Page Support and the Current Code Page ΓòÉΓòÉΓòÉ
  1678.  
  1679. DosQueryCp is used to determine the code page of the current process and the 
  1680. prepared system code pages. The following code fragment shows how to get the 
  1681. current code page, and then up to three other prepared pages: 
  1682.  
  1683.     #define INCL_DOSNLS   /* National Language Support values */
  1684.     #include <os2.h>
  1685.  
  1686.     ULONG  ulCpList[8];
  1687.     ULONG  ulCpSize;
  1688.     APIRET ulrc;    /* Return code */
  1689.  
  1690.     ulrc = DosQueryCp(sizeof(ulCpList),    /* Length of list          */
  1691.                       ulCpList,            /* List                    */
  1692.                       &ulCpSize);          /* Length of returned list */
  1693.  
  1694.  
  1695. The required code page is the current code page of the process at the time it 
  1696. opens a device, or a specific code page selected by the process with a 
  1697. set-code-page function. A character set can also be specified for some devices, 
  1698. for example, for some printers. 
  1699.  
  1700. The country functions retrieve country- and language-dependent information in 
  1701. the current code page of the calling process, or in a code page selected by the 
  1702. process. 
  1703.  
  1704.  
  1705. ΓòÉΓòÉΓòÉ 3.3.2. Setting the Code Page for Text Characters ΓòÉΓòÉΓòÉ
  1706.  
  1707. Each process has a code page tag maintained by OS/2. A code page tag is the 
  1708. identifier of the current code page for the process. 
  1709.  
  1710. A child process inherits the code page tag of its parent. The default code page 
  1711. for the first process in a session is the same as the session code page. The 
  1712. default code page for a new session is the primary code page specified in the 
  1713. CODEPAGE configuration statement. 
  1714.  
  1715. To change the code page tag of a process, call DosSetProcessCp. This will not 
  1716. change the process code page tag of its parent or any child process. 
  1717.  
  1718.  
  1719. ΓòÉΓòÉΓòÉ 3.3.3. Obtaining the Case Map String ΓòÉΓòÉΓòÉ
  1720.  
  1721. DosMapCase performs case mapping on a string of binary values that represent 
  1722. ASCII characters. 
  1723.  
  1724. The case map that is used is the one in the country file that corresponds to 
  1725. the system country code or selected country code, and to the process code page 
  1726. or selected code page. The default name of the country file is COUNTRY.SYS. 
  1727.  
  1728.  
  1729. ΓòÉΓòÉΓòÉ 3.3.4. Obtaining the DBCS Environment Vector ΓòÉΓòÉΓòÉ
  1730.  
  1731. DosQueryDBCSEnv obtains a double-byte character set (DBCS) environment vector 
  1732. that resides in the country file. The default name of the country file is 
  1733. COUNTRY.SYS. 
  1734.  
  1735. The vector corresponds to the system country code or selected country code, and 
  1736. to the process code page or selected code page. 
  1737.  
  1738. The following code fragment shows how to use DosQueryDBCSEnv: 
  1739.  
  1740.     #define INCL_DOSNLS   /* National Language Support values */
  1741.     #include <os2.h>
  1742.     #include <stdio.h>
  1743.  
  1744.     ULONG         ulLength;             /* Length of data area provided         */
  1745.     COUNTRYCODE   ccStructure;          /* Input data structure                 */
  1746.     UCHAR         ucMemoryBuffer[12];   /* DBCS environmental vector (returned) */
  1747.     APIRET        ulrc;                 /* Return code                          */
  1748.  
  1749.     ulLength = 12;                      /* A length of 12 bytes is sufficient   */
  1750.                                         /* to contain the DBCS data returned    */
  1751.  
  1752.     ccStructure.country = 0;            /* Use the default system country code  */
  1753.  
  1754.     ccStructure.codepage = 0;           /* Return DBSC information for the      */
  1755.                                         /* caller's current process code page   */
  1756.  
  1757.     ulrc = DosQueryDBCSEnv(ulLength,
  1758.                            &ccStructure,
  1759.                            ucMemoryBuffer);
  1760.  
  1761.     if (ulrc != 0) {
  1762.         printf("DosQueryDBCSEnv error: return code = %ld",
  1763.                ulrc);
  1764.         return;
  1765.     }
  1766.  
  1767. On successful return, the buffer MemoryBuffer will contain the country 
  1768. dependent information for the DBCS environmental vector. 
  1769.  
  1770. Instead of the single-byte character set (SBCS) representation used for Latin 
  1771. text, some Asian countries use code pages that consist of double-byte character 
  1772. set characters, in which each character is represented by a two-byte code. The 
  1773. DBCS code pages enable single-byte data, double-byte data, or mixed 
  1774. (single-byte and double-byte) data. 
  1775.  
  1776.  
  1777. ΓòÉΓòÉΓòÉ 3.3.5. Obtaining Formatting Information ΓòÉΓòÉΓòÉ
  1778.  
  1779. DosQueryCtryInfo obtains country dependent formatting information that resides 
  1780. in the country file. The default name of the country file is COUNTRY.SYS. 
  1781.  
  1782. The information corresponds to the system country code or selected country 
  1783. code, and to the process code page or selected code page. 
  1784.  
  1785.  
  1786. ΓòÉΓòÉΓòÉ 3.3.6. Obtaining Collating Information for SORT ΓòÉΓòÉΓòÉ
  1787.  
  1788. DosQueryCollate obtains a collating sequence table (for characters 00H through 
  1789. FFH) from the country file. The default name of the country file is 
  1790. COUNTRY.SYS. The SORT utility program uses this table to sort text according to 
  1791. the collating sequence. 
  1792.  
  1793. The collating table returned corresponds to the system country code or selected 
  1794. country code, and to the process code page or selected code page. 
  1795.  
  1796.  
  1797. ΓòÉΓòÉΓòÉ 4. Pipes ΓòÉΓòÉΓòÉ
  1798.  
  1799. Communication between processes is valuable in a multitasking operating system 
  1800. to enable concurrent processes to work together. Pipes are one of three forms 
  1801. of interprocess communication (IPC), the other forms of IPC being semaphores 
  1802. and queues. 
  1803.  
  1804. This chapter describes how to create, manage, and use pipes. Pipes enable two 
  1805. or more processes to communicate as if they were reading from and writing to a 
  1806. file. 
  1807.  
  1808. The following topics are related to the information in this chapter: 
  1809.  
  1810.      Memory (shared memory) 
  1811.      Program execution and control 
  1812.      Semaphores 
  1813.      Queues 
  1814.  
  1815.  
  1816. ΓòÉΓòÉΓòÉ 4.1. About Pipes ΓòÉΓòÉΓòÉ
  1817.  
  1818. A pipe is a named or unnamed buffer used to pass data between processes. A 
  1819. process writes to or reads from a pipe as if the pipe were standard input or 
  1820. standard output. A parent process can use pipes to control the input that a 
  1821. child process receives and to receive the output that the child process 
  1822. produces. 
  1823.  
  1824. There are two types of pipes-named and unnamed. 
  1825.  
  1826.  
  1827. ΓòÉΓòÉΓòÉ 4.1.1. Unnamed Pipes ΓòÉΓòÉΓòÉ
  1828.  
  1829. An unnamed pipe is a circular buffer in memory. The buffer has in and out 
  1830. pointers that are maintained by the system. 
  1831.  
  1832. An unnamed pipe can transfer information only between related processes. A 
  1833. child process started by a parent process with DosExecPgm inherits the handles 
  1834. to any unnamed pipes created by its parent. This inheritance enables the parent 
  1835. process and the child process to use the unnamed pipe to communicate with one 
  1836. another. This type of pipe is typically used to redirect the standard input and 
  1837. standard output of a child process. 
  1838.  
  1839. To do this, a process opens a pipe and duplicates the read and write handles of 
  1840. the pipe as the standard input and standard output files for the child process. 
  1841. Once the handles are duplicated, the parent process can use DosExecPgm to start 
  1842. the child process. When the child process reads and writes to its standard 
  1843. input and standard output handles, it is reading and writing to the pipe. The 
  1844. parent process can also communicate with the child process through the pipe. 
  1845.  
  1846. Using an unnamed pipe, a text editor could run another program, such as a 
  1847. compiler or assembler, and display the output of the compiler or assembler 
  1848. within the editor. 
  1849.  
  1850. DosCreatePipe creates an unnamed pipe. This function returns two file handles 
  1851. for the pipe, one for writing to the pipe and another for reading from the 
  1852. pipe. A process can then write to the pipe by using DosWrite and read from the 
  1853. pipe by using DosRead. 
  1854.  
  1855. A pipe exists until both handles are closed. The order in which the handles are 
  1856. closed is sometimes important. For example, DosWrite might wait for data to be 
  1857. read from the pipe before completing its operation. In this case, the read 
  1858. handle is closed before the write handle is closed, writing to the pipe 
  1859. generates an error. 
  1860.  
  1861. No control or permission mechanisms or checks are performed on operations to 
  1862. unnamed pipes. 
  1863.  
  1864.  
  1865. ΓòÉΓòÉΓòÉ 4.1.2. Named Pipes ΓòÉΓòÉΓòÉ
  1866.  
  1867. Named pipes enable related or unrelated processes on either the same computer 
  1868. system or different systems to communicate with each other. Any process that 
  1869. knows the name of a pipe can open and use a named pipe. In addition, named pipe 
  1870. data can be transparently redirected across a network, such as a local area 
  1871. network (LAN). (Unnamed pipes, by contrast, can be used only by related 
  1872. processes that are on the same computer system.) 
  1873.  
  1874. One process (the server process) creates the pipe and connects to one end of 
  1875. it. Other processes that access the named pipe are called client processes; 
  1876. they connect to the other end of the pipe. The server and client processes can 
  1877. then pass data back and forth by reading from and writing to the pipe. The 
  1878. server process controls access to the named pipe. 
  1879.  
  1880. The client process can be either local or remote. A local client process is one 
  1881. that runs on the same computer system as the server process. A remote client 
  1882. process runs on a different system and communicates with the server process 
  1883. across a local area network (LAN). 
  1884.  
  1885. When the server process creates a named pipe with DosCreateNPipe, it must 
  1886. specify the direction that data will flow through the pipe. The process 
  1887. specifies an inbound pipe if it intends to read data from the client process, 
  1888. an outbound pipe if it intends to write data to the client process, or a duplex 
  1889. pipe if it intends to read from and write to the client process. 
  1890.  
  1891. The server process also specifies whether data passes through the pipe as bytes 
  1892. or messages. A message is a block of data, with a system-supplied header, that 
  1893. is read or written as a single unit. The server and client processes define the 
  1894. size and format of a message. 
  1895.  
  1896. The server process also specifies whether child processes will inherit the 
  1897. named pipe and how information will be read from and written to the pipe. If 
  1898. the server specifies wait mode, DosRead will be blocked (it will not return to 
  1899. the process) until data is available in the pipe, and DosWrite will be blocked 
  1900. until there is enough room in the pipe to contain the entire data buffer. If 
  1901. the server specifies no-wait mode, reading from an empty pipe or writing to a 
  1902. full pipe immediately returns an error value. 
  1903.  
  1904. A named pipe consists of two pipe buffers, one for each direction of 
  1905. communication. However, each end of the pipe has only one handle associated 
  1906. with it. The server receives the handle for its end when it creates the pipe 
  1907. with DosCreateNPipe. The client receives the handle for its end when it opens 
  1908. the pipe with DosOpen. 
  1909.  
  1910. The server and the client use their respective handles both to read from the 
  1911. pipe and to write to it. (This is in contrast to unnamed pipes, for which both 
  1912. the server and the client read from one handle and write to another.) In other 
  1913. words, data that is written by the process at one end of the pipe is read by 
  1914. the process at the other end. 
  1915.  
  1916. A named pipe can have multiple instances, up to the number specified when the 
  1917. pipe is first created. Pipe instances are actually separate pipes-that is, 
  1918. unique sets of pipe buffers with unique handles-that share the same name. The 
  1919. ability to create multiple pipe instances enables the server to communicate 
  1920. with multiple client processes at the same time. 
  1921.  
  1922.  
  1923. ΓòÉΓòÉΓòÉ 4.1.2.1. Server-Client Communications Using Named Pipes ΓòÉΓòÉΓòÉ
  1924.  
  1925. A server process initiates a connection to a client process by using 
  1926. DosConnectNPipe. Once the pipe has been connected by the server process, the 
  1927. client process must open the pipe by using DosOpen to complete the connection. 
  1928. If no client process has opened the pipe when the server process calls 
  1929. DosConnectNPipe, the function either waits until a client opens the pipe or 
  1930. returns ERROR_PIPE_NOT_CONNECTED, depending on whether the server process 
  1931. created the pipe to wait for data. 
  1932.  
  1933. Each client process requires a separate instance of a pipe. For example, if a 
  1934. server process creates a named pipe and specifies that four instances of the 
  1935. pipe can be created, the process can then create three more instances of the 
  1936. named pipe (for a total of four pipes, including the original). Each instance 
  1937. has the same name, but each has a unique pipe handle. The process can then 
  1938. connect each pipe to the server. (Each instance must be connected by an 
  1939. explicit use of DosConnectNPipe.) In this example, the server must use each 
  1940. function four times to create and connect four separate instances of the named 
  1941. pipe. Each pipe is then available to a separate client process. 
  1942.  
  1943. If a client process receives the ERROR_PIPE_BUSY return value from DosOpen, no 
  1944. instances of the given pipe are available. The process can use DosWaitNPipe to 
  1945. wait for an instance to become available. The function waits until an instance 
  1946. is free or until the specified time interval elapses. When an instance becomes 
  1947. free, the process can open the pipe. If several processes are waiting for an 
  1948. instance to become available, the system gives the named pipe to the process 
  1949. that has been waiting the longest. 
  1950.  
  1951. The server process can disconnect a client process from a pipe by using 
  1952. DosDisConnectNPipe. Ideally, the client process closes the pipe by using 
  1953. DosClose before the server process disconnects the pipe. If the client process 
  1954. has not closed the pipe when the server process disconnects it, the server 
  1955. process forces the pipe closed and the client process subsequently receives 
  1956. errors if it attempts to access the pipe. Note that forcing the closure of the 
  1957. pipe might discard data in the pipe before the client process has had an 
  1958. opportunity to read it. 
  1959.  
  1960. A process can read and write bytes to a named pipe by using DosRead and 
  1961. DosWrite. A process can read or write messages by using DosTransactNPipe. 
  1962. Depending on the access mode, DosTransactNPipe writes a message to the pipe, 
  1963. reads a message from the pipe, or both. If a named pipe contains unread data or 
  1964. is not a message pipe, DosTransactNPipe fails. 
  1965.  
  1966. Named pipes created with the NP_ACCESS_INBOUND or NP_ACCESS_OUTBOUND access 
  1967. mode cannot use the DosTransactNPipe function. If the named pipe's client uses 
  1968. the DosTransactNPipe function, the function returns error code 5 
  1969. (ERROR_ACCESS_DENIED). 
  1970.  
  1971. If it is reading from the pipe, DosTransactNPipe does not return until a 
  1972. complete message is read, even if the server process specified no-wait mode 
  1973. when the pipe was created. 
  1974.  
  1975. A process can also read data from a named pipe without removing the data from 
  1976. the pipe by using DosPeekNPipe. This function copies the specified number of 
  1977. bytes from the pipe and returns the number of bytes of data left in the pipe 
  1978. and the number of bytes left in the current message, if any. 
  1979.  
  1980. DosPeekNPipe also returns the state of the pipe. A named pipe can be in one of 
  1981. the following states: 
  1982.  
  1983. Named Pipe States 
  1984.  
  1985. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1986. ΓöéState          ΓöéDescription                                  Γöé
  1987. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1988. ΓöéConnected      ΓöéThe pipe has been created and connected by   Γöé
  1989. Γöé               Γöéthe server process and has been opened by a  Γöé
  1990. Γöé               Γöéclient process.  Only connected pipes can be Γöé
  1991. Γöé               Γöéwritten to or read from.                     Γöé
  1992. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1993. ΓöéClosing        ΓöéThe pipe has been closed by the client       Γöé
  1994. Γöé               Γöéprocess but has not yet been disconnected by Γöé
  1995. Γöé               Γöéthe server process.                          Γöé
  1996. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1997. ΓöéDisconnected   ΓöéThe pipe has been created by the server      Γöé
  1998. Γöé               Γöéprocess but not connected, or has been       Γöé
  1999. Γöé               Γöéexplicitly disconnected and not yet          Γöé
  2000. Γöé               Γöéreconnected. A disconnected pipe cannot      Γöé
  2001. Γöé               Γöéaccept a DosOpen request.                    Γöé
  2002. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2003. ΓöéListening      ΓöéThe pipe has been created and connected by   Γöé
  2004. Γöé               Γöéthe server process but has not yet been      Γöé
  2005. Γöé               Γöéopened by a client process. A listening pipe Γöé
  2006. Γöé               Γöéis ready to accept a request to open. If the Γöé
  2007. Γöé               Γöépipe is not in a listening state, DosOpen    Γöé
  2008. Γöé               Γöéreturns ERROR_PIPE_BUSY.                     Γöé
  2009. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  2010. DosCallNPipe is used to open, write to, read from, and close a named 
  2011. message-format pipe. 
  2012.  
  2013. Named pipes created with the NP_ACCESS_INBOUND or NP_ACCESS_OUTBOUND access 
  2014. mode cannot use the DosCallNPipe function. If the named pipe's client uses the 
  2015. DosCallNPipe function, the function returns error code 5 (ERROR_ACCESS_DENIED). 
  2016. This function is equivalent to calling DosOpen, DosTransactNPipe, and DosClose 
  2017. If no instances of the pipe are available, DosCallNPipe waits for an instance 
  2018. or returns without opening the pipe if the specified interval of time elapses. 
  2019.  
  2020. A process can retrieve information about the handle state of a named pipe by 
  2021. using DosQueryNPHState. The handle state is a combination of the instance 
  2022. count, the access mode, and the pipe type (byte or message). DosQueryNPHState 
  2023. also specifies whether the process owning the handle is a server or client and 
  2024. whether the pipe waits if reading and writing cannot proceed. 
  2025.  
  2026. A process can modify the handle state of a named pipe by using DosSetNPHState. 
  2027. For example, the process can change the reading mode for the pipe, enabling a 
  2028. process to read bytes from the pipe instead of messages. 
  2029.  
  2030.  
  2031. ΓòÉΓòÉΓòÉ 4.1.2.2. Steps in Managing Server-Client Transactions ΓòÉΓòÉΓòÉ
  2032.  
  2033. The following sequence summarizes the typical steps in the management of a 
  2034. named pipe: 
  2035.  
  2036.    1. The server process creates the pipe by calling DosCreateNPipe. 
  2037.       DosCreateNPipe returns a handle for the server end of the pipe. (Note 
  2038.       that the server uses the same handle to both read from and write to the 
  2039.       pipe.) The pipe is now in the disconnected state and cannot be opened by 
  2040.       a client process. The server process calls DosConnectNPipe to put the 
  2041.       pipe into a listening state. 
  2042.  
  2043.    2. The pipe can now be opened by a client process. 
  2044.  
  2045.    3. A client process supplies the name of the pipe in a call to DosOpen and 
  2046.       receives a pipe handle in return. (The client uses the same handle to 
  2047.       both read from and write to the pipe.) The pipe is now in the connected 
  2048.       state and can be read from or written to by the client. 
  2049.  
  2050.    4. The server and client processes communicate by calling DosRead and 
  2051.       DosWrite. DosResetBuffer can be used to synchronize read and write 
  2052.       dialogs. A server process that supports a large number of clients for a 
  2053.       local named pipe can use DosSetNPipeSem and DosQueryNPipeSemState to 
  2054.       coordinate access to the pipe. Server and client processes can also use 
  2055.       DosTransactNPipe and DosCallNPipe to facilitate their communication. 
  2056.  
  2057.    5. After completing its transactions, the client process calls DosClose to 
  2058.       close its end of the pipe. The pipe is now in the closing state and 
  2059.       cannot be accessed by another client. 
  2060.  
  2061.    6. The server process calls DosDisConnectNPipe to acknowledge that the 
  2062.       client has closed its end of the pipe.  The pipe is now in the 
  2063.       disconnected state again. 
  2064.  
  2065.    7. To enable another client process to open the pipe, the server must call 
  2066.       DosConnectNPipe again. This puts the pipe back into the listening state. 
  2067.       To end its access to the pipe, the server calls DosClose. When all of the 
  2068.       handles for both ends of the pipe have been closed, the pipe is 
  2069.       deallocated by the system. 
  2070.  
  2071.  
  2072. ΓòÉΓòÉΓòÉ 4.1.2.3. Preparing a Named Pipe for a Client ΓòÉΓòÉΓòÉ
  2073.  
  2074. A server process uses DosConnectNPipe to put a newly created named pipe into 
  2075. the listening state. The pipe must be in the listening state in order for a 
  2076. client process to gain access to the pipe by calling DosOpen. 
  2077.  
  2078. After successfully opening the pipe and finishing its transactions, the client 
  2079. process calls DosClose to end its access to the pipe. The server process must 
  2080. acknowledge the close by calling DosDisConnectNPipe. It can then call 
  2081. DosConnectNPipe again to put the pipe into the listening state for the next 
  2082. client. 
  2083.  
  2084. Together, DosConnectNPipe and DosDisConnectNPipe enable a server to create a 
  2085. named pipe and to reuse it for communication with different clients. Without 
  2086. these functions, the server would have to delete and re-create the pipe for 
  2087. each client. 
  2088.  
  2089. Note:  If multiple instances of a named pipe have been created, then each 
  2090.        instance of the pipe must be put into the listening state before it can 
  2091.        be opened by a client. 
  2092.  
  2093.  
  2094. ΓòÉΓòÉΓòÉ 4.1.2.4. Facilitating Transaction Processing ΓòÉΓòÉΓòÉ
  2095.  
  2096. DosTransactNPipe and DosCallNPipe facilitate the use of named pipes by 
  2097. combining other named pipe functions. Compared to calling the other functions 
  2098. separately, DosTransactNPipe and DosCallNPipe provide significant performance 
  2099. gains for applications that operate in a networked environment.  They can also 
  2100. be used by local processes. However, both of these functions can be used only 
  2101. with duplex message pipes. 
  2102.  
  2103.      DosTransactNPipe performs a transaction (a DosWrite followed by DosRead) 
  2104.       on a duplex message pipe. 
  2105.  
  2106.      DosCallNPipe has the combined effect of DosOpen, DosTransactNPipe, and 
  2107.       DosClose, and is referred to as a procedure call. It provides an 
  2108.       efficient means of implementing local and remote procedure call 
  2109.       interfaces between processes. 
  2110.  
  2111.  
  2112. ΓòÉΓòÉΓòÉ 4.1.2.5. Coordinating Access to a Local Named Pipe with Semaphores ΓòÉΓòÉΓòÉ
  2113.  
  2114. When a process writes to a named pipe, the process at the other end (or handle) 
  2115. of the pipe might require notification that data is available to be read. 
  2116. Similarly, when a process reads from a named pipe, the process at the other end 
  2117. might require notification that write space has become available. As long as 
  2118. the communicating processes are on the same computer system, shared event 
  2119. semaphores and muxwait semaphores can be used to provide this notification. 
  2120. Using shared semaphores for this purpose is more efficient than dedicating a 
  2121. thread to periodically poll each pipe, particularly when a server process is 
  2122. communicating with a large number of client processes. Whenever data is 
  2123. available in the pipe, the system posts a semaphore to the server or client 
  2124. (whichever is reading from the pipe). This means that the reading process can 
  2125. use DosWaitEventSem or DosWaitMuxWaitSem to wait for data to arrive, rather 
  2126. than devote a thread to periodically polling the pipe. 
  2127.  
  2128. A process associates a semaphore with a named pipe by using DosSetNPipeSem. 
  2129. First, create an event semaphore with DosCreateEventSem, specifying the initial 
  2130. state of the semaphore as reset. Then call DosSetNPipeSem to attach the event 
  2131. semaphore to a particular named-pipe handle. Up to two event semaphores can be 
  2132. attached to each named pipe, one for the server process and one for the client 
  2133. process. If there is already a semaphore associated with one end of the pipe, 
  2134. that semaphore is replaced. A process can check the state of the semaphores by 
  2135. using DosQueryNPipeSemState. 
  2136.  
  2137. The server or client process must then call DosWaitEventSem. The particular 
  2138. thread that calls this function will block until data is either read from or 
  2139. written to the pipe. At that time, the system posts the event semaphore, 
  2140. enabling the blocked thread to resume its execution. 
  2141.  
  2142. If a process requires notification whenever any one of multiple named pipes has 
  2143. been written to or read from, it can either attach the same event semaphore to 
  2144. multiple pipes, or it can create a muxwait semaphore: 
  2145.  
  2146.      If the same event semaphore is attached to multiple pipes, then the 
  2147.       KeyHandle parameter of DosSetNPipeSem is used to assign a unique value to 
  2148.       each pipe. After the event semaphore has been posted, the process calls 
  2149.       DosQueryNPipeSemState. This function returns information about each of 
  2150.       the named pipes that are attached to the semaphore, including key-handle 
  2151.       values. The calling process can use this information to determine which 
  2152.       one of the named pipes has either data or write space available. 
  2153.  
  2154.      To use a muxwait semaphore, a process first creates an event semaphore 
  2155.       for each of the pipes that it wants to monitor. Each semaphore must then 
  2156.       be attached to a pipe by calling DosSetNPipeSem. Again, a unique 
  2157.       key-handle value must be assigned to each pipe. 
  2158.  
  2159.       Next, the process calls DosCreateMuxWaitSem to create the muxwait 
  2160.       semaphore, specifying DCMW_WAIT_ANY as one of the flAttr flags. The 
  2161.       muxwait semaphore will consist of a linked list of the previously created 
  2162.       event semaphores. 
  2163.  
  2164.       The process calls DosWaitMuxWaitSem so that it will be notified the next 
  2165.       time data is read from or written to any of the pipes. However, it must 
  2166.       call DosQueryNPipeSemState to determine which one of the pipes is ready 
  2167.       to be read from or written to. 
  2168.  
  2169.  
  2170. ΓòÉΓòÉΓòÉ 4.2. Using Unnamed Pipes ΓòÉΓòÉΓòÉ
  2171.  
  2172. Unnamed pipes are useful in applications that transfer data between related 
  2173. processes. They are commonly used to control the input and output of child 
  2174. processes by redirecting the standard input and output of the child process to 
  2175. a pipe controlled by the parent process. 
  2176.  
  2177. Note:  In the example code fragments that follow, error checking was left out 
  2178.        to conserve space. Applications should always check the return code that 
  2179.        the functions return. Control Program functions return an APIRET value. 
  2180.        A return code of 0 indicates success. If a non-zero value is returned, 
  2181.        an error occurred. 
  2182.  
  2183.  
  2184. ΓòÉΓòÉΓòÉ 4.2.1. Creating Unnamed Pipes ΓòÉΓòÉΓòÉ
  2185.  
  2186. DosCreatePipe creates an unnamed pipe. Two handles are returned: one for read 
  2187. access to the pipe and one for write access. The pipe size specified is 
  2188. advisory; its actual size is dependent on the amount of available memory. If 
  2189. the size parameter is 0, the pipe is created with the default size, which is 
  2190. 512 bytes. 
  2191.  
  2192. This example creates an unnamed pipe. The current process can use the unnamed 
  2193. pipe for communication between itself and a child process. 
  2194.  
  2195.     #define INCL_BASE    /* Queue values */
  2196.     #include <os2.h>
  2197.     #include <stdio.h>
  2198.  
  2199.     HFILE    hfReadHandle;    /* Pointer to the read handle      */
  2200.     HFILE    hfWriteHandle;   /* Pointer to the write handle     */
  2201.     ULONG    ulPipeSize;      /* Pipe size                       */
  2202.     APIRET   ulrc;            /* Return code                     */
  2203.  
  2204.     ulPipeSize = 4096;        /* Ask for 4KB of internal storage */
  2205.                               /* for the pipe                    */
  2206.  
  2207.     ulrc = DosCreatePipe(&hfReadHandle,
  2208.                          &hfWriteHandle,
  2209.                          ulPipeSize);
  2210.  
  2211.     if (ulrc != 0) {
  2212.         printf("DosCreatePipe error: return code = %ld",
  2213.                ulrc);
  2214.         return;
  2215.     }
  2216.  
  2217. On successful return, the ReadHandle variable contains the read handle for the 
  2218. pipe, and the WriteHandle variable contains the write handle for the pipe. 
  2219.  
  2220. After a process creates a pipe, any child process started with DosExecPgm 
  2221. inherits the pipe handles. Using shared memory, the parent process can pass one 
  2222. of the pipe handles to the child process; thus, one process can store data in 
  2223. the pipe and the other can retrieve it. 
  2224.  
  2225.  
  2226. ΓòÉΓòÉΓòÉ 4.2.2. Reading from and Writing to Unnamed Pipes ΓòÉΓòÉΓòÉ
  2227.  
  2228. Applications use the OS/2 file system functions to read from and write to 
  2229. unnamed pipes. 
  2230.  
  2231. The handles returned by DosCreatePipe are used as file handles to DosRead and 
  2232. DosWrite. 
  2233.  
  2234. To write (or add data) to an unnamed pipe, call DosWrite, specifying the write 
  2235. handle of the pipe in DosWrite's file handle parameter. DosWrite requests to a 
  2236. pipe are processed in the order in which they are made. Multiple calls to 
  2237. DosWrite can be made before data is read (or removed) from the pipe. When the 
  2238. pipe becomes full, write requests are blocked until space is freed by read 
  2239. requests. 
  2240.  
  2241. When the pipe is too full to hold the entire contents of the write request, the 
  2242. portion that will fit is written to the pipe before the writer is blocked. 
  2243.  
  2244. To read from a pipe, call DosRead, specifying the read handle of the pipe in 
  2245. DosRead's file handle parameter. Subsequent calls to DosRead can empty the pipe 
  2246. if no further calls to DosWrite are made in the meantime. 
  2247.  
  2248. Different threads writing to and reading from a pipe are not synchronized. It 
  2249. is possible for the pipe reader to obtain partial contents of a write request 
  2250. if the pipe becomes full during the write request. 
  2251.  
  2252. If the process reading the pipe ends, the next DosWrite request for that pipe 
  2253. returns ERROR_BROKEN_PIPE. 
  2254.  
  2255. Calling DosClose terminates access to an unnamed pipe. However, the pipe is not 
  2256. deleted from memory until all handles to the pipe have been closed, including 
  2257. any handles that were defined with DosDupHandle. 
  2258.  
  2259.  
  2260. ΓòÉΓòÉΓòÉ 4.2.3. Redirecting Standard I/O for Child Processes ΓòÉΓòÉΓòÉ
  2261.  
  2262. An application can use unnamed pipes to redirect the standard input and the 
  2263. standard output for a child process. 
  2264.  
  2265. A typical use of an unnamed pipe is to read the output of a child process. An 
  2266. application creates a pipe and then duplicates the standard output handle. When 
  2267. the child process is started, its standard output will be written into the 
  2268. pipe, where the application can read and display it. The following code 
  2269. fragment shows how to do this: 
  2270.  
  2271.  
  2272.     #define INCL_DOSPROCESS
  2273.     #define INCL_DOSNMPIPES
  2274.  
  2275.     #include <os2.h>
  2276.  
  2277.     #define PIPESIZE 256
  2278.     #define HF_STDOUT 1      /* Standard output handle */
  2279.  
  2280.     HPIPE hpR, hpW;
  2281.     RESULTCODES resc;
  2282.     ULONG ulRead, ulWritten;
  2283.     CHAR achBuf[PIPESIZE],
  2284.          szFailName[CCHMAXPATH];
  2285.  
  2286.     HFILE hfSave = -1,
  2287.           hfNew = HF_STDOUT;
  2288.  
  2289.     DosDupHandle(HF_STDOUT,
  2290.                  &hfSave); /* Saves standard output handle      */
  2291.  
  2292.     DosCreatePipe(&hpR,
  2293.                   &hpW,
  2294.                   PIPESIZE); /* Creates pipe                      */
  2295.  
  2296.     DosDupHandle(hpW,
  2297.                  &hfNew); /* Duplicates standard output handle */
  2298.  
  2299.  
  2300.     DosExecPgm(szFailName,
  2301.                sizeof(szFailName), /* Starts child process      */
  2302.                EXEC_ASYNC,
  2303.                (PSZ) NULL,
  2304.                (PSZ) NULL,
  2305.                &resc,
  2306.                "DUMMY.EXE");
  2307.  
  2308.     DosClose(hpW);                /* Closes write handle to ensure     */
  2309.                                   /* Notification at child termination */
  2310.  
  2311.     DosDupHandle(hfSave,
  2312.                  &hfNew);     /* Brings stdout back                */
  2313.  
  2314.     /*
  2315.      * Read from the pipe and write to the screen
  2316.      * as long as there are bytes to read.
  2317.      *
  2318.      */
  2319.  
  2320.     do {
  2321.         DosRead(hpR,
  2322.                 achBuf,
  2323.                 sizeof(achBuf),
  2324.                 &ulRead);
  2325.  
  2326.         DosWrite(HF_STDOUT,
  2327.                  achBuf,
  2328.                  ulRead,
  2329.                  &ulWritten);
  2330.  
  2331.     } while(ulRead);
  2332.  
  2333. A parent process can also use unnamed pipes to communicate with a child process 
  2334. by redirecting both the standard input and the standard output for the child 
  2335. process. To do this, the parent process: 
  2336.  
  2337.    1. Uses DosDupHandle to redefine the read handle of one pipe as standard 
  2338.       input (0000), and the write handle of the other pipe as standard output 
  2339.       (0001). 
  2340.    2. Starts the child process with DosExecPgm. 
  2341.    3. Uses the remaining pipe handles to read and write to the pipes. 
  2342.  
  2343.  The parent process controls the meanings for standard I/O for the child 
  2344.  process. Thus, when the child process uses standard I/O handles with DosRead 
  2345.  and DosWrite, it reads from and writes to the pipes of its parent instead of 
  2346.  reading from the keyboard and writing to the display. 
  2347.  
  2348.  
  2349. ΓòÉΓòÉΓòÉ 4.3. Using Named Pipes ΓòÉΓòÉΓòÉ
  2350.  
  2351. Named pipes are useful in applications that transfer data between processes. 
  2352. The processes using named pipes can be related, unrelated, or even on different 
  2353. computers. 
  2354.  
  2355.  
  2356. ΓòÉΓòÉΓòÉ 4.3.1. Creating Named Pipes ΓòÉΓòÉΓòÉ
  2357.  
  2358. The server process creates a named pipe by using DosCreateNPipe. 
  2359.  
  2360. To create a named pipe, specify on the DosCreateNPipe function: 
  2361.  
  2362.      The name of the pipe 
  2363.      The access modes 
  2364.      The type of pipe (byte or message) 
  2365.      The sizes of the input and output buffers 
  2366.  
  2367.  DosCreateNPipe returns a pipe handle that can be used in subsequent pipe 
  2368.  operations. 
  2369.  
  2370.  Each named pipe must have a unique name of the following form: 
  2371.  
  2372.       \PIPE\PipeName
  2373.  
  2374.  The "\PIPE\" in the name above is required, but need not be uppercase.  It is 
  2375.  not the name of a subdirectory. 
  2376.  
  2377.  To open a pipe on a remote computer, the client process must specify the name 
  2378.  of the server process that opened the pipe as part of the pipe name, as 
  2379.  follows: 
  2380.  
  2381.       \\Server\PIPE\PipeName
  2382.  
  2383.  "\\Server" in the name above is the name of the remote computer; again, 
  2384.  "\PIPE\" is required. 
  2385.  
  2386.  The name parameter must conform to the rules for OS/2 file names, but no 
  2387.  actual file is created for the pipe. 
  2388.  
  2389.  Named pipes created with certain access modes prevent the named pipes' clients 
  2390.  from using certain functions. If the named pipe is created with access mode 
  2391.  NP_ACCESS_INBOUND, the named pipe's client cannot use these functions: 
  2392.  
  2393.      DosCallNPipe 
  2394.      DosTransactNPipe 
  2395.      DosPeekNPipe 
  2396.  If the named pipe is created with access mode NP_ACCESS_OUTBOUND, the named 
  2397.  pipe's client cannot use these functions: 
  2398.  
  2399.      DosCallNPipe 
  2400.      DosTransactNPipe 
  2401.      DosWrite 
  2402.  
  2403.  If the named pipe's client uses an incorrect function, the function returns 
  2404.  error code 5 (ERROR_ACCESS_DENIED). 
  2405.  
  2406.  In the following code fragment, DosCreateNPipe creates a pipe named 
  2407.  \pipe\pipe1 and supplies a unique handle identifying the pipe. OpenMode is set 
  2408.  to NP_ACCESS_DUPLEX. This activates full duplex access to the named pipe. 
  2409.  There will be no inheritance to child process, and no write-through 
  2410.  (write-through only affects remote pipes). PipeMode is set to "NP_WMESG | 
  2411.  NP_RMESG | 0x01". This specifies that the pipe should be read as a message 
  2412.  stream for both reading and writing and an instance count of 1 (only one 
  2413.  instance of the named pipe can be created at a time). The pipe will block on 
  2414.  Read/Write if no data is available. 
  2415.  
  2416.       #define INCL_DOSNMPIPES   /* Named-pipe values */
  2417.       #include <os2.h>
  2418.       #include <stdio.h>
  2419.  
  2420.       UCHAR   ucFileName[40];  /* Pipe name              */
  2421.       HPIPE   hpPipeHandle;    /* Pipe handle (returned) */
  2422.       ULONG   ulOpenMode;      /* Open-mode parameters   */
  2423.       ULONG   ulPipeMode;      /* Pipe-mode parameters   */
  2424.       ULONG   ulOutBufSize;    /* Size of the out-buffer */
  2425.       ULONG   ulInBufSize;     /* Size of the in-buffer  */
  2426.       ULONG   ulTimeOut;       /* Default value for      */
  2427.                                /* DosWaitNPipe time-out  */
  2428.                                /* parameter              */
  2429.       APIRET  ulrc;            /* Return code            */
  2430.  
  2431.       strcpy(ucFileName,
  2432.              "\\PIPE\\PIPE1");
  2433.  
  2434.       ulOpenMode = NP_ACCESS_DUPLEX;            /* Full duplex, no inheritance,     */
  2435.                                                 /* no write-through                 */
  2436.  
  2437.       ulPipeMode = NP_WMESG |
  2438.                    NP_RMESG |
  2439.                    0x01;     /* Block on read and write, message                   */
  2440.                              /* stream, instance count of 1                        */
  2441.  
  2442.       ulOutBufSize = 4096;   /* The outgoing buffer must be 4KB in size            */
  2443.  
  2444.       ulInBufSize = 2048;    /* The incoming buffer must be 2KB in size            */
  2445.  
  2446.       ulTimeOut = 10000;     /* Time-out is 10 seconds (units are in milliseconds) */
  2447.  
  2448.       ulrc = DosCreateNPipe(ucFileName,
  2449.                             &hpPipeHandle,
  2450.                             ulOpenMode,
  2451.                             ulPipeMode,
  2452.                             ulOutBufSize,
  2453.                             ulInBufSize,
  2454.                             ulTimeOut);
  2455.  
  2456.       if (ulrc != 0) {
  2457.           printf("DosCreateNPipe error: return code = %ld",
  2458.                  ulrc);
  2459.           return;
  2460.       }
  2461.  
  2462.  Once the named pipe is created, the application can call DosConnectNPipe to 
  2463.  connect a client process to the pipe. 
  2464.  
  2465.  Once a client process connects to the pipe, the process can read from and 
  2466.  write to the pipe. The preceding example creates a byte pipe, so the process 
  2467.  can use DosRead and DosWrite to read from and write to the pipe. 
  2468.  
  2469.  After the client process finishes using the pipe, the server process can 
  2470.  disconnect the pipe by using DosDisConnectNPipe. The server process can either 
  2471.  connect again or close the named pipe by using DosClose. 
  2472.  
  2473.  When a server process creates a named pipe, it defines the pipe to the system 
  2474.  by specifying the file write-through mode, the inheritance mode, the access 
  2475.  and blocking modes, the pipe type, the read mode, the size of the in and out 
  2476.  buffers, and the instance count.  The following list describes these modes, 
  2477.  types, and buffers. 
  2478.  
  2479.      The file write-through mode has significance only for communication with 
  2480.       remote client processes. When the file write-through bit is set, data is 
  2481.       sent across the network as soon as it is written; otherwise, OS/2 will in 
  2482.       some cases hold data briefly in a local buffer before sending it across 
  2483.       the network. 
  2484.  
  2485.      The inheritance mode specifies whether or not the pipe handle will be 
  2486.       inherited by a child process. 
  2487.  
  2488.      The access mode specifies the direction in which data will flow through 
  2489.       the pipe. The server creates an inbound pipe (a pipe with inbound access 
  2490.       mode) if it intends to read data from the client process, an outbound 
  2491.       pipe if it intends to write data to the client process, or a duplex pipe 
  2492.       if it intends to both read from and write to the client process. 
  2493.  
  2494.      The blocking mode specifies whether or not DosRead and DosWrite will 
  2495.       block when no data is available to read, or there is no room to write 
  2496.       data. 
  2497.  
  2498.      The pipe type is the form in which a stream of data is written to the 
  2499.       pipe. If the pipe is a byte pipe, the server and client processes write 
  2500.       data as an undifferentiated stream of bytes. If the pipe is a message 
  2501.       pipe, the processes write data as a stream of messages;  messages are 
  2502.       blocks of data, each with a system-supplied header, that are written as 
  2503.       single units. The server and client processes define the size and format 
  2504.       of a message. 
  2505.  
  2506.      The read mode is the form in which data is read from the pipe. The data 
  2507.       in a pipe that was created as a byte pipe can only be read as bytes; 
  2508.       therefore, a byte pipe will always be in byte-read mode. The data in a 
  2509.       message pipe, however, can be read either as messages or as bytes.  (If 
  2510.       it is to be read as bytes, DosRead skips over the message headers). 
  2511.       Therefore, message pipes can be in either message-read mode or byte-read 
  2512.       mode. 
  2513.  
  2514.       Note:  The terms "byte pipe" and "message pipe" always refer to the pipe 
  2515.              type-the form in which data is written to the pipe. When the read 
  2516.              mode of a pipe is being referred to, it is always explicitly 
  2517.              identified as either message-read mode or byte-read mode. 
  2518.  
  2519.      The in and out buffers can be up to 64KB in size. If the pipe will be 
  2520.       read in message-read mode, and if the message size is known, the server 
  2521.       can control how many messages the buffer will hold at one time by 
  2522.       specifying the appropriate buffer size. 
  2523.  
  2524.      The instance count is the maximum number of instances of the named pipe 
  2525.       that can be created. A pipe instance is actually a separate pipe-that is, 
  2526.       a unique set of pipe buffers with unique handles. However, the term "pipe 
  2527.       instance" is used to distinguish pipes that share the same name from 
  2528.       pipes with different names. Because a client process uses only the name 
  2529.       of the pipe when opening it, the existence of multiple pipe instances is 
  2530.       transparent to a client process. 
  2531.  
  2532.  Creating Multiple Instances of a Named Pipe 
  2533.  Although each named pipe must have a unique name, a server process can create 
  2534.  multiple instances of a pipe, all of which have the same name. A pipe instance 
  2535.  is actually a separate pipe-that is, a unique set of pipe buffers with unique 
  2536.  handles. 
  2537.  
  2538.  The ability to create multiple pipe instances enables the server to 
  2539.  communicate with multiple client processes at the same time. Because a client 
  2540.  process uses only the name of the pipe when opening it, the existence of 
  2541.  multiple pipe instances is transparent to a client process. 
  2542.  
  2543.  The ICount parameter of DosCreateNPipe specifies the maximum number of named 
  2544.  pipe instances that can be created. (An unlimited number can also be 
  2545.  specified.) This parameter is specified only when the first instance of a 
  2546.  named pipe is created; any subsequent attempt to redefine the instance count 
  2547.  will be ignored. 
  2548.  
  2549.  If the instance count is greater than 1, the server process can create 
  2550.  additional pipe instances by specifying the same pipe name in subsequent calls 
  2551.  to DosCreateNPipe. Generally, the attributes of the subsequent pipe instances 
  2552.  are defined to be the same as those of the original pipe instance, because a 
  2553.  client process that requests the pipe has no way of controlling which pipe 
  2554.  instance will be assigned to it. 
  2555.  
  2556.  After an additional pipe instance has been created, it is used in the same 
  2557.  manner as the original pipe instance.  That is, the same sequence of named 
  2558.  pipe functions is used in the control or management of all named pipe 
  2559.  instances. (See Steps in Managing Server-Client Transactions for more 
  2560.  information.) 
  2561.  
  2562.  Note:  If all of the instances of a named pipe are in use when a client calls 
  2563.         DosOpen, ERROR_PIPE_BUSY is returned. However, the client can wait for 
  2564.         an instance of that pipe to become available by calling DosWaitNPipe. 
  2565.  
  2566.  Multiple instances of a named pipe can be created by different processes. That 
  2567.  is, multiple server processes can create and use instances of the same named 
  2568.  pipe to communicate with their clients. 
  2569.  
  2570.  
  2571. ΓòÉΓòÉΓòÉ 4.3.2. Opening Named Pipes ΓòÉΓòÉΓòÉ
  2572.  
  2573. A client process can open the client end of a named pipe by using DosOpen. 
  2574. DosOpen opens the client end of a pipe by name and returns a handle. The 
  2575. application must use the appropriate pipe name and access modes to open the 
  2576. pipe for reading, writing, or both. (To open a pipe on a remote computer, the 
  2577. client process must also specify the name of the computer system as part of the 
  2578. pipe name, as follows: 
  2579.  
  2580.     \\ComputerName\PIPE\PipeName.)
  2581.  
  2582. If a pipe name includes a remote LAN server name, DosOpen attempts to open the 
  2583. pipe on a remote computer. The server process can then read input from the 
  2584. client process through the pipe. 
  2585.  
  2586. The following code fragment opens a remote pipe, reads from the standard input 
  2587. (usually the keyboard), and sends the information to the server process through 
  2588. the pipe: 
  2589.  
  2590.     #define INCL_DOSQUEUES   /* Queue values          */
  2591.     #include <os2.h>
  2592.  
  2593.     #define PIPESIZE 256
  2594.     #define SERVER_PIPE_NAME "\\\\myserver\\pipe\\mypipe"
  2595.     #define HF_STDIN 0       /* Standard input handle */
  2596.  
  2597.     HPIPE   hp;
  2598.     BYTE    abBuf[PIPESIZE];
  2599.     ULONG   ulAction, ulRead, ulWritten;
  2600.     APIRET  ulrc;
  2601.  
  2602.     ulrc = DosOpen(SERVER_PIPE_NAME,
  2603.                    &hp,
  2604.                    &ulAction,
  2605.                    0,
  2606.                    FILE_NORMAL,
  2607.                    FILE_OPEN,
  2608.                    OPEN_ACCESS_READWRITE |
  2609.                    OPEN_SHARE_DENYNONE,
  2610.                    (PEAOP) NULL);
  2611.  
  2612.     if (ulrc)
  2613.         DosExit(EXIT_PROCESS,
  2614.                 0);                    /* Open pipe failed      */
  2615.  
  2616.     do {                               /* Open pipe succeeded   */
  2617.         DosRead(HF_STDIN,
  2618.                 abBuf,
  2619.                 sizeof(abBuf),
  2620.                 &ulRead);
  2621.  
  2622.         DosWrite(hp,
  2623.                  abBuf,
  2624.                  ulRead,
  2625.                  &ulWritten);     /* Writes to the pipe    */
  2626.     } while (ulRead > 2);         /* Stop on a blank line  */
  2627.  
  2628.     DosClose(hp);
  2629.  
  2630. The client process checks the return value from DosOpen to verify that the pipe 
  2631. was actually opened. If the server process has not yet created the pipe, 
  2632. DosOpen returns an error. When the client process finishes using the pipe, it 
  2633. closes the pipe by using DosClose. 
  2634.  
  2635. When a named pipe is opened, its initial state is set by the system to block 
  2636. read and write operations (blocking mode), and to read data as a byte stream 
  2637. (byte-read mode). However, the client can change these modes by calling 
  2638. DosSetNPHState. A call to DosOpen fails if all instances of the named pipe are 
  2639. already open. 
  2640.  
  2641. The open also fails if the pipe has been closed by a client, but the server has 
  2642. not called DosDisConnectNPipe (to acknowledge the client's close), followed by 
  2643. DosConnectNPipe (to prepare the pipe for the next client). In both of these 
  2644. situations, ERROR_PIPE_BUSY is returned. 
  2645.  
  2646. If all instances of a named pipe are busy, a client process can call 
  2647. DosWaitNPipe to wait for an instance to become available before it calls 
  2648. DosOpen again. 
  2649.  
  2650. After a pipe instance has been opened by a client, that same instance cannot be 
  2651. opened by another client at the same time.  However, the opening process can 
  2652. duplicate the handle as many times as desired by calling DosDupHandle. This 
  2653. enables child processes to share access to a pipe instance with a parent 
  2654. process. 
  2655.  
  2656. The access-mode and sharing-mode fields that are specified for DosOpen must be 
  2657. the same as those that were specified by the server when it created the pipe 
  2658. with DosCreateNPipe. 
  2659.  
  2660.  
  2661. ΓòÉΓòÉΓòÉ 4.3.3. Reading from Named Pipes ΓòÉΓòÉΓòÉ
  2662.  
  2663. Both the server and the client processes read data from a pipe by calling 
  2664. DosRead. The server reads from the handle that was returned when it created the 
  2665. pipe with DosCreateNPipe, and the client reads from the handle that was 
  2666. returned to it by DosOpen. 
  2667.  
  2668. When a pipe is created, the PipeMode parameter is used to specify both the pipe 
  2669. type and the read mode for the server end of the pipe: 
  2670.  
  2671.      A byte pipe can be read-only in byte-read mode. (DosCreateNPipe and 
  2672.       DosSetNPHState return ERROR_INVALID_PARAMETER if message-read mode is 
  2673.       specified for a byte pipe.) In byte-read mode, all currently available 
  2674.       data is returned, up to the buffer size specified by DosRead. 
  2675.  
  2676.      A message pipe can be read in either byte-read mode or message-read mode, 
  2677.       as follows: 
  2678.  
  2679.         -  When a message pipe is read in byte-read mode, the message headers 
  2680.            are skipped, and the pipe is read as if it were a byte pipe. 
  2681.  
  2682.         -  When a message pipe is read in message-read mode, each message is 
  2683.            read either in its entirety, or not at all, depending on the size of 
  2684.            the message and the buffer length: 
  2685.  
  2686.              -- If the buffer length that was specified for DosRead is larger 
  2687.                 than the next available message, then only that message is 
  2688.                 read, and the Bytes-Read parameter indicates the size of the 
  2689.                 message. 
  2690.  
  2691.              -- If the buffer length for DosRead is smaller than the next 
  2692.                 available message, DosRead returns the number of bytes 
  2693.                 requested and ERROR_MORE_DATA. Subsequent calls to DosRead are 
  2694.                 blocked until the rest of the message can be transferred. 
  2695.                 (DosPeekNPipe can be used to find out how many bytes are left 
  2696.                 in the message.) 
  2697.  
  2698.  The PipeMode parameter of DosCreateNPipe also specifies the blocking mode for 
  2699.  the server end of the pipe: 
  2700.  
  2701.      If nonblocking mode was specified, DosRead returns immediately with 0 in 
  2702.       the Bytes-Read parameter if no data is available. 
  2703.  
  2704.      If blocking mode was specified, DosRead blocks until data is available; 
  2705.       the only time it will return with 0 in the Bytes-Read parameter is if it 
  2706.       reaches end-of-file. 
  2707.  
  2708.  DosRead works the same for both ends of the pipe. However, the read mode and 
  2709.  blocking mode are not necessarily the same for the client end of the pipe as 
  2710.  they are for the server end, because DosOpen always opens the CLIENT end in 
  2711.  byte-read mode and blocking mode. 
  2712.  
  2713.  The read mode and blocking mode for either end of the pipe can be changed by 
  2714.  calling DosSetNPHState. The pipe type, however, is always the same for both 
  2715.  the server and client ends of the pipe, and it cannot be changed. 
  2716.  
  2717.  
  2718. ΓòÉΓòÉΓòÉ 4.3.4. Writing to Named Pipes ΓòÉΓòÉΓòÉ
  2719.  
  2720. Both the server and the client processes write to a pipe by calling DosWrite. 
  2721. The server writes to the handle that was returned to it by DosCreateNPipe, and 
  2722. the client writes to the handle that was returned to it by DosOpen. 
  2723.  
  2724. Either bytes or messages can be written, depending on whether the pipe was 
  2725. created as a byte pipe or as a message pipe. 
  2726.  
  2727. Named pipes created with the NP_ACCESS_OUTBOUND access mode cannot use the 
  2728. DosWrite function. If the named pipe's client uses the DosWrite function, the 
  2729. function returns error code 5 (ERROR_ACCESS_DENIED). 
  2730.  
  2731. An attempt to write to a pipe whose other end has been closed returns 
  2732. ERROR_BROKEN_PIPE or, if the other end was closed without without reading all 
  2733. pending data, ERROR_DISCARDED. 
  2734.  
  2735. When a process writes to a message pipe, the buffer-length parameter for 
  2736. DosWrite holds the size of the message that the process is writing. Because 
  2737. DosWrite automatically encodes message lengths in the pipe, applications do not 
  2738. have to encode this information in the data buffers. 
  2739.  
  2740. The action taken by DosWrite depends on the blocking mode of the pipe, which is 
  2741. not necessarily the same for the server and client ends of the pipe. For the 
  2742. server process, the blocking mode of the pipe is specified when the pipe is 
  2743. created. For a client process, the blocking mode is automatically set to 
  2744. blocking when the pipe is opened. The blocking mode can also be reset by 
  2745. calling DosSetNPHState. 
  2746.  
  2747. If the end of the message pipe that is being written to is in blocking mode, 
  2748. DosWrite does not return until all of the requested bytes have been written. 
  2749. (It might have to wait for the first part of the message to be read before it 
  2750. can write the rest of the message.) 
  2751.  
  2752. If the message pipe is in nonblocking mode, DosWrite takes the following 
  2753. action: 
  2754.  
  2755.      If the message is larger than the pipe buffer, DosWrite blocks until the 
  2756.       entire message has been written. (Again, it might have to wait for the 
  2757.       first part of the message to be read before it can write the rest of the 
  2758.       message.) 
  2759.  
  2760.      If the message is smaller than the pipe buffer, but there is currently 
  2761.       not enough room in the buffer, DosWrite returns with a value of 0 in the 
  2762.       Bytes-Written parameter. 
  2763.  
  2764.  If a byte pipe is in nonblocking mode, and if there is more data to be written 
  2765.  than will fit in the pipe buffer, then DosWrite writes as many bytes as will 
  2766.  fit in the buffer and returns the number of bytes that were actually written. 
  2767.  
  2768.  If a process tries to write to a pipe whose other end is closed, 
  2769.  ERROR_BROKEN_PIPE is returned. 
  2770.  
  2771.  
  2772. ΓòÉΓòÉΓòÉ 4.3.5. Synchronizing Named Pipe Dialogs ΓòÉΓòÉΓòÉ
  2773.  
  2774. Communicating processes can synchronize their named pipe dialogs by calling 
  2775. DosResetBuffer after each call to DosWrite. 
  2776.  
  2777. When used with external files, DosResetBuffer flushes the buffer cache of the 
  2778. requesting process to disk. When used with named pipes, this function blocks 
  2779. the calling process at one end of the pipe until the data the calling process 
  2780. has written to the pipe has been successfully read at the other end of the 
  2781. pipe. 
  2782.  
  2783.  
  2784. ΓòÉΓòÉΓòÉ 4.3.6. Determining Pipe Status ΓòÉΓòÉΓòÉ
  2785.  
  2786. DosQueryNPHState and DosQueryNPipeInfo can be used to obtain information about 
  2787. named pipes. 
  2788.  
  2789. DosQueryNPHState 
  2790. A client process can read data from the pipe, write data to the pipe, or both, 
  2791. depending on the access mode specified when the pipe was created. To check the 
  2792. current access mode, the client process can call DosQueryNPHState. 
  2793.  
  2794. The following code fragment shows how to use DosQueryNPHState to obtain 
  2795. information about a named pipe: 
  2796.  
  2797.     #define INCL_DOSNMPIPES   /* Named-pipe values */
  2798.     #include <os2.h>
  2799.     #include <stdio.h>
  2800.  
  2801.     HPIPE    hpHandle;            /* Pipe handle       */
  2802.     ULONG    ulPipeHandleState;   /* Pipe-handle state */
  2803.     APIRET   ulrc;                /* Return code       */
  2804.  
  2805.     ulrc = DosQueryNPHState(hpHandle, &ulPipeHandleState);
  2806.  
  2807.     if (ulrc != 0) {
  2808.         printf("DosQueryNPHState error: return code = %ld",
  2809.                ulrc);
  2810.         return;
  2811.     }
  2812.  
  2813. On successful return, PipeHandleState will contain information that describes 
  2814. the nature of the named pipe. 
  2815.  
  2816. DosQueryNPHState returns the following information about the pipe handle and 
  2817. the attributes of the pipe: 
  2818.  
  2819.      The end of the pipe that the handle is for (server or client end) 
  2820.  
  2821.      The pipe type (byte pipe or message pipe) 
  2822.  
  2823.      The instance count 
  2824.  
  2825.      The blocking mode (blocking or nonblocking) 
  2826.  
  2827.      The read mode (byte-read mode or message-read mode) 
  2828.  
  2829.  The values for pipe type and instance count cannot be changed, so they are 
  2830.  always the same as those that were specified when the pipe was created with 
  2831.  DosCreateNPipe. The information returned for blocking mode and read mode, 
  2832.  however, can come from different sources: 
  2833.  
  2834.      If the handle is for the server end of the pipe, then the blocking mode 
  2835.       and the read mode were set with DosCreateNPipe, but could have been reset 
  2836.       with DosSetNPHState. 
  2837.  
  2838.      If the handle is for the client end of the pipe, then the blocking mode 
  2839.       and the read mode were set to "blocking" and "byte-read" by the system 
  2840.       when the client called DosOpen. However, again, they could have been 
  2841.       reset with DosSetNPHState. 
  2842.  
  2843.  The pipe attributes are described in more detail in Creating Named Pipes. 
  2844.  
  2845.  An application can use DosSetNPHState to change the wait mode and the read 
  2846.  mode. The pipe cannot be changed to no-wait mode when another thread is 
  2847.  blocked on a read or write operation to the same end of the pipe. 
  2848.  
  2849.  DosQueryNPipeInfo 
  2850.  More detailed information about a named pipe can be obtained by using 
  2851.  DosQueryNPipeInfo. This function returns information in a PIPEINFO data 
  2852.  structure that includes the name of the pipe, the current and maximum instance 
  2853.  counts (the current number of pipes and the maximum number of times the pipe 
  2854.  can be created), the size of the input and output buffers for the pipe, and 
  2855.  the pipe identifier of the client process. 
  2856.  
  2857.  The following code fragment shows how to use DosQueryNPipeInfo: 
  2858.  
  2859.       #define INCL_DOSNMPIPES   /* Named-pipe values */
  2860.       #include <os2.h>
  2861.       #include <stdio.h>
  2862.  
  2863.       HPIPE    hpHandle;          /* Pipe handle                     */
  2864.       ULONG    ulInfoLevel;       /* Pipe data required              */
  2865.       PIPEINFO pipInfoBuf;        /* Pipe information data structure */
  2866.       ULONG    ulInfoBufSize;     /* Pipe data-buffer size           */
  2867.       APIRET   ulrc;              /* Return code                     */
  2868.  
  2869.       ulInfoLevel = 1;                    /* Ask for standard level of pipe info */
  2870.  
  2871.       ulInfoBufSize = sizeof(PIPEINFO);   /* Length of pipe info data structure  */
  2872.  
  2873.       ulrc = DosQueryNPipeInfo(hpHandle,
  2874.                                ulInfoLevel,
  2875.                                &pipInfoBuf,
  2876.                                ulInfoBufSize);
  2877.  
  2878.       if (ulrc != 0) {
  2879.           printf("DosQueryNPipeInfo error: return code = %ld",
  2880.                  ulrc);
  2881.           return;
  2882.       }
  2883.  
  2884.  On successful return, the pipe information data structure contains a set of 
  2885.  information describing the nature and the current state of the named pipe. 
  2886.  
  2887.  DosQueryNPipeInfo returns level 1 or level 2 file information for the pipe. 
  2888.  Level 1 information includes the following: 
  2889.  
  2890.      The actual sizes of the in-buffer and out-buffer 
  2891.  
  2892.      The maximum number of pipe instances permitted 
  2893.  
  2894.      The current number of pipe instances 
  2895.  
  2896.      The length of the pipe name 
  2897.  
  2898.      The ASCIIZ name of the pipe, including \\ComputerName if the pipe is in a 
  2899.       remote computer system. 
  2900.  
  2901.       Level 2 information consists of a unique 2-byte identifier for each of 
  2902.       the pipe's client processes. 
  2903.  
  2904.  
  2905. ΓòÉΓòÉΓòÉ 4.3.7. Examining the Contents of Named Pipes ΓòÉΓòÉΓòÉ
  2906.  
  2907. DosPeekNPipe examines the current contents of a named pipe. 
  2908.  
  2909. Named pipes created with the NP_ACCESS_INBOUND access mode cannot use the 
  2910. DosPeekNPipe function. If the named pipe's client uses the DosPeekNPipe 
  2911. function, the function returns error code 5 (ERROR_ACCESS_DENIED). 
  2912.  
  2913. It is similar to DosRead, except that DosPeekNPipe does not remove data from 
  2914. the pipe. In addition, DosPeekNPipe never blocks, even if the pipe is in 
  2915. blocking mode; if the pipe cannot be accessed immediately, ERROR_PIPE_BUSY is 
  2916. returned. 
  2917.  
  2918. Because DosPeekNPipe does not block, it returns only what is currently in the 
  2919. pipe. Thus, if a message pipe is being examined, only a portion of a message 
  2920. might be returned, even though the specified buffer length could accommodate 
  2921. the entire message. 
  2922.  
  2923. DosPeekNPipe also returns the state of the pipe. A named pipe can be in any of 
  2924. the following states: Connected, Disconnected, Listening, Closing. 
  2925.  
  2926. The following code fragment shows how to use DosPeekNPipe: 
  2927.  
  2928.     #define INCL_DOSNMPIPES   /* Named-pipe values */
  2929.     #include <os2.h>
  2930.     #include <stdio.h>
  2931.  
  2932.     HPIPE              hpHandle;      /* Pipe handle                */
  2933.     UCHAR              ucBuffer[200]; /* Address of user buffer     */
  2934.     ULONG              ulBufferLen;   /* Buffer length              */
  2935.     ULONG              ulBytesRead;   /* Bytes read (returned)      */
  2936.     struct _AVAILDATA  BytesAvail;    /* Bytes available (returned) */
  2937.     ULONG              ulPipeState;   /* Pipe state (returned)      */
  2938.     APIRET             ulrc;          /* Return code                */
  2939.  
  2940.     ulBufferLen = 200;  /* Length of the read buffer */
  2941.  
  2942.     ulrc = DosPeekNPipe(hpHandle,
  2943.                         ucBuffer,
  2944.                         ulBufferLen,
  2945.                         &ulBytesRead,
  2946.                         &BytesAvail,
  2947.                         &ulPipeState);
  2948.  
  2949.     if (ulrc != 0) {
  2950.         printf("DosPeekNPipe error: return code = %ld",
  2951.                ulrc);
  2952.         return;
  2953.     }
  2954.  
  2955. On successful return, the input buffer Buffer will contain up to the first 200 
  2956. bytes from the named pipe, BytesRead will contain the number of bytes read into 
  2957. Buffer, BytesAvail will contain the total number of bytes that were available 
  2958. in the pipe, and PipeState will contain a value indicating the state of the 
  2959. named pipe. 
  2960.  
  2961.  
  2962. ΓòÉΓòÉΓòÉ 4.3.8. Closing Named Pipes ΓòÉΓòÉΓòÉ
  2963.  
  2964. DosClose closes the specified pipe handle. When all of the handles that access 
  2965. one end of a pipe have been closed, the pipe is referred to as a broken pipe. 
  2966.  
  2967. If the client end of the pipe closes, no other process can reopen the pipe 
  2968. until the server calls DosDisConnectNPipe (to acknowledge the client's close) 
  2969. followed by DosConnectNPipe (to prepare the pipe for a new client). Until it 
  2970. calls DosDisConnectNPipe, the server will receive ERROR_EOF if it tries to read 
  2971. from the pipe, and ERROR_BROKEN_PIPE if it tries to write to it. Clients that 
  2972. attempt to open the pipe receive ERROR_PIPE_BUSY. 
  2973.  
  2974. If the server end closes when the client end is already closed, the pipe is 
  2975. deallocated immediately; otherwise, the pipe is not deallocated until the last 
  2976. client handle is closed. 
  2977.  
  2978. The following code fragment shows how to close a named pipe.  Assume that a 
  2979. previous call to DosOpen provided the named pipe handle that is contained in 
  2980. Handle. 
  2981.  
  2982.     #define INCL_DOSNMPIPES   /* Named-pipe values */
  2983.     #include <os2.h>
  2984.     #include <stdio.h>
  2985.  
  2986.     HPIPE   hpHandle;      /* Pipe handle */
  2987.     APIRET  ulrc;          /* Return code */
  2988.  
  2989.     ulrc = DosDisConnectNPipe(hpHandle);
  2990.  
  2991.     if (ulrc != 0) {
  2992.         printf("DosDisConnectNPipe error: return code = %ld",
  2993.                ulrc);
  2994.         return;
  2995.     }
  2996.  
  2997.  
  2998. ΓòÉΓòÉΓòÉ 5. Program Execution Control ΓòÉΓòÉΓòÉ
  2999.  
  3000. Multitasking is the ability of OS/2 to manage the execution of more than one 
  3001. application at a time. A multitasking operating system, such as OS/2 enables 
  3002. users to run many applications simultaneously. 
  3003.  
  3004. For the programmer, OS/2 supports two types of multitasking. An application can 
  3005. start other programs, in separate processes, that will execute concurrently 
  3006. with the application. These programs can be a new copy of the application, a 
  3007. related program that is designed to work with the application, or an unrelated 
  3008. program. Running multiple processes is the first type of multitasking provided 
  3009. for programmers. 
  3010.  
  3011. Running multiple threads is the second type of multitasking supported by OS/2. 
  3012. OS/2 enables applications to run multiple threads of execution within the same 
  3013. process; separate activities can be multitasked within the application. An 
  3014. example of multiple-thread multitasking would be for the application to 
  3015. dispatch a separate subroutine to load a file from the disk, and have the 
  3016. subroutine execute at the same time the main program continues to monitor and 
  3017. respond to user input. 
  3018.  
  3019. This chapter describes processes, threads, and sessions, and the OS/2 functions 
  3020. used to create and manage them. Additionally, there is a section describing CPU 
  3021. scheduling. 
  3022.  
  3023. The following topics are related to the information in this chapter: 
  3024.  
  3025.      Memory 
  3026.      Semaphores 
  3027.      Queues 
  3028.      Pipes 
  3029.      Exception handling 
  3030.      Debugging 
  3031.  
  3032.  
  3033. ΓòÉΓòÉΓòÉ 5.1. About Program Execution Control-Thread, Processes, and Sessions ΓòÉΓòÉΓòÉ
  3034.  
  3035. To successfully use multitasking-multiple processes and multiple threads-in 
  3036. your programs, you need to understand the difference between a thread, a 
  3037. process, and a session. 
  3038.  
  3039. A thread is a dispatchable unit of execution that consists of a set of 
  3040. instructions, related CPU register values, and a stack. Each process has at 
  3041. least one thread, called the main thread or thread 1, and can have many threads 
  3042. running simultaneously. The application runs when OS/2 gives control to a 
  3043. thread in the process. The thread is the basic unit of execution scheduling. 
  3044.  
  3045. A process is the code, data, and other resources-such as file handles, 
  3046. semaphores, pipes, queues, and so on-of an application in memory. OS/2 
  3047. considers every application it loads to be a process. System resources are 
  3048. allocated on a per-process basis. 
  3049.  
  3050. A session is one (or more) processes with their own virtual console. (A virtual 
  3051. console is a virtual screen-either a character-based, full screen or a 
  3052. Presentation Manager window-and buffers for keyboard and mouse input.) 
  3053.  
  3054. OS/2 supports up to 255 concurrent sessions and up to 4095 processes. OS/2 
  3055. supports a system-wide maximum of 4095 threads, but the number of threads 
  3056. available in a single process will be lower, and will vary, because of resource 
  3057. usage within the process. 
  3058.  
  3059.  
  3060. ΓòÉΓòÉΓòÉ 5.1.1. Threads ΓòÉΓòÉΓòÉ
  3061.  
  3062. Applications always have at least one thread of execution-thread 1. Using 
  3063. multiple threads of execution, an application can do several things at the same 
  3064. time. 
  3065.  
  3066. For example, a simple Presentation Manager application consists of a single 
  3067. process with two threads: 
  3068.  
  3069.      A user interface thread that listens and responds to user requests, and 
  3070.       that queues work for the second thread 
  3071.  
  3072.      A processing thread that handles lengthy processing 
  3073.  
  3074.  OS/2 creates the first thread of execution for a process when it starts the 
  3075.  executable file. To create another thread of execution, a thread calls 
  3076.  DosCreateThread, specifying the address within the program module where the 
  3077.  thread begins asynchronous execution. Although a thread can execute any part 
  3078.  of the application, including a part being executed by another thread, threads 
  3079.  typically are used to execute separate sections of the application. By using 
  3080.  several threads, the system can distribute the available CPU time and enable 
  3081.  an application to carry out several tasks simultaneously. For example, an 
  3082.  application can load a file and prompt the user for input at the same time. 
  3083.  
  3084.  Each thread in a process has a unique stack and register context. Threads 
  3085.  shares the resources of the process with the other threads in the process. For 
  3086.  example, threads in the same process have access to the memory spaces of other 
  3087.  threads within the process. However, threads of one process do not have access 
  3088.  to the data spaces of other processes. 
  3089.  
  3090.  Each thread has a priority, that determines the amount of CPU time the thread 
  3091.  is allocated. Threads inherit the priority of the thread that creates them. 
  3092.  The priority of a thread can be changed by the application; see Changing the 
  3093.  Priority of a Thread for details. 
  3094.  
  3095.  An application can use DosSuspendThread and DosResumeThread to suspend and 
  3096.  resume the execution of a given thread. When an application suspends a thread, 
  3097.  the thread remains suspended until the application calls DosResumeThread. 
  3098.  
  3099.  When an application has more than one thread, it might be necessary to ensure 
  3100.  that one thread is finished executing before another thread uses a shared 
  3101.  resource, such as a disk file. DosWaitThread causes the application to wait 
  3102.  until a specific thread has finished. DosWaitThread can also be used to 
  3103.  determine the state of a thread; the function can return immediately with an 
  3104.  error value if the identified thread is still running. 
  3105.  
  3106.  A thread ends when it calls DosExit. 
  3107.  
  3108.  
  3109. ΓòÉΓòÉΓòÉ 5.1.2. Processes ΓòÉΓòÉΓòÉ
  3110.  
  3111. An OS/2 application that has been loaded into memory and prepared for execution 
  3112. is called a process. As mentioned earlier, a process consists of the code, 
  3113. data, and other resources (for example, open file handles) that belong to the 
  3114. application. Each process has at least one thread, called the main thread or 
  3115. thread 1. 
  3116.  
  3117. When OS/2 runs an application, it confirms that the process code and data are 
  3118. in memory and that the main thread's registers and stack are set before 
  3119. starting the application. Each application has access to all resources of the 
  3120. computer, such as memory, disk drives, screen, keyboard, and the CPU itself. 
  3121. The system carefully manages these resources so that applications can access 
  3122. them without conflict. 
  3123.  
  3124. A process can have more than one thread. OS/2 creates the first thread of 
  3125. execution for a process when it starts the executable file. More threads can be 
  3126. created with DosCreateThread. Each thread runs independently, with its own 
  3127. stack and register values. Unless the application changes a thread's priority, 
  3128. each thread gets a slice of the CPU in a round-robin strategy. All the threads 
  3129. in a process share the application's globally defined variables and other 
  3130. resources (open file handles, and so on). 
  3131.  
  3132. A process or thread ends when it calls DosExit. OS/2 automatically closes any 
  3133. files or other resources left open by the process when the process ends. When a 
  3134. thread ends, however, any open resources remain open until another thread 
  3135. closes them or the process ends. A process can direct OS/2 to carry out other 
  3136. actions when the process ends, by using DosExitList to create a list of 
  3137. termination functions. OS/2 calls the termination functions, in the order 
  3138. given, when the process is about to end. If the thread has registered any 
  3139. exception handlers, the exception handlers will also be called before the 
  3140. thread ends. 
  3141.  
  3142.  
  3143. ΓòÉΓòÉΓòÉ 5.1.2.1. Creating Processes ΓòÉΓòÉΓòÉ
  3144.  
  3145. An application can load and execute other applications by using DosExecPgm. The 
  3146. new application, once loaded, is called a child process. The process that 
  3147. starts the new application is called the parent process. 
  3148.  
  3149. A child process is like any other process. It has its own code, data, and 
  3150. threads. The child process inherits the resources-such as file handles, pipes, 
  3151. and queues-that belong to the parent process at the time the child process is 
  3152. created, although not necessarily with the same access rights. The parent 
  3153. process can place restrictions on the access of the child process to these 
  3154. resources: 
  3155.  
  3156.      Files are inherited except for files that were opened with no inheritance 
  3157.       indicated. 
  3158.  
  3159.      Pipes are inherited. 
  3160.  
  3161.  Assuming that the parent process gives the child process appropriate access 
  3162.  rights, the child process can use the inherited resources without preparing 
  3163.  them. For example, if the parent process opens a file for reading and then 
  3164.  starts a child process, the child process can read from the file immediately; 
  3165.  it does not have to open the file. However, once the child process is created 
  3166.  additional resources that the parent process creates are not available to the 
  3167.  child process. Similarly, resources the child process creates are not 
  3168.  available to the parent process. 
  3169.  
  3170.  The parent process also has control over the meanings of standard input, 
  3171.  output, and error for the child process. For example, the parent can write a 
  3172.  series of records to a file, open the file as standard input, open a listing 
  3173.  file as standard output, and then execute a sort program that takes its input 
  3174.  from standard input and writes to standard output. 
  3175.  
  3176.  Note that memory is not included in the list of things that a child process 
  3177.  can inherit from its parent process. The child process is created with its own 
  3178.  process address space that is separate and distinct from the memory of the 
  3179.  parent process. A new linear address space is built for the new process. The 
  3180.  only way for a parent process and a child process to access the same memory is 
  3181.  to set up a shared memory area. 
  3182.  
  3183.  The executable file of the child process can be started either synchronously 
  3184.  or asynchronously to the parent process. If the parent process starts the 
  3185.  child process running synchronously, the parent process is suspended and waits 
  3186.  until the child process ends before continuing. A child process running 
  3187.  asynchronously executes independently of the parent process (that is, both run 
  3188.  at the same time). The parent process specifies how the child process is to 
  3189.  run by setting a parameter in the call to DosExecPgm. 
  3190.  
  3191.  The OS/2 command processor, CMD.EXE, starts most child processes 
  3192.  synchronously. The parent process waits for each child process to end before 
  3193.  it prompts the user for the next command. The command processor also enables 
  3194.  the user to start asynchronous applications by using the DETACH command. When 
  3195.  the user detaches an application, the command processor starts the application 
  3196.  asynchronously, in the background, and continues to prompt for input. 
  3197.  
  3198.  
  3199. ΓòÉΓòÉΓòÉ 5.1.2.2. Process Termination ΓòÉΓòÉΓòÉ
  3200.  
  3201. A parent process can use DosWaitChild to determine the termination status of a 
  3202. child process that is running independently. The parent process can have one of 
  3203. its threads call DosWaitChild to wait for completion of the child process while 
  3204. other threads of the parent continue processing. 
  3205.  
  3206. If the child has started another process, DosWaitChild waits for the completion 
  3207. of any grandchild processes before returning, but does not report their status. 
  3208. If the specified child process has multiple threads, DosWaitChild returns the 
  3209. result code of the last DosExit request. 
  3210.  
  3211. If there are no child processes, either active or ended with a return code, 
  3212. DosWaitChild returns with an error code. If no child processes have ended, 
  3213. DosWaitChild can optionally wait until one ends before returning to the parent. 
  3214.  
  3215.  
  3216. ΓòÉΓòÉΓòÉ 5.1.2.3. Process Exit Lists ΓòÉΓòÉΓòÉ
  3217.  
  3218. Because any process can end any other process for which it has a process 
  3219. identifier, applications might lose information if a process ends the 
  3220. application before it can save its work. To prevent this loss of data, you can 
  3221. create a list of functions to clean up data and files before OS/2 ends the 
  3222. process. This list is called an exit list. OS/2 maintains an exit list for each 
  3223. process and calls these functions whenever the application is ended, whether by 
  3224. another process or by itself. 
  3225.  
  3226. You call DosExitList to add to the exit list a routine that is to be given 
  3227. control when a process is ended (or finishes its execution). Multiple routines 
  3228. can be added to the list. When the process is ending, OS/2 transfers control to 
  3229. each address on the list. 
  3230.  
  3231. Exit-list functions perform clean-up operations on resources. For example, an 
  3232. exit-list function can be used in a dynamic link library module to free 
  3233. resources or clear flags and semaphores when a client program has ended. 
  3234.  
  3235.  
  3236. ΓòÉΓòÉΓòÉ 5.1.3. Multitasking with Threads and Multitasking with Processes ΓòÉΓòÉΓòÉ
  3237.  
  3238. The creation and termination of a process is relatively slow compared to the 
  3239. creation and termination of a thread, and is more costly in terms of system 
  3240. resources. 
  3241.  
  3242. For example, sharing data and resources between processes requires shared 
  3243. memory and the mechanisms of interprocess communication; threads, on the other 
  3244. hand, have full access to the memory and other resources that belong to the 
  3245. process the threads are part of and can be coordinated using semaphores. For 
  3246. these reasons, thread-to-thread task context switches are faster than 
  3247. process-to-process context switches. 
  3248.  
  3249. Because OS/2 can create and execute threads more quickly than processes, the 
  3250. preferred multitasking method for applications is to distribute tasks among 
  3251. threads in the same process instead of among processes. 
  3252.  
  3253.  
  3254. ΓòÉΓòÉΓòÉ 5.1.4. Sessions ΓòÉΓòÉΓòÉ
  3255.  
  3256. OS/2 uses sessions to help the user move from one application to the next 
  3257. without disrupting the screen display of an application. 
  3258.  
  3259. A session consists of at least one process and a virtual console-buffers for 
  3260. keyboard and mouse input and either a character-based, full screen or a 
  3261. Presentation Manager window. When the system creates a session, the process in 
  3262. the session displays output in the screen or window. The user can view the 
  3263. output and supply input by moving to the session. The user moves to a session 
  3264. by pressing the Alt+Esc key combination, by selecting the title of the session 
  3265. from the Window List, or, for windowed sessions, by clicking the mouse in the 
  3266. session window. 
  3267.  
  3268. A child session is under the control of the session that creates it. The 
  3269. session that starts the child session is called the parent session. Any process 
  3270. in the parent session can exercise control over a child session. 
  3271.  
  3272. An unrelated session is not under the control of the session that started it. 
  3273. The process that creates the unrelated session cannot select it, make it 
  3274. nonselectable, bind it, or end it, nor can any other session. DosStartSession 
  3275. does not even return a session identifier when an unrelated session is started. 
  3276. Unrelated sessions are controlled entirely by the user. When OS/2 starts new 
  3277. sessions, it starts them as unrelated sessions. 
  3278.  
  3279.  
  3280. ΓòÉΓòÉΓòÉ 5.1.4.1. Creating Sessions ΓòÉΓòÉΓòÉ
  3281.  
  3282. A process creates a new session by using DosStartSession. DosStartSession 
  3283. enables an application to start another session and to specify the name of the 
  3284. application to be started in that session. 
  3285.  
  3286. DosStartSession also specifies which of the five session types is to be 
  3287. started: 
  3288.  
  3289.      Full screen, protect mode 
  3290.      Text windowed, protect mode 
  3291.      Presentation Manager (PM) 
  3292.      Full screen DOS Session 
  3293.      Windowed DOS Session 
  3294.  Protect mode applications run in full screen and text windowed sessions, PM 
  3295.  and AVIO applications run in PM windows, and DOS applications run in full 
  3296.  screen DOS Sessions and windowed DOS Sessions. 
  3297.  
  3298.  OS/2 applications running in any of the OS/2 session types-full screen, text 
  3299.  windowed, and PM-can start sessions of any other type, including DOS Sessions. 
  3300.  DOS Session applications cannot start other sessions. 
  3301.  
  3302.  An application can start another process in a separate session when the 
  3303.  application will not manage any I/O done by the process. For example, an 
  3304.  application that starts an unrelated application could start it in a separate 
  3305.  session. 
  3306.  
  3307.  A session can be started as a related or an unrelated session. A related 
  3308.  session is called a child session, and the session starting the child session 
  3309.  is called the parent session. An application can control its child sessions by 
  3310.  using the session identifier returned by DosStartSession with the 
  3311.  DosSetSession, DosSelectSession, and DosStopSession. If an application starts 
  3312.  an unrelated session, the new session cannot be controlled by the application. 
  3313.  The Related field in the STARTDATA structure specifies whether the new session 
  3314.  is related to the session calling DosStartSession. 
  3315.  
  3316.  After a process has started a child session, no other process in its session 
  3317.  can start a child session until all dependent sessions started by this process 
  3318.  have ended. 
  3319.  
  3320.  When a session is created, the title specified in the function call (or the 
  3321.  application name if no title is specified) is added to the Window List. 
  3322.  
  3323.  DosStartSession can be used to start either a foreground or a background 
  3324.  session, but a new session can be started in the foreground only when the 
  3325.  caller's session, or one of the caller's descendant sessions, is currently 
  3326.  executing in the foreground. The foreground session for windowed applications 
  3327.  is the session of the application that owns the window focus. 
  3328.  
  3329.  Termination Queues 
  3330.  The parent session must create a termination queue prior to specifying the 
  3331.  queue name in a call to DosStartSession. OS/2 will continue to notify the 
  3332.  parent session through the specified queue as long as the session calling 
  3333.  DosStartSession remains a parent session. In other words, when all the child 
  3334.  sessions for a particular parent session end, the termination queue is closed 
  3335.  by OS/2. An existing queue name must be specified on the next DosStartSession 
  3336.  call if the caller wants to continue receiving termination notification 
  3337.  messages. 
  3338.  
  3339.  OS/2 writes a data element to the specified queue when any child session ends. 
  3340.  The queue is posted regardless or who ends the child session (the child, the 
  3341.  parent, or the user) and whether the termination is normal or abnormal. 
  3342.  
  3343.  A parent session calls DosReadQueue to receive notification when a child 
  3344.  session has ended. The word that contains the request parameter, returned by 
  3345.  DosReadQueue, will be 0. The data element has the following format: 
  3346.  
  3347.  Termination Queue Element Format 
  3348.  
  3349.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  3350.   ΓöéSize      ΓöéDescription                                       Γöé
  3351.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3352.   ΓöéWORD      ΓöéSession ID of the child session that ended        Γöé
  3353.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3354.   ΓöéWORD      ΓöéResult code                                       Γöé
  3355.   ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  3356.  
  3357.  The process that originally called the DosStartSession request should call 
  3358.  DosReadQueue, with the NOWAIT parameter set to 0. This is the only process 
  3359.  that has addressability to the notification data element. After reading and 
  3360.  processing the data element, the caller must free the segment containing the 
  3361.  data element by calling DosFreeMem. 
  3362.  
  3363.  When a child session ends, the result code returned in the termination queue's 
  3364.  data element is the result code of the program specified in the 
  3365.  DosStartSession call, providing either one of the following is true: 
  3366.  
  3367.      The program was run directly, with no intermediate secondary command 
  3368.       processor 
  3369.  
  3370.      The program is run indirectly through a secondary command processor, and 
  3371.       the /C parameter is specified 
  3372.  
  3373.  When a child session is running in the foreground at the time it ends, the 
  3374.  parent session becomes the new foreground session. When a parent session ends, 
  3375.  any child sessions are ended. When an unrelated session ends in the 
  3376.  foreground, OS/2 selects the next foreground session. 
  3377.  
  3378.  
  3379. ΓòÉΓòÉΓòÉ 5.1.4.2. Child Session Control ΓòÉΓòÉΓòÉ
  3380.  
  3381. A session can be either a child session or an unrelated session. A child 
  3382. session is under the control of the processes in the session that creates it 
  3383. (the parent session). A process can select, set, or stop a child session by 
  3384. using DosSelectSession, DosSetSession, or DosStopSession, respectively. 
  3385. DosStartSession returns a unique session identifier for the child session for 
  3386. use in these functions. 
  3387.  
  3388. A session can run in either the foreground or background. A process can create 
  3389. a foreground session only if the creating process or one of its descendant 
  3390. sessions is executing in the current foreground session. A process can move a 
  3391. child session to the foreground by selecting the child session using the 
  3392. session identifier and calling DosSelectSession. A process can make a child 
  3393. session nonselectable by using DosSetSession to change the SelectInd field in 
  3394. the STATUSDATA structure. This prevents the user from selecting the session 
  3395. from the Window List but does not prevent a process from selecting the child 
  3396. session by using DosSelectSession. 
  3397.  
  3398. A process can bind a child session to its own session by using DosSetSession. 
  3399. Binding a session causes that session to move to the foreground whenever the 
  3400. user selects the parent session from the Window List. 
  3401.  
  3402. A parent session can use a session identifier with the DosSetSession function 
  3403. only if the parent session created the child session associated with that 
  3404. identifier. It cannot use identifiers for child sessions created by other 
  3405. parent processes. This is true for all session management functions. 
  3406.  
  3407. Although a child session is related to the session that started it, the 
  3408. processes in the child and original sessions are not related. This means that 
  3409. even though DosStartSession supplies the process identifier of the process in 
  3410. the child session, the process identifier cannot be used with OS/2 functions 
  3411. such as DosSetPriority. 
  3412.  
  3413.  
  3414. ΓòÉΓòÉΓòÉ 5.1.4.3. Child Session Termination ΓòÉΓòÉΓòÉ
  3415.  
  3416. A parent session can stop a child session by using DosStopSession. Stopping the 
  3417. child session ends the processes in that session. It also stops any sessions 
  3418. related to the child session. If a child session is in the foreground when it 
  3419. is stopped, the parent session becomes the foreground session. DosStopSession 
  3420. breaks any bond that exists between the parent session and the specified child 
  3421. session. 
  3422.  
  3423. A process running in the session specified in the call to DosStopSession can 
  3424. ignore the request to end. If this happens, DosStopSession still returns 0 
  3425. (indicating success). The only way to be certain that the child session has 
  3426. ended is to wait for notification through the termination queue specified in 
  3427. the call to DosStartSession. OS/2 writes a data element into the specified 
  3428. queue when the child session ends. The process in the parent session must call 
  3429. DosReadQueue to retrieve this data element, which contains the session 
  3430. identifier for the child session and the return value for the process in the 
  3431. child session. Only the process that created the child session can read the 
  3432. data element. 
  3433.  
  3434.  
  3435. ΓòÉΓòÉΓòÉ 5.2. About CPU Scheduling ΓòÉΓòÉΓòÉ
  3436.  
  3437. OS/2 performs prioritized, preemptive, multitasking. Prioritized means that 
  3438. OS/2 does not divide CPU time equally among all threads. All programs do not 
  3439. get equal access to the CPU. A prioritizing, time-slicing strategy is used to 
  3440. allocate access to the CPU among competing threads. Each thread has a priority 
  3441. and OS/2 runs the highest priority thread that is ready to run. Programs with 
  3442. higher priorities (a real-time robotic application, for example), are given 
  3443. access to the CPU before programs with lower priorities. If a thread with a 
  3444. higher priority than the currently running thread becomes ready to run, the 
  3445. current thread is stopped immediately, or preempted, and the higher priority 
  3446. thread is given the CPU. The lower priority thread does not get to complete its 
  3447. time slice. Threads of equal priority are given CPU time in a round-robin 
  3448. manner. 
  3449.  
  3450. Preemptive means that the multitasking activity needs no cooperation from the 
  3451. executing programs. OS/2 maintains control over executing programs, and stops, 
  3452. or preempts, them when their time slice with the CPU is over or when a higher 
  3453. priority program is ready to run. 
  3454.  
  3455. CPU scheduling is based on four priority classes-Time Critical, Fixed-High, 
  3456. Regular, and Idle-Time. Each class has 32 levels of execution ordering. 
  3457. Scheduling parameters are user-selectable at the time the system is started or 
  3458. can be varied dynamically based on system load. 
  3459.  
  3460. Depending on a thread's priority class and level, OS/2 periodically gives each 
  3461. thread in each process a small slice of CPU time. Threads with higher 
  3462. priorities always run before threads having lower priorities. A thread runs 
  3463. until its time is up or until a thread with a higher priority is ready to run. 
  3464. At that time, OS/2 preempts the thread and starts another thread. Threads can 
  3465. also voluntarily relinquish the CPU (for example, by calling DosSleep). 
  3466.  
  3467. The amount of time in each time slice is defined by the TIMESLICE command in 
  3468. the CONFIG.SYS file. The TIMESLICE command can be used by the user to customize 
  3469. the size of the time slices that a thread gets. The default is for OS/2 to 
  3470. dynamically vary the size of the time slice based on the activity of the thread 
  3471. and the overall system load. 
  3472.  
  3473. When a thread is created (using DosCreateThread), it inherits the priority of 
  3474. the thread that started it. DosSetPriority enables threads to change their 
  3475. priority classes and levels in response to changes in their execution 
  3476. environments. DosSetPriority enables a thread to change its own priority, or 
  3477. the priority of any thread within its process. DosSetPriority also enables 
  3478. changing priorities for the entire process and for descendant processes. Within 
  3479. each class, the priority level of a thread can vary because of a DosSetPriorty 
  3480. request or, if dynamic priority variation is being used, because of action 
  3481. taken by OS/2. 
  3482.  
  3483.  
  3484. ΓòÉΓòÉΓòÉ 5.2.1. Priority Classes ΓòÉΓòÉΓòÉ
  3485.  
  3486. OS/2 uses four priority classes to determine when a thread receives a time 
  3487. slice: 
  3488.  
  3489. Priority Classes 
  3490.  
  3491. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  3492. ΓöéPriority                      ΓöéDescription                   Γöé
  3493. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3494. ΓöéTime-critical                 ΓöéHighest priority.  For use    Γöé
  3495. Γöé                              Γöéwhen response time is         Γöé
  3496. Γöé                              Γöécritical.                     Γöé
  3497. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3498. ΓöéFixed-high                    ΓöéUsed by threads that provide  Γöé
  3499. Γöé                              Γöéservice to other threads. ThisΓöé
  3500. Γöé                              Γöépriority class is to be used  Γöé
  3501. Γöé                              Γöéwhen it is desirable that the Γöé
  3502. Γöé                              Γöéthread not be too sensitive toΓöé
  3503. Γöé                              Γöéthe foreground/background     Γöé
  3504. Γöé                              Γöéboost provided by dynamic     Γöé
  3505. Γöé                              Γöépriority variation. It is     Γöé
  3506. Γöé                              Γöémeant for programs that need  Γöé
  3507. Γöé                              Γöéto execute before regular     Γöé
  3508. Γöé                              Γöéprograms, but without the     Γöé
  3509. Γöé                              Γöéimmediate response time       Γöé
  3510. Γöé                              Γöérequirement called for by     Γöé
  3511. Γöé                              Γöétime-critical threads.        Γöé
  3512. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3513. ΓöéRegular                       ΓöéDefault priority.  Most       Γöé
  3514. Γöé                              Γöéthreads belong in this class. Γöé
  3515. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3516. ΓöéIdle-time                     ΓöéLowest priority.  This        Γöé
  3517. Γöé                              Γöépriority only gets CPU time   Γöé
  3518. Γöé                              Γöéwhen there is no other work toΓöé
  3519. Γöé                              Γöédo.                           Γöé
  3520. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  3521.  
  3522. A time-critical thread always receives a time slice before a fixed-high thread, 
  3523. a fixed-high thread always receives a time slice before a regular thread, and a 
  3524. regular thread always receives a time slice before an idle-time thread. 
  3525.  
  3526. Time-Critical Threads 
  3527. Time-critical threads have the highest priority class and execute before any 
  3528. fixed-high, regular, or idle-time threads. 
  3529.  
  3530. The time-critical class is for threads that must react to events outside the 
  3531. system. For example, in a communications application, a thread responsible for 
  3532. reading data from the communications device needs enough time to read all 
  3533. incoming data. Because more than a regular time slice might be needed, a 
  3534. time-critical classification ensures that the thread gets all the time 
  3535. required. 
  3536.  
  3537. Time-critical threads have a static priority that is not varied by OS/2. They 
  3538. are scheduled among themselves in priority level order, with round-robin 
  3539. scheduling of threads of equal priority. 
  3540.  
  3541. Time-critical threads must be executed quickly, then free the CPU for other 
  3542. work until another time-critical event occurs. This is important to maintain 
  3543. good interactive responsiveness to the user and enable communications and other 
  3544. time  critical applications to run concurrently. The time-critical activity 
  3545. should, when possible, be in a thread separate from the rest of the 
  3546. application, to isolate and minimize the time spent processing at the 
  3547. time-critical level. A good rule of thumb is that a time-critical thread should 
  3548. consist of no more than about 20,000 assembly language instructions. 
  3549.  
  3550. Fixed-High Threads 
  3551. A fixed-high thread has a priority class that is lower than time-critical but 
  3552. executes before any regular or idle-time threads. This class of threads should 
  3553. be used to provide service for other threads where it is desirable that the 
  3554. thread not be too sensitive to the foreground/background boost provided by 
  3555. dynamic priority variation. A messaging thread, would be a good example of this 
  3556. type of thread. 
  3557.  
  3558. OS/2 varies the priority of a fixed-high thread around a base value according 
  3559. to the activity of the thread and the system at any point in time. The base 
  3560. value can be set by the thread itself. 
  3561.  
  3562. Regular Threads 
  3563. A regular thread is the class that the majority of threads fall into. No 
  3564. explicit action is necessary by the application to run at this priority, it is 
  3565. the default. 
  3566.  
  3567. OS/2 varies the priority level of a regular thread around a base value 
  3568. according to the activity of the thread and the system at any point in time. 
  3569. The base value can be set by the thread itself. 
  3570.  
  3571. Idle-Time Threads 
  3572. An idle-time thread is one with very low priority that executes only when there 
  3573. are no regular, fixed-high, or time-critical threads to execute. Idle-time 
  3574. threads get CPU time only when there is no other work to do. The idle-time 
  3575. class is for threads that need very little CPU time. 
  3576.  
  3577. Idle-time threads have a static priority that is not varied by OS/2. 
  3578.  
  3579.  
  3580. ΓòÉΓòÉΓòÉ 5.2.2. Priority Levels ΓòÉΓòÉΓòÉ
  3581.  
  3582. Within each class, OS/2 maintains a priority level for a thread. For each of 
  3583. the four priority classes, there are 32 priority levels-0 to 31. A thread with 
  3584. priority level 31 always receives a time slice before a thread with priority 
  3585. level 30, and so on. 
  3586.  
  3587. If two or more threads have the same priority level, OS/2 distributes the CPU 
  3588. time equally by using a round-robin scheme; that is, OS/2 gives a time slice to 
  3589. first one, then another, and so on, and then goes back to the first. A thread 
  3590. can use DosSetPriority to change its own priority or the priority of any other 
  3591. thread within its process. 
  3592.  
  3593. Although an application can set the priority level of a thread at any time, 
  3594. only applications that use more than one thread or process should do so. The 
  3595. best use of priority is to speed up threads or processes on which other threads 
  3596. or processes depend. For example, an application might temporarily raise the 
  3597. priority of a thread loading a file if another thread is waiting for that file 
  3598. to be loaded. Because the priority of a thread is relative to all other threads 
  3599. in the system, raising the priority of the threads in an application merely to 
  3600. get the extra CPU time adversely affects the overall operation of the system. 
  3601.  
  3602. There are other ways to affect the amount of CPU time a thread is given. A 
  3603. thread can define a critical section of code by using DosEnterCritSec and 
  3604. DosExitCritSec. While inside the critical section of code, a thread cannot be 
  3605. preempted by any other thread within its process (threads in other processes 
  3606. are still given their time slices). Using critical sections enables threads to 
  3607. get more CPU time, while not unduly affecting the rest of the system. 
  3608.  
  3609. The priority class and priority level are set using DosSetPriority. The 
  3610. priority class is changed by passing the new priority class to the function. 
  3611. The priority level, however, is changed by passing a value, called the 
  3612. priority-delta, that is added to the existing priority level to produce the new 
  3613. priority level; changes to the priority level are relative to the current 
  3614. priority level. Specifying a positive priority-delta increases the priority 
  3615. level, enabling the thread to obtain more CPU time than it normally would. A 
  3616. negative priority-delta decreases the priority level, giving the thread less 
  3617. CPU time than it would normally receive. The value is restricted to the valid 
  3618. range, based upon the current priority class of the process. 
  3619.  
  3620. If you change the priority level without changing the priority class, the 
  3621. priority-delta is relative to the current priority level. However, if you 
  3622. change the priority class at the same time that you change the priority level, 
  3623. the priority-delta value is relative to 0. Whenever DosSetPriority is called 
  3624. with a class specification, but no value is specified for priority-delta, the 
  3625. base priority level defaults to 0. 
  3626.  
  3627. The process identifier parameter of DosSetPriority specifies which process is 
  3628. affected by the call. A process can change the priority of itself, of any 
  3629. process that is a descendant of itself, or of one of its threads. 
  3630.  
  3631. A thread can change the priority of any thread within its current process. When 
  3632. a thread changes the priority of threads in a descendant process, however, only 
  3633. those threads running at the default priority will be changed. You cannot 
  3634. change the priority of a thread in a child process that has already changed its 
  3635. priority from the default. 
  3636.  
  3637. The initial thread of execution for an application is given a regular class 
  3638. priority that varies by the system. When a thread is created, it is initially 
  3639. dispatched in the same class and priority as the thread that started it. A 
  3640. child process inherits the priority of the thread in the parent process that 
  3641. creates it. 
  3642.  
  3643.  
  3644. ΓòÉΓòÉΓòÉ 5.2.3. Priority Guidelines ΓòÉΓòÉΓòÉ
  3645.  
  3646. Within the two most common priority classes-time-critical and regular-there are 
  3647. certain broad guidelines recommended for choosing the priority level for a 
  3648. program. 
  3649.  
  3650.      TIME-CRITICAL CLASS 
  3651.  
  3652.       The guidelines for level within the time critical class are set to 
  3653.       maximize the number of different applications that can successfully 
  3654.       multitask in an OS/2 system. The guidelines are described in the 
  3655.       following table. 
  3656.  
  3657.       Recommended Priority Levels for Time-Critical Threads 
  3658.  
  3659.             ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  3660.             ΓöéActivity            ΓöéRange of RecommendedΓöéJustification/Comments                                      Γöé
  3661.             Γöé                    ΓöéPriority Levels     Γöé                                                            Γöé
  3662.             Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3663.             ΓöéRobotics/Real time  Γöé20-31               ΓöéOS/2 systems can be used on manufacturing lines to control  Γöé
  3664.             Γöéprocess control     Γöé                    Γöéequipment or in other real time process control             Γöé
  3665.             Γöé                    Γöé                    Γöéapplications. In this case a slow response from the PC couldΓöé
  3666.             Γöé                    Γöé                    Γöécause expensive damage to equipment or even human injury.   Γöé
  3667.             Γöé                    Γöé                    ΓöéTherefore the highest priority levels should be reserved forΓöé
  3668.             Γöé                    Γöé                    Γöéthese applications.                                         Γöé
  3669.             Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3670.             ΓöéCommunications      Γöé10-19               ΓöéIn communications, the inability to get the processor could Γöé
  3671.             Γöé                    Γöé                    Γöécause a loss of data or communications sessions. Therefore  Γöé
  3672.             Γöé                    Γöé                    Γöéthis class of applications is next highest.                 Γöé
  3673.             Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3674.             ΓöéOther               Γöé0-09                ΓöéOther threads might need to preempt the foreground in       Γöé
  3675.             Γöé                    Γöé                    Γöéspecial cases (for example, Control-Break). These should be Γöé
  3676.             Γöé                    Γöé                    Γöéset below the other 2 classes.                              Γöé
  3677.             ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  3678.  
  3679.       In general, application performance is not a good reason to make a thread 
  3680.       time critical. 
  3681.  
  3682.      REGULAR CLASS 
  3683.  
  3684.       In cases where explicit priority levels are set, they should follow the 
  3685.       guidelines listed below. 
  3686.  
  3687.       Recommended Priority Levels for Regular Priority Threads 
  3688.  
  3689.             ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  3690.             ΓöéActivity            ΓöéRange of RecommendedΓöéJustification                                     Γöé
  3691.             Γöé                    ΓöéPriority Level      Γöé                                                  Γöé
  3692.             Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3693.             ΓöéCommunications      Γöé26-31               ΓöéCommunications should take priority over other    Γöé
  3694.             Γöé                    Γöé                    Γöébackground processing to increase overlap with    Γöé
  3695.             Γöé                    Γöé                    Γöétransmission and processing on the partner PC or  Γöé
  3696.             Γöé                    Γöé                    Γöéhost.  This gives the best system performance.    Γöé
  3697.             Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3698.             ΓöéOther               Γöé0-25.               ΓöéIf an application has multiple threads it might beΓöé
  3699.             Γöé                    Γöé                    Γöénecessary to set them to several different        Γöé
  3700.             Γöé                    Γöé                    Γöépriorities to optimize the order in which they    Γöé
  3701.             Γöé                    Γöé                    Γöérun. A range of priority levels is provided to    Γöé
  3702.             Γöé                    Γöé                    Γöéfacilitate this. (The default priority is regular Γöé
  3703.             Γöé                    Γöé                    Γöéclass, level = 0.)                                Γöé
  3704.             ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  3705.  
  3706.  
  3707. ΓòÉΓòÉΓòÉ 5.2.4. Dynamic Priority Alteration ΓòÉΓòÉΓòÉ
  3708.  
  3709. OS/2 can be configured to dynamically alter the priority of a process. The 
  3710. PRIORITY statement in CONFIG.SYS can be set to either ABSOLUTE or DYNAMIC. If 
  3711. PRIORITY specifies the ABSOLUTE option, all processes receive CPU time based on 
  3712. the priority established by calls to DosSetPriority. If the PRIORITY command in 
  3713. the CONFIG.SYS file specifies the DYNAMIC option, OS/2 adjusts process 
  3714. priorities based on system load and process activity, and on whether the 
  3715. process is in the foreground. DYNAMIC is the default setting; if the PRIORITY 
  3716. command is not specified, the system uses DYNAMIC priority. DYNAMIC is designed 
  3717. to gives the best overall system performance under most conditions. 
  3718.  
  3719. When dynamic priority variation is enabled, OS/2 grants higher priority to the 
  3720. foreground process than to background processes. System load and process 
  3721. activity are also taken into consideration. The priority of the process 
  3722. consists of a computed priority value that is based upon the display status of 
  3723. the process (foreground or background), and its recent I/O and CPU time usage 
  3724. history. When dynamic priority variation is enabled, I/O priority boosts are 
  3725. generated for keyboard input, window, foreground, processor starvation, device 
  3726. I/O, and DOS Session interrupts. This ensures that the foreground process-the 
  3727. process most likely to be in use-receives enough CPU time to provide quick 
  3728. response to user input. 
  3729.  
  3730. There are times when dynamic priority variation can interfere with a 
  3731. multi-threaded application's execution.  For example, if you are doing a lot of 
  3732. keyboard input on a thread, its priority will get boosted and other threads may 
  3733. not get enough CPU time.  A communication thread is an example of a time 
  3734. sensitive background thread which would be one case.  The solution is to either 
  3735. set PRIORITY = ABSOLUTE or to call DosSetPriority on a regular basis to keep 
  3736. the threads priority at the desired level. 
  3737.  
  3738.  
  3739. ΓòÉΓòÉΓòÉ 5.2.5. Altering the Size of the Time Slice ΓòÉΓòÉΓòÉ
  3740.  
  3741. The TIMESLICE command in CONFIG.SYS sets the minimum and maximum amount of 
  3742. processor time allocated to processes and programs for both OS/2 and DOS 
  3743. sessions. 
  3744.  
  3745. The first parameter selects the minimum TIMESLICE value in milliseconds. This 
  3746. value is the minimum amount of time a thread is to be processed before yielding 
  3747. the processor to a thread of the same priority level. This value must be an 
  3748. integer greater than or equal to 32. 
  3749.  
  3750. The second parameter selects the maximum TIMESLICE value in milliseconds. The 
  3751. value of this parameter is the maximum amount of time a thread can be processed 
  3752. before yielding processor time. This value must be an integer greater than or 
  3753. equal to the minimum value, and less than 65536. 
  3754.  
  3755. The default is dynamic time slicing, which varies the size of the time slice 
  3756. depending on system load and paging activity. Dynamic time slicing is designed 
  3757. to give the best performance in most situations. 
  3758.  
  3759.  
  3760. ΓòÉΓòÉΓòÉ 5.3. Using Processes ΓòÉΓòÉΓòÉ
  3761.  
  3762. An OS/2 application that has been loaded into memory and prepared for execution 
  3763. is called a process. A process is the code, data, and other resources of the 
  3764. application, such as the open file handles, semaphores, pipes, queues and so 
  3765. on. OS/2 considers every application it loads to be a process. 
  3766.  
  3767. Each process has at least one thread, called the main thread or thread 1. The 
  3768. application runs when the system scheduler gives control to a thread in the 
  3769. process. For more on thread management, see Using Threads. 
  3770.  
  3771. Note:  In the example code fragments that follow, error checking was left out 
  3772.        to conserve space. Applications should always check the return code that 
  3773.        the functions return. Control Program functions return an APIRET value. 
  3774.        A return code of 0 indicates success. If a non-zero value is returned, 
  3775.        an error occurred. 
  3776.  
  3777.  
  3778. ΓòÉΓòÉΓòÉ 5.3.1. Starting a Child Process ΓòÉΓòÉΓòÉ
  3779.  
  3780. You start a process by calling DosExecPgm. The process you start is a child of 
  3781. the calling, or parent, process and inherits many of the resources owned by the 
  3782. parent process, such as file handles. 
  3783.  
  3784. DosExecPgm creates a process environment from an executable file. The target 
  3785. program is loaded into storage, and it begins execution. 
  3786.  
  3787. The following code fragment starts an application named ABC: 
  3788.  
  3789.     #define INCL_DOSPROCESS       /* Process and thread values */
  3790.     #include <os2.h>
  3791.  
  3792.     CHAR szFailName[CCHMAXPATH];
  3793.     RESULTCODES resc;
  3794.  
  3795.     DosExecPgm(szFailName,           /* Object-name buffer  */
  3796.                sizeof(szFailName),   /* Length of buffer    */
  3797.                EXEC_SYNC,            /* Sync flag           */
  3798.                (PSZ) NULL,           /* Argument string     */
  3799.                (PSZ) NULL,           /* Environment string  */
  3800.                &resc,                /* Address for result  */
  3801.                "ABC.EXE");           /* Name of application */
  3802.  
  3803. In this example, ABC runs synchronously (as specified by EXEC_SYNC). This means 
  3804. the parent process temporarily stops while the child process runs. The parent 
  3805. process does not continue until the child process ends. 
  3806.  
  3807.  
  3808. ΓòÉΓòÉΓòÉ 5.3.1.1. Starting an Asynchronous Child Process ΓòÉΓòÉΓòÉ
  3809.  
  3810. To start a child process and enable it to run asynchronously (that is, without 
  3811. suspending the parent process until the child process ends), you use the 
  3812. EXEC_ASYNC constant in a call to DosExecPgm. If you start a process in this 
  3813. way, the function copies the process identifier of the child process to the 
  3814. codeTerminate field of the RESULTCODES structure that is returned by 
  3815. DosExecPgm. You can use this process identifier to check the progress of the 
  3816. child process or to end the process. 
  3817.  
  3818. You can also run a child process asynchronously by using DosExecPgm with the 
  3819. EXEC_ASYNCRESULT constant. In addition to causing DosExecPgm to return to the 
  3820. parent process immediately, this constant also directs OS/2 to save a copy of 
  3821. the termination status when the child process ends. This status specifies the 
  3822. reason the child process stopped. The parent process can retrieve the 
  3823. termination status by using DosWaitChild. 
  3824.  
  3825. The following code fragment starts the program SIMPLE.EXE, and then waits for 
  3826. it to finish. It then prints the termination code and the return code. 
  3827.  
  3828.     #define INCL_DOSPROCESS       /* Process and thread values */
  3829.     #include <os2.h>
  3830.     #include <stdio.h>
  3831.  
  3832.     #define START_PROGRAM "SIMPLE.EXE"
  3833.  
  3834.     CHAR         szLoadError[100];
  3835.     PSZ          pszArgs;
  3836.     PSZ          pszEnvs;
  3837.     RESULTCODES  rcReturnCodes;
  3838.     APIRET       ulrc;
  3839.  
  3840.     ulrc = DosExecPgm(szLoadError,         /* Object name buffer           */
  3841.                       sizeof(szLoadError), /* Length of object name buffer */
  3842.                       EXEC_SYNC,           /* Asynchronous/Trace flags     */
  3843.                       pszArgs,             /* Argument string              */
  3844.                       pszEnvs,             /* Environment string           */
  3845.                       &rcReturnCodes,      /* Termination codes            */
  3846.                       START_PROGRAM);      /* Program file name            */
  3847.  
  3848.     printf("Termination Code %d  Return Code %d \n",
  3849.            rcReturnCodes.codeTerminate,
  3850.            rcReturnCodes.codeResult);
  3851.  
  3852. /*----------------SIMPLE.EXE------------------*/
  3853.  
  3854.     #define INCL_DOSPROCESS       /* Process and thread values */
  3855.     #include <os2.h>
  3856.     #include <stdio.h>
  3857.  
  3858.     #define RETURN_CODE 0
  3859.  
  3860.     main()
  3861.     {
  3862.         printf("Hello!\n");
  3863.         DosExit(EXIT_PROCESS,     /* End the thread or process */
  3864.                 RETURN_CODE);     /* Result code               */
  3865.     }
  3866.  
  3867.  
  3868. ΓòÉΓòÉΓòÉ 5.3.1.2. Starting a Background Process ΓòÉΓòÉΓòÉ
  3869.  
  3870. You can start a child process in the background by specifying the 
  3871. EXEC_BACKGROUND constant in DosExecPgm. A background process runs independently 
  3872. of the parent process and is called a detached process. A detached process 
  3873. should not require any input from the keyboard or output to the video screen, 
  3874. but it can use interprocess communication, such as pipes, queues, and shared 
  3875. memory. 
  3876.  
  3877. The following code fragment starts the program BATCH.EXE in the background. 
  3878.  
  3879.     #define INCL_DOSPROCESS       /* Process and thread values */
  3880.     #include <os2.h>
  3881.     #include <stdio.h>
  3882.  
  3883.     #define START_PROGRAM "BATCH.EXE"
  3884.  
  3885.     CHAR         szLoadError[100];
  3886.     PSZ          pszArgs;
  3887.     PSZ          pszEnvs;
  3888.     RESULTCODES  rcReturnCodes;
  3889.     APIRET       ulrc;
  3890.  
  3891.     ulrc = DosExecPgm(szLoadError,         /* Object name buffer           */
  3892.                       sizeof(szLoadError), /* Length of object name buffer */
  3893.                       EXEC_BACKGROUND,     /* Asynchronous/Trace flags     */
  3894.                       pszArgs,             /* Argument string              */
  3895.                       pszEnvs,             /* Environment string           */
  3896.                       &rcReturnCodes,      /* Termination codes            */
  3897.                       START_PROGRAM);      /* Program file name            */
  3898.  
  3899.     if (ulrc != 0) {
  3900.         printf("DosExecPgm error: return code = %ld",
  3901.                ulrc);
  3902.         return;
  3903.     }
  3904.  
  3905.  
  3906. ΓòÉΓòÉΓòÉ 5.3.1.3. Setting the Command Line and Environment for a Child Process ΓòÉΓòÉΓòÉ
  3907.  
  3908. When you start a process, it inherits many of the resources of the parent. This 
  3909. includes file handles, such as the standard input and standard output files. A 
  3910. child process also inherits the resources of the screen group, such as the 
  3911. mouse and video modes, and the environment variables of the parent process. 
  3912.  
  3913. The call to DosExecPgm determines the command line and environment that the 
  3914. child process receives. The fourth and fifth parameters of the function are 
  3915. pointers to the command line and the environment, respectively. If these 
  3916. pointers are NULL, the child process receives nothing for a command line and 
  3917. only an exact duplicate of the environment of the parent process. The parent 
  3918. process can modify this information by creating a string (ending with two NULL 
  3919. characters) and passing the address of the string to the function. The command 
  3920. line string must include the name of the application, followed by a NULL 
  3921. character, and the command line arguments, followed by two NULL characters. Any 
  3922. number of arguments can be passed to the child process, as long as the argument 
  3923. string ends with two NULL characters. 
  3924.  
  3925. The following code fragment passes to the child process the string "test 
  3926. -option1 -option2" as its command line: 
  3927.  
  3928.     #define INCL_DOSPROCESS    /* Process and thread values */
  3929.     #include <os2.h>
  3930.  
  3931.     RESULTCODES resc;
  3932.     CHAR szFailName[CCHMAXPATH];
  3933.  
  3934.     CHAR szCommandLine[] = "test\0-option1 -option2\0";
  3935.  
  3936.     DosExecPgm(szFailName,          /* Object-name buffer  */
  3937.                sizeof(szFailName),  /* Length of buffer    */
  3938.                EXEC_SYNC,           /* Sync flag           */
  3939.                szCommandLine,       /* Argument string     */
  3940.                (PSZ) NULL,          /* Environment string  */
  3941.                &resc,               /* Address of result   */
  3942.                "test.exe");         /* Name of application */
  3943.  
  3944.  
  3945. ΓòÉΓòÉΓòÉ 5.3.2. Changing the Priority of a Process ΓòÉΓòÉΓòÉ
  3946.  
  3947. Changing the priority of a process is simply a matter of changing the priority 
  3948. of every thread executing in the process. For the details see the section on 
  3949. changing thread priorities, Changing the Priority of a Thread. 
  3950.  
  3951.  
  3952. ΓòÉΓòÉΓòÉ 5.3.3. Obtaining Information about Child Processes ΓòÉΓòÉΓòÉ
  3953.  
  3954. OS/2 creates and maintains a process information block for every process. An 
  3955. application can use DosGetInfoBlocks to access the process information block. 
  3956. This function returns a pointer to a PIB data structure, which contains the 
  3957. information from the process information block. 
  3958.  
  3959. The following code fragment returns the address of the process information 
  3960. block of the current process. The calling thread can subsequently browse either 
  3961. the PIB block. 
  3962.  
  3963.     #define INCL_DOSPROCESS     /* Process and thread values */
  3964.     #include <os2.h>
  3965.  
  3966.     PTIB     ptib;      /* Address of pointer to thread information block  */
  3967.     PPIB     ppib;      /* Address of pointer to process information block */
  3968.     APIRET   rc;        /* Return code                                     */
  3969.  
  3970.     rc = DosGetInfoBlocks(&ptib,
  3971.                           &ppib);
  3972.  
  3973. DosGetInfoBlocks also returns the address of the thread information block of 
  3974. the current thread. 
  3975.  
  3976.  
  3977. ΓòÉΓòÉΓòÉ 5.3.4. Waiting for a Child Process to End ΓòÉΓòÉΓòÉ
  3978.  
  3979. You can synchronize the execution of a process with the execution of one of its 
  3980. child processes by calling DosWaitChild. DosWaitChild does not return until the 
  3981. specified child process ends. This can be useful, for example, if the parent 
  3982. process needs to ensure that the child process has completed its task before 
  3983. the parent process continues with its own task. 
  3984.  
  3985. In the following code fragment, the parent process starts a child process and 
  3986. then waits for the child process to finish: 
  3987.  
  3988.     #define INCL_DOSPROCESS     /* Process and thread values */
  3989.     #include <os2.h>
  3990.  
  3991.     RESULTCODES resc;
  3992.     PID pidEnded;
  3993.     CHAR szFailName[CCHMAXPATH];
  3994.  
  3995.     CHAR szCommandLine[] = "APP\0test\0";
  3996.  
  3997.     DosExecPgm(szFailName,              /* Failed-name buffer     */
  3998.                sizeof(szFailName),      /* Length of buffer       */
  3999.                EXEC_ASYNC,              /* Sync flag              */
  4000.                szCommandLine,           /* Argument string        */
  4001.                (PSZ) NULL,              /* Environment string     */
  4002.                &resc,                   /* Address of result      */
  4003.                "APP.EXE");              /* Name of application    */
  4004.  
  4005.     DosWaitChild(DCWA_PROCESS,          /* Only the process       */
  4006.                  DCWW_WAIT,             /* Waits until it is done */
  4007.                  &resc,                 /* Puts the result here   */
  4008.                  &pidEnded,             /* PID of ended process   */
  4009.                  resc.codeTerminate);   /* Child to wait for      */
  4010.  
  4011. You can cause a process to wait for all its child processes to end by using the 
  4012. DCWA_PROCESSTREE constant in the call to DosWaitChild. 
  4013.  
  4014.  
  4015. ΓòÉΓòÉΓòÉ 5.3.5. Ending the Current Process ΓòÉΓòÉΓòÉ
  4016.  
  4017. You end the current process by calling DosExit. When you exit, the system stops 
  4018. the process and frees any existing resources the process owns. 
  4019.  
  4020. In the following code fragment, DosExit is used to end the process if the given 
  4021. file does not exist: 
  4022.  
  4023.     #define INCL_DOSPROCESS     /* Process and thread values */
  4024.     #include <os2.h>
  4025.  
  4026.     #define HF_STDERR 2         /* Standard error handle     */
  4027.  
  4028.     HFILE   hf;
  4029.     ULONG   ulAction, ulWritten;
  4030.     APIRET  rc;
  4031.  
  4032.     rc = DosOpen("SAMPLE.TXT",
  4033.                  &hf,
  4034.                  &ulAction,
  4035.                  0,
  4036.                  FILE_NORMAL,
  4037.                  FILE_OPEN,
  4038.                  OPEN_ACCESS_WRITEONLY |
  4039.                  OPEN_SHARE_DENYWRITE,
  4040.                  (PEAOP2) NULL);
  4041.  
  4042.     if (rc) {
  4043.         DosWrite(HF_STDERR,
  4044.                  "Cannot open file\r\n",
  4045.                  18,
  4046.                  &ulWritten);
  4047.  
  4048.         DosExit(EXIT_PROCESS,
  4049.                 rc);
  4050.     }
  4051.  
  4052. EXIT_PROCESS directs DosExit to end all the threads in a process including the 
  4053. calling thread, thus ending the process. DosExit includes an error value that 
  4054. is returned to the parent process through the RESULTCODES structure specified 
  4055. in the DosExecPgm call that started the process. If you started the application 
  4056. from the command line, the command processor, CMD.EXE, makes this value 
  4057. available through the ERRORLEVEL variable. If another process started the 
  4058. application, that process can call DosWaitChild to determine the error value. 
  4059.  
  4060. If you want to exit only from a given thread, you can call DosExit with the 
  4061. EXIT_THREAD constant. This will end only the calling thread;  other threads in 
  4062. the process are not affected. If the thread you end is the last thread in the 
  4063. process, the process also ends. If the thread consists of a function, the 
  4064. thread ends when the function returns. 
  4065.  
  4066.  
  4067. ΓòÉΓòÉΓòÉ 5.3.6. Terminating a Process ΓòÉΓòÉΓòÉ
  4068.  
  4069. A process can end the execution of a descendant process by calling 
  4070. DosKillProcess. This causes OS/2 to send a XCPT_SIGNAL_KILLPROC exception to 
  4071. the target process. The child processes of the target process can also be 
  4072. ended. 
  4073.  
  4074. The following code fragment ends the specified process and all child processes 
  4075. belonging to that process: 
  4076.  
  4077.     #define INCL_DOSPROCESS       /* Process and thread values */
  4078.     #include <os2.h>
  4079.  
  4080.     PID pidProcess;
  4081.  
  4082.     DosKillProcess(DKP_PROCESSTREE,
  4083.                    pidProcess);
  4084.  
  4085. In this example, the pidProcess parameter specifies which descendant process to 
  4086. end. The process identifier is returned by DosExecPgm in the codeTerminate 
  4087. field of the RESULTCODES structure when you start the child process. 
  4088.  
  4089. The parameter DKP_PROCESSTREE in the example indicates that the specified 
  4090. process, pidProcess, and all of its descendant processes are to be ended. 
  4091.  
  4092. If you specify DKP_PROCESS in a call to DosKillProcess, only the specified 
  4093. process is ended. Its child processes, if any, continue to run. 
  4094.  
  4095. The process to be ended must either be the current process, or it must have 
  4096. been directly created by the current process with DosExecPgm for asynchronous 
  4097. execution. That is, a process can end itself and its descendants. 
  4098.  
  4099. The process to be ended need not still be executing. If it has started its own 
  4100. child processes, but has stopped executing, its children can still be flagged 
  4101. for termination. 
  4102.  
  4103. Obtaining the Termination Status of a Child Process 
  4104.  
  4105. OS/2 saves the termination status for a process if the process was started by 
  4106. using the EXEC_ASYNCRESULT constant in the call to DosExecPgm. 
  4107. You can retrieve the termination status of the most recently ended process by 
  4108. using the DCWW_NOWAIT constant with DosWaitChild and setting the child process 
  4109. identification parameter to 0. The DCWW_NOWAIT constant directs the function to 
  4110. return immediately, without waiting for a process to end. Instead, the function 
  4111. retrieves the termination status from the process that most recently ended. If 
  4112. you specify a child process identification with DCWW_NOWAIT, DosWaitChild 
  4113. returns ERROR_CHILD_NOT_COMPLETE if the child process has not ended. Once the 
  4114. specified process has ended, DosWaitChild returns its termination code. 
  4115.  
  4116. The following code fragment starts a child session (the program SIMPLE.EXE), 
  4117. and then retrieves the termination status from the process that most recently 
  4118. ended. 
  4119.  
  4120.     #define INCL_DOSPROCESS         /* Process and thread values */
  4121.     #include <os2.h>
  4122.     #include <stdio.h>
  4123.  
  4124.     #define START_PROGRAM "SIMPLE.EXE"
  4125.  
  4126.     CHAR         szLoadError[100];
  4127.     PSZ          pszArgs;
  4128.     PSZ          pszEnvs;
  4129.     RESULTCODES  rcReturnCodes;
  4130.     ULONG        ulPid;           /* Process ID (returned)             */
  4131.     ULONG        ulTarget;        /* Process ID of process to wait for */
  4132.     APIRET       ulrc;            /* Return code                       */
  4133.  
  4134.     strcpy(pszArgs,
  4135.            "-a2 -l");   /* Pass arguments "-a2" and "-l"                         */
  4136.  
  4137.     ulTarget = 0;       /* Process ID for the most recently ended process   */
  4138.  
  4139.     ulrc = DosExecPgm(szLoadError,            /* Object name buffer                */
  4140.                       sizeof(szLoadError),    /* Length of object name buffer      */
  4141.                       EXEC_ASYNCRESULT,       /* Asynchronous/Trace flags          */
  4142.                       pszArgs,                /* Argument string                   */
  4143.                       pszEnvs,                /* Environment string                */
  4144.                       &rcReturnCodes,         /* Termination codes                 */
  4145.                       START_PROGRAM);         /* Program file name                 */
  4146.  
  4147.     if (ulrc != 0) {
  4148.         printf("DosExecPgm error: return code = %ld",
  4149.                ulrc);
  4150.         return;
  4151.     }
  4152.  
  4153.     ulrc = DosWaitChild(DCWA_PROCESS,         /* Execution options                 */
  4154.                         DCWW_NOWAIT,          /* Wait options                      */
  4155.                         &rcReturnCodes,       /* Termination codes                 */
  4156.                         &ulPid,               /* Process ID (returned)             */
  4157.                         ulTarget);            /* Process ID of process to wait for */
  4158.  
  4159.     if (ulrc != 0) {
  4160.         printf("DosWaitChild error: return code = %ld",
  4161.                ulrc);
  4162.         return;
  4163.     }
  4164.  
  4165.  
  4166. ΓòÉΓòÉΓòÉ 5.3.7. Creating an Exit List ΓòÉΓòÉΓòÉ
  4167.  
  4168. You call DosExitList to add to the exit list a routine that is to be given 
  4169. control when a process is ended (or finishes its execution). Multiple routines 
  4170. can be added to the list. When the process is ending, OS/2 transfers control to 
  4171. each address on the list. 
  4172.  
  4173. If there are multiple addresses on the list, each function gets control in 
  4174. numerical order (with 0 being first and 0FFH being last), based on a value 
  4175. supplied by the application when it calls DosExitList. In case of duplicate 
  4176. entries for this parameter, the routines will be executed in LIFO (last in, 
  4177. first out) order. 
  4178.  
  4179. DosExitList requires a function code that specifies an action and a pointer to 
  4180. the function that is to receive control upon termination. 
  4181.  
  4182. The following code fragment adds the locally defined function SaveFiles to the 
  4183. exit list: 
  4184.  
  4185.     #define INCL_DOSPROCESS         /* Process and thread values */
  4186.     #include <os2.h>
  4187.  
  4188.     #define HF_STDOUT 1             /* Standard output handle    */
  4189.  
  4190.     VOID main(VOID)
  4191.     {
  4192.         .
  4193.         .
  4194.         .
  4195.         DosExitList(EXLST_ADD,
  4196.                     (PFNEXITLIST) SaveFiles);
  4197.         .
  4198.         .
  4199.         .
  4200.         DosExit(EXIT_PROCESS,
  4201.                 0);
  4202.     }
  4203.  
  4204.     VOID APIENTRY SaveFiles(ULONG ulTermCode)
  4205.     {
  4206.         ULONG ulWritten;
  4207.  
  4208.         switch (ulTermCode) {
  4209.             case TC_EXIT:
  4210.             case TC_KILLPROCESS:
  4211.                  DosWrite(HF_STDOUT,
  4212.                           "Goodbye\r\n",
  4213.                           10,
  4214.                           &ulWritten);
  4215.                  break;
  4216.  
  4217.             case TC_HARDERROR:
  4218.             case TC_TRAP:
  4219.                  break;
  4220.  
  4221.         }
  4222.         DosExitList(EXLST_EXIT,
  4223.                     0);
  4224.     }
  4225.  
  4226. Any function that you add to the list must take one parameter. The function can 
  4227. carry out any task, as shown in the preceding example, but as its last action 
  4228. it must call DosExitList, specifying the EXLST_EXIT constant. An exit-list 
  4229. function must not have a return value and must not call DosExit to end. 
  4230.  
  4231. When an exit-list routine receives control, the parameter (located at ESP+4 on 
  4232. the stack) contains an indicator of why the process ended. The values returned 
  4233. are the same as those for termination codes returned by DosWaitChild or 
  4234. DosExecPgm requests. These values are: 
  4235.  
  4236.  TC_EXIT (0)           Normal exit 
  4237.  TC_HARDERROR (1)      Hard-error halt 
  4238.  TC_TRAP (2)           Trap operation for a 16-bit child process 
  4239.  TC_KILLPROCESS (3)    Unintercepted DosKillProcess 
  4240.  TC_EXCEPTION (4)      Exception operation for a 32-bit child process 
  4241.  
  4242.  To execute the exit-list functions, OS/2 reassigns thread 1 after ending all 
  4243.  other threads in the process. If thread 1 has already exited (for example, if 
  4244.  it called DosExit without ending other threads in the process), the exit-list 
  4245.  functions cannot be executed. In general, it is poor practice to end thread 1 
  4246.  without ending all other threads. 
  4247.  
  4248.  Before transferring control to the termination routines, OS/2 resets the stack 
  4249.  to its initial value. Transfer is by way of an assembly language JMP 
  4250.  instruction. The routine must be in the address space of the ending process. 
  4251.  The termination routine at that address takes the necessary steps and then 
  4252.  calls DosExitList with FunctionOrder=EXLST_EXIT. Control is then transferred 
  4253.  to the next address in the invocation order of the exit list. When all such 
  4254.  addresses have been processed, the process completes exiting. If a routine on 
  4255.  the list does not call DosExitList at the completion of its processing, the 
  4256.  process waits, and OS/2 prevents termination. 
  4257.  
  4258.  During DosExitList processing, the process is in a state of partial 
  4259.  termination. All threads of the process are ended, except for the one 
  4260.  executing the exit-list routines. To ensure good response to a user request to 
  4261.  end a program, there should be minimal delay in completing termination. 
  4262.  Termination routines should be short and fail-safe. 
  4263.  
  4264.  You can use DosExitList with the EXLST_REMOVE constant to remove a function 
  4265.  from the list. 
  4266.  
  4267.  The designer of an exit-list routine must carefully consider which functions 
  4268.  will be used by the routine. In general, calls to most OS/2 functions are 
  4269.  valid in a DosExitList routine, but certain functions, such as DosCreateThread 
  4270.  and DosExecPgm, are not. 
  4271.  
  4272.  
  4273. ΓòÉΓòÉΓòÉ 5.4. Using Threads ΓòÉΓòÉΓòÉ
  4274.  
  4275. A thread is a dispatchable unit of execution that consists of a set of 
  4276. instructions, related CPU register values, and a stack. Every process has at 
  4277. least one thread and can have many threads running at the same time. The 
  4278. application runs when OS/2 gives control to a thread in the process. The thread 
  4279. is the basic unit of execution scheduling. 
  4280.  
  4281. Every process has at least one thread, called the main thread or thread 1. To 
  4282. execute different parts of an application simultaneously, you can start several 
  4283. threads. 
  4284.  
  4285. A new thread inherits all the resources currently owned by the process. This 
  4286. means that if you opened a file before creating the thread, the file is 
  4287. available to the thread. Similarly, if the new thread creates or opens a 
  4288. resource, such as another file, that resource is available to the other threads 
  4289. in the process. 
  4290.  
  4291.  
  4292. ΓòÉΓòÉΓòÉ 5.4.1. Creating a Thread ΓòÉΓòÉΓòÉ
  4293.  
  4294. You use DosCreateThread to create a new thread for a process. 
  4295.  
  4296. DosCreateThread requires the address of the code to execute and a variable to 
  4297. receive the identifier of the thread. The address of the code is typically the 
  4298. address of a function that is defined within the application. 
  4299.  
  4300. You can pass one ULONG parameter to the thread when you start it. To pass more 
  4301. information to the thread, pass the address of a data structure. 
  4302.  
  4303. You specify how you want the thread to run when you call DosCreateThread. If 
  4304. bit 1 of the flag parameter in the function call is 0, the thread starts 
  4305. immediately. If bit 1 of the flag parameter is 1, the thread starts suspended 
  4306. and will not run until the application calls DosResumeThread. 
  4307.  
  4308. Each thread maintains its own stack. You specify the size of the stack when you 
  4309. call DosCreateThread. The amount of space needed depends on a number of 
  4310. factors, including the number of function calls the thread makes and the number 
  4311. of parameters and local variables used by each function. If you plan to call 
  4312. OS/2 functions, a reasonable stack size is 8192 bytes (8KB); 4096 bytes (4KB) 
  4313. should be the absolute minimum. If bit 1 of the flag parameter is 0, OS/2 uses 
  4314. the default method for initializing the thread's stack. If bit 1 of the flag 
  4315. parameter is 1, memory for the thread's entire stack is pre-committed. 
  4316.  
  4317. The following code fragment creates a thread: 
  4318.  
  4319.     #define INCL_DOSPROCESS         /* Process and thread values */
  4320.     #include <os2.h>
  4321.     #include <stdio.h>
  4322.  
  4323.     #define HF_STDOUT 1             /* Standard output handle    */
  4324.  
  4325.     VOID _System ThreadFunc(ULONG ulBeepLen);
  4326.  
  4327.     INT main(VOID)
  4328.       {
  4329.       ULONG ulBeepLen;
  4330.       TID   tidThread;
  4331.  
  4332.       ulBeepLen = 1000;
  4333.       DosCreateThread(&tidThread,       /* Thread ID returned by DosCreateThread */
  4334.                       &ThreadFunc,      /* Address of the thread function        */
  4335.                       ulBeepLen,        /* Parameter passed to thread            */
  4336.                       0,                /* Immediate execution, default stack    */
  4337.                                         /* initialization                        */
  4338.                       4096);            /* Stack size                            */
  4339.  
  4340.       DosWaitThread(&tidThread,
  4341.                     DCWW_WAIT);
  4342.       return 0;
  4343.       } /* end main */
  4344.  
  4345. /***************************************************/
  4346. /* ThreadFunc                                      */
  4347. /***************************************************/
  4348.     VOID _System ThreadFunc(ULONG ulBeepLen)
  4349.       {
  4350.       ULONG ulWritten; /* needed for DosWrite */
  4351.  
  4352.       DosBeep(750, ulBeepLen);
  4353.  
  4354.       DosWrite(HF_STDOUT,
  4355.                "Message from new thread\r\n",
  4356.                25,
  4357.                &ulWritten);
  4358.  
  4359.       DosExit(EXIT_PROCESS, 0);
  4360.       } /* end ThreadFunc */
  4361.  
  4362. A thread continues to run until it calls DosExit, returns control to OS/2, or 
  4363. is ended by a DosKillThread call. 
  4364.  
  4365. In the preceding example, the thread exits when the function implicitly returns 
  4366. control at the end of the function. 
  4367.  
  4368.  
  4369. ΓòÉΓòÉΓòÉ 5.4.2. Obtaining Information about a Thread ΓòÉΓòÉΓòÉ
  4370.  
  4371. OS/2 creates and maintains a thread information block for each thread. An 
  4372. application can use DosGetInfoBlocks to access the thread information block. 
  4373. This function returns a pointer to a TIB data structure. 
  4374.  
  4375. The code fragment below returns the address of the thread information block of 
  4376. the current thread. The calling thread can subsequently browse the TIB. 
  4377.  
  4378. DosGetInfoBlocks also returns the address of the process information block of 
  4379. the current process. 
  4380.  
  4381.  
  4382. ΓòÉΓòÉΓòÉ 5.4.3. Changing the Priority of a Thread ΓòÉΓòÉΓòÉ
  4383.  
  4384. You can use DosSetPriority to change the execution priority of threads in a 
  4385. process. The execution priority defines when or how often a thread receives an 
  4386. execution time slice. Threads with higher priorities receive time slices before 
  4387. those with lower priorities. When a thread that is higher in priority than the 
  4388. currently running thread becomes ready to run, it immediately preempts the 
  4389. lower priority thread (the lower priority thread does not get to complete its 
  4390. time slice). Threads with equal priority receive time slices in a round-robin 
  4391. order. If you raise the priority of a thread, the thread is executed more 
  4392. frequently. 
  4393.  
  4394. You can use DosSetPriority to set the priority for one thread in a process, for 
  4395. all threads in a process (and thus the process itself), or for threads in a 
  4396. child process. 
  4397.  
  4398. A process can change the priority of any thread within itself. When a process 
  4399. changes the priority of threads in a descendant process, however, only those 
  4400. with default priorities are changed. The priority of any thread in a descendant 
  4401. process that has already explicitly changed its priority from the default with 
  4402. DosSetPriority is not changed. 
  4403.  
  4404. In the following code fragment, DosSetPriority lowers the priority of a process 
  4405. to be used as a background process: 
  4406.  
  4407.     #define INCL_DOSPROCESS       /* Process and thread values */
  4408.     #include <os2.h>
  4409.  
  4410.     PTIB ptib;    /* thread information block          */
  4411.     PPIB ppib;    /* process information block         */
  4412.     APIRET rc;    /* return code from DosGetInfoBlocks */
  4413.  
  4414.     rc = DosGetInfoBlocks(&ptib,
  4415.                           &ppib);
  4416.  
  4417.     DosSetPriority(PRTYS_PROCESSTREE,
  4418.                    PRTYC_IDLETIME,
  4419.                    0,
  4420.                    ppib->pib_ulpid);
  4421.  
  4422. DosGetInfoBlocks retrieves the process information blocks and thread 
  4423. information blocks. DosSetPriority then uses the process identifier to change 
  4424. the priority to idle time (idle-time processes receive the least attention by 
  4425. OS/2). 
  4426.  
  4427. If you specify PRTYS_PROCESS when calling DosSetPriority, only the priority of 
  4428. the specified process changes. The priorities of all child processes remain 
  4429. unchanged. 
  4430.  
  4431. If you specify PRTYS_THREAD in the call to DosSetPriority, you must specify a 
  4432. thread identifier as the last parameter.  The priority of the specified thread 
  4433. changes, but the priorities of all other threads in the process remain 
  4434. unchanged. 
  4435.  
  4436. Whenever DosSetPriority is called with a class specification, but no value is 
  4437. specified for priority-delta, the base priority level defaults to 0. 
  4438.  
  4439.  
  4440. ΓòÉΓòÉΓòÉ 5.4.4. Suspending the Current Thread ΓòÉΓòÉΓòÉ
  4441.  
  4442. You can temporarily suspend the execution of the current thread for a set 
  4443. amount of time by using DosSleep. This function suspends execution of the 
  4444. thread for the specified number of milliseconds. DosSleep is useful when you 
  4445. need to delay the execution of a task. For example, you can use DosSleep to 
  4446. delay a response when the user presses a DIRECTION key. The delay provides the 
  4447. user with enough time to observe the results and release the key. 
  4448.  
  4449. The following code fragment uses DosSleep to suspend execution of a thread for 
  4450. 1000 milliseconds (1 second): 
  4451.  
  4452.     #define INCL_DOSPROCESS       /* Process and thread values */
  4453.     #include <os2.h>
  4454.  
  4455.     DosSleep(1000);
  4456.  
  4457.  
  4458. ΓòÉΓòÉΓòÉ 5.4.5. Suspending and Resuming Execution of a Thread ΓòÉΓòÉΓòÉ
  4459.  
  4460. DosSuspendThread and DosResumeThread are used to temporarily suspend the 
  4461. execution of a thread when it is not needed and resume execution when the 
  4462. thread is needed. 
  4463.  
  4464. These functions are best used when it is necessary for a process to temporarily 
  4465. suspend execution of a thread that is in the middle of a task. For example, 
  4466. consider a thread that opens and reads files from a disk. If other threads in 
  4467. the process do not require input from these files, the process can suspend 
  4468. execution of the thread so that OS/2 does not needlessly grant control to it. 
  4469.  
  4470. The specified thread might not be suspended immediately if it has some system 
  4471. resources locked that must be freed first. However, the thread is not permitted 
  4472. to execute further application program instructions until a corresponding 
  4473. DosResumeThread is called. 
  4474.  
  4475. A thread can only suspend another thread that is within its process. 
  4476.  
  4477. DosResumeThread is used to enable the suspended thread to resume execution. 
  4478.  
  4479. The following code fragment temporarily suspends the execution of another 
  4480. thread within the same process. A subsequent call to DosResumeThread restarts 
  4481. the suspended thread. Assume that the thread identifier of the target thread 
  4482. has been placed int ThreadID already. 
  4483.  
  4484.     #define INCL_DOSPROCESS     /* Process and thread values */
  4485.     #include <os2.h>
  4486.     #include <stdio.h>
  4487.  
  4488.     TID     tidThreadID;     /* Thread identifier */
  4489.     APIRET  ulrc;            /* Return code       */
  4490.  
  4491.     ulrc = DosSuspendThread(tidThreadID);
  4492.  
  4493.     if (ulrc != 0) {
  4494.         printf("DosSuspendThread error: return code = %ld",
  4495.                ulrc);
  4496.         return;
  4497.     }
  4498.  
  4499.     ulrc = DosResumeThread(tidThreadID);
  4500.  
  4501.     if (ulrc != 0) {
  4502.         printf("DosResumeThread error: return code = %ld",
  4503.                ulrc);
  4504.         return;
  4505.     }
  4506.  
  4507.  
  4508. ΓòÉΓòÉΓòÉ 5.4.6. Entering Critical Sections ΓòÉΓòÉΓòÉ
  4509.  
  4510. A thread can prevent execution of any of the other threads in its process by 
  4511. calling DosEnterCritSec. 
  4512.  
  4513. This function temporarily prevents a thread from being preempted by other 
  4514. threads within its process. The other threads in the process will not be 
  4515. executed until the current thread calls DosExitCritSec. This enables the 
  4516. calling thread to access a time-critical resource of the process. 
  4517.  
  4518. The following code fragment enters a section that will not be preempted, 
  4519. performs a simple task, and then exits quickly. 
  4520.  
  4521.     #define INCL_DOSPROCESS     /* Process and thread values */
  4522.     #include <os2.h>
  4523.     #include <stdio.h>
  4524.  
  4525.     BOOL    flag;         /* Program control flag */
  4526.     APIRET  ulrc;         /* Return code          */
  4527.  
  4528.     ulrc = DosEnterCritSec();
  4529.  
  4530.     if (ulrc != 0) {
  4531.         printf("DosEnterCritSec error: return code = %ld",
  4532.                ulrc);
  4533.         return;
  4534.     }
  4535.  
  4536.     flag = TRUE;           /* Set the flag */
  4537.  
  4538.     ulrc = DosExitCritSec();
  4539.  
  4540.     if (ulrc != 0) {
  4541.         printf("DosExitCritSec error: return code = %ld",
  4542.                ulrc);
  4543.         return;
  4544.     }
  4545.  
  4546. A count is maintained of the outstanding DosEnterCritSec requests. The count is 
  4547. incremented when a DosEnterCritSec request is made, and decremented when a 
  4548. DosExitCritSec request is made. A DosExitCritSec request will not cause normal 
  4549. thread dispatching to be restored while the count is greater than 0. 
  4550.  
  4551. This count is maintained in a WORD-sized variable. If overflow occurs, the 
  4552. count is set to its maximum value, and an error is returned. The operation is 
  4553. not performed when this occurs. 
  4554.  
  4555. Threads that call DosEnterCritSec must not must not make dynamic link calls 
  4556. within these critical sections. The dynamic link procedure could be using 
  4557. semaphores to serialize a resource. If a thread entering the critical section 
  4558. blocks another thread that already owns the resource which the dynamic link 
  4559. function is about to request, a deadlock occurs. 
  4560.  
  4561. For example, threads of an application are serializing their access to a queue 
  4562. by means of a semaphore. A thread enters a critical section and makes a request 
  4563. to read the queue while another thread already has the semaphore that controls 
  4564. access to the queue. The thread that has the semaphore is now effectively 
  4565. blocked by DosEnterCritSec, and the thread that has requested the queue waits 
  4566. forever to access it. 
  4567.  
  4568. Note:  Thread 1 is the initial thread of execution. It handles all signals 
  4569.        (Ctrl+C, Ctrl+Break, and KillProcess). If a signal occurs while 
  4570.        DosEnterCritSec is active, thread 1 can begin execution to process the 
  4571.        signal. Thread 1 must not access the critical resource that is being 
  4572.        protected by the use of DosEnterCritSec. 
  4573.  
  4574.  
  4575. ΓòÉΓòÉΓòÉ 5.4.7. Waiting for a Thread to End ΓòÉΓòÉΓòÉ
  4576.  
  4577. An application might need to ensure that one thread has finished executing 
  4578. before another thread continues with its own task. For example, one thread 
  4579. might have to finish reading a disk file into memory before another thread can 
  4580. use the information. You can use DosWaitThread to suspend a thread until 
  4581. another thread has ended. 
  4582.  
  4583. DosWaitThread places the current thread into a wait state until another thread 
  4584. in the current process has ended. It then returns the thread identifier of the 
  4585. ending thread. 
  4586.  
  4587. The following code fragment creates three threads. The thread identifier for 
  4588. each thread is returned by DosCreateThread in the atid array. Using &atid[0] as 
  4589. a parameter in the call to DosWaitThread causes OS/2 to wait until the thread 
  4590. with that identifier (the thread running Thread2Func) ends. 
  4591.  
  4592.     #define INCL_DOSPROCESS       /* Process and thread values */
  4593.     #include <os2.h>
  4594.  
  4595.     #define HF_STDOUT 1           /* Standard output handle    */
  4596.  
  4597.     TID tidAtid[3];
  4598.     ULONG ulWritten;
  4599.  
  4600.     DosCreateThread(&tidAtid[0],
  4601.                     Thread2Func,
  4602.                     0,
  4603.                     0,
  4604.                     4096);
  4605.  
  4606.     DosCreateThread(&tidAtid[1],
  4607.                     Thread3Func,
  4608.                     0,
  4609.                     0,
  4610.                     4096);
  4611.  
  4612.     DosCreateThread(&tidAtid[2],
  4613.                     Thread4Func,
  4614.                     0,
  4615.                     0,
  4616.                     4096);
  4617.  
  4618.     DosWaitThread(&tidAtid[0],
  4619.                   DCWW_WAIT);
  4620.  
  4621.     DosWrite(HF_STDOUT,
  4622.              "The thread has ended\r\n",
  4623.              27,
  4624.              &ulWritten);
  4625.  
  4626. If you set the tid parameter to 0 in the call to DosWaitThread, OS/2 waits only 
  4627. until the next thread (any thread in the process) ends. The identifier for the 
  4628. ended thread is then returned in the tid parameter. 
  4629.  
  4630. After the threads are created as in the preceding example, the following code 
  4631. fragment waits until one of the threads ends, and then returns its thread 
  4632. identifier: 
  4633.  
  4634.     #define INCL_DOSPROCESS       /* Process and thread values */
  4635.     #include <os2.h>
  4636.  
  4637.     TID tid;
  4638.  
  4639.     tid = 0;
  4640.  
  4641.     DosWaitThread(&tid,
  4642.                   DCWW_WAIT);
  4643.  
  4644. The thread identifier of the next thread to end after the DosWaitThread call is 
  4645. returned in the tid parameter. 
  4646.  
  4647. You can use DosWaitThread so that you can recover thread resources when the 
  4648. thread ends, or to synchronize the execution of a thread with the execution of 
  4649. other threads. 
  4650.  
  4651.  
  4652. ΓòÉΓòÉΓòÉ 5.4.8. Ending the Current Thread ΓòÉΓòÉΓòÉ
  4653.  
  4654. To end the execution of the current thread, call DosExit, specifying the action 
  4655. code as 0. It is good practice to end each thread in the application 
  4656. individually. 
  4657.  
  4658. If the thread that is ending is the last thread in the process, or if the 
  4659. request is to end all threads in the process, then the process also ends.  All 
  4660. threads except one are ended, and that thread executes any routines in the list 
  4661. specified by DosExitList. When this is complete, the resources of the process 
  4662. are released, and the result code that was specified in the DosExit call is 
  4663. passed to any thread that calls DosWaitChild for this process. 
  4664.  
  4665. In the following code fragment, the main routine starts another program, 
  4666. SIMPLE.EXE, and then expects a return code of 3 to be returned. SIMPLE.EXE sets 
  4667. the return code with DosExit. 
  4668.  
  4669.     #define INCL_DOSPROCESS           /* Process and thread values */
  4670.     #include <os2.h>
  4671.     #include <stdio.h>
  4672.  
  4673.     #define START_PROGRAM "SIMPLE.EXE"
  4674.     #define RETURN_OK 3
  4675.  
  4676.     CHAR        szLoadError[100];
  4677.     PSZ         pszArgs;
  4678.     PSZ         pszEnvs;
  4679.     RESULTCODES rcReturnCodes;
  4680.     APIRET      ulrc;
  4681.  
  4682.     ulrc = DosExecPgm(szLoadError,                /* Object name buffer           */
  4683.                       sizeof(szLoadError),        /* Length of object name buffer */
  4684.                       EXEC_SYNC,                  /* Asynchronous/Trace flags     */
  4685.                       pszArgs,                    /* Argument string              */
  4686.                       pszEnvs,                    /* Environment string           */
  4687.                       &rcReturnCodes,             /* Termination codes            */
  4688.                       START_PROGRAM);             /* Program file name            */
  4689.  
  4690.     if (ReturnCodes.codeResult == RETURN_OK)      /* Check result code            */
  4691.         printf("Things are ok...");
  4692.     else
  4693.         printf("Something is wrong...");
  4694.  
  4695. /*----------------SIMPLE.EXE------------------*/
  4696.  
  4697.     #define INCL_DOSPROCESS          /* Process and thread values */
  4698.     #include <os2.h>
  4699.     #include <stdio.h>
  4700.  
  4701.     #define RETURN_CODE 3
  4702.  
  4703.     main()
  4704.     {
  4705.         printf("Hello!\n");
  4706.         DosExit(EXIT_THREAD,         /* End thread/process */
  4707.                 RETURN_CODE);        /* Result code        */
  4708.     }
  4709.  
  4710. When you specify DosExit for thread 1 (the initial thread of execution started 
  4711. by OS/2 for this process), all of the threads in the process are ended, and the 
  4712. process is ended. 
  4713.  
  4714.  
  4715. ΓòÉΓòÉΓòÉ 5.4.9. Ending a Thread ΓòÉΓòÉΓòÉ
  4716.  
  4717. DosKillThread ends a thread in the current process. DosKillThread enables a 
  4718. thread in a process to end any other thread in the process. 
  4719.  
  4720. DosKillThread is used to force a thread within the current process to end 
  4721. without causing the entire process to be ended. 
  4722.  
  4723.     #define INCL_DOSPROCESS       /* Process and thread values */
  4724.     #include <os2.h>
  4725.  
  4726.     TID tidThread;    /* ThreadID of the thread to be ended */
  4727.  
  4728.     DosCreateThread(&tidThread,
  4729.                     ThreadFunction,
  4730.                     0,
  4731.                     0,
  4732.                     4096);
  4733.     .
  4734.     .
  4735.     .
  4736.     DosKillThread(tidThread);
  4737.  
  4738. DosKillThread returns to the requestor without waiting for the target thread to 
  4739. complete its termination processing. 
  4740.  
  4741. It is an invalid operation to use DosKillThread to kill the current thread. 
  4742.  
  4743. Terminating thread 1 will cause the entire process to end similar to executing 
  4744. DosExit on thread 1. DosKillThread will not end a thread that is suspended. 
  4745. Instead the suspended thread will be ended when it resumes execution. For this 
  4746. reason, you should not kill the main thread of an application if there are any 
  4747. secondary threads that are suspended. 
  4748.  
  4749. If the target thread is executing 16-bit code or was created by a 16-bit 
  4750. requester, ERROR_BUSY is returned. 
  4751.  
  4752.  
  4753. ΓòÉΓòÉΓòÉ 5.5. Using Sessions ΓòÉΓòÉΓòÉ
  4754.  
  4755. A session consists of at least one process and a virtual console (either full 
  4756. screen, or Presentation Manager window, and buffers for keyboard and mouse 
  4757. input). An application can manage its own child sessions by using 
  4758. DosStartSession, DosStopSession, DosSelectSession, and DosSetSession. 
  4759.  
  4760.  
  4761. ΓòÉΓòÉΓòÉ 5.5.1. Starting a Session ΓòÉΓòÉΓòÉ
  4762.  
  4763. DosStartSession is used to start new sessions and to specify the name of the 
  4764. application to be started in the new session. 
  4765.  
  4766. There are five types of sessions that you can start: full screen, text window, 
  4767. Presentation Manager (PM), full screen DOS Session, and windowed DOS Session. 
  4768. OS/2 applications running in any of the OS/2 session types-full screen, text 
  4769. window, and PM-can start a session for any other application type, including 
  4770. DOS Sessions. Applications running in DOS Sessions cannot start sessions. 
  4771.  
  4772. DosStartSession can be used to start either a foreground or a background 
  4773. session, but a new session can be started in the foreground only when the 
  4774. session of the caller, or one of the descendant sessions of the caller, is 
  4775. currently executing in the foreground. 
  4776.  
  4777. A session can be started as an unrelated session or as a child session. 
  4778.  
  4779. In the following code fragment, an unrelated, foreground session is created, 
  4780. and the application, SIMON.EXE, is started in the new session: 
  4781.  
  4782.     #define INCL_DOSPROCESS       /* Process and thread values */
  4783.     #define INCL_DOSSESMGR
  4784.     #include <os2.h>
  4785.  
  4786.     #define HF_STDOUT 1      /* Standard output handle */
  4787.  
  4788.     STARTDATA  sd;
  4789.     PID        pidProcess;
  4790.     CHAR       szBuf[CCHMAXPATH];
  4791.     ULONG      ulSessionID, cbWritten;
  4792.     APIRET     rc;
  4793.     CHAR       szPgmName[] = "SIMON.EXE";
  4794.  
  4795.     sd.Length = sizeof(sd);                    /* Length of the structure */
  4796.     sd.Related = SSF_RELATED_INDEPENDENT;      /* Unrelated session       */
  4797.     sd.FgBg = SSF_FGBG_FORE;                   /* In the foreground       */
  4798.     sd.TraceOpt = SSF_TRACEOPT_NONE;           /* No tracing              */
  4799.     sd.PgmTitle = (PSZ) NULL;                  /* Title is PgmName        */
  4800.     sd.PgmName = szPgmName;                    /* Address of szPgmName    */
  4801.     sd.PgmInputs = (PBYTE) NULL;               /* No command line args    */
  4802.     sd.TermQ = (PBYTE) NULL;                   /* No terminal queue       */
  4803.     sd.Environment = (PBYTE) NULL;             /* Inherits environment    */
  4804.     sd.InheritOpt = SSF_INHERTOPT_PARENT;      /* Uses parent environment */
  4805.     sd.SessionType = SSF_TYPE_PM;              /* PM session              */
  4806.     sd.IconFile = (PSZ) NULL;                  /* Uses default icon       */
  4807.     sd.PgmHandle = 0;                          /* Used by Win calls       */
  4808.     sd.PgmControl = SSF_CONTROL_MAXIMIZE;      /* Starts app maximized    */
  4809.     sd.InitXPos = 0;                           /* Lower left corner       */
  4810.     sd.InitYPos = 0;                           /* Lower left corner       */
  4811.     sd.InitXSize = 0;                          /* Ignored for maximized   */
  4812.     sd.InitYSize = 0;                          /* Ignored for maximized   */
  4813.     sd.ObjectBuffer = szBuf;                   /* Fail-name buffer        */
  4814.     sd.ObjectBuffLen = sizeof(szBuf);          /* Buffer length           */
  4815.  
  4816.     rc = DosStartSession(&sd, &ulSessionID, &pidProcess);
  4817.  
  4818.     if (rc) {
  4819.         DosBeep(750,250);
  4820.         DosWrite(HF_STDOUT, "error starting new session\r\n", 28, &cbWritten);
  4821.         DosExit(EXIT_PROCESS, rc);
  4822.     }
  4823.  
  4824. Before calling DosStartSession, you must create a STARTDATA data structure that 
  4825. defines the session to be started. Different lengths for the data structure are 
  4826. supported to provide compatibility and various levels of application control. 
  4827.  
  4828. DosStartSession uses the STARTDATA structure to specify the details of the new 
  4829. session, such as the name of the application to start in the session, whether 
  4830. the new session should be started in the foreground or background, and whether 
  4831. the new session is unrelated or is a child session of the session calling 
  4832. DosStartSession. 
  4833.  
  4834. When a session is created, the title specified in STARTDATA, (or the 
  4835. application title if no title is specified in STARTDATA) is added to the Window 
  4836. List. 
  4837.  
  4838. The Related field in the STARTDATA structure specifies whether the new session 
  4839. is related to the session calling DosStartSession. 
  4840.  
  4841. If the InheritOpt field in the STARTDATA data structure is set to 1, the new 
  4842. session inherits the environment and open file handles of the calling process. 
  4843. This applies for both unrelated and related sessions. 
  4844.  
  4845.  
  4846. ΓòÉΓòÉΓòÉ 5.5.2. Controlling the Execution of Child Sessions ΓòÉΓòÉΓòÉ
  4847.  
  4848. Once a process has started a child session, it can use DosSelectSession to 
  4849. control the child session. 
  4850.  
  4851. A process calls DosSetSession to set the selectability and bonding of a child 
  4852. session. 
  4853.  
  4854.  
  4855. ΓòÉΓòÉΓòÉ 5.5.2.1. Setting User Selectability of a Child Session ΓòÉΓòÉΓòÉ
  4856.  
  4857. A process calls DosSetSession to set the selectability of a child session. 
  4858. When a child session is selectable, the user can select it from the Window List 
  4859. or by using Alt+Esc. When a child session is nonselectable, the user cannot 
  4860. select the session from the Window List or move to it by using the Alt+Esc 
  4861. keys. 
  4862.  
  4863. In the following code fragment, DosSetSession makes a child session 
  4864. nonselectable: 
  4865.  
  4866.     #define INCL_DOSPROCESS       /* Process and thread values */
  4867.     #define INCL_DOSSESMGR
  4868.     #include <os2.h>
  4869.  
  4870.     ULONG ulSessionID;
  4871.     STATUSDATA stsdata;
  4872.  
  4873.     stsdata.Length = sizeof(stsdata);
  4874.     stsdata.SelectInd = SET_SESSION_NON_SELECTABLE;  /* Non-selectable         */
  4875.     stsdata.BondInd = SET_SESSION_UNCHANGED;         /* Leaves session bonding */
  4876.                                                      /* index unchanged        */
  4877.  
  4878.     DosSetSession(ulSessionID,
  4879.                   &stsdata);
  4880.  
  4881. Once a child session is made nonselectable, the user cannot select the session 
  4882. from the Window List or move to it by using the Alt+Esc keys. However, the 
  4883. parent session can still bring the child session to the foreground by using 
  4884. DosSelectSession. If the session contains a Presentation Manager application or 
  4885. is a windowed session, the user will still be able to select it with a mouse. 
  4886.  
  4887. The parent session can make a nonselectable child session selectable by setting 
  4888. the SelectInd field to SET_SESSION_SELECTABLE in the STATUSDATA structure. 
  4889. DosSetSession can be called only by a parent session and only for a child 
  4890. session. That is, the calling process must be the process that started the 
  4891. child session using DosStartSession. Neither the parent session itself nor any 
  4892. grandchild, nor any other descendant session beyond a child session can be the 
  4893. target of this call. 
  4894.  
  4895. Additionally, DosSetSession cannot be used to change the status of a session 
  4896. that was started as an unrelated session. The Related field in the STARTDATA 
  4897. structure must have been set to 1 when the session was started. 
  4898.  
  4899.  
  4900. ΓòÉΓòÉΓòÉ 5.5.2.2. Binding Child Sessions to Parent Sessions ΓòÉΓòÉΓòÉ
  4901.  
  4902. An application can use DosSetSession to establish a bond between a parent 
  4903. session and one of its child sessions. When the two sessions are bound, OS/2 
  4904. brings the child session to the foreground when the user selects the parent 
  4905. session. 
  4906.  
  4907. In the following code fragment, a parent session is bound to the child session 
  4908. specified by the ulSessionID parameter: 
  4909.  
  4910.     #define INCL_DOSPROCESS       /* Process and thread values */
  4911.     #define INCL_DOSSESMGR
  4912.     #include <os2.h>
  4913.  
  4914.     ULONG ulSessionID;
  4915.     STATUSDATA stsdata;
  4916.  
  4917.     stsdata.Length = sizeof(stsdata);
  4918.     stsdata.SelectInd = SET_SESSION_UNCHANGED;   /* Leaves select setting alone */
  4919.     stsdata.BondInd = SET_SESSION_BOND;          /* Binds parent and child      */
  4920.  
  4921.     DosSetSession(ulSessionID, &stsdata);
  4922.  
  4923. When the application uses DosSetSession to establish a parent-child bond, any 
  4924. bond the parent has with another child session is broken. The application can 
  4925. remove the parent-child bond by calling DosSetSession with the BondInd field 
  4926. (in the STATUSDATA structure) set to SET_SESSION_NO_BOND. 
  4927.  
  4928. A parent session can be executing in either the foreground or the background 
  4929. when it calls DosSetSession. 
  4930.  
  4931.  
  4932. ΓòÉΓòÉΓòÉ 5.5.2.3. Switching a Session to the Foreground ΓòÉΓòÉΓòÉ
  4933.  
  4934. An application can bring a session to the foreground, or select the session, by 
  4935. calling DosSelectSession. 
  4936.  
  4937. DosSelectSession can only be used to select the current session or one of the 
  4938. current session's child sessions. It cannot be used to select a grandchild 
  4939. session, or any other descendant session beyond a child session, or any 
  4940. sessions that were started as unrelated sessions. 
  4941.  
  4942. The session making the call, or one of its child sessions, must be executing in 
  4943. the foreground at the time the function is called. A process can call 
  4944. DosSelectSession with its own session identifier to switch itself to the 
  4945. foreground when one of its descendants is executing in the foreground. 
  4946.  
  4947. The following code fragment uses DosSelectSession to switch the child session 
  4948. specified by the ulSessionID parameter to the foreground for five seconds. The 
  4949. application then switches the parent session back to the foreground: 
  4950.  
  4951.     #define INCL_DOSPROCESS         /* Process and thread values   */
  4952.     #include <os2.h>
  4953.  
  4954.     ULONG ulSessionID;
  4955.  
  4956.     DosSelectSession(ulSessionID);   /* Switches child to foreground */
  4957.     DosSleep(5000);                  /* Sleeps for 5 seconds         */
  4958.     DosSelectSession(0);             /* Switches parent back         */
  4959.  
  4960.  
  4961. ΓòÉΓòÉΓòÉ 5.5.3. Terminating a Session ΓòÉΓòÉΓòÉ
  4962.  
  4963. DosStopSession can be used by a parent session to stop one or all of its child 
  4964. sessions. If the child session specified in the call to DosStopSession has 
  4965. related sessions, the related sessions are also ended. The parent session can 
  4966. be running in the foreground or the background when it calls DosStopSession. If 
  4967. the child session is running in the foreground when it is ended, the parent 
  4968. session becomes the foreground session. 
  4969.  
  4970. DosStopSession can only be called by a parent session for a child session. 
  4971. Neither the parent session itself, nor any grandchild, nor any other descendant 
  4972. session beyond a child session, nor any unrelated session, can be the target of 
  4973. this call. 
  4974.  
  4975. In the following code fragment, the child session specified by the ulSessionID 
  4976. parameter is ended: 
  4977.  
  4978.     #define INCL_DOSPROCESS       /* Process and thread values */
  4979.     #define INCL_DOSSESMGR
  4980.     #include <os2.h>
  4981.  
  4982.     ULONG ulSessionID;
  4983.  
  4984.     DosStopSession(STOP_SESSION_SPECIFIED,
  4985.                    ulSessionID);
  4986.  
  4987. An application can end all its child sessions by setting the first parameter to 
  4988. STOP_SESSION_ALL in the call to DosStopSession. If this is specified, the 
  4989. second parameter is ignored. 
  4990.  
  4991. A process running in a child session can ignore the request to end. If the 
  4992. process has set up its own exception handler, it might not end immediately 
  4993. after the call to DosStopSession. The only way the parent process can be 
  4994. certain that the child session has ended is to wait for notification through 
  4995. the termination queue specified in the call to DosStartSession that started the 
  4996. session. When the child session ends, OS/2 writes a data element into the 
  4997. termination queue, specifying the child process identifier and the termination 
  4998. status. 
  4999.  
  5000. If the process in the session specified by DosStopSession has not ended, then 
  5001. DosStopSession still returns a normal return code. You can ensure that a 
  5002. process in a session has ended by waiting for notification from the termination 
  5003. queue specified with DosStartSession. 
  5004.  
  5005.  
  5006. ΓòÉΓòÉΓòÉ 6. Queues ΓòÉΓòÉΓòÉ
  5007.  
  5008. Communication between processes is valuable in a multitasking operating system 
  5009. to enable concurrent processes to work together. Queues are one of three forms 
  5010. of interprocess communication (IPC), the other forms of IPC being semaphores 
  5011. and pipes. 
  5012.  
  5013. This chapter describes how to create and use queues. Queues enable one or more 
  5014. processes to transfer data to a specific target process. 
  5015.  
  5016. Note:  The queues used for interprocess communication should not to be confused 
  5017.        with the message queues used for communication between Presentation 
  5018.        Manager (PM) and PM applications, nor with the printer queues used by 
  5019.        the print spooler in managing print jobs. 
  5020.  
  5021.  The following topics are related to the information in this chapter: 
  5022.  
  5023.      Memory (shared memory) 
  5024.      Program execution and control 
  5025.      Semaphores 
  5026.      Pipes 
  5027.  
  5028.  
  5029. ΓòÉΓòÉΓòÉ 6.1. About Queues ΓòÉΓòÉΓòÉ
  5030.  
  5031. A queue is a named, ordered list of elements that is used to pass information 
  5032. between threads of the same (related) process or between different (unrelated) 
  5033. processes. 
  5034.  
  5035. Processes pass information to a queue in the form of elements. An element is a 
  5036. 32-bit unit of information. Queue elements can be values, flags, pointers to 
  5037. shared memory regions, anything that can fit into 32 bits. The format of a 
  5038. queue element depends entirely on the process that creates the queue (the queue 
  5039. owner). Only the queue owner can read elements from the queue; other processes 
  5040. can only write to the queue. Reading an element automatically removes it from 
  5041. the queue. 
  5042.  
  5043. The process that creates the queue is known as the server process of the queue. 
  5044. The other processes that access the queue are known as client processes. 
  5045.  
  5046. The owner of the queue (the server process) can choose the order in which to 
  5047. read incoming information and can examine queue elements without removing them 
  5048. from the queue. Queue elements can be added and accessed in First-In-First-Out 
  5049. (FIFO), Last-In-First-Out (LIFO), or priority-based order. 
  5050.  
  5051. Any process that has the name of a queue can open the queue and write to it. 
  5052. The processes writing elements to the queue must use the format determined by 
  5053. the queue owner. 
  5054.  
  5055. Queues are very efficient. They pass only 32-bit sized elements, rather than 
  5056. large data structures. However, queues can be used only for one-way 
  5057. communication, because a client process can write to a queue but cannot read 
  5058. from one. 
  5059.  
  5060. Typically, processes use queues to transfer information about the contents of a 
  5061. shared memory. The elements in the queue could contain the address and length 
  5062. of data areas in shared memory objects. The sending process allocates a shared 
  5063. memory object and gives access to the shared memory to the queue owner. The 
  5064. sending process can free the shared memory after writing the elements to the 
  5065. queue because the shared memory will not be deallocated until the queue owner 
  5066. frees it. 
  5067.  
  5068. Any thread in the process that owns the queue can examine queue elements 
  5069. without removing them. This is called peeking at the queue. 
  5070.  
  5071. OS/2 supplies the process identifier of the process that writes an element to 
  5072. the queue, so that a process reading from or peeking at the queue can determine 
  5073. the origin of the element. The process identifier is returned as part of a 
  5074. REQUESTDATA data structure. Threads can use the ulData field of the REQUESTDATA 
  5075. data structure to pass additional information about the queue element. 
  5076.  
  5077. If the queue is empty when a process attempts to read from it, the process can 
  5078. either wait for an element to become available or continue executing without 
  5079. reading from the queue. Semaphores can be used to indicate when an element is 
  5080. in the queue. 
  5081.  
  5082.  
  5083. ΓòÉΓòÉΓòÉ 6.1.1. Queues and Semaphores ΓòÉΓòÉΓòÉ
  5084.  
  5085. If a process manages only one queue, it typically waits for an element to 
  5086. become available. However, if a process manages several queues, waiting for one 
  5087. queue means that other queues cannot be read. To avoid wasting time while 
  5088. waiting, a process can supply an event semaphore when it calls DosReadQueue or 
  5089. DosPeekQueue. The process can then continue to execute without actually reading 
  5090. an element from the queue, because DosWriteQueue will post the semaphore only 
  5091. when an element is ready. The semaphore remains posted until someone resets it; 
  5092. usually  the queue owner process resets the semaphore after it reads all the 
  5093. available information from the queue. 
  5094.  
  5095. If a process uses a unique semaphore for each queue, it can use 
  5096. DosWaitMuxWaitSem to wait for the first queue to receive an element. 
  5097.  
  5098. Only one semaphore is permitted per queue. 
  5099.  
  5100.  
  5101. ΓòÉΓòÉΓòÉ 6.1.2. Queue Servers and Clients ΓòÉΓòÉΓòÉ
  5102.  
  5103. The server process and its threads have certain queue-managing privileges. Only 
  5104. the server process and its threads can: 
  5105.  
  5106.      Examine queue elements without removing them (DosPeekQueue) 
  5107.      Remove elements from the queue (DosReadQueue) 
  5108.      Purge all the elements in a queue (DosPurgeQueue) 
  5109.      Write to the queue without opening it first (DosWriteQueue) 
  5110.      Delete the queue (DosCloseQueue). 
  5111.  Both server and client processes can query the number of elements in the queue 
  5112.  using DosQueryQueue. 
  5113.  
  5114.  Client processes can query the queue (DosQueryQueue) and add elements to it 
  5115.  (DosWriteQueue), but they must first gain access to the queue by calling 
  5116.  DosOpenQueue. When a client process is finished with a queue, it ends its 
  5117.  access to the queue by calling DosCloseQueue. (Note that, unlike the server 
  5118.  process and its threads, a client process cannot use DosCloseQueue to delete a 
  5119.  queue.) 
  5120.  
  5121.  When a queue is opened by a client process, an access count is set to 1. Each 
  5122.  client process has its own access count. The access count is incremented 
  5123.  whenever a thread in a process opens the queue and decremented whenever a 
  5124.  thread in the process closes the queue. Access to the queue by the client 
  5125.  process ends when the access count for the process reaches 0. When the server 
  5126.  process closes the queue, the queue is terminated and removed from the system. 
  5127.  
  5128.  
  5129. ΓòÉΓòÉΓòÉ 6.1.3. Queue Element Order ΓòÉΓòÉΓòÉ
  5130.  
  5131. DosReadQueue reads either a specified element or the first element in the 
  5132. queue. The first element in the queue depends on the queue type, which is 
  5133. specified when the queue is created. A queue can have FIFO, LIFO, or priority 
  5134. ordering. 
  5135.  
  5136. Priority values range from 0 (lowest priority) through 15 (highest priority). 
  5137. The writing process assigns a priority to a queue element when the element is 
  5138. written to the queue. DosReadQueue reads elements from the queue in descending 
  5139. order of priority, regardless of the order in which DosWriteQueue placed the 
  5140. elements in the queue. Elements with equal priority are read in FIFO order. 
  5141.  
  5142.  
  5143. ΓòÉΓòÉΓòÉ 6.1.4. Obtaining Information about Queues and Queue Elements ΓòÉΓòÉΓòÉ
  5144.  
  5145. Any thread in the process that owns the queue can use DosPeekQueue to examine 
  5146. the elements in the queue to determine which one to actually read. Each call to 
  5147. DosPeekQueue returns the identifier of the next element in the queue, so the 
  5148. function can be called repeatedly to move through the queue. The identifier of 
  5149. the desired element can then be supplied to DosReadQueue. 
  5150.  
  5151. Any process that has opened a queue can use DosQueryQueue to determine the 
  5152. number of elements in the queue. This function also returns an error value if 
  5153. the queue owner has closed the queue. 
  5154.  
  5155.  
  5156. ΓòÉΓòÉΓòÉ 6.2. Using Queues ΓòÉΓòÉΓòÉ
  5157.  
  5158. Queues are useful for a process to manage input from other processes. The 
  5159. examples in the following sections show how to create and use queues. 
  5160.  
  5161. Note:  In the example code fragments that follow, error checking was left out 
  5162.        to conserve space. Applications should always check the return code that 
  5163.        the functions return. Control Program functions return an APIRET value. 
  5164.        A return code of 0 indicates success. If a non-zero value is returned, 
  5165.        an error occurred. 
  5166.  
  5167.  
  5168. ΓòÉΓòÉΓòÉ 6.2.1. Creating a Queue ΓòÉΓòÉΓòÉ
  5169.  
  5170. A thread creates a queue by using DosCreateQueue and specifying a queue name 
  5171. and the queue type as arguments. The queue name must be unique and have the 
  5172. following form: 
  5173.  
  5174.     \QUEUES\QueName
  5175.  
  5176. The "\QUEUES\" is required, though it need not be uppercase.  It is not a 
  5177. subdirectory. 
  5178.  
  5179. The QueName parameter must conform to the rules for OS/2 file names, although 
  5180. no actual file is created for the queue. 
  5181.  
  5182. The process that creates the queue is known as the server process of the queue. 
  5183. The other processes that access the queue are known as client processes. 
  5184.  
  5185. The following code fragment creates a FIFO queue named \queues\sample.que: 
  5186.  
  5187.     #define INCL_DOSQUEUES   /* Queue values */
  5188.     #include <os2.h>
  5189.  
  5190.     HQUEUE hq;
  5191.  
  5192.     DosCreateQueue(&hq, QUE_FIFO |
  5193.                    QUE_CONVERT_ADDRESS,
  5194.                    "\\queues\\sample.que");
  5195.  
  5196. When the server process creates the queue, it determines whether the ordering 
  5197. of queue elements is based on arrival (FIFO or LIFO) or priority. If the 
  5198. ordering is based on priority, then priority values must be assigned whenever 
  5199. data is added to the queue. 
  5200.  
  5201. The server must also specify whether OS/2 is to convert 16-bit addresses of 
  5202. elements placed in the queue by 16-bit processes to 32-bit addresses. 
  5203.  
  5204. After a process has created a queue, any thread in that process can access the 
  5205. queue with equal authority. 
  5206.  
  5207.  
  5208. ΓòÉΓòÉΓòÉ 6.2.2. Allocating Memory for Queue Data ΓòÉΓòÉΓòÉ
  5209.  
  5210. When queues are used only to pass the addresses to data rather than the data 
  5211. itself, processes must allocate shared memory objects for storing queue data. 
  5212. The two most common methods of storing queue data are: 
  5213.  
  5214.      Using a named shared memory object - for related processes 
  5215.      Using unnamed shared memory objects - for unrelated processes 
  5216.  
  5217.  
  5218. ΓòÉΓòÉΓòÉ 6.2.2.1. Named Shared Memory Objects ΓòÉΓòÉΓòÉ
  5219.  
  5220. Related processes generally use a single named shared memory object for storing 
  5221. queue data.  The server process allocates the memory object by calling 
  5222. DosAllocSharedMem. Care must be taken to ensure that the memory object is large 
  5223. enough to meet application requirements. 
  5224.  
  5225. The name of the shared memory object is established by agreement among the 
  5226. server and the client processes. For simplicity, the name can be the same as 
  5227. the queue name, except that the prefix \SHAREMEM\ must be used instead of 
  5228. \QUEUES\. 
  5229.  
  5230. A client process accesses the named shared memory object by calling 
  5231. DosGetNamedSharedMem. It must then call DosOpenQueue to gain access to the 
  5232. queue of the server. 
  5233.  
  5234. Before the server process ends, it releases the memory object by calling 
  5235. DosFreeMem. 
  5236.  
  5237.  
  5238. ΓòÉΓòÉΓòÉ 6.2.2.2. Unnamed Shared Memory Objects ΓòÉΓòÉΓòÉ
  5239.  
  5240. Unrelated processes generally use unnamed shared memory objects for storing 
  5241. queue data. This makes it possible for a client process to store data in a 
  5242. shared memory object without knowing its name. To use unnamed shared memory 
  5243. objects for storing queue data, the server process must take the following 
  5244. steps whenever it is called by a client: 
  5245.  
  5246.    1. Save the process identification (PID) of the client process. 
  5247.    2. Allocate an unnamed shared memory object for the data of the client 
  5248.       process by calling DosAllocSharedMem. 
  5249.    3. Give the client process the capability of accessing the memory object by 
  5250.       calling DosGiveSharedMem with the client's PID. 
  5251.  The client process must then call DosOpenQueue to gain access to the server's 
  5252.  queue. 
  5253.  
  5254.  After each client completes its queue requests or ends, the server calls 
  5255.  DosFreeMem to release the client's memory object. 
  5256.  
  5257.  
  5258. ΓòÉΓòÉΓòÉ 6.2.3. Opening a Queue ΓòÉΓòÉΓòÉ
  5259.  
  5260. Once the queue is created, the server process of the queue and the threads of 
  5261. the server process have immediate access to the queue and can proceed to access 
  5262. the queue. A client process must request access to a queue by calling 
  5263. DosOpenQueue. Once the queue is open, the client process can add an element to 
  5264. the queue with DosWriteQueue, and it can query the number of elements in the 
  5265. queue with DosQueryQueue. 
  5266.  
  5267. DosOpenQueue retrieves the queue handle and the process identifier of the queue 
  5268. owner. The function also increments the queue's access count. 
  5269.  
  5270. The following code fragment shows how another process would open the queue 
  5271. created with DosCreateQueue. 
  5272.  
  5273.     #define INCL_DOSQUEUES
  5274.     #include<os2.h>
  5275.  
  5276.     #define HF_STDOUT 1    /* Standard output handle */
  5277.  
  5278.     HQUEUE  hq;
  5279.     PID     pidOwner;
  5280.     ULONG   ulWritten;
  5281.     APIRET  ulrc;
  5282.  
  5283.     ulrc = DosOpenQueue(&pidOwner,
  5284.                         &hq,
  5285.                         "\\queues\\sample.que");
  5286.  
  5287.     if (ulrc) {
  5288.         DosWrite(HF_STDOUT,
  5289.                  "\r\n Queue open failed. \r\n",
  5290.                  24,
  5291.                  &ulWritten);
  5292.  
  5293.         DosExit(EXIT_PROCESS,
  5294.                 1);
  5295.     }
  5296.     else {
  5297.         DosWrite(HF_STDOUT,
  5298.                  "\r\n Queue opened. \r\n",
  5299.                  19,
  5300.                  &ulWritten);
  5301.     }
  5302.  
  5303. When it is finished with the queue, a thread in the client process ends its 
  5304. access by calling DosCloseQueue. DosCloseQueue decrements the access count for 
  5305. the process each time it is called. When the access count reaches 0, the 
  5306. connection between the client process and the queue is terminated. 
  5307.  
  5308. After a process has opened a queue, any thread in that process can access the 
  5309. queue with equal authority. 
  5310.  
  5311. Note:  If a queue was created by a call to the 16-bit DosCreateQueue, then it 
  5312.        is not accessible to 32-bit DosOpenQueue requests, and 
  5313.        ERROR_QUE_PROC_NO_ACCESS will be returned. 
  5314.  
  5315.  
  5316. ΓòÉΓòÉΓòÉ 6.2.4. Writing to a Queue ΓòÉΓòÉΓòÉ
  5317.  
  5318. The server process and any of its threads can add an element to a queue simply 
  5319. by calling DosWriteQueue. A client process, however, must first request access 
  5320. to the queue by calling DosOpenQueue. 
  5321.  
  5322. Processes that communicate by passing the addresses of shared memory objects 
  5323. through the queue must have a shared memory object that they each have access 
  5324. to. Once a process opens the queue, it can allocate shared memory by using 
  5325. DosAllocMem with the OBJ_GIVEABLE attribute and then give the shared memory to 
  5326. the queue owner with DosGiveSharedMem. 
  5327.  
  5328. A process that has opened a queue can write to the queue by using 
  5329. DosWriteQueue. The writing process must create elements in a form that the 
  5330. queue owner can read. 
  5331.  
  5332. The following code fragment adds an element to a queue. Assume that the caller 
  5333. has placed the handle of the queue into QueueHandle already. Assume also that 
  5334. DataBuffer has been set to point to a data element in shared memory, and that 
  5335. DataLength has been set to contain the length of the data element in shared 
  5336. memory. 
  5337.  
  5338.     #define INCL_DOSQUEUES   /* Queue values */
  5339.     #include <os2.h>
  5340.     #include <stdio.h>
  5341.  
  5342.     HQUEUE   hqQueueHandle;   /* Queue handle                         */
  5343.     ULONG    ulRequest;       /* Request-identification data          */
  5344.     ULONG    ulDataLength;    /* Length of element being added        */
  5345.     PVOID    pDataBuffer;     /* Element being added                  */
  5346.     ULONG    ulElemPriority;  /* Priority of element being added      */
  5347.     APIRET   ulrc;            /* Return code                          */
  5348.  
  5349.     ulRequest = 0;            /* Assume that no special data is being */
  5350.                               /* sent along with this write request   */
  5351.  
  5352.     ulElemPriority = 0;       /* For priority-based queues: add the   */
  5353.                               /* new queue element at the logical end */
  5354.                               /* of the queue                         */
  5355.  
  5356.     ulrc = DosWriteQueue(hqQueueHandle,
  5357.                          ulRequest,
  5358.                          ulDataLength,
  5359.                          pDataBuffer,
  5360.                          ulElemPriority);
  5361.  
  5362.     if (ulrc != 0) {
  5363.         printf("DosWriteQueue error: return code = %ld",
  5364.                ulrc);
  5365.         return;
  5366.     }
  5367.  
  5368. Once the process has written to the queue, it frees the shared memory. However, 
  5369. the memory will not be freed until the queue owner also frees it. 
  5370.  
  5371. If the queue was created as a priority-based queue (as specified in the 
  5372. QueueFlags parameter of DosCreateQueue), then the priority of the element that 
  5373. is being added must be specified. 
  5374.  
  5375. If the server process has ended, or if it has closed the queue before 
  5376. DosWriteQueue is called, then ERROR_QUE_INVALID_HANDLE is returned. 
  5377.  
  5378.  
  5379. ΓòÉΓòÉΓòÉ 6.2.5. Reading from a Queue ΓòÉΓòÉΓòÉ
  5380.  
  5381. The queue owner (server process) and its threads can read an element from the 
  5382. queue by using DosReadQueue. The owner can read the first element in the queue 
  5383. by specifying 0 as the element number. Alternatively, the owner can read a 
  5384. particular element in the queue by specifying an element code returned from 
  5385. DosPeekQueue. This function is not available to client processes. 
  5386.  
  5387. DosReadQueue can either remove queue elements in the order that was specified 
  5388. when the queue was created (FIFO, LIFO, or priority), or it can use an element 
  5389. identifier from DosPeekQueue as input to remove a previously examined element. 
  5390.  
  5391. The following code fragment reads an element from the queue. Assume that the 
  5392. caller has placed the handle of the queue into QueueHandle already and that the 
  5393. identifier of the process that owns the queue has been placed into OwningPID 
  5394. already. 
  5395.  
  5396.     #define INCL_DOSQUEUES   /* Queue values */
  5397.     #include <os2.h>
  5398.     #include <stdio.h>
  5399.  
  5400.     HQUEUE        hqQueueHandle;   /* Queue handle                 */
  5401.     REQUESTDATA   rqRequest;       /* Request-identification data  */
  5402.     ULONG         ulDataLength;    /* Length of element received   */
  5403.     PULONG        pulDataAddress;  /* Address of element received  */
  5404.     ULONG         ulElementCode;   /* Request a particular element */
  5405.     BOOL32        bNoWait;         /* No wait if queue is empty    */
  5406.     BYTE          bElemPriority;   /* Priority of element received */
  5407.     HEV           hevSemHandle;    /* Semaphore handle             */
  5408.     PID           pidOwningPID;    /* PID of queue owner           */
  5409.     APIRET        ulrc;            /* Return code                  */
  5410.  
  5411.     rqRequest.pid = pidOwningPID;     /* Set request data block to indicate  */
  5412.                                       /* queue owner                         */
  5413.  
  5414.     ulElementCode = 0;                /* Indicate that the read should start */
  5415.                                       /* at the front of the queue           */
  5416.  
  5417.     bNoWait = 0;                      /* Indicate that the read should wait  */
  5418.                                       /* if the queue is currently empty     */
  5419.  
  5420.     hevSemHandle = 0;                 /* Unused since this is a call that    */
  5421.                                       /* waits synchronously                 */
  5422.  
  5423.     ulrc = DosReadQueue(hqQueueHandle,
  5424.                         &rqRequest,
  5425.                         &ulDataLength,
  5426.                         (PVOID *) &pulDataAddress,
  5427.                         ulElementCode,
  5428.                         bNoWait,
  5429.                         &bElemPriority,
  5430.                         hevSemHandle);
  5431.  
  5432.     if (ulrc != 0) {
  5433.         printf("DosReadQueue error: return code = %ld",
  5434.                ulrc);
  5435.         return;
  5436.     }
  5437.  
  5438. On successful return, DataLength contains the size of the element on the queue 
  5439. that is pointed to by the pointer within DataAddress, ElemPriority has been 
  5440. updated to contain the priority of the queue element pointed to by DataAddress, 
  5441. and Request.ulData contains any special data that the DosWriteQueue caller 
  5442. placed into the queue. 
  5443.  
  5444. If the queue is empty and NoWait is set to DCWW_WAIT (0), the calling thread 
  5445. waits until an element is placed in the queue. If the queue is empty and NoWait 
  5446. is set to DCWW_NOWAIT (1), DosReadQueue returns immediately with 
  5447. ERROR_QUE_EMPTY. 
  5448.  
  5449. If NoWait is set to DCWW_NOWAIT, an event semaphore must be provided so that 
  5450. the calling thread can determine when an element has been placed in the queue. 
  5451. The semaphore is created by calling DosCreateEventSem, and its handle is 
  5452. supplied as a DosReadQueue parameter. The first time an event semaphore handle 
  5453. is supplied in a DosReadQueue or DosPeekQueue request for which DCWW_NOWAIT has 
  5454. been specified for a particular queue, the handle is saved by the system. The 
  5455. same handle must be supplied in all subsequent DosReadQueue and DosPeekQueue 
  5456. requests that are called for that queue; if a different handle is supplied, 
  5457. ERROR_INVALID_PARAMETER is returned. 
  5458.  
  5459. When a client process adds an element to the queue, the system automatically 
  5460. opens the semaphore (if necessary) and posts it. The server can either call 
  5461. DosQueryEventSem periodically to determine whether the semaphore has been 
  5462. posted, or it can call DosWaitEventSem. DosWaitEventSem causes the calling 
  5463. thread to block until the semaphore is posted. 
  5464.  
  5465. After the event semaphore has been posted, the calling thread must call 
  5466. DosReadQueue again to remove the newly added queue element. 
  5467.  
  5468. If QUE_CONVERT_ADDRESS is specified in the call to DosCreateQueue, OS/2 will 
  5469. automatically convert 16-bit addresses to 32-bit addresses. 
  5470.  
  5471.  
  5472. ΓòÉΓòÉΓòÉ 6.2.6. Peeking at a Queue ΓòÉΓòÉΓòÉ
  5473.  
  5474. The server process and its threads can examine a queue element by calling 
  5475. DosPeekQueue. This function is not available to client processes. 
  5476.  
  5477. Unlike DosReadQueue, DosPeekQueue does not remove the element from the queue. 
  5478.  
  5479. DosPeekQueue can either examine elements in the order that was specified when 
  5480. the queue was created (FIFO, LIFO, or priority), or it can examine the next 
  5481. element in the queue after a previous DosPeekQueue request has been called. By 
  5482. making multiple DosPeekQueue requests, the server process can search through a 
  5483. queue, examining each element in turn. When it locates the element it is 
  5484. searching for, the server process can remove the element from the queue by 
  5485. calling DosReadQueue. 
  5486.  
  5487. If several threads are using the same queue, the process writing to the queue 
  5488. can use the ulData field of the REQUESTDATA data structure to indicate that an 
  5489. element is directed to a particular thread. The thread can peek at the queue 
  5490. whenever data is available and read any elements containing the appropriate 
  5491. value in the ulData field. 
  5492.  
  5493. The following code fragment shows how a thread can use DosPeekQueue to examine 
  5494. the elements in a queue. Assume that a previous call to DosOpenQueue provided 
  5495. the queue handle that is contained in QueueHandle. Assume that the identifier 
  5496. of the process that owns the queue has been placed into OwningPID already. 
  5497.  
  5498.     #define INCL_DOSQUEUES       /* Queue values */
  5499.     #define INCL_DOSPROCESS      /* needed for DCWW_WAIT */
  5500.  
  5501.     #include <os2.h>
  5502.     #include <stdio.h>
  5503.  
  5504.     HQUEUE        hqQueueHandle;   /* Queue handle                  */
  5505.     REQUESTDATA   rqRequest;       /* Request-identification data   */
  5506.     ULONG         ulDataLength;    /* Length of examined element    */
  5507.     PVOID         pDataAddress;    /* Address of examined element   */
  5508.     ULONG         ulElementCode;   /* Indicator of examined element */
  5509.     BOOL32        bNoWait;         /* No wait if queue is empty     */
  5510.     BYTE          bElemPriority;   /* Priority of examined element  */
  5511.     HEV           hevSemHandle;    /* Semaphore handle              */
  5512.     PID           pidOwningPID;    /* PID of queue owner            */
  5513.     APIRET        ulrc;            /* Return code                   */
  5514.  
  5515.     rqRequest.pid = pidOwningPID; /* Set request data block to indicate   */
  5516.                                   /* queue owner                          */
  5517.  
  5518.     ulElementCode = 0;           /* Indicate that the peek should start  */
  5519.                                  /* at the front of the queue            */
  5520.  
  5521.     bNoWait = DCWW_WAIT;          /* Indicate that the peek call should   */
  5522.                                   /* wait if the queue is currently empty */
  5523.  
  5524.     hevSemHandle = 0;             /* Unused since this is a call that     */
  5525.                                   /* synchronously waits                  */
  5526.  
  5527.     ulrc = DosPeekQueue(hqQueueHandle,
  5528.                         &rqRequest,
  5529.                         &ulDataLength,
  5530.                         &pDataAddress,
  5531.                         &ulElementCode,
  5532.                         bNoWait,
  5533.                         &bElemPriority,
  5534.                         hevSemHandle);
  5535.  
  5536.     if (ulrc != 0) {
  5537.         printf("DosPeekQueue error: return code = %ld",
  5538.                ulrc);
  5539.         return;
  5540.     }
  5541.  
  5542. On successful return, DataLength contains the size of the element on the queue 
  5543. that is pointed to by the pointer within DataAddress, ElementCode has been 
  5544. updated to indicate the next queue element, ElemPriority has been updated to 
  5545. contain the priority of the queue element pointed to by DataAddress, and 
  5546. Request.ulData contains any special data that the DosWriteQueue caller placed 
  5547. into the queue. 
  5548.  
  5549. If the queue is empty and NoWait is set to DCWW_WAIT (0), the calling thread 
  5550. waits until an element is placed in the queue. If the queue is empty and NoWait 
  5551. is set to DCWW_NOWAIT (1), DosPeekQueue returns immediately with 
  5552. ERROR_QUE_EMPTY. 
  5553.  
  5554. If NoWait is set to DCWW_NOWAIT, an event semaphore must be provided so that 
  5555. the calling thread can determine when an element has been placed in the queue. 
  5556. The semaphore is created by calling DosCreateEventSem, and its handle is 
  5557. supplied as a DosPeekQueue parameter. The first time an event semaphore handle 
  5558. is supplied in a DosPeekQueue or DosReadQueue request for which DCWW_NOWAIT has 
  5559. been specified for a particular queue, the handle is saved by the system. The 
  5560. same handle must be supplied in all subsequent DosPeekQueue and DosReadQueue 
  5561. requests that are called for that queue; if a different handle is supplied, 
  5562. ERROR_INVALID_PARAMETER is returned. 
  5563.  
  5564. When a client process adds an element to the queue, the system automatically 
  5565. opens the semaphore (if necessary) and posts it. The server can either call 
  5566. DosQueryEventSem periodically to determine whether the semaphore has been 
  5567. posted, or it can call DosWaitEventSem. DosWaitEventSem causes the calling 
  5568. thread to block until the semaphore is posted. 
  5569.  
  5570. After the event semaphore has been posted, the calling thread must call 
  5571. DosPeekQueue again to examine the newly added queue element. 
  5572.  
  5573. If QUE_CONVERT_ADDRESS is specified in the call to DosCreateQueue, OS/2 will 
  5574. automatically convert 16-bit addresses to 32-bit addresses. 
  5575.  
  5576.  
  5577. ΓòÉΓòÉΓòÉ 6.2.7. Purging a Queue ΓòÉΓòÉΓòÉ
  5578.  
  5579. The server process or any of its threads can empty a queue of all its elements 
  5580. by calling DosPurgeQueue. This function is not available to client processes. 
  5581.  
  5582. Warning: This is an unconditional purge of all elements in the queue. 
  5583.  
  5584. The following code fragment shows how the owner of a queue can empty the queue 
  5585. of all data elements. Assume that the owner of the queue has saved the queue's 
  5586. handle (obtained in a previous call to DosCreateQueue) in QueueHandle. 
  5587.  
  5588.     #define INCL_DOSQUEUES    /* Queue values */
  5589.     #include <os2.h>
  5590.     #include <stdio.h>
  5591.  
  5592.     HQUEUE   hqQueueHandle;     /* Queue handle */
  5593.     APIRET   ulrc;              /* Return code  */
  5594.  
  5595.     ulrc = DosPurgeQueue(hqQueueHandle);
  5596.  
  5597.     if (ulrc != 0) {
  5598.         printf("DosPurgeQueue error: return code = %ld",
  5599.                ulrc);
  5600.         return;
  5601.     }
  5602.  
  5603.  
  5604. ΓòÉΓòÉΓòÉ 6.2.8. Closing a Queue ΓòÉΓòÉΓòÉ
  5605.  
  5606. DosCloseQueue can be used both to end access to a queue and to delete a queue. 
  5607. The action taken as a result of a DosCloseQueue request depends on: 
  5608.  
  5609.      Whether the requesting process is the server process or a client process 
  5610.      The value of the access count, which is maintained for each client 
  5611.       process by OS/2. The access count for a client process is incremented 
  5612.       whenever DosOpenQueue is called, and decremented whenever DosCloseQueue 
  5613.       is called. 
  5614.  
  5615.  If the requesting process is a client, and the access count equals 0, 
  5616.  DosCloseQueue ends the client's access to the queue, but the queue itself is 
  5617.  not affected. If the access count does not equal 0, the count is decremented, 
  5618.  but the process retains access to the queue. 
  5619.  
  5620.  If the requesting process is the server, DosCloseQueue purges any outstanding 
  5621.  elements from the queue and deletes the queue regardless of the access count; 
  5622.  client processes that still have the queue open receive 
  5623.  ERROR_QUE_INVALID_HANDLE on their next request. 
  5624.  
  5625.  
  5626. ΓòÉΓòÉΓòÉ 7. Semaphores ΓòÉΓòÉΓòÉ
  5627.  
  5628. Communication between processes is valuable in a multitasking operating system 
  5629. to enable concurrent processes to work together. Semaphores are one of three 
  5630. forms of interprocess communication (IPC), the other forms of IPC being pipes 
  5631. and queues. 
  5632.  
  5633. This chapter describes how to create and use semaphores. Semaphores enable an 
  5634. application to signal the completion of tasks and control access to resources 
  5635. that are shared between more than one thread or process. 
  5636.  
  5637. The following topics are related to the information in this chapter: 
  5638.  
  5639.      Memory (shared memory) 
  5640.      Program execution and control 
  5641.      Pipes 
  5642.      Queues 
  5643.  
  5644.  
  5645. ΓòÉΓòÉΓòÉ 7.1. About Semaphores ΓòÉΓòÉΓòÉ
  5646.  
  5647. Semaphores signal the beginning or ending of an operation and provide mutually 
  5648. exclusive ownership of resources. Typically, semaphores are used to prevent 
  5649. more than one process or thread within a process from accessing a resource, 
  5650. such as shared memory, at the same time. 
  5651.  
  5652. Semaphores are defined by OS/2 and reside in an internal memory buffer. They 
  5653. are divided into three types, according to the functionality they provide: 
  5654.  
  5655.      Event semaphores enable a thread to notify waiting threads that an event 
  5656.       has occurred. The waiting threads then resume execution, performing 
  5657.       operations that are dependent on the completion of the signaled event. 
  5658.  
  5659.      Mutual exclusion (mutex) semaphores enable threads to serialize their 
  5660.       access to shared resources. That is, ownership of a mutex semaphore is 
  5661.       used by cooperating threads as a prerequisite for performing operations 
  5662.       on a resource. (Threads cooperate by using the mutex semaphore functions 
  5663.       to ensure that access to the resource is mutually exclusive.) 
  5664.  
  5665.      Multiple wait (muxwait) semaphores enable threads to wait either for 
  5666.       multiple events to occur, or for multiple resources to become available. 
  5667.       Alternatively, a flag can be set so that a thread waits for any one of 
  5668.       multiple events to occur, or for any one of multiple resources to become 
  5669.       available. 
  5670.  
  5671.  
  5672. ΓòÉΓòÉΓòÉ 7.1.1. Event Semaphores ΓòÉΓòÉΓòÉ
  5673.  
  5674. An event semaphore provides a signaling mechanism among threads or processes, 
  5675. ensuring that events occur in the desired sequence. Event semaphores are used 
  5676. by one thread to signal other threads that an event has occurred. An 
  5677. application can use this type of semaphore to block a thread or process until 
  5678. the event has occurred. 
  5679.  
  5680. An event semaphore has two states, reset and posted. When an event semaphore is 
  5681. in the reset state, OS/2 blocks any thread or process that is waiting on the 
  5682. semaphore. When an event semaphore is in the posted state, all threads or 
  5683. processes waiting on the semaphore resume execution. 
  5684.  
  5685. For example, assume thread 1 is allocating a shared memory object and threads 2 
  5686. and 3 must wait for the memory to be allocated before they attempt to examine 
  5687. its contents. Before thread 1 allocates the memory, it creates an event 
  5688. semaphore, specifying the initial state of the semaphore as reset. (If the 
  5689. event semaphore has already been created, thread 1 simply resets the 
  5690. semaphore.) Threads 2 and 3 use DosWaitEventSem to wait for the semaphore to 
  5691. signal that the event, in this case the allocation and preparation of the 
  5692. shared memory object, has been completed. Because the semaphore was reset by 
  5693. thread 1, threads 2 and 3 are blocked when they call DosWaitEventSem. After 
  5694. thread 1 has finished allocating and placing data in the shared memory object, 
  5695. it signals the completion of its task by posting the event semaphore. The 
  5696. posting of the event semaphore unblocks threads 2 and 3, enabling them to 
  5697. resume execution. They can then proceed to examine the contents of the 
  5698. allocated memory. 
  5699.  
  5700. In the example above, one thread controls the resetting and posting of the 
  5701. event semaphore, while other threads merely wait on the semaphore. Another 
  5702. approach could be for an application or thread to reset an event semaphore, 
  5703. then block itself on that semaphore. At a later time, another application or 
  5704. thread would post the event semaphore, unblocking the first thread. 
  5705.  
  5706.  
  5707. ΓòÉΓòÉΓòÉ 7.1.2. Mutual Exclusion (Mutex) Semaphores ΓòÉΓòÉΓòÉ
  5708.  
  5709. A mutual exclusion (mutex) semaphore protects resources (such as files, data in 
  5710. memory, and peripheral devices) from simultaneous access by several processes. 
  5711. Mutex semaphores enable threads to serialize their access to resources. It does 
  5712. so by preventing the processes from concurrently executing the sections of code 
  5713. through which access is made. These sections of code are called critical 
  5714. sections. For example, a mutex semaphore could be used to prevent two or more 
  5715. threads from simultaneously writing to the same file on a disk. 
  5716.  
  5717. Before a thread can execute a mutex-protected critical section, it must request 
  5718. and receive ownership of the mutex semaphore. Only the thread that has gained 
  5719. ownership of the mutex semaphore is permitted to perform operations on the 
  5720. protected resource. Only one thread at a time can own the mutex semaphore, and 
  5721. the owner thread retains ownership  until it finishes executing its critical 
  5722. section. When finished, the owner thread releases the mutex semaphore, enabling 
  5723. another thread to become the owner. 
  5724.  
  5725. When a thread requests ownership of a mutex semaphore that is already owned, 
  5726. OS/2 blocks the thread. When more than one thread requests ownership of the 
  5727. same semaphore, OS/2 queues the requests and grants subsequent ownership based 
  5728. on the thread's priority and the order in which the requests were received. 
  5729.  
  5730. If more than one thread is blocked on a DosRequestMutexSem request, then 
  5731. ownership is given to the thread that has the highest priority level. If more 
  5732. than one of the waiting threads have the same priority level, then FIFO 
  5733. ordering is used to determine which thread is unblocked and given ownership of 
  5734. the semaphore. 
  5735.  
  5736. For example, both thread 1 and thread 2 must write information to the same disk 
  5737. file. Thread 1 claims ownership of an agreed-upon mutex semaphore and starts 
  5738. writing its information to the file. If thread 2 also requests ownership of the 
  5739. semaphore, it will be blocked. When thread 1 has finished writing to the file, 
  5740. it releases the semaphore. OS/2 then unblocks thread 2 and designates it as the 
  5741. new owner of the semaphore so that it can write to the file. 
  5742.  
  5743. During process termination, after delivery of process-termination exceptions 
  5744. and unwind exceptions, if any threads in the process aside from Thread 1 (the 
  5745. main thread) own a mutex semaphore, ownership of the semaphore (and therefore, 
  5746. the shared resource) passes to Thread 1. This gives Thread 1 a last chance to 
  5747. clean up the semaphore and the shared resource before the process ends. If 
  5748. Thread 1 ends without releasing the semaphore, all threads that are currently 
  5749. waiting on ownership of the semaphore will be unblocked with the SEM_OWNER_DIED 
  5750. return code. Any thread that attempts to open it or request ownership of the 
  5751. semaphore will receive a SEM_OWNER_DIED return code. 
  5752.  
  5753. The recommended way to clean up semaphores, and other resources, is for each 
  5754. thread, especially Thread 1, to have an exception handler to handle clean up 
  5755. during process termination (the XCPT_PROCESS_TERMINATE or 
  5756. XCPT_ASYNC_PROCESS_TERMINATE exceptions). When it is not possible to register 
  5757. an exception handler for a thread, (a DLL, for example, must de-register its 
  5758. exception handlers when it returns control to the thread that called it), you 
  5759. should add a clean up routine to the exit list of the process. 
  5760.  
  5761.  
  5762. ΓòÉΓòÉΓòÉ 7.1.3. Multiple Wait (Muxwait) Semaphores ΓòÉΓòÉΓòÉ
  5763.  
  5764. A multiple wait (muxwait) semaphore enables a thread to wait on several event 
  5765. or mutex semaphores simultaneously. A muxwait semaphore is a compound semaphore 
  5766. that consists of a list of up to 64 event semaphores or mutex semaphores (the 
  5767. two types cannot be mixed). 
  5768.  
  5769. A flag is set when the muxwait semaphore is created to enable threads to use 
  5770. the semaphore in either of two ways: 
  5771.  
  5772.      Threads can wait for all of the mutex semaphores to be released, or for 
  5773.       all of the event semaphores to be posted. 
  5774.  
  5775.      Threads can wait for any one of the mutex semaphores in the list to be 
  5776.       released, or for any one of the event semaphores in the list to be 
  5777.       posted. 
  5778.  
  5779.  Depending on the value of the flag, a muxwait semaphore is said to have 
  5780.  cleared when either any or all of the semaphores in the muxwait list have been 
  5781.  posted or released. 
  5782.  
  5783.  For example, suppose a thread requires access to several regions of shared 
  5784.  memory at the same time. OS/2 blocks the thread until the thread acquires 
  5785.  ownership of all the mutex semaphores protecting the shared regions. The 
  5786.  thread can then access all the memory regions. Meanwhile, OS/2 prevents access 
  5787.  by other threads. 
  5788.  
  5789.  
  5790. ΓòÉΓòÉΓòÉ 7.1.4. Named and Anonymous Semaphores ΓòÉΓòÉΓòÉ
  5791.  
  5792. A semaphore can be either named or anonymous. A named semaphore is always 
  5793. shared; that is, it is always available to any process that knows the name. An 
  5794. anonymous semaphore can be either private to a process or shared among 
  5795. processes, depending on whether the application includes the DC_SEM_SHARED flag 
  5796. in the function that creates the semaphore. A semaphore intended for use solely 
  5797. among threads of the same process can be anonymous and private. 
  5798.  
  5799. OS/2 creates a named semaphore when an application specifies a name in the 
  5800. function that creates the semaphore. The name must have the following form: 
  5801.  
  5802.     \SEM32\SemName
  5803.  
  5804. The "\SEM32\" is required, though it need not be uppercase. The semaphore name 
  5805. must conform to the rules for OS/2 file names, although no actual file is 
  5806. created for the semaphore. If the application does not specify a name in the 
  5807. function that creates the semaphore, OS/2 creates an anonymous semaphore. 
  5808.  
  5809. OS/2 permits a system-wide maximum of 65536 (64K) shared semaphores. In 
  5810. addition, each process can use up to 65536 (64K) private semaphores. 
  5811.  
  5812. A shared muxwait semaphore must contain either all shared event semaphores or 
  5813. all shared mutex semaphores. However, a private muxwait semaphore can contain a 
  5814. combination of shared and private event or mutex semaphores. OS/2 generates a 
  5815. unique handle when it creates a semaphore. Processes must obtain this handle 
  5816. before they can access the semaphore. A semaphore's handle is always available 
  5817. to the process that created the semaphore. A process can obtain the handle of a 
  5818. named semaphore created in another process by using the appropriate 
  5819. semaphore-opening function. A process that requires access to an anonymous 
  5820. shared semaphore that was created in another process must obtain the handle of 
  5821. the semaphore through some other form of interprocess communication, such as a 
  5822. pipe or a queue. 
  5823.  
  5824.  
  5825. ΓòÉΓòÉΓòÉ 7.1.5. Semaphore Management ΓòÉΓòÉΓòÉ
  5826.  
  5827. After one process creates a semaphore, threads in other processes must open the 
  5828. semaphore before they can access it. (Creating a semaphore automatically opens 
  5829. it for the creating process.) The open operation ensures that the process is a 
  5830. valid user of the semaphore. OS/2 keeps track of the number of open operations 
  5831. that each process performs on a semaphore. A process can have up to 65535 (64K 
  5832. - 1) open operations performed on a semaphore at any one time. 
  5833.  
  5834. If a process finishes using a semaphore and will not use it again, the process 
  5835. should close the semaphore so that OS/2 can free the memory the semaphore is 
  5836. using. OS/2 returns the ERROR_SEM_BUSY error value if a thread tries to close a 
  5837. semaphore that has another thread in the same process still waiting for it. 
  5838.  
  5839. If a process terminates with open semaphores, OS/2 automatically closes the 
  5840. semaphores for that process. 
  5841.  
  5842. Semaphores reside in a memory buffer rather than a disk file. Therefore, when 
  5843. the last process that has a semaphore open exits or closes that semaphore, OS/2 
  5844. frees the associated handle or name. 
  5845.  
  5846. When an application calls a function that causes a thread to wait on a 
  5847. semaphore, the application can specify the amount of time for the thread to 
  5848. wait. When the interval elapses without the semaphore being posted or released, 
  5849. the function returns the ERROR_TIMEOUT error value and the thread continues 
  5850. running. The application can provide a specific time-out value in milliseconds, 
  5851. or it can specify either the SEM_INDEFINITE_WAIT or the SEM_IMMEDIATE_RETURN 
  5852. flag. If a thread is interrupted while it is waiting on a semaphore, the 
  5853. ERROR_INTERRUPT error value is returned to the caller. 
  5854.  
  5855.  
  5856. ΓòÉΓòÉΓòÉ 7.2. Using Event Semaphores ΓòÉΓòÉΓòÉ
  5857.  
  5858. An application can use an event semaphore to trigger execution of other 
  5859. processes. This is useful if, for example, one process provides data to many 
  5860. other processes. Using an event semaphore frees the other process from the 
  5861. trouble of polling to determine when new data is available. 
  5862.  
  5863. Note:  In the example code fragments that follow, error checking was left out 
  5864.        to conserve space. Applications should always check the return code that 
  5865.        the functions return. Control Program functions return an APIRET value. 
  5866.        A return code of 0 indicates success. If a non-zero value is returned, 
  5867.        an error occurred. 
  5868.  
  5869.  
  5870. ΓòÉΓòÉΓòÉ 7.2.1. Creating an Event Semaphore ΓòÉΓòÉΓòÉ
  5871.  
  5872. Processes create an event semaphore by using DosCreateEventSem. The process 
  5873. that controls the event or resource is usually the one that creates the 
  5874. semaphore, but it does not have to be. 
  5875.  
  5876. Threads in the process that creates the semaphore do not have to open the 
  5877. semaphore before using it. DosCreateEventSem obtains access to the semaphore 
  5878. for the calling process and its threads. Threads in other processes must call 
  5879. DosOpenEventSem to open the semaphore before they can use it. 
  5880.  
  5881. Event semaphores can be defined as either private or shared: 
  5882.  
  5883.      Private semaphores are always unnamed and are therefore always identified 
  5884.       by their handles. They can be used only by threads within a single 
  5885.       process. 
  5886.  
  5887.      Shared semaphores can be either named or unnamed. If named, they can be 
  5888.       opened using either the name or the handle. The handle returned by 
  5889.       DosOpenEventSem is then used to identify the semaphore for all other 
  5890.       functions. Semaphore names must include the prefix \SEM32\ and must 
  5891.       conform to file system naming conventions. Shared semaphores can be used 
  5892.       by threads in multiple processes. 
  5893.  
  5894.  In the following code fragment, the controlling process creates a named event 
  5895.  semaphore and posts the semaphore after writing data to a shared file: 
  5896.  
  5897.       #define INCL_DOSSEMAPHORES   /* Semaphore values */
  5898.       #include <os2.h>
  5899.  
  5900.       HEV hevWriteEvent;
  5901.  
  5902.       DosCreateEventSem("\\sem32\\wrtevent",          /* Named-shared semaphore */
  5903.                          &hevWriteEvent, 0, FALSE);   /* Initially reset        */
  5904.           .
  5905.           .
  5906.           /* Write data to shared file. */
  5907.           .
  5908.           .
  5909.       DosPostEventSem(hevWriteEvent);                 /* Posts the event        */
  5910.           .
  5911.           .    /* Continue execution. */
  5912.           .
  5913.  
  5914.  There is a system-wide limit of 65536 (64K) shared semaphores (including 
  5915.  mutex, event, and muxwait semaphores); in addition, each process can have up 
  5916.  to 65536 (64K) private semaphores. 
  5917.  
  5918.  When an event semaphore is created, a flag is used to specify the initial 
  5919.  state of the event semaphore, either reset or posted. If the initial state is 
  5920.  reset, a thread that calls DosWaitEventSem will be blocked until a process 
  5921.  that has access to the semaphore uses DosPostEventSem to post the event 
  5922.  semaphore. If the initial state is posted, then a thread that calls 
  5923.  DosWaitEventSem will return immediately to continue its execution. If the 
  5924.  thread calling DosWaitEventSem is not in the process that created the 
  5925.  semaphore, the thread must open the semaphore with DosOpenEventSem before 
  5926.  calling DosWaitEventSem. 
  5927.  
  5928.  OS/2 maintains a usage count for each semaphore. DosCreateEventSem initializes 
  5929.  the usage count to 1. Thereafter, each call to DosOpenEventSem increments the 
  5930.  count, and each call to DosCloseEventSem decrements it. 
  5931.  
  5932.  
  5933. ΓòÉΓòÉΓòÉ 7.2.2. Opening an Event Semaphore ΓòÉΓòÉΓòÉ
  5934.  
  5935. When a process creates an event semaphore, all of the threads that belong to 
  5936. the process have immediate access to the semaphore. 
  5937.  
  5938. Threads in other processes must open the semaphore by calling DosOpenEventSem 
  5939. before they can use the semaphore in any other event semaphore function. 
  5940.  
  5941. The following code fragment shows how processes can open an event semaphore 
  5942. that was created in a different process and then wait for the event to be 
  5943. posted: 
  5944.  
  5945.     #define INCL_DOSSEMAPHORES   /* Semaphore values */
  5946.     #include <os2.h>
  5947.  
  5948.     HEV hevEventHandle = 0;                 /* Must be 0 because we are opening */
  5949.                                             /* the semaphore by name            */
  5950.  
  5951.     DosOpenEventSem("\\sem32\\wrtevent", &hevEventHandle);
  5952.  
  5953.     DosWaitEventSem(hevEventHandle,
  5954.                     SEM_INDEFINITE_WAIT);   /* Waits until event is posted      */
  5955.         .
  5956.         .    /* Read from file when event is posted. */
  5957.         .
  5958.  
  5959. Applications can open an event semaphore by name or by handle. If the name is 
  5960. used to open the semaphore, as in the code fragment above, the handle parameter 
  5961. must be 0. If the handle is used to open the semaphore, the name parameter must 
  5962. be NULL. 
  5963.  
  5964. Access to semaphores is on a per-process basis. Therefore, a semaphore that has 
  5965. been opened by one thread in a process is open to all other threads in that 
  5966. process as well. 
  5967.  
  5968. DosOpenEventSem merely provides access to an event semaphore. In order to wait 
  5969. for an event semaphore to be posted, a thread must call DosWaitEventSem. In 
  5970. order to post or reset an open event semaphore, a thread uses DosPostEventSem 
  5971. or DosResetEventSem respectively. 
  5972.  
  5973. When a process no longer requires access to an event semaphore, it closes the 
  5974. semaphore by calling DosCloseEventSem. If a process ends without closing an 
  5975. open semaphore, the semaphore is closed by OS/2. 
  5976.  
  5977. Each call to DosOpenEventSem increments the usage count of the semaphore. This 
  5978. count is initialized to 1 when the semaphore is created and is decremented by 
  5979. each call to DosCloseEventSem. When the usage count reaches 0, the semaphore is 
  5980. deleted by OS/2. 
  5981.  
  5982. Calls to DosOpenEventSem and DosCloseEventSem can be nested, but the usage 
  5983. count for a semaphore cannot exceed 65535. If an attempt is made to exceed this 
  5984. number, ERROR_TOO_MANY_OPENS is returned. 
  5985.  
  5986.  
  5987. ΓòÉΓòÉΓòÉ 7.2.3. Closing an Event Semaphore ΓòÉΓòÉΓòÉ
  5988.  
  5989. When a process no longer requires access to an event semaphore, it closes the 
  5990. semaphore by calling DosCloseEventSem. 
  5991.  
  5992. The following code fragment closes an event semaphore. Assume that the handle 
  5993. of the semaphore has been placed into HEV already. 
  5994.  
  5995.     #define INCL_DOSSEMAPHORES   /* Semaphore values */
  5996.     #include <os2.h>
  5997.     #include <stdio.h>
  5998.  
  5999.     HEV     hev;     /* Event semaphore handle */
  6000.     APIRET  ulrc;    /* Return code            */
  6001.  
  6002.     ulrc = DosCloseEventSem(hev);
  6003.  
  6004.     if (ulrc != 0) {
  6005.         printf("DosCloseEventSem error: return code = %ld",
  6006.                ulrc);
  6007.         return;
  6008.     }
  6009.  
  6010. Calls to DosOpenEventSem and DosCloseEventSem can be nested, but the usage 
  6011. count for a semaphore cannot exceed 65535. If an attempt is made to exceed this 
  6012. number, ERROR_TOO_MANY_OPENS is returned. 
  6013.  
  6014. If a process ends without closing an open semaphore, the semaphore is closed by 
  6015. OS/2. 
  6016.  
  6017. Each call to DosCloseEventSem decrements the usage count of the semaphore. This 
  6018. count is initialized to 1 when the semaphore is created and is incremented by 
  6019. each call to DosOpenEventSem. When the usage count reaches 0, the semaphore is 
  6020. deleted from OS/2. The call to DosCloseEventSem that decrements the usage count 
  6021. to 0 and causes the semaphore to be deleted is referred to as the final close. 
  6022. If a thread attempts to perform the final close for a semaphore while another 
  6023. thread in the same process is still waiting for it, ERROR_SEM_BUSY is returned. 
  6024.  
  6025.  
  6026. ΓòÉΓòÉΓòÉ 7.2.4. Resetting an Event Semaphore ΓòÉΓòÉΓòÉ
  6027.  
  6028. DosResetEventSem resets an event semaphore if it is not already reset, and 
  6029. returns the number of times the semaphore was posted since it was last reset. 
  6030. All threads that subsequently call DosWaitEventSem for this semaphore will be 
  6031. blocked. 
  6032.  
  6033. Any thread belonging to the process that created the event semaphore can change 
  6034. the state of the semaphore to reset by calling DosResetEventSem. Threads in 
  6035. other processes can also call DosResetEventSem, but they must first gain access 
  6036. to the semaphore by calling DosOpenEventSem. 
  6037.  
  6038. When an event semaphore is in the reset state, any thread that calls 
  6039. DosWaitEventSem to wait for the semaphore will be blocked. When the event 
  6040. semaphore is posted, all of the threads that are waiting for the semaphore are 
  6041. released to continue execution. 
  6042.  
  6043. The following code fragment resets an event semaphore. Assume that the handle 
  6044. of the semaphore has been placed into HEV already. 
  6045.  
  6046.     #define INCL_DOSSEMAPHORES   /* Semaphore values */
  6047.     #include <os2.h>
  6048.     #include <stdio.h>
  6049.  
  6050.     HEV     hev;        /* Event semaphore handle                        */
  6051.     ULONG   ulPostCt;   /* Post count for the event semaphore (returned) */
  6052.     APIRET  ulrc;       /* Return code                                   */
  6053.  
  6054.     ulrc = DosResetEventSem(hev, &ulPostCt);
  6055.  
  6056.     if (ulrc != 0) {
  6057.         printf("DosResetEventSem error: return code = %ld",
  6058.                ulrc);
  6059.         return;
  6060.     }
  6061.  
  6062. DosResetEventSem returns the post count of the event semaphore and resets the 
  6063. post count to 0. The post count is the number of times the semaphore has been 
  6064. posted (using DosPostEventSem) since the last time the semaphore was in the 
  6065. reset state. (An event semaphore can be reset when it is created, as well as by 
  6066. calling DosResetEventSem.) The post count can also be obtained by calling 
  6067. DosQueryEventSem. 
  6068.  
  6069. If the event semaphore is already reset when DosResetEventSem is called, 
  6070. ERROR_ALREADY_RESET is returned, along with a post count of 0. The semaphore is 
  6071. not reset a second time. 
  6072.  
  6073.  
  6074. ΓòÉΓòÉΓòÉ 7.2.5. Posting an Event Semaphore ΓòÉΓòÉΓòÉ
  6075.  
  6076. DosPostEventSem posts the semaphore, if it is not already posted, and 
  6077. increments the post count. All threads that have called DosWaitEventSem for 
  6078. this semaphore are unblocked and resume execution. Threads that call 
  6079. DosWaitEventSem after the event semaphore has been posted and before the next 
  6080. time it is reset, will return immediately from a call to DosWaitEventSem and 
  6081. continue execution. If the semaphore is subsequently reset, threads that call 
  6082. DosWaitEventSem will again be blocked. 
  6083.  
  6084. Any thread in the process that created an event semaphore can post the 
  6085. semaphore by calling DosPostEventSem. Threads in other processes can also call 
  6086. DosPostEventSem, but they must first gain access to the semaphore by calling 
  6087. DosOpenEventSem. 
  6088.  
  6089. The following code fragment posts a system event semaphore. Assume that the 
  6090. handle of the semaphore has been placed into HEV already. 
  6091.  
  6092.     #define INCL_DOSSEMAPHORES   /* Semaphore values */
  6093.     #include <os2.h>
  6094.     #include <stdio.h>
  6095.  
  6096.     HEV     hev;     /* Event semaphore handle */
  6097.     APIRET  ulrc;    /* Return code            */
  6098.  
  6099.     ulrc = DosPostEventSem(hev);
  6100.  
  6101.     if (ulrc != 0) {
  6102.         printf("DosPostEventSem error: return code = %ld",
  6103.                ulrc);
  6104.         return;
  6105.     }
  6106.  
  6107. OS/2 maintains a post count for each event semaphore. The post count is the 
  6108. number of times the semaphore has been posted (with DosPostEventSem) since the 
  6109. last time the semaphore was in the reset state. 
  6110.  
  6111. If the event semaphore is reset when DosPostEventSem is called, the semaphore 
  6112. is posted and the post count is set to 1. If the event semaphore is already 
  6113. posted when DosPostEventSem is called, the post count is incremented, and 
  6114. ERROR_ALREADY_POSTED is returned to the calling thread. 
  6115.  
  6116. The post count is returned as output by DosResetEventSem; it can also be 
  6117. obtained by calling DosQueryEventSem. 
  6118.  
  6119. The maximum number of times an event semaphore can be posted is 65535. The 
  6120. value of the post count cannot exceed 65535. If an attempt is made to exceed 
  6121. this number, DosPostEventSem returns ERROR_TOO_MANY_POSTS. 
  6122.  
  6123.  
  6124. ΓòÉΓòÉΓòÉ 7.2.6. Waiting for an Event Semaphore ΓòÉΓòÉΓòÉ
  6125.  
  6126. Any thread in the process that created an event semaphore can wait for the 
  6127. semaphore to be posted by calling DosWaitEventSem. Threads in other processes 
  6128. can also call DosWaitEventSem, but they must first gain access to the semaphore 
  6129. by calling DosOpenEventSem. 
  6130.  
  6131. If the semaphore is already posted when DosWaitEventSem is called, the function 
  6132. returns immediately, and the thread continues to run. Otherwise, the thread is 
  6133. blocked until the semaphore is posted. 
  6134.  
  6135. The following code fragment causes the calling thread to wait until the 
  6136. specified event semaphore is posted. Assume that the handle of the semaphore 
  6137. has been placed into HEV already. ulTimeout is the number of milliseconds that 
  6138. the calling thread will wait for the event semaphore to be posted. If the 
  6139. specified event semaphore is not posted during this time interval, the request 
  6140. times out. 
  6141.  
  6142.     #define INCL_DOSSEMAPHORES   /* Semaphore values */
  6143.     #define INCL_DOSERRORS       /* error codes      */
  6144.  
  6145.     #include <os2.h>
  6146.     #include <stdio.h>
  6147.  
  6148.     HEV     hev;        /* Event semaphore handle         */
  6149.     ULONG   ulTimeout;  /* Number of milliseconds to wait */
  6150.     APIRET  ulrc;       /* Return code                    */
  6151.  
  6152.     ulTimeout = 60000;  /* Wait for a maximum of 1 minute */
  6153.  
  6154.     ulrc = DosWaitEventSem(hev,
  6155.                            ulTimeout);
  6156.  
  6157.     if (ulrc == ERROR_TIMEOUT) {
  6158.         printf("DosWaitEventSem call timed out");
  6159.         return;
  6160.     }
  6161.  
  6162.     if (ulrc == ERROR_INTERRUPT) {
  6163.         printf("DosWaitEventSem call was interrupted");
  6164.         return;
  6165.     }
  6166.  
  6167.     if (ulrc != 0) {
  6168.         printf("DosWaitEventSem error: return code = %ld",
  6169.                ulrc);
  6170.         return;
  6171.     }
  6172.  
  6173. If the time limit specified in ulTimeout is reached before the semaphore is 
  6174. posted, ERROR_TIMEOUT is returned. If the waiting period is interrupted for 
  6175. some reason before the semaphore is posted, ERROR_INTERRUPT is returned. If 
  6176. SEM_IMMEDIATE_RETURN is specified for the time limit, DosWaitEventSem returns 
  6177. to the calling thread immediately. If SEM_INDEFINITE_WAIT is specified for the 
  6178. time limit, the thread waits indefinitely. 
  6179.  
  6180. Unlike multiple event semaphores in a muxwait list, which are level-triggered, 
  6181. single event semaphores are edge-triggered. This means that if an event 
  6182. semaphore is posted and then reset before a waiting thread gets a chance to 
  6183. run, the semaphore is considered to be posted for the rest of that thread's 
  6184. waiting period; the thread does not have to wait for the semaphore to be posted 
  6185. again. 
  6186.  
  6187.  
  6188. ΓòÉΓòÉΓòÉ 7.2.7. Querying an Event Semaphore ΓòÉΓòÉΓòÉ
  6189.  
  6190. DosQueryEventSem returns the current post count of a semaphore. The post count 
  6191. is the number of times that the semaphore has been posted (with 
  6192. DosPostEventSem) since the last time the semaphore was reset. A count of 0 
  6193. indicates that the semaphore is in the reset state; therefore, OS/2 will block 
  6194. any threads that call DosWaitEventSem to wait on the semaphore. 
  6195.  
  6196. Any thread in the process that created an event semaphore can obtain the post 
  6197. count for the semaphore by calling DosQueryEventSem. Threads in other processes 
  6198. can also call DosQueryEventSem, but they must first gain access to the 
  6199. semaphore by calling DosOpenEventSem. 
  6200.  
  6201. The following code fragment retrieves the post count for an event semaphore. 
  6202. Assume that the handle of the semaphore has been placed into HEV already. 
  6203.  
  6204.     #define INCL_DOSSEMAPHORES   /* Semaphore values */
  6205.     #include <os2.h>
  6206.     #include <stdio.h>
  6207.  
  6208.     HEV     hev;       /* Event semaphore handle                          */
  6209.     ULONG   ulPostCt;  /* Current post count for the semaphore (returned) */
  6210.     APIRET  ulrc;      /* Return code                                     */
  6211.  
  6212.     ulrc = DosQueryEventSem(hev,
  6213.                             &ulPostCt);
  6214.  
  6215.     if (ulrc != 0) {
  6216.         printf("DosQueryEventSem error: return code = %ld",
  6217.                ulrc);
  6218.         return;
  6219.     }
  6220.  
  6221. If the specified event semaphore does not exist, ERROR_INVALID_HANDLE is 
  6222. returned. 
  6223.  
  6224.  
  6225. ΓòÉΓòÉΓòÉ 7.3. Using Mutex Semaphores ΓòÉΓòÉΓòÉ
  6226.  
  6227. An application can use a mutual exclusion (mutex) semaphore to protect a shared 
  6228. resource from simultaneous access by multiple threads or processes. For 
  6229. example, if several processes must write to the same disk file, the mutex 
  6230. semaphore ensures that only one process at a time writes to the file. 
  6231.  
  6232.  
  6233. ΓòÉΓòÉΓòÉ 7.3.1. Creating a Mutex Semaphore ΓòÉΓòÉΓòÉ
  6234.  
  6235. Mutex semaphores are created by calling DosCreateMutexSem. This function also 
  6236. opens the semaphore for the calling process and its threads. 
  6237.  
  6238. When a mutex semaphore is created, a flag is set to specify the initial state 
  6239. of the semaphore, owned or unowned. If the semaphore is owned by a thread, 
  6240. other threads requesting the semaphore are blocked. If the semaphore is 
  6241. unowned-not owned by any thread- then any thread requesting ownership will be 
  6242. granted ownership immediately. 
  6243.  
  6244. If the calling thread sets the initial state to owned, it owns the semaphore as 
  6245. soon as OS/2 creates the semaphore and can proceed to access the resource that 
  6246. the semaphore was created to protect. 
  6247.  
  6248. If the semaphore is unowned, any thread in the creating process can 
  6249. subsequently request ownership of the semaphore by calling DosRequestMutexSem. 
  6250. Threads in other processes can gain ownership of the semaphore, but they must 
  6251. call DosOpenMutexSem to acquire access to the semaphore before they can call 
  6252. DosRequestMutexSem. 
  6253.  
  6254. Mutex semaphores can be defined as either private or shared. 
  6255.  
  6256.      Private semaphores are always unnamed and are therefore identified by 
  6257.       their handles. They can be used only by threads within a single process. 
  6258.  
  6259.      Shared semaphores can be either named or unnamed. If named, they can be 
  6260.       opened using either the name or the handle. The handle returned by 
  6261.       DosOpenMutexSem is then used to identify the semaphore for all other 
  6262.       functions. Semaphore names must include the prefix \SEM32\ and must 
  6263.       conform to file system naming conventions. Shared semaphores can be used 
  6264.       by threads in multiple processes. 
  6265.  
  6266.  The following code fragment creates a mutex semaphore: 
  6267.  
  6268.       #define INCL_DOSSEMAPHORES   /* Semaphore values */
  6269.       #include <os2.h>
  6270.  
  6271.       HMTX hmtxProtFile;
  6272.  
  6273.       DosCreateMutexSem("\\sem32\\ProtFile",          /* Named-shared semaphore */
  6274.                         &hmtxProtFile,
  6275.                         0,
  6276.                         FALSE);                       /* Initially unowned      */
  6277.           .
  6278.           .    /* Get data to write to shared file. */
  6279.           .
  6280.  
  6281.  There is a system-wide limit of 65536 shared semaphores (including mutex, 
  6282.  event, and muxwait semaphores); in addition, each process can have up to 65536 
  6283.  private semaphores. 
  6284.  
  6285.  OS/2 maintains a usage count for each semaphore. DosCreateMutexSem initializes 
  6286.  the usage count to 1. Thereafter, each call to DosOpenMutexSem increments the 
  6287.  count, and each call to DosCloseMutexSem decrements it. 
  6288.  
  6289.  
  6290. ΓòÉΓòÉΓòÉ 7.3.2. Opening a Mutex Semaphore ΓòÉΓòÉΓòÉ
  6291.  
  6292. All of the threads belonging to the process that creates a mutex semaphore have 
  6293. immediate access to the semaphore. Threads in other processes must request 
  6294. access to the semaphore by calling DosOpenMutexSem before they can use the 
  6295. semaphore in other mutex semaphore functions. 
  6296.  
  6297. Access to system resources is granted on a per-process basis. Therefore, a 
  6298. semaphore that has been opened by one thread in a process is open to all other 
  6299. threads in that process as well. 
  6300.  
  6301. DosOpenMutexSem merely provides access to a mutex semaphore. To request 
  6302. ownership of a mutex semaphore, a thread must call DosRequestMutexSem. 
  6303.  
  6304. When a process no longer requires access to a mutex semaphore, it should close 
  6305. the semaphore by calling DosCloseMutexSem. However, if a process ends without 
  6306. closing an open semaphore, the semaphore is closed by OS/2. 
  6307.  
  6308. Each call to DosOpenMutexSem. increments the usage count of the semaphore. This 
  6309. count is initialized to 1 when the semaphore is created and is decremented by 
  6310. each call to DosCloseMutexSem. When the usage count reaches 0, the semaphore is 
  6311. deleted by the system. 
  6312.  
  6313. Calls to DosOpenMutexSem and DosCloseMutexSem. can be nested, but the usage 
  6314. count for a semaphore cannot exceed 65535. If an attempt is made to exceed this 
  6315. number, ERROR_TOO_MANY_OPENS is returned. 
  6316.  
  6317. If a process ends without releasing a mutex semaphore that it owns, any other 
  6318. thread that subsequently tries to open the semaphore will receive 
  6319. ERROR_SEM_OWNER_DIED. This return code indicates that the owning process ended 
  6320. abnormally, leaving the protected resource in an indeterminate state. However, 
  6321. the semaphore is still opened for the calling thread, enabling the thread to 
  6322. call DosQueryMutexSem to find out which process ended without releasing the 
  6323. semaphore. The thread can then take appropriate action concerning the semaphore 
  6324. and the protected resource. 
  6325.  
  6326.  
  6327. ΓòÉΓòÉΓòÉ 7.3.3. Requesting a Mutex Semaphore ΓòÉΓòÉΓòÉ
  6328.  
  6329. In order to access a shared resource, a process must own the mutex semaphore 
  6330. that is protecting the shared resource. Ownership is obtained by first opening 
  6331. the mutex semaphore with DosOpenMutexSem, then using DosRequestMutexSem to 
  6332. request ownership of the semaphore. If another process already owns the 
  6333. semaphore, the requesting process is blocked. If the semaphore is not owned, 
  6334. OS/2 grants ownership to the requesting process and the process can access the 
  6335. shared resource. When the process is finished using the shared resource, it 
  6336. uses DosReleaseMutexSem to relinquish its ownership of the semaphore, thereby 
  6337. enabling another process to gain ownership. 
  6338.  
  6339. A process can gain ownership of a mutex semaphore in three ways: 
  6340.  
  6341.    1. The thread that creates a mutex semaphore can designate itself as the 
  6342.       owner by setting a flag when it calls DosCreateMutexSem. 
  6343.  
  6344.    2. Any thread in the process that created the semaphore can request 
  6345.       ownership by calling DosRequestMutexSem. 
  6346.  
  6347.    3. A thread in another process must request access to the semaphore with 
  6348.       DosOpenMutexSem before it can call DosRequestMutexSem. 
  6349.  
  6350.  Note that ownership of a mutex semaphore is given only to the requesting 
  6351.  thread; it is not shared by other threads in the same process. 
  6352.  
  6353.  If a mutex semaphore is unowned, DosRequestMutexSem sets it as owned and 
  6354.  returns immediately to the caller. If the semaphore is already owned, the 
  6355.  calling thread is blocked until either the owning thread calls 
  6356.  DosReleaseMutexSem to release the semaphore, or a specified time limit is 
  6357.  reached. 
  6358.  
  6359.  The following code fragment shows how a process opens a mutex semaphore, 
  6360.  requests it, and, after writing to the shared file, releases and closes the 
  6361.  semaphore: 
  6362.  
  6363.       #define INCL_DOSSEMAPHORES   /* Semaphore values */
  6364.       #include <os2.h>
  6365.  
  6366.       HMTX hmtxProtFile;
  6367.  
  6368.       DosOpenMutexSem("\\sem32\\ProtFile",
  6369.                       &hmtxProtFile);           /* Opens for this process    */
  6370.  
  6371.       DosRequestMutexSem(hmtxProtFile,
  6372.                          5000);                 /* Returns in 5 seconds if   */
  6373.           .                                     /* Ownership not obtained    */
  6374.           .
  6375.           .                                     /* Write data to shared file */
  6376.           .
  6377.           .
  6378.       DosReleaseMutexSem(hmtxProtFile);         /* Releases ownership        */
  6379.           .
  6380.           .                                     /* Continue execution        */
  6381.           .
  6382.           .
  6383.       DosCloseMutexSem(hmtxProtFile);           /* Finished with shared file */
  6384.  
  6385.  If more than one thread is blocked on a DosRequestMutexSem request, the thread 
  6386.  with the highest priority level is the first to be unblocked and given 
  6387.  ownership of the semaphore. If more than 1 of the waiting threads have the 
  6388.  same priority level, then FIFO ordering is used to determine which thread is 
  6389.  unblocked and given ownership. 
  6390.  
  6391.  The time-out parameter (5000 milliseconds in the example above) places a limit 
  6392.  on the amount of time a thread blocks on a DosRequestMutexSem request. If the 
  6393.  time limit is reached before the thread gains ownership of the semaphore, 
  6394.  ERROR_TIMEOUT is returned. If SEM_IMMEDIATE_RETURN is specified for the time 
  6395.  limit, DosRequestMutexSem returns without blocking the thread. The thread can 
  6396.  then perform other operations and call DosRequestMutexSem again later if it 
  6397.  still requires access to the protected resource. If SEM_INDEFINITE_WAIT is 
  6398.  specified for the time limit, the thread waits indefinitely. If the thread is 
  6399.  unblocked by an external event while it is waiting for the mutex semaphore (as 
  6400.  when a No Wait I/O request has just been completed), ERROR_INTERRUPT is 
  6401.  returned to the caller. 
  6402.  
  6403.  In addition to the usage count that OS/2 maintains for all semaphores, OS/2 
  6404.  maintains a request count for each mutex semaphore. Each call to 
  6405.  DosRequestMutexSem increments the count, and each call to DosReleaseMutexSem 
  6406.  decrements it. 
  6407.  
  6408.  Calls to DosRequestMutexSem and DosReleaseMutexSem can be nested, but the 
  6409.  request count for a semaphore cannot exceed 65535. If an attempt is made to 
  6410.  exceed this number, ERROR_TOO_MANY_SEM_REQUESTS is returned. When calls to 
  6411.  DosRequestMutexSem and DosReleaseMutexSem are nested, a call to 
  6412.  DosReleaseMutexSem merely decrements the request count for the semaphore; the 
  6413.  semaphore is not actually released to another thread until its request count 
  6414.  is 0. If a process ends while it owns a mutex semaphore, all of the currently 
  6415.  blocked DosRequestMutexSem requests, as well as any future requests for the 
  6416.  semaphore, return ERROR_SEM_OWNER_DIED. This return code indicates that the 
  6417.  owning process ended abnormally, leaving the protected resource in an 
  6418.  indeterminate state. An application that receives this error should close the 
  6419.  mutex semaphore (so that it can be deleted from OS/2), because it is no longer 
  6420.  valid. Appropriate action should also be taken concerning the protected 
  6421.  resource. 
  6422.  
  6423.  
  6424. ΓòÉΓòÉΓòÉ 7.3.4. Releasing a Mutex Semaphore ΓòÉΓòÉΓòÉ
  6425.  
  6426. A thread can release ownership of a mutex semaphore by calling 
  6427. DosReleaseMutexSem. Each call to DosReleaseMutexSem decrements the request 
  6428. count that is maintained for the semaphore by OS/2. Each call to 
  6429. DosRequestMutexSem increments the count. 
  6430.  
  6431. The following code fragment relinquishes ownership of a mutex semaphore. Assume 
  6432. that the handle of the semaphore has been placed into hmtx already. 
  6433.  
  6434.     #define INCL_DOSSEMAPHORES   /* Semaphore values */
  6435.     #include <os2.h>
  6436.     #include <stdio.h>
  6437.  
  6438.     HMTX    hmtx;    /* Mutex semaphore handle */
  6439.     APIRET  ulrc;    /* Return code            */
  6440.  
  6441.     ulrc = DosReleaseMutexSem(hmtx);
  6442.  
  6443.     if (ulrc != 0) {
  6444.         printf("DosReleaseMutexSem error: return code = %ld",
  6445.                ulrc);
  6446.         return;
  6447.     }
  6448.  
  6449. Calls to DosRequestMutexSem and DosReleaseMutexSem can be nested, but the 
  6450. request count cannot exceed 65535. If an attempt is made to exceed this number, 
  6451. ERROR_TOO_MANY_SEM_REQUESTS is returned. When calls to DosRequestMutexSem and 
  6452. DosReleaseMutexSem are nested, a call to DosReleaseMutexSem merely decrements 
  6453. the request count for the semaphore; the semaphore is not actually released to 
  6454. another thread until its request count is 0. 
  6455.  
  6456.  
  6457. ΓòÉΓòÉΓòÉ 7.3.5. Closing a Mutex Semaphore ΓòÉΓòÉΓòÉ
  6458.  
  6459. When a process no longer requires access to a mutex semaphore, it can close the 
  6460. semaphore by calling DosCloseMutexSem. However, if a process ends without 
  6461. closing an open semaphore, the semaphore is closed by OS/2. 
  6462.  
  6463. The following code fragment closes a mutex semaphore. Assume that the handle of 
  6464. the semaphore has been placed into hmtx already. 
  6465.  
  6466.     #define INCL_DOSSEMAPHORES   /* Semaphore values */
  6467.     #include <os2.h>
  6468.     #include <stdio.h>
  6469.  
  6470.     HMTX    hmtx;    /* Mutex semaphore handle */
  6471.     APIRET  ulrc;    /* Return code            */
  6472.  
  6473.     ulrc = DosCloseMutexSem(hmtx);
  6474.  
  6475.     if (ulrc != 0) {
  6476.         printf("DosCloseMutexSem error: return code = %ld",
  6477.                ulrc);
  6478.         return;
  6479.     }
  6480.  
  6481. Each call to DosCloseMutexSem decrements the usage count of the semaphore. This 
  6482. count is initialized to 1 when the semaphore is created and is incremented by 
  6483. each call to DosOpenMutexSem. When the usage count reaches 0, the semaphore is 
  6484. deleted by OS/2. 
  6485.  
  6486. The call to DosCloseMutexSem that decrements the usage count to 0 and causes 
  6487. the semaphore to be deleted is referred to as the final close. The final close 
  6488. will not succeed if either of the following conditions exists: 
  6489.  
  6490.      The semaphore is owned by another thread in the same process. 
  6491.  
  6492.      Another thread in the same process is still blocked on a 
  6493.       DosRequestMutexSem request for the semaphore. 
  6494.  
  6495.  For both conditions, ERROR_SEM_BUSY is returned. 
  6496.  
  6497.  ERROR_SEM_BUSY is also returned if a thread tries to close a mutex semaphore 
  6498.  that it still owns. The thread must first relinquish ownership of the 
  6499.  semaphore by calling DosReleaseMutexSem. 
  6500.  
  6501.  Calls to DosOpenMutexSem and DosCloseMutexSem can be nested, but the usage 
  6502.  count for a semaphore cannot exceed 65535. If an attempt is made to exceed 
  6503.  this number, ERROR_TOO_MANY_OPENS is returned. 
  6504.  
  6505.  
  6506. ΓòÉΓòÉΓòÉ 7.3.6. Querying a Mutex Semaphore ΓòÉΓòÉΓòÉ
  6507.  
  6508. An application can use DosQueryMutexSem to determine the current owner of a 
  6509. mutex semaphore and to obtain a count of the number of requests on it. If the 
  6510. mutex semaphore is not owned, the request count is 0. 
  6511.  
  6512. Any thread in the process that created a mutex semaphore can obtain information 
  6513. about the semaphore by calling DosQueryMutexSem. Threads in other processes can 
  6514. also call DosQueryMutexSem, but they must first gain access to the semaphore by 
  6515. calling DosOpenMutexSem. 
  6516.  
  6517. If the mutex semaphore exists and is owned, DosQueryMutexSem returns the 
  6518. process and thread identifications of the owner, as well as the request count 
  6519. for the semaphore. The request count is the number of DosRequestMutexSem calls 
  6520. minus the number of DosReleaseMutexSem calls that have been made for the 
  6521. semaphore by the owning thread. 
  6522.  
  6523. If DosQueryMutexSem returns a request count of 0, the mutex semaphore is 
  6524. unowned. 
  6525.  
  6526. If the owning process ended without calling DosCloseMutexSem, then 
  6527. ERROR_SEM_OWNER_DIED is returned, and the output parameters contain information 
  6528. about the ended owning process. 
  6529.  
  6530.  
  6531. ΓòÉΓòÉΓòÉ 7.4. Using Muxwait Semaphores ΓòÉΓòÉΓòÉ
  6532.  
  6533. A process that requires exclusive use of several shared resources at once can 
  6534. use a multiple wait (muxwait) semaphore to obtain ownership of all the mutex 
  6535. semaphores protecting the shared resources. A process can also use a muxwait 
  6536. semaphore to wait on a group of event semaphores so that the process continues 
  6537. running whenever events of interest occur. 
  6538.  
  6539. A muxwait semaphore can refer to up to 64 event or mutex semaphores. An 
  6540. application cannot refer to event and mutex semaphores in a single muxwait 
  6541. semaphore, or include a muxwait semaphore in another muxwait semaphore. 
  6542.  
  6543.  
  6544. ΓòÉΓòÉΓòÉ 7.4.1. Creating a Muxwait Semaphore ΓòÉΓòÉΓòÉ
  6545.  
  6546. DosCreateMuxWaitSem is used to create muxwait semaphores. This function also 
  6547. opens (obtains access to) the semaphore for the calling process and its 
  6548. threads. Threads in other processes must call DosOpenMuxWaitSem to open the 
  6549. semaphore before they can use it in any other muxwait semaphore function. 
  6550.  
  6551. All the semaphores in the muxwait list must be created and opened before the 
  6552. muxwait list can be created. 
  6553.  
  6554. The following code fragment creates five event semaphores and a corresponding 
  6555. array of semaphore records. The array is used to specify the semaphores 
  6556. included in the muxwait semaphore in the subsequent call to 
  6557. DosCreateMuxWaitSem. 
  6558.  
  6559.  
  6560. #define INCL_DOSSEMAPHORES   /* DOS semaphore values */
  6561. #define INCL_DOSERRORS       /* DOS error values */
  6562. #include <os2.h>
  6563. #include <stdio.h>
  6564.  
  6565. int main(VOID) {
  6566.  HMUX      hmuxHandAny = NULLHANDLE;      /* Muxwait handle    */
  6567.  HEV       hev[5]      = {0};             /* Event semaphores  */
  6568.  SEMRECORD apsr[5]     = {{0}};           /* Semaphore records */
  6569.  APIRET    ulrc        = NO_ERROR;        /* Return code       */
  6570.  ULONG     ulLoop      = 0;               /* Loop count        */
  6571.  ULONG     ulSem       = 0;
  6572.  
  6573. for (ulLoop = 0; ulLoop < 5; ulLoop++) {
  6574.     ulrc = DosCreateEventSem((PSZ) NULL,
  6575.                              &hev[ulLoop],
  6576.                              0,
  6577.                              FALSE);
  6578.  
  6579.     if (ulrc != NO_ERROR) {
  6580.       printf("DosCreateEventSem error:  return code = %u\n",
  6581.              ulrc);
  6582.       return 1;
  6583.     }
  6584.     apsr[ulLoop].hsemCur = (HSEM) hev[ulLoop],
  6585.     apsr[ulLoop].ulUser = 0;
  6586. } /* end for */
  6587.  
  6588. ulrc = DosCreateMuxWaitSem((PSZ) NULL,
  6589.                            &hmuxHandAny,
  6590.                            5L,              /* Number of semaphores in list */
  6591.                            apsr,            /* Semaphore list               */
  6592.                            DCMW_WAIT_ANY);  /* Wait for any semaphore       */
  6593.  
  6594.     if (ulrc != NO_ERROR) {
  6595.       printf("DosCreateMuxWaitSem error:  return code = %u\n",
  6596.              ulrc);
  6597.       return 1;
  6598.     }
  6599.  
  6600.  
  6601. ulrc = DosWaitMuxWaitSem(hmuxHandAny,
  6602.                          SEM_IMMEDIATE_RETURN,
  6603.                          &ulSem);           /* No semaphores have been posted, so
  6604.                                                we should see a timeout below...    */
  6605.  
  6606.     if (ulrc != ERROR_TIMEOUT) {
  6607.       printf("DosWaitMuxWaitSem error:  return code = %u\n",
  6608.              ulrc);
  6609.       return 1;
  6610.     }
  6611.  
  6612. ulrc = DosDeleteMuxWaitSem(hmuxHandAny,
  6613.                            apsr[0].hsemCur);
  6614.  
  6615.     if (ulrc != NO_ERROR) {
  6616.       printf("DosDeleteMuxWaitSem error:  return code = %u\n",
  6617.              ulrc);
  6618.       return 1;
  6619.     }
  6620.  
  6621. ulrc = DosCloseMuxWaitSem(hmuxHandAny);
  6622.      if (ulrc != NO_ERROR) {
  6623.        printf("DosCloseMuxWaitSem error: return code = %u\n",
  6624.               ulrc);
  6625.        return 1;
  6626.      }
  6627.  
  6628. return NO_ERROR;
  6629. }
  6630.  
  6631. Muxwait semaphores can be defined as either private or shared: 
  6632.  
  6633.      Private semaphores are always unnamed and are therefore always identified 
  6634.       by their handles. They can be used only by threads within a single 
  6635.       process. 
  6636.  
  6637.      Shared semaphores can be either named or unnamed. If named, they can be 
  6638.       opened using either the name or the handle. The handle returned by 
  6639.       DosOpenMuxWaitSem is then used to identify the semaphore for all other 
  6640.       functions. Semaphore names must include the prefix \SEM32\ and must 
  6641.       conform to file system naming conventions. Shared semaphores can be used 
  6642.       by threads in multiple processes. 
  6643.  
  6644.  There is a system-wide limit of 65536 (64K) shared semaphores (including 
  6645.  mutex, event, and muxwait semaphores); in addition, each process can have up 
  6646.  to 65536 (64K) private semaphores. 
  6647.  
  6648.  The following conditions apply to the kinds of semaphores that can be included 
  6649.  in a muxwait-semaphore list: 
  6650.  
  6651.      The list must contain either mutex semaphores or event semaphores. It 
  6652.       cannot contain both at the same time and it cannot contain other muxwait 
  6653.       semaphores. 
  6654.  
  6655.      If the muxwait semaphore is shared, then all the semaphores in the list 
  6656.       must also be shared. 
  6657.  
  6658.      If the muxwait semaphore is private, then the semaphores in its list can 
  6659.       be either private or shared. 
  6660.  
  6661.  If any of these conditions is violated, ERROR_WRONG_TYPE is returned. 
  6662.  
  6663.  The muxwait list can contain a maximum of 64 event semaphores or mutex 
  6664.  semaphores. If an attempt is made to exceed this maximum, 
  6665.  ERROR_TOO_MANY_SEMAPHORES is returned. 
  6666.  
  6667.  If the owners of any of the mutex semaphores in the muxwait semaphore list 
  6668.  have ended without releasing them, ERROR_SEM_OWNER_DIED is returned. The 
  6669.  thread should call DosQueryMutexSem for each mutex semaphore in the 
  6670.  muxwait-semaphore list so that it can determine which semaphores are in the 
  6671.  Owner Died state. 
  6672.  
  6673.  Each mutex semaphore that returns ERROR_SEM_OWNER_DIED from the query should 
  6674.  be closed by calling DosCloseMutexSem. Also, because semaphore handles can be 
  6675.  reused, the mutex semaphores that are closed must be deleted from the 
  6676.  muxwait-semaphore list by calling DosDeleteMuxWaitSem. 
  6677.  
  6678.  OS/2 maintains a usage count for each semaphore. DosCreateMuxWaitSem 
  6679.  initializes the usage count to 1. Thereafter, each call to DosOpenMuxWaitSem 
  6680.  increments the count, and each call to DosCloseMuxWaitSem decrements it. 
  6681.  
  6682.  One parameter of this function is a pointer to an array of SEMRECORD data 
  6683.  structures. Each data structure contains one semaphore record for each of the 
  6684.  semaphores to be included in the muxwait semaphore. A semaphore record 
  6685.  contains the handle and a programmer-defined identifier for that semaphore. 
  6686.  
  6687.  
  6688. ΓòÉΓòÉΓòÉ 7.4.2. Opening a Muxwait Semaphore ΓòÉΓòÉΓòÉ
  6689.  
  6690. Processes other than the semaphore-creating process must use DosOpenMuxWaitSem 
  6691. to gain access to the muxwait semaphore before they can use the semaphore in 
  6692. any other muxwait semaphore function. All of the threads that belong to the 
  6693. process that creates the muxwait semaphore have immediate access to the 
  6694. semaphore. 
  6695.  
  6696. The following code fragment opens a system muxwait semaphore. 
  6697.  
  6698.     #define INCL_DOSSEMAPHORES   /* Semaphore values */
  6699.     #include <os2.h>
  6700.     #include <stdio.h>
  6701.     #include <string.h>
  6702.  
  6703.     UCHAR   ucName[40];  /* Semaphore name           */
  6704.     HMUX    hmux;        /* Muxwait semaphore handle */
  6705.     APIRET  ulrc;        /* Return code              */
  6706.  
  6707.     strcpy(ucName,
  6708.            "\\SEM32\\MUXWAIT1");  /* Name of the system muxwait semaphore */
  6709.  
  6710.     ulrc = DosOpenMuxWaitSem(ucName,
  6711.                              &hmux);
  6712.  
  6713.     if (ulrc != 0) {
  6714.         printf("DosOpenMuxWaitSem error: return code = %ld",
  6715.                ulrc);
  6716.         return;
  6717.     }
  6718.  
  6719. On successful return, hmux contains the handle of the system muxwait semaphore. 
  6720.  
  6721. Opening a muxwait semaphore does not open the semaphores in its muxwait list. A 
  6722. process must open each of the semaphores included in a muxwait semaphore before 
  6723. it opens the muxwait semaphore. Otherwise, DosOpenMuxWaitSem returns the 
  6724. ERROR_INVALID_HANDLE error value to the calling function. 
  6725.  
  6726. Access to semaphores is on a per-process basis. Therefore, a semaphore that has 
  6727. been opened by one thread in a process is open to all other threads in that 
  6728. process as well. 
  6729.  
  6730. Note that DosOpenMuxWaitSem merely provides access to a muxwait semaphore. In 
  6731. order to wait for a muxwait semaphore to clear, a thread must call 
  6732. DosWaitMuxWaitSem. 
  6733.  
  6734. When a process no longer requires access to a muxwait semaphore, it closes the 
  6735. semaphore by calling DosCloseMuxWaitSem. However, if a process ends without 
  6736. closing an open semaphore, the semaphore is closed by OS/2. 
  6737.  
  6738. Each call to DosOpenMuxWaitSem increments the usage count of the semaphore. 
  6739. This count is initialized to 1 when the semaphore is created and is decremented 
  6740. by each call to DosCloseMuxWaitSem. When the usage count reaches 0, the 
  6741. semaphore is deleted by OS/2. 
  6742.  
  6743. Calls to DosOpenMuxWaitSem and DosCloseMuxWaitSem can be nested, but the usage 
  6744. count for a semaphore cannot exceed 65535. If an attempt is made to exceed this 
  6745. number, ERROR_TOO_MANY_OPENS is returned. 
  6746.  
  6747. Even if the owner of a mutex semaphore in a muxwait-semaphore list has ended 
  6748. without releasing the semaphore, the muxwait semaphore is still opened. 
  6749. Subsequent calls to the muxwait semaphore will return ERROR_SEM_OWNER_DIED. But 
  6750. because the process has opened the semaphore, it can then call 
  6751. DosQueryMuxWaitSem to identify all the mutex semaphores in the muxwait list. 
  6752. Next, the process can call DosQueryMutexSem for each mutex semaphore in the 
  6753. list to find out which ones are in the Owner Died state. Each mutex semaphore 
  6754. that returns ERROR_SEM_OWNER_DIED from the query should be closed by calling 
  6755. DosCloseMutexSem. Also, because semaphore handles can be reused, the mutex 
  6756. semaphores that are closed should be deleted from the muxwait-semaphore list by 
  6757. calling DosDeleteMuxWaitSem. 
  6758.  
  6759.  
  6760. ΓòÉΓòÉΓòÉ 7.4.3. Closing a Muxwait Semaphore ΓòÉΓòÉΓòÉ
  6761.  
  6762. When a process no longer requires access to a muxwait semaphore, it closes the 
  6763. semaphore by calling DosCloseMuxWaitSem. However, if a process ends without 
  6764. closing an open semaphore, the semaphore is closed by OS/2. 
  6765.  
  6766. Each call to DosCloseMuxWaitSem decrements the usage count of the semaphore. 
  6767. This count is initialized to 1 when the semaphore is created and is incremented 
  6768. by each call to DosOpenMuxWaitSem. When the usage count reaches 0, the 
  6769. semaphore is deleted by OS/2. 
  6770.  
  6771. The call to DosCloseMuxWaitSem that decrements the usage count to 0 and causes 
  6772. the semaphore to be deleted is referred to as the final close. If a thread 
  6773. attempts to perform the final close for a semaphore while another thread in the 
  6774. same process is still waiting for it, ERROR_SEM_BUSY is returned. 
  6775.  
  6776. Calls to DosOpenMuxWaitSem and DosCloseMuxWaitSem can be nested, but the usage 
  6777. count for a semaphore cannot exceed 65535. If an attempt is made to exceed this 
  6778. number, ERROR_TOO_MANY_OPENS is returned. 
  6779.  
  6780.  
  6781. ΓòÉΓòÉΓòÉ 7.4.4. Waiting for a Muxwait Semaphore ΓòÉΓòÉΓòÉ
  6782.  
  6783. A thread can wait on a muxwait semaphore by using DosWaitMuxWaitSem. 
  6784.  
  6785. Any thread in the process that created a muxwait semaphore can wait for the 
  6786. semaphore to clear by calling DosWaitMuxWaitSem. Threads in other processes can 
  6787. also call DosWaitMuxWaitSem, but they must first gain access to the semaphore 
  6788. by calling DosOpenMuxWaitSem. 
  6789.  
  6790. The following code fragment waits for a muxwait semaphore to clear. Assume that 
  6791. the handle of the semaphore has been placed into hmux already. ulTimeout is the 
  6792. number of milliseconds that the calling thread will wait for the muxwait 
  6793. semaphore to clear. If the specified muxwait semaphore is not cleared during 
  6794. this time interval, the request times out. 
  6795.  
  6796.     #define INCL_DOSSEMAPHORES   /* Semaphore values */
  6797.     #include <os2.h>
  6798.     #include <stdio.h>
  6799.  
  6800.     HMUX     hmux;      /* Muxwait semaphore handle              */
  6801.     ULONG    ulTimeout; /* Number of milliseconds to wait        */
  6802.     ULONG    ulUser;    /* User field for the semaphore that was */
  6803.                         /* posted or released (returned)         */
  6804.     APIRET   ulrc;      /* Return code                           */
  6805.  
  6806.     ulTimeout = 60000;  /* Wait for a maximum of 1 minute        */
  6807.  
  6808.     ulrc = DosWaitMuxWaitSem(hmux,
  6809.                              ulTimeout,
  6810.                              &ulUser);
  6811.  
  6812.     if (ulrc == ERROR_TIMEOUT) {
  6813.         printf("DosWaitMuxWaitSem call timed out");
  6814.         return;
  6815.     }
  6816.  
  6817.     if (ulrc == ERROR_INTERRUPT) {
  6818.         printf("DosWaitMuxWaitSem call was interrupted");
  6819.         return;
  6820.     }
  6821.  
  6822.     if (ulrc != 0) {
  6823.         printf("DosWaitMuxWaitSem error: return code = %ld",
  6824.                ulrc);
  6825.         return;
  6826.     }
  6827.  
  6828. On successful return, the ulUser variable contains the user identifier of the 
  6829. semaphore that caused the wait to terminate. If the caller had to wait for all 
  6830. the semaphores within the muxwait semaphore to clear, then the value 
  6831. corresponds to the last semaphore within the muxwait semaphore to clear. If the 
  6832. caller had to wait for any semaphore with the muxwait semaphore to clear, then 
  6833. the value corresponds to that semaphore. 
  6834.  
  6835. An application can use the DCMW_WAIT_ANY flag in DosCreateMuxWaitSem to block a 
  6836. thread until any one of the event or mutex semaphores included in the muxwait 
  6837. semaphore is posted or released. If the muxwait semaphore refers to mutex 
  6838. semaphores, the thread only gains ownership of the one mutex semaphore that was 
  6839. released. 
  6840.  
  6841. An application can use the DCMW_WAIT_ALL flag in DosCreateMuxWaitSem to block a 
  6842. thread until all of the event or mutex semaphores included in the muxwait 
  6843. semaphore are posted or released. If the muxwait semaphore refers to mutex 
  6844. semaphores, the thread does not gain ownership of any of the mutex semaphores 
  6845. until they are all released. When all are released, the thread becomes owner of 
  6846. all the mutex semaphores included in the muxwait semaphore. If the muxwait 
  6847. semaphore refers to event semaphores, the thread will not run until all of the 
  6848. event semaphores are in the posted state at the same time. This is because 
  6849. event semaphores in a muxwait list are level-triggered, unlike individual event 
  6850. semaphores, which are edge-triggered. 
  6851.  
  6852. For example, suppose that a thread is waiting for five event semaphores in a 
  6853. muxwait list to be posted. The first semaphore is posted and then reset. Next, 
  6854. the remaining semaphores are all posted, and they remain in the posted state. 
  6855. The thread that is waiting for the muxwait semaphore will not run until the 
  6856. first semaphore is posted again. 
  6857.  
  6858. If an application specifies the DCMW_WAIT_ANY flag when the semaphore is 
  6859. created, DosWaitMuxWaitSem returns the programmer-defined identifier of the 
  6860. semaphore that is subsequently posted or released. If an application specifies 
  6861. the DCMW_WAIT_ALL flag, DosWaitMuxWaitSem returns the programmer-defined 
  6862. identifier of the last semaphore that was posted or released. 
  6863.  
  6864. The ulTimeout parameter places a limit on the amount of time a thread blocks on 
  6865. a DosWaitMuxWaitSem request. If the time limit is reached before the semaphore 
  6866. has cleared, ERROR_TIMEOUT is returned. If SEM_IMMEDIATE_RETURN is specified as 
  6867. the time limit, DosWaitMuxWaitSem returns without blocking the thread. The 
  6868. thread can then go on to perform other operations and call DosWaitMuxWaitSem 
  6869. again later to wait for the event or mutex semaphores in the muxwait list to be 
  6870. posted or released. If a time limit of SEM_INDEFINITE_WAIT is specified, the 
  6871. thread waits (is blocked) indefinitely. If the thread is unblocked by an 
  6872. external event while it is waiting for the muxwait semaphore (as when a "no 
  6873. wait" I/O request has just been completed), DosWaitMuxWaitSem returns 
  6874. ERROR_INTERRUPT. 
  6875.  
  6876. When a thread is waiting for any one of the semaphores in a muxwait list to be 
  6877. posted or released, the semaphores are checked in the order in which they are 
  6878. defined in the list. 
  6879.  
  6880. Waiting for Multiple Event Semaphores 
  6881. The following information pertains only to muxwait semaphores that consist of 
  6882. multiple event semaphores: 
  6883.  
  6884. Unlike individual event semaphores, which are edge-triggered, event semaphores 
  6885. in a muxwait list are level-triggered. This means that if a thread is waiting 
  6886. for all of the event semaphores in the muxwait list, it will not run until all 
  6887. of the event semaphores are in the posted state at the same time. 
  6888.  
  6889. For example, a thread is waiting for five event semaphores in a muxwait list to 
  6890. be posted. The first semaphore is posted and then reset. Next, the remaining 
  6891. semaphores are all posted, and they remain in the posted state. The thread that 
  6892. is waiting for the muxwait semaphore will not run until the first semaphore is 
  6893. posted again. 
  6894.  
  6895. Waiting for Multiple Mutex Semaphores 
  6896. The following information pertains only to muxwait semaphores that consist of 
  6897. multiple mutex semaphores: 
  6898.  
  6899.      If a thread is waiting for all of the mutex semaphores in a muxwait list 
  6900.       to be released, it does not receive ownership of any of the semaphores 
  6901.       until all of the semaphores have been released. 
  6902.  
  6903.      If a thread is waiting for any one of the mutex semaphores in a muxwait 
  6904.       list, then the thread gains ownership only of the first mutex semaphore 
  6905.       that is released. The ownership of all other mutex semaphores in the 
  6906.       muxwait list remains unchanged. 
  6907.  
  6908.      If two threads have the same priority, then a thread that is waiting for 
  6909.       a mutex semaphore in a muxwait list takes precedence over a thread that 
  6910.       has requested ownership of only the individual semaphore, provided all 
  6911.       other mutex semaphores in the muxwait list have been released. For 
  6912.       example, a mutex semaphore that is part of a muxwait semaphore is 
  6913.       released. One thread has requested ownership of that single mutex 
  6914.       semaphore, and another thread with the same priority is waiting for the 
  6915.       muxwait semaphore that contains the same mutex semaphore. If all of the 
  6916.       other mutex semaphores in the muxwait list are unowned and ready to be 
  6917.       given to the muxwait semaphore, then the thread that is waiting for the 
  6918.       muxwait semaphore will run first. 
  6919.  
  6920.      If the owners of any of the mutex semaphores in the muxwait semaphore 
  6921.       list have ended without releasing them, ERROR_SEM_OWNER_DIED is returned. 
  6922.       The thread must then call DosQueryMuxWaitSem to obtain the records of all 
  6923.       the semaphores in the muxwait list. Next, the thread must call 
  6924.       DosQueryMutexSem for each mutex semaphore in the muxwait-semaphore list 
  6925.       so that it can determine which semaphores are in the Owner Died state. 
  6926.  
  6927.       Each mutex semaphore that returns ERROR_SEM_OWNER_DIED from the query 
  6928.       should be closed by calling DosCloseMutexSem. Also, because semaphore 
  6929.       handles can be reused, the mutex semaphores that are closed should be 
  6930.       deleted from the muxwait-semaphore list by calling DosDeleteMuxWaitSem. 
  6931.  
  6932.      If any of the mutex semaphores in the muxwait list are owned by the 
  6933.       calling thread, ERROR_MUTEX_OWNED is returned. 
  6934.  
  6935.  
  6936. ΓòÉΓòÉΓòÉ 7.4.5. Adding a Semaphore to a Muxwait List ΓòÉΓòÉΓòÉ
  6937.  
  6938. An application uses DosAddMuxWaitSem to add semaphores to a muxwait semaphore 
  6939. that has already been created, even while threads are waiting on the muxwait 
  6940. semaphore. 
  6941.  
  6942. Any thread in the process that created a muxwait semaphore can add a mutex 
  6943. semaphore or an event semaphore to the muxwait list by calling 
  6944. DosAddMuxWaitSem. Threads in other processes can also use this function, but 
  6945. they must first gain access to the semaphore by calling DosOpenMuxWaitSem. 
  6946.  
  6947. A maximum of 64 semaphores can be included in a muxwait-semaphore list. If an 
  6948. attempt is made to exceed this maximum, ERROR_TOO_MANY_SEMAPHORES is returned. 
  6949.  
  6950. All of the semaphores in a muxwait-semaphore list must be of the same type. 
  6951. That is, if a mutex semaphore is being added, then the other semaphores in the 
  6952. list must be mutex semaphores. If an event semaphore is being added, then the 
  6953. other semaphores in the list must be event semaphores. A shared muxwait 
  6954. semaphore can contain only shared semaphores in its list. A private muxwait 
  6955. semaphore can contain both private and shared semaphores. If any of these 
  6956. conditions is violated, ERROR_WRONG_TYPE is returned. 
  6957.  
  6958. If the semaphore is successfully added to the muxwait list, DosAddMuxWaitSem 
  6959. checks to see whether each thread that is waiting for the muxwait semaphore has 
  6960. the newly added semaphore open in its process. The muxwait semaphore is invalid 
  6961. for any waiting threads that do not have the newly added semaphore open in 
  6962. their process; these threads are unblocked with a return code of 
  6963. ERROR_INVALID_HANDLE. Any processes that opened the muxwait semaphore before 
  6964. the add operation and that do not have the new semaphore open, will have to 
  6965. open the new semaphore before making any further use of the muxwait semaphore. 
  6966. Any future calls concerning the muxwait semaphore by processes that do not have 
  6967. the new semaphore open will have ERROR_INVALID_HANDLE returned until the new 
  6968. semaphore is opened. 
  6969.  
  6970. A thread that receives a return code of ERROR_INVALID_HANDLE can take the 
  6971. following corrective action: 
  6972.  
  6973.    1. First, the thread can obtain the records of all the semaphores in the 
  6974.       muxwait list by calling DosQueryMuxWaitSem. 
  6975.  
  6976.    2. Next, it can query each semaphore in the muxwait list, using 
  6977.       DosQueryMutexSem or DosQueryEventSem, to find out which semaphore is not 
  6978.       open to its process. 
  6979.  
  6980.    3. Finally, it can open the semaphores that are not open by calling 
  6981.       DosOpenMutexSem or DosOpenEventSem. 
  6982.  
  6983.  As soon as this semaphore is opened, the muxwait semaphore becomes valid again 
  6984.  for the process, as long as no other changes have been made to the muxwait 
  6985.  list to make it invalid. However, in order to successfully wait for the 
  6986.  muxwait semaphore, the process must call DosWaitMuxWaitSem again. 
  6987.  
  6988.  A semaphore must be open for a process before the process can add that 
  6989.  semaphore to a muxwait semaphore. If it is not open and a thread is waiting on 
  6990.  the muxwait semaphore, DosAddMuxWaitSem returns ERROR_INVALID_HANDLE to the 
  6991.  process adding the new semaphore, and the waiting thread continues waiting. 
  6992.  
  6993.  
  6994. ΓòÉΓòÉΓòÉ 7.4.6. Deleting a Semaphore from a Muxwait List ΓòÉΓòÉΓòÉ
  6995.  
  6996. An application can delete semaphores from a muxwait semaphore by using 
  6997. DosDeleteMuxWaitSem. 
  6998.  
  6999. Any thread in the process that created a muxwait semaphore can delete a mutex 
  7000. or event semaphore from the muxwait list by calling DosDeleteMuxWaitSem. 
  7001. Threads in other processes can also use this function, but they must first gain 
  7002. access to the semaphore by calling DosOpenMuxWaitSem. 
  7003.  
  7004. Semaphores can be deleted from the muxwait list even while threads are 
  7005. currently waiting for the semaphore. If the deleted semaphore is the only one 
  7006. in the muxwait list that has not yet been posted or released, then threads that 
  7007. are waiting for the muxwait semaphore are unblocked. Also, if the deleted 
  7008. semaphore happens to be the last one that a particular thread was waiting for, 
  7009. that thread is unblocked. Also, if the deleted semaphore is the last one in the 
  7010. muxwait list (that is, if the list is now empty), then all the threads that are 
  7011. waiting for the muxwait semaphore are unblocked. 
  7012.  
  7013.  
  7014. ΓòÉΓòÉΓòÉ 7.4.7. Querying a Muxwait Semaphore ΓòÉΓòÉΓòÉ
  7015.  
  7016. Processes use DosQueryMuxWaitSem to obtain the semaph ore records for each of 
  7017. the semaphores included in the muxwait semaphore. 
  7018.  
  7019. Any thread in the process that created a muxwait semaphore can obtain 
  7020. information about the semaphores in the muxwait list by calling 
  7021. DosQueryMuxWaitSem. Threads in other processes can also use this function, but 
  7022. they must first gain access to the semaphore by calling DosOpenMuxWaitSem. 
  7023.  
  7024. An application must provide this function with an array in which to store the 
  7025. semaphore records. If the array is not large enough to hold all of the 
  7026. semaphore records that are in the muxwait list, then ERROR_PARAM_TOO_SMALL is 
  7027. returned, and the record-counting parameter of DosQueryMuxWaitSem will contain 
  7028. the number of semaphore records that are in the muxwait list. The calling 
  7029. thread can then allocate the correct amount of space and call 
  7030. DosQueryMuxWaitSem again with the correct amount of space for the list of 
  7031. records. 
  7032.  
  7033. If the owner of any mutex semaphore in the muxwait-semaphore list has ended 
  7034. without releasing the semaphore, the records of all the semaphores in the list 
  7035. are still returned, but DosQueryMuxWaitSem also returns ERROR_SEM_OWNER_DIED. 
  7036. The calling thread can call DosQueryMutexSem for each mutex semaphore in the 
  7037. muxwait-semaphore list so that it can determine which semaphores are in the 
  7038. Owner Died state. The process can then close the unowned mutex semaphores. 
  7039.  
  7040. Each mutex semaphore that returns ERROR_SEM_OWNER_DIED from the query should be 
  7041. closed by calling DosCloseMutexSem. Also, because semaphore handles can be 
  7042. reused, the mutex semaphores that are closed should be deleted from the 
  7043. muxwait-semaphore list by calling DosDeleteMuxWaitSem. 
  7044.  
  7045. If the specified muxwait semaphore does not exist, ERROR_INVALID_HANDLE is 
  7046. returned. 
  7047.  
  7048.  
  7049. ΓòÉΓòÉΓòÉ 8. Timers ΓòÉΓòÉΓòÉ
  7050.  
  7051. This chapter describes how to create and use timers. Timers enable applications 
  7052. to time events by waiting for an interval to elapse or by waiting for a 
  7053. semaphore to be posted. 
  7054.  
  7055. The following topics are related to the information in this chapter: 
  7056.  
  7057.      Program execution and control 
  7058.      Semaphores 
  7059.  
  7060.  
  7061. ΓòÉΓòÉΓòÉ 8.1. About Timers ΓòÉΓòÉΓòÉ
  7062.  
  7063. Because OS/2 is a multitasking system, an application cannot predict when it 
  7064. will lose execution control or how much time will elapse before control 
  7065. returns. A timer enables an application to suspend operation for a specific 
  7066. length of time, to block a thread until an interval has elapsed, or to post an 
  7067. event semaphore at repeated intervals. 
  7068.  
  7069. Timers are managed by OS/2. When an application requests a timer, the system 
  7070. monitors the system clock and notifies the application when the interval has 
  7071. elapsed. 
  7072.  
  7073. The system clock counts the number of system-clock interrupts (clock ticks) 
  7074. that have occurred since the system was started. On most hardware, clock ticks 
  7075. occur approximately 32 times a second, so the length of a tick is approximately 
  7076. 31.25 milliseconds. 
  7077.  
  7078. When an application specifies a timer interval, the system rounds up the 
  7079. interval to the next clock tick. For example, if an application requests a 10 
  7080. millisecond interval, it will sleep for at least 31.25 milliseconds. If an 
  7081. application requests a 100 millisecond interval, the actual interval will be at 
  7082. least 125 milliseconds (4 ticks). 
  7083.  
  7084. Because OS/2 is a preemptive operating system, there is no guarantee that a 
  7085. thread will resume immediately after the timer interval. If a higher priority 
  7086. process or thread is executing, the timed thread must wait. 
  7087.  
  7088. Although timers are not absolutely accurate, they can be used where the 
  7089. inaccuracy can be ignored. In a real-time control application, for example, an 
  7090. event can be timed in seconds or minutes, so an error of a few milliseconds is 
  7091. unimportant. If an application requires as much accuracy as the system can 
  7092. provide, it can dedicate a thread to managing timer intervals and then elevate 
  7093. the priority of that thread. 
  7094.  
  7095.  
  7096. ΓòÉΓòÉΓòÉ 8.1.1. Suspending Threads ΓòÉΓòÉΓòÉ
  7097.  
  7098. An application can use DosSleep to suspend operation of a thread for a 
  7099. specified interval. The system waits the specified number of milliseconds 
  7100. (subject to the round-off error just discussed) before returning control to the 
  7101. application. Because a sleeping application yields execution control to the 
  7102. system, the system can execute other processes or threads while the application 
  7103. sleeps. 
  7104.  
  7105. The following code fragment shows how to suspend the calling thread for one 
  7106. minute: 
  7107.  
  7108.     #define INCL_DOSPROCESS   /* Process and thread values */
  7109.     #include <os2.h>
  7110.     #include <stdio.h>
  7111.  
  7112.     ULONG   ulTimeInterval;   /* Interval in milliseconds  */
  7113.     APIRET  ulrc;             /* Return code               */
  7114.  
  7115.     ulTimeInterval = 60000;
  7116.  
  7117.     ulrc = DosSleep(ulTimeInterval);
  7118.  
  7119.     if (ulrc != 0) {
  7120.         printf("DosSleep error: return code = %ld",
  7121.                ulrc);
  7122.         return;
  7123.     }
  7124.  
  7125. See Suspending the Current Thread for more information on DosSleep. 
  7126.  
  7127.  
  7128. ΓòÉΓòÉΓòÉ 8.1.2. Asynchronous Timers ΓòÉΓòÉΓòÉ
  7129.  
  7130. DosSleep is useful for temporarily suspending a thread but is much less useful 
  7131. for timing. Typically, an application carries out part of its task and then 
  7132. waits an interval. If the execution time varies (as it will if the application 
  7133. runs on different hardware), the overall interval varies. In these situations, 
  7134. asynchronous timers provide greater precision than DosSleep. 
  7135.  
  7136. OS/2 supports two types of asynchronous timers, single-interval (one-shot) and 
  7137. repeated. DosAsyncTimer starts a single-interval timer. During the timing 
  7138. interval, the application can carry out other tasks. The system posts an event 
  7139. semaphore when the timing interval elapses. The application can reset the 
  7140. semaphore with DosResetEventSem before starting the timer. DosAsyncTimer yields 
  7141. a more accurate timing interval than DosSleep because the interval is 
  7142. independent of the execution time. 
  7143.  
  7144. DosStartTimer starts a repeated timer. The system posts an event semaphore each 
  7145. time the interval expires. The application can reset the semaphore before 
  7146. starting the timer and after each posting. When the application resets the 
  7147. semaphore with DosResetEventSem, it can check the cPosts value to determine how 
  7148. many times the semaphore has been posted. If the semaphore has been posted more 
  7149. than once, the application has missed a timer interval. 
  7150.  
  7151.  
  7152. ΓòÉΓòÉΓòÉ 8.2. Using Timers ΓòÉΓòÉΓòÉ
  7153.  
  7154. Applications frequently need to synchronize the execution of threads, to cause 
  7155. an event to occur after a specified interval, or to cause an event to occur at 
  7156. regular intervals. Timers are typically used to enable an application to pause 
  7157. before processing user input or to carry out a task at a given time. 
  7158.  
  7159. OS/2 provides the following timer functions: 
  7160.  
  7161.      DosSleep suspends the execution of the calling thread, enabling other 
  7162.       threads to run while the calling thread sleeps. 
  7163.  
  7164.      DosAsyncTimer starts a single-interval timer. 
  7165.  
  7166.      DosStartTimer starts a repeated-interval timer. 
  7167.  
  7168.      DosStopTimer stops a single-interval or repeated-interval timer. 
  7169.  
  7170.  The system also provides two functions, DosGetDateTime and DosSetDateTime, for 
  7171.  getting and setting the system date and time. 
  7172.  
  7173.  The timers that are started by DosAsyncTimer and DosStartTimer are 
  7174.  asynchronous timers; that is, the timers run independently of the calling 
  7175.  thread, enabling the calling thread to perform other operations while the 
  7176.  timer is running. When an asynchronous timer interval expires, the system 
  7177.  notifies the application by posting an event semaphore. 
  7178.  
  7179.  Time intervals for DosAsyncTimer, DosStartTimer, and DosSleep are specified in 
  7180.  milliseconds; however, it is important to recognize that the actual duration 
  7181.  of the specified time interval will be affected by two factors: 
  7182.  
  7183.      First, the system clock keeps track of time in less precise units known 
  7184.       as clock ticks.  On most hardware, clock ticks occur approximately 32 
  7185.       times a second, so each tick interval lasts approximately 31.25 
  7186.       milliseconds. (To determine the duration of a clock tick on your 
  7187.       computer, call DosQuerySysInfo, and examine the timer-interval field.) 
  7188.  
  7189.       Because clock ticks are less precise than millisecond values, any time 
  7190.       interval that is specified in milliseconds will essentially be rounded up 
  7191.       to the next clock tick. 
  7192.  
  7193.      Second, because OS/2 is a priority-based, multitasking operating system, 
  7194.       there is no guarantee that a thread will resume execution immediately 
  7195.       after the timer interval expires. If a higher priority process or thread 
  7196.       is running, or if a hardware interrupt occurs, the timed thread blocks. 
  7197.       (To minimize delays caused by preemptive scheduling, an application can 
  7198.       dedicate a thread to managing time-critical tasks, and then raise that 
  7199.       thread to a higher priority.) 
  7200.  
  7201.  These factors usually cause the timer interval to be longer than requested; 
  7202.  however, it will generally be within a few clock ticks. 
  7203.  
  7204.  Timers for Presentation Manager applications are provided through the message 
  7205.  queue. Therefore, a Presentation Manager application will not use the timer 
  7206.  functions unless it performs some real-time control task. 
  7207.  
  7208.  Note:  In the example code fragments that follow, error checking was left out 
  7209.         to conserve space. Applications should always check the return code 
  7210.         that the functions return. Control Program functions return an APIRET 
  7211.         value. A return code of 0 indicates success. If a non-zero value is 
  7212.         returned, an error occurred. 
  7213.  
  7214.  
  7215. ΓòÉΓòÉΓòÉ 8.2.1. Suspending the Current Thread ΓòÉΓòÉΓòÉ
  7216.  
  7217. An application can suspend a thread by using DosSleep. DosSleep suspends the 
  7218. execution of the calling thread for a specified time interval. 
  7219.  
  7220. DosSleep requires one argument-the amount of time (in milliseconds) to suspend 
  7221. the thread. This value is rounded up to the nearest clock tick. If a time 
  7222. interval of 0 is specified, the thread gives up the remainder of the current 
  7223. time slice, enabling other ready threads of equal or higher priority to run; 
  7224. the calling thread will run again during its next scheduled time slice. If 
  7225. there is no other ready thread of equal or higher priority, DosSleep returns 
  7226. immediately; it does not yield to a thread of lower priority. 
  7227.  
  7228. If there is a round-off error or if other threads in the system have higher 
  7229. priority, a thread might not resume execution immediately after the sleep 
  7230. interval. 
  7231.  
  7232. The following DosSleep call suspends a thread for at least 5 seconds: 
  7233.  
  7234.     DosSleep(5000);
  7235. Note that the specified time interval refers to execution time (accumulated 
  7236. scheduled time slices), not to elapsed real time. Elapsed real time will be 
  7237. longer and will vary, depending on the hardware and on the number and 
  7238. priorities of other threads running in the system. In addition, even though the 
  7239. calling thread is scheduled for execution as soon as the specified time 
  7240. interval has elapsed, its execution could be delayed if a higher priority 
  7241. thread is running or if a hardware interrupt occurs. 
  7242.  
  7243. Because the above factors usually cause the sleep interval to be longer than 
  7244. requested (though generally within a few clock ticks), DosSleep should not be 
  7245. used as a substitute for a real-time clock. 
  7246.  
  7247. Note: 
  7248.  
  7249.    1. Elapsed real time for the asynchronous timers (started by DosAsyncTimer 
  7250.       and DosStartTimer) will be much closer to their specified time intervals 
  7251.       because these timers run independent of the execution of the calling 
  7252.       thread. 
  7253.  
  7254.    2. To ensure optimal performance, do not use DosSleep in a single-thread 
  7255.       Presentation Manager application. (Use WinStartTimer.) 
  7256.  
  7257.  
  7258. ΓòÉΓòÉΓòÉ 8.2.2. Timing a Single Interval ΓòÉΓòÉΓòÉ
  7259.  
  7260. To carry out other tasks while the timer counts an interval, an application can 
  7261. use DosAsyncTimer. This function sets a single-interval timer without stopping 
  7262. the application-the timer runs asynchronously to the calling thread, enabling 
  7263. the thread to perform other operations while it is waiting for the specified 
  7264. time interval to expire. When the interval elapses, OS/2 notifies the 
  7265. application of the expiration of the timer by posting an event semaphore. The 
  7266. application resets the semaphore before starting the timer and monitors the 
  7267. semaphore to determine when the time has elapsed. The application can use 
  7268. DosCreateEventSem with the initial state FALSE to create a reset semaphore. For 
  7269. more information on semaphores, see Semaphores. 
  7270.  
  7271. The following code fragment creates an event semaphore and then calls 
  7272. DosAsyncTimer to count an interval while the application performs other tasks: 
  7273.  
  7274.     #define INCL_DOSDATETIME    /* Date/Time and Timer Support */
  7275.     #define INCL_DOSSEMAPHORES  /* for semaphores              */
  7276.  
  7277.     #include <os2.h>
  7278.  
  7279.     HEV hev;
  7280.     HTIMER hTimer;
  7281.  
  7282.     /* First create a private, reset, event semaphore. */
  7283.  
  7284.     DosCreateEventSem((PSZ) NULL,
  7285.                       &hev,
  7286.                       DC_SEM_SHARED,
  7287.                       FALSE);
  7288.  
  7289.     /* Start async (one-shot) timer; post semaphore in 10 seconds.  */
  7290.  
  7291.     DosAsyncTimer(10000,       /* Time in milliseconds (10 sec)     */
  7292.                   (HSEM) hev,  /* Semaphore handle                  */
  7293.                   &hTimer);    /* Timer handle (used to stop timer) */
  7294.  
  7295.         .
  7296.         .    /* Do other processing here, then wait for semaphore.  */
  7297.         .
  7298.  
  7299.     DosWaitEventSem(hev,
  7300.                     SEM_INDEFINITE_WAIT);
  7301.  
  7302. Before starting the timer, the thread creates the event semaphore with 
  7303. DosCreateEventSem, specifying its initial state as reset. If the semaphore was 
  7304. previously created by the same process, the thread resets it by calling 
  7305. DosResetEventSem. If the semaphore was previously created by another process, 
  7306. then the thread must call DosOpenEventSem to gain access to the semaphore 
  7307. before calling DosResetEventSem. 
  7308.  
  7309. Next, the thread calls DosAsyncTimer, specifying the handle of the event 
  7310. semaphore and the desired time interval. The thread can then perform other 
  7311. tasks. However, in order for the application to be notified of the expiration 
  7312. of the timer, one or more threads in the application must call DosWaitEventSem. 
  7313.  
  7314. When the time interval expires, the system posts the semaphore, and any threads 
  7315. that were blocked on DosWaitEventSem requests can resume their execution. If 
  7316. another time interval is required, the semaphore is reset, and both 
  7317. DosAsyncTimer and DosWaitEventSem are called again. (To time regular repeated 
  7318. intervals, use DosStartTimer.) 
  7319.  
  7320. The timer can be canceled before its time interval expires by calling 
  7321. DosStopTimer. 
  7322.  
  7323.  
  7324. ΓòÉΓòÉΓòÉ 8.2.3. Timing Repeated Intervals ΓòÉΓòÉΓòÉ
  7325.  
  7326. To count an interval repeatedly, an application can use DosStartTimer. This 
  7327. function starts a repeated-interval timer. 
  7328.  
  7329. Unlike DosAsyncTimer, DosStartTimer does not stop after the first interval is 
  7330. counted. The timer runs asynchronously to the calling thread, enabling the 
  7331. thread to perform other operations while it is waiting for the specified time 
  7332. intervals to expire. The system notifies the application of the timer's 
  7333. expirations by posting an event semaphore. 
  7334.  
  7335. The application resets the semaphore before starting the timer and whenever the 
  7336. system posts the semaphore. The application can use the value returned in the 
  7337. post-counting parameter by DosResetEventSem to assure the semaphore was posted 
  7338. only once before it was reset. 
  7339.  
  7340. The following code fragment starts a timer and then waits on and resets the 
  7341. associated event semaphore. Assume that the handle of the targeted event 
  7342. semaphore has been placed into SemHandle. 
  7343.  
  7344.     #define INCL_DOSDATETIME   /* Date and time values */
  7345.     #include <os2.h>
  7346.     #include <stdio.h>
  7347.  
  7348.     ULONG    ulTimeInterval;   /* Interval (milliseconds) */
  7349.     HSEM     hsemSemHandle;    /* Event-semaphore handle  */
  7350.     HTIMER   hHandle;          /* Timer handle (returned) */
  7351.     APIRET   ulrc;             /* Return code             */
  7352.  
  7353.     ulTimeInterval = 30000;    /* Set the periodic time interval to */
  7354.                                /* elapse every 30 seconds           */
  7355.  
  7356.     ulrc = DosStartTimer(ulTimeInterval,
  7357.                          hsemSemHandle,
  7358.                          &hHandle);
  7359.  
  7360.     if (ulrc != 0) {
  7361.         printf("DosStartTimer error: return code = %ld",
  7362.                ulrc);
  7363.         return;
  7364.     }
  7365.  
  7366. On successful return, Handle will contain the handle of this periodic timer. 
  7367. DosStopTimer can be used later to stop the periodic timer. 
  7368.  
  7369. A repeated timer will continue to count the interval and post the semaphore 
  7370. until the application terminates or the application uses DosStopTimer to stop 
  7371. the timer explicitly. The following code fragment shows how to stop a periodic 
  7372. timer that has been started previously with DosStartTimer: 
  7373.  
  7374.     #define INCL_DOSDATETIME   /* Date and time values */
  7375.     #include <os2.h>
  7376.     #include <stdio.h>
  7377.  
  7378.     HTIMER   hHandle;     /* Handle of the timer */
  7379.     APIRET   ulrc;        /* Return code         */
  7380.  
  7381.     ulrc = DosStopTimer(hHandle);
  7382.  
  7383.     if (ulrc != 0) {
  7384.         printf("DosStopTimer error: return code = %ld",
  7385.                ulrc);
  7386.         return;
  7387.     }
  7388.  
  7389. Before starting the timer, the event semaphore must be reset. If the semaphore 
  7390. does not exist, the thread can create it with DosCreateEventSem, specifying its 
  7391. initial state as reset. If the semaphore was previously created by the same 
  7392. process, the thread resets it by calling DosResetEventSem. If the semaphore was 
  7393. previously created by another process, then the thread calls DosOpenEventSem to 
  7394. gain access to the semaphore before calling DosResetEventSem. 
  7395.  
  7396. Next, the thread calls DosStartTimer, specifying the handle of the event 
  7397. semaphore and the desired time interval. The thread can then perform other 
  7398. tasks. However, in order for the application to be notified of the timer's 
  7399. expirations, one or more threads in the application must call DosWaitEventSem. 
  7400.  
  7401. When the time interval expires, the system posts the semaphore, and any threads 
  7402. that were blocked on DosWaitEventSem requests can resume their execution. Each 
  7403. time the semaphore is posted, it must be reset with DosResetEventSem before the 
  7404. next timer expiration. DosWaitEventSem must also be called to wait for the 
  7405. semaphore to be posted again. 
  7406.  
  7407. In addition to resetting the event semaphore, DosResetEventSem returns the 
  7408. semaphore's post count (the number of times the semaphore has been posted since 
  7409. the last time it was in the set state). An application can use the post count 
  7410. to ensure that it has not missed a timer interval; if the post count is greater 
  7411. than one, the application missed a timer interval. 
  7412.  
  7413.  
  7414. ΓòÉΓòÉΓòÉ 9. Glossary ΓòÉΓòÉΓòÉ
  7415.  
  7416. This glossary defines many of the terms used in this book. It includes terms 
  7417. and definitions from the IBM Dictionary of Computing, as well as terms specific 
  7418. to the OS/2 operating system and the Presentation Manager. It is not a complete 
  7419. glossary for the entire OS/2 operating system; nor is it a complete dictionary 
  7420. of computer terms. 
  7421.  
  7422. Other primary sources for these definitions are: 
  7423.  
  7424.      The American National Standard Dictionary for Information Systems, ANSI 
  7425.       X3.172-1990, copyrighted 1990 by the American National Standards 
  7426.       Institute, 11 West 42nd Street, New York, New York 10036. These 
  7427.       definitions are identified by the symbol (A) after the definition. 
  7428.  
  7429.      The Information Technology Vocabulary, developed by Subcommittee 1, Joint 
  7430.       Technical Committee 1, of the International Organization for 
  7431.       Standardization and the International Electrotechnical Commission 
  7432.       (ISO/IEC JTC1/SC1). Definitions of published parts of this vocabulary are 
  7433.       identified by the symbol (I) after the definition; definitions taken from 
  7434.       draft international standards, committee drafts, and working papers being 
  7435.       developed by ISO/IEC JTC1/SC1 are identified by the symbol (T) after the 
  7436.       definition, indicating that final agreement has not yet been reached 
  7437.       among the participating National Bodies of SC1. 
  7438.  
  7439.  
  7440. ΓòÉΓòÉΓòÉ 9.1. Glossary Listing ΓòÉΓòÉΓòÉ
  7441.  
  7442. Select a starting letter of glossary terms: 
  7443.  
  7444.  A    N 
  7445.  B    O 
  7446.  C    P 
  7447.  D    Q 
  7448.  E    R 
  7449.  F    S 
  7450.  G    T 
  7451.  H    U 
  7452.  I    V 
  7453.  J    W 
  7454.  K    X 
  7455.  L    Y 
  7456.  M    Z 
  7457.  
  7458.  
  7459. ΓòÉΓòÉΓòÉ <hidden> Glossary - A ΓòÉΓòÉΓòÉ
  7460.  
  7461.  accelerator - In SAA Common User Access architecture, a key or combination of 
  7462.    keys that invokes an application-defined function. 
  7463.  
  7464.  accelerator table - A table used to define which key strokes are treated as 
  7465.    accelerators and the commands they are translated into. 
  7466.  
  7467.  access mode - The manner in which an application gains access to a file it has 
  7468.    opened. Examples of access modes are read-only, write-only, and read/write. 
  7469.  
  7470.  access permission - All access rights that a user has regarding an object. (I)
  7471.  
  7472.  action - One of a set of defined tasks that a computer performs. Users request 
  7473.    the application to perform an action in several ways, such as typing a 
  7474.    command, pressing a function key, or selecting the action name from an 
  7475.    action bar or menu. 
  7476.  
  7477.  action bar - In SAA Common User Access architecture, the area at the top of a 
  7478.    window that contains choices that give a user access to actions available in 
  7479.    that window. 
  7480.  
  7481.  action point - The current position on the screen at which the pointer is 
  7482.    pointing. Contrast with hot spot and input focus. 
  7483.  
  7484.  active program - A program currently running on the computer.  An active 
  7485.    program can be interactive (running and receiving input from the user) or 
  7486.    noninteractive (running but not receiving input from the user). See also 
  7487.    interactive program and noninteractive program. 
  7488.  
  7489.  active window - The window with which the user is currently interacting. 
  7490.  
  7491.  address space - (1) The range of addresses available to a program. (A)  (2) 
  7492.    The area of virtual storage available for a particular job. 
  7493.  
  7494.  alphanumeric video output - Output to the logical video buffer when the video 
  7495.    adapter is in text mode and the logical video buffer is addressed by an 
  7496.    application as a rectangular array of character cells. 
  7497.  
  7498.  American National Standard Code for Information Interchange - The standard 
  7499.    code, using a coded character set consisting of 7-bit coded characters (8 
  7500.    bits including parity check), that is used for information interchange among 
  7501.    data processing systems, data communication systems, and associated 
  7502.    equipment. The ASCII set consists of control characters and graphic 
  7503.    characters. (A) 
  7504.  
  7505.    Note:  IBM has defined an extension to ASCII code (characters 128-255). 
  7506.  
  7507.  anchor - A window procedure that handles Presentation Manager message 
  7508.    conversions between an icon procedure and an application. 
  7509.  
  7510.  anchor block - An area of Presentation-Manager-internal resources to allocated 
  7511.    process or thread that calls WinInitialize. 
  7512.  
  7513.  anchor point - A point in a window used by a program designer or by a window 
  7514.    manager to position a subsequently appearing window. 
  7515.  
  7516.  ANSI - American National Standards Institute. 
  7517.  
  7518.  APA - All points addressable. 
  7519.  
  7520.  API - Application programming interface. 
  7521.  
  7522.  application - A collection of software components used to perform specific 
  7523.    types of work on a computer; for example, a payroll application, an airline 
  7524.    reservation application, a network application. 
  7525.  
  7526.  application object - In SAA Advanced Common User Access architecture, a form 
  7527.    that an application provides for a user; for example, a spreadsheet form. 
  7528.    Contrast with user object. 
  7529.  
  7530.  application programming interface (API) - A functional interface supplied by 
  7531.    the operating system or by a separately orderable licensed program that 
  7532.    allows an application program written in a high-level language to use 
  7533.    specific data or functions of the operating system or the licensed program. 
  7534.  
  7535.  application-modal - Pertaining to a message box or dialog box for which 
  7536.    processing must be completed before further interaction with any other 
  7537.    window owned by the same application may take place. 
  7538.  
  7539.  area - In computer graphics, a filled shape such as a solid rectangle. 
  7540.  
  7541.  ASCII - American National Standard Code for Information Interchange. 
  7542.  
  7543.  ASCIIZ - A string of ASCII characters that is terminated with a byte 
  7544.    containing the value 0. 
  7545.  
  7546.  aspect ratio - In computer graphics, the width-to-height ratio of an area, 
  7547.    symbol, or shape. 
  7548.  
  7549.  asynchronous (ASYNC) - (1) Pertaining to two or more processes that do not 
  7550.    depend upon the occurrence of specific events such as common timing 
  7551.    signals. (T)  (2) Without regular time relationship;  unexpected or 
  7552.    unpredictable with respect to the execution of program instructions. See 
  7553.    also synchronous. 
  7554.  
  7555.  atom - A constant that represents a string. As soon as a string has been 
  7556.    defined as an atom, the atom can be used in place of the string to save 
  7557.    space. Strings are associated with their respective atoms in an atom table. 
  7558.    See also integer atom. 
  7559.  
  7560.  atom table - A table used to relate atoms with the strings that they 
  7561.    represent. Also in the table is the mechanism by which the presence of a 
  7562.    string can be checked. 
  7563.  
  7564.  atomic operation - An operation that completes its work on an object before 
  7565.    another operation can be performed on the same object. 
  7566.  
  7567.  attribute - A characteristic or property that can be controlled, usually to 
  7568.    obtain a required appearance;  for example, the color of a line. See also 
  7569.    graphics attributes and segment attributes. 
  7570.  
  7571.  automatic link - In Information Presentation Facility (IPF), a link that 
  7572.    begins a chain reaction at the primary window. When the user selects the 
  7573.    primary window, an automatic link is activated to display secondary windows. 
  7574.  
  7575.  AVIO - Advanced Video Input/Output. 
  7576.  
  7577.  
  7578. ΓòÉΓòÉΓòÉ <hidden> Glossary - B ΓòÉΓòÉΓòÉ
  7579.  
  7580.  B╨Æzier curve - (1) A mathematical technique of specifying smooth continuous 
  7581.    lines and surfaces, which require a starting point and a finishing point 
  7582.    with several intermediate points that influence or control the path of the 
  7583.    linking curve. Named after Dr. P. B╨Æzier. (2) (D of C) In the AIX Graphics 
  7584.    Library, a cubic spline approximation to a set of four control points that 
  7585.    passes through the first and fourth control points and that has a continuous 
  7586.    slope where two spline segments meet. Named after Dr. P. B╨Æzier. 
  7587.  
  7588.  background - (1) In multiprogramming, the conditions under which low-priority 
  7589.    programs are executed. Contrast with foreground. (2) An active session that 
  7590.    is not currently displayed on the screen. 
  7591.  
  7592.  background color - The color in which the background of a graphic primitive is 
  7593.    drawn. 
  7594.  
  7595.  background mix - An attribute that determines how the background of a graphic 
  7596.    primitive is combined with the existing color of the graphics presentation 
  7597.    space. Contrast with mix. 
  7598.  
  7599.  background program - In multiprogramming, a program that executes with a low 
  7600.    priority. Contrast with foreground program. 
  7601.  
  7602.  bit map - A representation in memory of the data displayed on an APA device, 
  7603.    usually the screen. 
  7604.  
  7605.  block - (1) A string of data elements recorded or transmitted as a unit. The 
  7606.    elements may be characters, words, or logical records. (T)  (2) To record 
  7607.    data in a block. (3) A collection of contiguous records recorded as a unit. 
  7608.    Blocks are separated by interblock gaps and each block may contain one or 
  7609.    more records. (A)
  7610.  
  7611.  block device - A storage device that performs I/O operations on blocks of data 
  7612.    called sectors. Data on block devices can be randomly accessed. Block 
  7613.    devices are designated by a drive letter (for example, C:). 
  7614.  
  7615.  blocking mode - A condition set by an application that determines when its 
  7616.    threads might block. For example, an application might set the Pipemode 
  7617.    parameter for the DosCreateNPipe function so that its threads perform I/O 
  7618.    operations to the named pipe block when no data is available. 
  7619.  
  7620.  border - A visual indication (for example, a separator line or a background 
  7621.    color) of the boundaries of a window. 
  7622.  
  7623.  boundary determination - An operation used to compute the size of the smallest 
  7624.    rectangle that encloses a graphics object on the screen. 
  7625.  
  7626.  breakpoint - (1) A point in a computer program where execution may be halted. 
  7627.    A breakpoint is usually at the beginning of an instruction where halts, 
  7628.    caused by external intervention, are convenient for resuming 
  7629.    execution. (T)  (2) A place in a program, specified by a command or a 
  7630.    condition, where the system halts execution and gives control to the 
  7631.    workstation user or to a specified program. 
  7632.  
  7633.  broken pipe - When all of the handles that access one end of a pipe have been 
  7634.    closed. 
  7635.  
  7636.  bucket - One or more fields in which the result of an operation is kept. 
  7637.  
  7638.  buffer - (1) A portion of storage used to hold input or output data 
  7639.    temporarily. (2) To allocate and schedule the use of buffers. (A)
  7640.  
  7641.  button - A mechanism used to request or initiate an action. See also barrel 
  7642.    buttons, bezel buttons, mouse button, push button, and radio button. 
  7643.  
  7644.  byte pipe - Pipes that handle data as byte streams. All unnamed pipes are byte 
  7645.    pipes. Named pipes can be byte pipes or message pipes. See byte stream. 
  7646.  
  7647.  byte stream - Data that consists of an unbroken stream of bytes. 
  7648.  
  7649.  
  7650. ΓòÉΓòÉΓòÉ <hidden> Glossary - C ΓòÉΓòÉΓòÉ
  7651.  
  7652.  cache - A high-speed buffer storage that contains frequently accessed 
  7653.    instructions and data; it is used to reduce access time. 
  7654.  
  7655.  cached micro presentation space - A presentation space from a 
  7656.    Presentation-Manager-owned store of micro presentation spaces. It can be 
  7657.    used for drawing to a window only, and must be returned to the store when 
  7658.    the task is complete. 
  7659.  
  7660.  CAD - Computer-Aided Design. 
  7661.  
  7662.  call - (1) The action of bringing a computer program, a routine, or a 
  7663.    subroutine into effect, usually by specifying the entry conditions and 
  7664.    jumping to an entry point. (I)  (A)  (2) To transfer control to a procedure, 
  7665.    program, routine, or subroutine. 
  7666.  
  7667.  calling sequence - A sequence of instructions together with any associated 
  7668.    data necessary to execute a call. (T)
  7669.  
  7670.  Cancel - An action that removes the current window or menu without processing 
  7671.    it, and returns the previous window. 
  7672.  
  7673.  cascaded menu - In the OS/2 operating system, a menu that appears when the 
  7674.    arrow to the right of a cascading choice is selected. It contains a set of 
  7675.    choices that are related to the cascading choice. Cascaded menus are used to 
  7676.    reduce the length of a menu. See also cascading choice. 
  7677.  
  7678.  cascading choice - In SAA Common User Access architecture, a choice in a menu 
  7679.    that, when selected, produces a cascaded menu containing other choices.  An 
  7680.    arrow () appears to the right of the cascading choice. 
  7681.  
  7682.  CASE statement - In PM programming, provides the body of a window procedure. 
  7683.    There is usually one CASE statement for each message type supported by an 
  7684.    application. 
  7685.  
  7686.  CGA - Color graphics adapter. 
  7687.  
  7688.  chained list - A list in which the data elements may be dispersed but in which 
  7689.    each data element contains information for locating the 
  7690.    next. (T)Synonymous with linked list. 
  7691.  
  7692.  character - A letter, digit, or other symbol. 
  7693.  
  7694.  character box - In computer graphics, the boundary that defines, in world 
  7695.    coordinates, the horizontal and vertical space occupied by a single 
  7696.    character from a character set. See also character mode. Contrast with 
  7697.    character cell. 
  7698.  
  7699.  character cell - The physical, rectangular space in which any single character 
  7700.    is displayed on a screen or printer device. Position is addressed by row and 
  7701.    column coordinates. Contrast with character box. 
  7702.  
  7703.  character code - The means of addressing a character in a character set, 
  7704.    sometimes called code point. 
  7705.  
  7706.  character device - A device that performs I/O operations on one character at a 
  7707.    time. Because character devices view data as a stream of bytes, 
  7708.    character-device data cannot be randomly accessed. Character devices include 
  7709.    the keyboard, mouse, and printer, and are referred to by name. 
  7710.  
  7711.  character mode - A mode that, in conjunction with the font type, determines 
  7712.    the extent to which graphics characters are affected by the character box, 
  7713.    shear, and angle attributes. 
  7714.  
  7715.  character set - (1) An ordered set of unique representations called 
  7716.    characters; for example, the 26 letters of English alphabet, Boolean 0 and 
  7717.    1, the set of symbols in the Morse code, and the 128 ASCII 
  7718.    characters. (A)  (2) All the valid characters for a programming language or 
  7719.    for a computer system. (3) A group of characters used for a specific reason; 
  7720.    for example, the set of characters a printer can print. 
  7721.  
  7722.  check box - In SAA Advanced Common User Access architecture, a square box with 
  7723.    associated text that represents a choice. When a user selects a choice, an X 
  7724.    appears in the check box to indicate that the choice is in effect. The user 
  7725.    can clear the check box by selecting the choice again. Contrast with radio 
  7726.    button. 
  7727.  
  7728.  check mark -  (1) (D of C) In SAA Advanced Common User Access architecture, a 
  7729.    symbol that shows that a choice is currently in effect. (2) The symbol that 
  7730.    is used to indicate a selected item on a pull-down menu. 
  7731.  
  7732.  child process - In the OS/2 operating system, a process started by another 
  7733.    process, which is called the parent process. Contrast with parent process. 
  7734.  
  7735.  child window - A window that appears within the border of its parent window 
  7736.    (either a primary window or another child window). When the parent window is 
  7737.    resized, moved, or destroyed, the child window also is resized, moved, or 
  7738.    destroyed; however, the child window can be moved or resized independently 
  7739.    from the parent window, within the boundaries of the parent window. Contrast 
  7740.    with parent window. 
  7741.  
  7742.  choice - (1) An option that can be selected. The choice can be presented as 
  7743.    text, as a symbol (number or letter), or as an icon (a pictorial symbol). 
  7744.    (2) (D of C) In SAA Common User Access architecture, an item that a user can 
  7745.    select. 
  7746.  
  7747.  chord - (1) To press more than one button on a pointing device while the 
  7748.    pointer is within the limits that the user has specified for the operating 
  7749.    environment. (2) (D of C) In graphics, a short line segment whose end points 
  7750.    lie on a circle. Chords are a means for producing a circular image from 
  7751.    straight lines. The higher the number of chords per circle, the smoother the 
  7752.    circular image. 
  7753.  
  7754.  class - A way of categorizing objects based on their behavior and shape. A 
  7755.    class is, in effect, a definition of a generic object. In SOM, a class is a 
  7756.    special kind of object that can manufacture other objects that all have a 
  7757.    common shape and exhibit similar behavior (more precisely, all of the 
  7758.    objects manufactured by a class have the same memory layout and share a 
  7759.    common set of methods). New classes can be defined in terms of existing 
  7760.    classes through a technique known as inheritance. 
  7761.  
  7762.  class method - A class method of class <X> is a method provided by the 
  7763.    metaclass of class <X>. Class methods are executed without requiring any 
  7764.    instances of class <X> to exist, and are frequently used to create 
  7765.    instances. In System Object Model, an action that can be performed on a 
  7766.    class object. 
  7767.  
  7768.  class object - In System Object Model, the run-time implementation of a class. 
  7769.  
  7770.  class style - The set of properties that apply to every window in a window 
  7771.    class. 
  7772.  
  7773.  client - (1) A functional unit that receives shared services from a 
  7774.    server. (T)  (2) A user, as in a client process that uses a named pipe or 
  7775.    queue that is created and owned by a server process. 
  7776.  
  7777.  client area - The part of the window, inside the border, that is below the 
  7778.    menu bar. It is the user's work space, where a user types information and 
  7779.    selects choices from selection fields.  In primary windows, it is where an 
  7780.    application programmer presents the objects that a user works on. 
  7781.  
  7782.  client program - An application that creates and manipulates instances of 
  7783.    classes. 
  7784.  
  7785.  client window - The window in which the application displays output and 
  7786.    receives input. This window is located inside the frame window, under the 
  7787.    window title bar and any menu bar, and within any scroll bars. 
  7788.  
  7789.  clip limits - The area of the paper that can be reached by a printer or 
  7790.    plotter. 
  7791.  
  7792.  clipboard - In SAA Common User Access architecture, an area of computer 
  7793.    memory, or storage, that temporarily holds data. Data in the clipboard is 
  7794.    available to other applications. 
  7795.  
  7796.  clipping - In computer graphics, removing those parts of a display image that 
  7797.    lie outside a given boundary. (I)  (A)
  7798.  
  7799.  clipping area - The area in which the window can paint. 
  7800.  
  7801.  clipping path - A clipping boundary in world-coordinate space. 
  7802.  
  7803.  clock tick - The minimum unit of time that the system tracks. If the system 
  7804.    timer currently counts at a rate of X Hz, the system tracks the time every 
  7805.    1/X of a second. Also known as time tick. 
  7806.  
  7807.  CLOCK$ - Character-device name reserved for the system clock. 
  7808.  
  7809.  code page - An assignment of graphic characters and control-function meanings 
  7810.    to all code points. 
  7811.  
  7812.  code point - (1) Synonym for character code. (2) (D of C) A 1-byte code 
  7813.    representing one of 256 potential characters. 
  7814.  
  7815.  code segment - An executable section of programming code within a load module. 
  7816.  
  7817.  color dithering - See dithering. 
  7818.  
  7819.  color graphics adapter (CGA) - An adapter that simultaneously provides four 
  7820.    colors and is supported by all IBM Personal Computer and Personal System/2 
  7821.    models. 
  7822.  
  7823.  command - The name and parameters associated with an action that a program can 
  7824.    perform. 
  7825.  
  7826.  command area - An area composed of a command field prompt and a command entry 
  7827.    field. 
  7828.  
  7829.  command entry field - An entry field in which users type commands. 
  7830.  
  7831.  command line - On a display screen, a display line, sometimes at the bottom of 
  7832.    the screen, in which only commands can be entered. 
  7833.  
  7834.  command mode - A state of a system or device in which the user can enter 
  7835.    commands. 
  7836.  
  7837.  command prompt - A field prompt showing the location of the command entry 
  7838.    field in a panel. 
  7839.  
  7840.  Common Programming Interface (CPI) - Definitions of those application 
  7841.    development languages and services that have, or are intended to have, 
  7842.    implementations on and a high degree of commonality across the SAA 
  7843.    environments. One of the three SAA architectural areas. See also Common User 
  7844.    Access architecture. 
  7845.  
  7846.  Common User Access (CUA) architecture -  Guidelines for the dialog between a 
  7847.    human and a workstation or terminal. One of the three SAA architectural 
  7848.    areas. See also Common Programming Interface. 
  7849.  
  7850.  compile - To translate a program written in a higher-level programming 
  7851.    language into a machine language program. 
  7852.  
  7853.  composite window - A window composed of other windows (such as a frame window, 
  7854.    frame-control windows, and a client window) that are kept together as a unit 
  7855.    and that interact with each other. 
  7856.  
  7857.  computer-aided design (CAD) - The use of a computer to design or change a 
  7858.    product, tool, or machine, such as using a computer for drafting or 
  7859.    illustrating. 
  7860.  
  7861.  COM1, COM2, COM3 - Character-device names reserved for serial ports 1 through 
  7862.    3. 
  7863.  
  7864.  CON - Character-device name reserved for the console keyboard and screen. 
  7865.  
  7866.  conditional cascaded menu - A pull-down menu associated with a menu item that 
  7867.    has a cascade mini-push button beside it in an object's pop-up menu. The 
  7868.    conditional cascaded menu is displayed when the user selects the mini-push 
  7869.    button. 
  7870.  
  7871.  container - In SAA Common User Access architecture, an object that holds other 
  7872.    objects. A folder is an example of a container object. See also folder and 
  7873.    object. 
  7874.  
  7875.  contextual help - In SAA Common User Access Architecture, help that gives 
  7876.    specific information about the item the cursor is on. The help is contextual 
  7877.    because it provides information about a specific item as it is currently 
  7878.    being used. Contrast with extended help. 
  7879.  
  7880.  contiguous - Touching or joining at a common edge or boundary, for example, an 
  7881.    unbroken consecutive series of storage locations. 
  7882.  
  7883.  control - In SAA Advanced Common User Access architecture, a component of the 
  7884.    user interface that allows a user to select choices or type information; for 
  7885.    example, a check box, an entry field, a radio button. 
  7886.  
  7887.  control area - A storage area used by a computer program to hold control information. (I)  (A)
  7888.  
  7889.  Control Panel - In the Presentation Manager, a program used to set up user 
  7890.    preferences that act globally across the system. 
  7891.  
  7892.  Control Program - (1) The basic functions of the operating system, including 
  7893.    DOS emulation and the support for keyboard, mouse, and video input/output. 
  7894.    (2) A computer program designed to schedule and to supervise the execution 
  7895.    of programs of a computer system. (I)  (A)
  7896.  
  7897.  control window - A window that is used as part of a composite window to 
  7898.    perform simple input and output tasks. Radio buttons and check boxes are 
  7899.    examples. 
  7900.  
  7901.  control word - An instruction within a document that identifies its parts or 
  7902.    indicates how to format the document. 
  7903.  
  7904.  coordinate space - A two-dimensional set of points used to generate output on 
  7905.    a video display of printer. 
  7906.  
  7907.  Copy - A choice that places onto the clipboard, a copy of what the user has 
  7908.    selected. See also Cut and Paste. 
  7909.  
  7910.  correlation - The action of determining which element or object within a 
  7911.    picture is at a given position on the display. This follows a pick 
  7912.    operation. 
  7913.  
  7914.  coverpage window - A window in which the application's help information is 
  7915.    displayed. 
  7916.  
  7917.  CPI - Common Programming Interface. 
  7918.  
  7919.  critical extended attribute - An extended attribute that is necessary for the 
  7920.    correct operation of the system or a particular application. 
  7921.  
  7922.  critical section - (1) In programming languages, a part of an asynchronous 
  7923.    procedure that cannot be executed simultaneously with a certain part of 
  7924.    another asynchronous procedure. (I)
  7925.  
  7926.    Note:  Part of the other asynchronous procedure also is a critical section. 
  7927.    (2) A section of code that is not reentrant; that is, code that can be 
  7928.    executed by only one thread at a time. 
  7929.  
  7930.  CUA architecture - Common User Access architecture. 
  7931.  
  7932.  current position - In computer graphics, the position, in user coordinates, 
  7933.    that becomes the starting point for the next graphics routine, if that 
  7934.    routine does not explicitly specify a starting point. 
  7935.  
  7936.  cursor - A symbol displayed on the screen and associated with an input device. 
  7937.    The cursor indicates where input from the device will be placed. Types of 
  7938.    cursors include text cursors, graphics cursors, and selection cursors. 
  7939.    Contrast with pointer and input focus. 
  7940.  
  7941.  Cut - In SAA Common User Access architecture, a choice that removes a selected 
  7942.    object, or a part of an object, to the clipboard, usually compressing the 
  7943.    space it occupied in a window. See also Copy and Paste. 
  7944.  
  7945.  
  7946. ΓòÉΓòÉΓòÉ <hidden> Glossary - D ΓòÉΓòÉΓòÉ
  7947.  
  7948.  daisy chain - A method of device interconnection for determining interrupt 
  7949.    priority by connecting the interrupt sources serially. 
  7950.  
  7951.  data segment - A nonexecutable section of a program module; that is, a section 
  7952.    of a program that contains data definitions. 
  7953.  
  7954.  data structure - The syntactic structure of symbolic expressions and their 
  7955.    storage-allocation characteristics. (T)
  7956.  
  7957.  data transfer - The movement of data from one object to another by way of the 
  7958.    clipboard or by direct manipulation. 
  7959.  
  7960.  DBCS - Double-byte character set. 
  7961.  
  7962.  DDE - Dynamic data exchange. 
  7963.  
  7964.  deadlock - (1) Unresolved contention for the use of a resource. (2) An error 
  7965.    condition in which processing cannot continue because each of two elements 
  7966.    of the process is waiting for an action by, or a response from, the other. 
  7967.    (3) An impasse that occurs when multiple processes are waiting for the 
  7968.    availability of a resource that will not become available because it is 
  7969.    being held by another process that is in a similar wait state. 
  7970.  
  7971.  debug - To detect, diagnose, and eliminate errors in programs. (T)
  7972.  
  7973.  decipoint - In printing, one tenth of a point.  There are 72 points in an 
  7974.    inch. 
  7975.  
  7976.  default procedure - A function provided by the Presentation Manager Interface 
  7977.    that may be used to process standard messages from dialogs or windows. 
  7978.  
  7979.  default value - A value assumed when no value has been specified. Synonymous 
  7980.    with assumed value. For example, in the graphics programming interface, the 
  7981.    default line-type is 'solid'. 
  7982.  
  7983.  definition list - A type of list that pairs a term and its description. 
  7984.  
  7985.  delta - An application-defined threshold, or number of container items, from 
  7986.    either end of the list. 
  7987.  
  7988.  descendant - See child process. 
  7989.  
  7990.  descriptive text - Text used in addition to a field prompt to give more 
  7991.    information about a field. 
  7992.  
  7993.  Deselect all - A choice that cancels the selection of all of the objects that 
  7994.    have been selected in that window. 
  7995.  
  7996.  Desktop Manager - In the Presentation Manager, a window that displays a list 
  7997.    of groups of programs, each of which can be started or stopped. 
  7998.  
  7999.  desktop window - The window, corresponding to the physical device, against 
  8000.    which all other types of windows are established. 
  8001.  
  8002.  detached process - A background process that runs independent of the parent 
  8003.    process. 
  8004.  
  8005.  detent - A point on a slider that represents an exact value to which a user 
  8006.    can move the slider arm. 
  8007.  
  8008.  device context - A logical description of a data destination such as memory, 
  8009.    metafile, display, printer, or plotter. See also direct device context, 
  8010.    information device context, memory device context, metafile device context, 
  8011.    queued device context, and screen device context. 
  8012.  
  8013.  device driver - A file that contains the code needed to attach and use a 
  8014.    device such as a display, printer, or plotter. 
  8015.  
  8016.  device space - (1) Coordinate space in which graphics are assembled after all 
  8017.    GPI transformations have been applied. Device space is defined in 
  8018.    device-specific units. (2) ( D of C) In computer graphics, a space defined 
  8019.    by the complete set of addressable points of a display device. (A)
  8020.  
  8021.  dialog - The interchange of information between a computer and its user 
  8022.    through a sequence of requests by the user and the presentation of responses 
  8023.    by the computer. 
  8024.  
  8025.  dialog box - In SAA Advanced Common User Access architecture, a movable 
  8026.    window, fixed in size, containing controls that a user uses to provide 
  8027.    information required by an application so that it can continue to process a 
  8028.    user request. See also message box, primary window, secondary window. Also 
  8029.    known as a pop-up window. 
  8030.  
  8031.  Dialog Box Editor - A WYSIWYG editor that creates dialog boxes for 
  8032.    communicating with the application user. 
  8033.  
  8034.  dialog item - A component (for example, a menu or a button) of a dialog box. 
  8035.    Dialog items are also used when creating dialog templates. 
  8036.  
  8037.  dialog procedure - A dialog window that is controlled by a window procedure. 
  8038.    It is responsible for responding to all messages sent to the dialog window. 
  8039.  
  8040.  dialog tag language - A markup language used by the DTL compiler to create 
  8041.    dialog objects. 
  8042.  
  8043.  dialog template - The definition of a dialog box, which contains details of 
  8044.    its position, appearance, and window ID, and the window ID of each of its 
  8045.    child windows. 
  8046.  
  8047.  direct device context - A logical description of a data destination that is a 
  8048.    device other than the screen (for example, a printer or plotter), and where 
  8049.    the output is not to go through the spooler. Its purpose is to satisfy 
  8050.    queries. See also device context. 
  8051.  
  8052.  direct manipulation - The user's ability to interact with an object by using 
  8053.    the mouse, typically by dragging an object around on the Desktop and 
  8054.    dropping it on other objects. 
  8055.  
  8056.  direct memory access (DMA) - A technique for moving data directly between main 
  8057.    storage and peripheral equipment without requiring processing of the data by 
  8058.    the processing unit.(T)
  8059.  
  8060.  directory - A type of file containing the names and controlling information 
  8061.    for other files or other directories. 
  8062.  
  8063.  display point - Synonym for pel. 
  8064.  
  8065.  dithering - (1) The process used in color displays whereby every other pel is 
  8066.    set to one color, and the intermediate pels are set to another. Together 
  8067.    they produce the effect of a third color at normal viewing distances. This 
  8068.    process can only be used on solid areas of color; it does not work, for 
  8069.    example, on narrow lines. (2) (D of C ) In computer graphics, a technique of 
  8070.    interleaving dark and light pixels so that the resulting image looks 
  8071.    smoothly shaded when viewed from a distance. 
  8072.  
  8073.  DMA - Direct memory access. 
  8074.  
  8075.  DOS Protect Mode Interface (DPMI) - An interface between protect mode and real 
  8076.    mode programs. 
  8077.  
  8078.  double-byte character set (DBCS) - A set of characters in which each character 
  8079.    is represented by two bytes.  Languages such as Japanese, Chinese, and 
  8080.    Korean, which contain more characters than can be represented by 256 code 
  8081.    points, require double-byte character sets. Since each character requires 
  8082.    two bytes, the entering, displaying, and printing of DBCS characters 
  8083.    requires hardware and software that can support DBCS. 
  8084.  
  8085.  doubleword - A contiguous sequence of bits or characters that comprises two 
  8086.    computer words and is capable of being addressed as a unit. (A)
  8087.  
  8088.  DPMI - DOS Protect Mode Interface. 
  8089.  
  8090.  drag - In SAA Common User Access, to use a pointing device to move an object; 
  8091.    for example, clicking on a window border, and dragging it to make the window 
  8092.    larger. 
  8093.  
  8094.  dragging - (1) In computer graphics, moving an object on the display screen as 
  8095.    if it were attached to the pointer. (2) (D of C) In computer graphics, 
  8096.    moving one or more segments on a display surface by translating. (I)  (A)
  8097.  
  8098.  drawing chain - See segment chain. 
  8099.  
  8100.  drop - To fix the position of an object that is being dragged, by releasing 
  8101.    the select button of the pointing device. See also drag. 
  8102.  
  8103.  DTL - Dialog tag language. 
  8104.  
  8105.  dual-boot function - A feature of the OS/2 operating system that allows the 
  8106.    user to start DOS from within the operating system, or an OS/2 session from 
  8107.    within DOS. 
  8108.  
  8109.  duplex - Pertaining to communication in which data can be sent and received at 
  8110.    the same time. Synonymous with full duplex. 
  8111.  
  8112.  dynamic data exchange (DDE) - A message protocol used to communicate between 
  8113.    applications that share data. The protocol uses shared memory as the means 
  8114.    of exchanging data between applications. 
  8115.  
  8116.  dynamic data formatting - A formatting procedure that enables you to 
  8117.    incorporate text, bit maps or metafiles in an IPF window at execution time. 
  8118.  
  8119.  dynamic link library - A collection of executable programming code and data 
  8120.    that is bound to an application at load time or run time, rather than during 
  8121.    linking. The programming code and data in a dynamic link library can be 
  8122.    shared by several applications simultaneously. 
  8123.  
  8124.  dynamic linking - The process of resolving external references in a program 
  8125.    module at load time or run time rather than during linking. 
  8126.  
  8127.  dynamic segments - Graphics segments drawn in exclusive-OR mix mode so that 
  8128.    they can be moved from one screen position to another without affecting the 
  8129.    rest of the displayed picture. 
  8130.  
  8131.  dynamic storage - (1) A device that stores data in a manner that permits the 
  8132.    data to move or vary with time such that the specified data is not always 
  8133.    available for recovery. (A)  (2) A storage in which the cells require 
  8134.    repetitive application of control signals in order to retain stored data. 
  8135.    Such repetitive application of the control signals is called a refresh 
  8136.    operation. A dynamic storage may use static addressing or sensing 
  8137.    circuits. (A)  (3) See also static storage. 
  8138.  
  8139.  dynamic time slicing - Varies the size of the time slice depending on system 
  8140.    load and paging activity. 
  8141.  
  8142.  dynamic-link module - A module that is linked at load time or run time. 
  8143.  
  8144.  
  8145. ΓòÉΓòÉΓòÉ <hidden> Glossary - E ΓòÉΓòÉΓòÉ
  8146.  
  8147.  EBCDIC - Extended binary-coded decimal interchange code. A coded character set 
  8148.    consisting of 8-bit coded characters (9 bits including parity check), used 
  8149.    for information interchange among data processing systems, data 
  8150.    communications systems, and associated equipment. 
  8151.  
  8152.  edge-triggered - Pertaining to an event semaphore that is posted then reset 
  8153.    before a waiting thread gets a chance to run. The semaphore is considered to 
  8154.    be posted for the rest of that thread's waiting period; the thread does not 
  8155.    have to wait for the semaphore to be posted again. 
  8156.  
  8157.  EGA - Extended graphics adapter. 
  8158.  
  8159.  element - An entry in a graphics segment that comprises one or more graphics 
  8160.    orders and that is addressed by the element pointer. 
  8161.  
  8162.  EMS - Expanded Memory Specification. 
  8163.  
  8164.  encapsulation - Hiding an object's implementation, that is, its private, 
  8165.    internal data and methods. Private variables and methods are accessible only 
  8166.    to the object that contains them. 
  8167.  
  8168.  entry field - In SAA Common User Access architecture, an area where a user 
  8169.    types information. Its boundaries are usually indicated. See also selection 
  8170.    field. 
  8171.  
  8172.  entry panel - A defined panel type containing one or more entry fields and 
  8173.    protected information such as headings, prompts, and explanatory text. 
  8174.  
  8175.  entry-field control - The component of a user interface that provides the 
  8176.    means by which the application receives data entered by the user in an entry 
  8177.    field. When it has the input focus, the entry field displays a flashing 
  8178.    pointer at the position where the next typed character will go. 
  8179.  
  8180.  environment segment - The list of environment variables and their values for a 
  8181.    process. 
  8182.  
  8183.  environment strings - ASCII text strings that define the value of environment 
  8184.    variables. 
  8185.  
  8186.  environment variables - Variables that describe the execution environment of a 
  8187.    process. These variables are named by the operating system or by the 
  8188.    application. Environment variables named by the operating system are PATH, 
  8189.    DPATH, INCLUDE, INIT, LIB, PROMPT, and TEMP. The values of environment 
  8190.    variables are defined by the user in the CONFIG.SYS file, or by using the 
  8191.    SET command at the OS/2 command prompt. 
  8192.  
  8193.  error message - An indication that an error has been detected. (A)
  8194.  
  8195.  event semaphore - A semaphore that enables a thread to signal a waiting thread 
  8196.    or threads that an event has occurred or that a task has been completed. The 
  8197.    waiting threads can then perform an action that is dependent on the 
  8198.    completion of the signaled event. 
  8199.  
  8200.  exception - An abnormal condition such as an I/O error encountered in 
  8201.    processing a data set or a file. 
  8202.  
  8203.  exclusive system semaphore - A system semaphore that can be modified only by 
  8204.    threads within the same process. 
  8205.  
  8206.  executable file - (1) A file that contains programs or commands that perform 
  8207.    operations or actions to be taken. (2) A collection of related data records 
  8208.    that execute programs. 
  8209.  
  8210.  exit - To execute an instruction within a portion of a computer program in 
  8211.    order to terminate the execution of that portion. Such portions of computer 
  8212.    programs include loops, subroutines, modules, and so on. (T)  Repeated exit 
  8213.    requests return the user to the point from which all functions provided to 
  8214.    the system are accessible. Contrast with cancel. 
  8215.  
  8216.  expanded memory specification (EMS) - Enables DOS applications to access 
  8217.    memory above the 1MB real mode addressing limit. 
  8218.  
  8219.  extended attribute - An additional piece of information about a file object, 
  8220.    such as its data format or category. It consists of a name and a value. A 
  8221.    file object may have more than one extended attribute associated with it. 
  8222.  
  8223.  extended help - In SAA Common User Access architecture, a help action that 
  8224.    provides information about the contents of the application window from which 
  8225.    a user requested help. Contrast with contextual help. 
  8226.  
  8227.  extended-choice selection - A mode that allows the user to select more than 
  8228.    one item from a window. Not all windows allow extended choice selection. 
  8229.    Contrast with multiple-choice selection. 
  8230.  
  8231.  extent - Continuous space on a disk or diskette that is occupied by or 
  8232.    reserved for a particular data set, data space, or file. 
  8233.  
  8234.  external link - In Information Presentation Facility, a link that connects 
  8235.    external online document files. 
  8236.  
  8237.  
  8238. ΓòÉΓòÉΓòÉ <hidden> Glossary - F ΓòÉΓòÉΓòÉ
  8239.  
  8240.  family-mode application - An application program that can run in the OS/2 
  8241.    environment and in the DOS environment; however, it cannot take advantage of 
  8242.    many of the OS/2-mode facilities, such as multitasking, interprocess 
  8243.    communication, and dynamic linking. 
  8244.  
  8245.  FAT - File allocation table. 
  8246.  
  8247.  FEA - Full extended attribute. 
  8248.  
  8249.  field-level help - Information specific to the field on which the cursor is 
  8250.    positioned. This help function is "contextual" because it provides 
  8251.    information about a specific item as it is currently used; the information 
  8252.    is dependent upon the context within the work session. 
  8253.  
  8254.  FIFO - First-in-first-out. (A)
  8255.  
  8256.  file - A named set of records stored or processed as a unit. (T)
  8257.  
  8258.  file allocation table (FAT) - In IBM personal computers, a table used by the 
  8259.    operating system to allocate space on a disk for a file, and to locate and 
  8260.    chain together parts of the file that may be scattered on different sectors 
  8261.    so that the file can be used in a random or sequential manner. 
  8262.  
  8263.  file attribute - Any of the attributes that describe the characteristics of a 
  8264.    file. 
  8265.  
  8266.  File Manager - In the Presentation Manager, a program that displays 
  8267.    directories and files, and allows various actions on them. 
  8268.  
  8269.  file specification - The full identifier for a file, which includes its drive 
  8270.    designation, path, file name, and extension. 
  8271.  
  8272.  file system - The combination of software and hardware that supports storing 
  8273.    information on a storage device. 
  8274.  
  8275.  file system driver (FSD) - A program that manages file I\O and controls the 
  8276.    format of information on the storage media. 
  8277.  
  8278.  fillet - A curve that is tangential to the end points of two adjoining lines. 
  8279.    See also polyfillet. 
  8280.  
  8281.  filtering - An application process that changes the order of data in a queue. 
  8282.  
  8283.  first-in-first-out (FIFO) - A queuing technique in which the next item to be 
  8284.    retrieved is the item that has been in the queue for the longest time. (A)
  8285.  
  8286.  flag - (1) An indicator or parameter that shows the setting of a switch. (2) A 
  8287.    character that signals the occurrence of some condition, such as the end of 
  8288.    a word. (A)  (3) (D of C) A characteristic of a file or directory that 
  8289.    enables it to be used in certain ways. See also archive flag, hidden flag, 
  8290.    and read-only flag. 
  8291.  
  8292.  focus - See input focus. 
  8293.  
  8294.  folder - A container used to organize objects. 
  8295.  
  8296.  font - A particular size and style of typeface that contains definitions of 
  8297.    character sets, marker sets, and pattern sets. 
  8298.  
  8299.  Font Editor - A utility program provided with the IBM Developers Toolkit that 
  8300.    enables the design and creation of new fonts. 
  8301.  
  8302.  foreground program - (1) The program with which the user is currently 
  8303.    interacting. Also known as interactive program. Contrast with background 
  8304.    program. (2) (D of C) In multiprogramming,  a high-priority program. 
  8305.  
  8306.  frame - The part of a window that can contain several different visual 
  8307.    elements specified by the application, but drawn and controlled by the 
  8308.    Presentation Manager. The frame encloses the client area. 
  8309.  
  8310.  frame styles - Standard window layouts provided by the Presentation Manager. 
  8311.  
  8312.  FSD - File system driver. 
  8313.  
  8314.  full-duplex - Synonym for duplex. 
  8315.  
  8316.  full-screen application - An application that has complete control of the 
  8317.    screen. 
  8318.  
  8319.  function - (1) In a programming language, a block, with or without formal 
  8320.    parameters, whose execution is invoked by means of a call. (2) A set of 
  8321.    related control statements that cause one or more programs to be performed. 
  8322.  
  8323.  function key - A key that causes a specified sequence of operations to be 
  8324.    performed when it is pressed, for example, F1 and Alt-K. 
  8325.  
  8326.  function key area - The area at the bottom of a window that contains function 
  8327.    key assignments such as F1=Help. 
  8328.  
  8329.  
  8330. ΓòÉΓòÉΓòÉ <hidden> Glossary - G ΓòÉΓòÉΓòÉ
  8331.  
  8332.  GDT - Global Descriptor Table. 
  8333.  
  8334.  general protection fault - An exception condition that occurs when a process 
  8335.    attempts to use storage or a module that has some level of protection 
  8336.    assigned to it, such as I/O privilege level. See also IOPL code segment. 
  8337.  
  8338.  Global Descriptor Table (GDT) - A table that defines code and data segments 
  8339.    available to all tasks in an application. 
  8340.  
  8341.  global dynamic-link module - A dynamic-link module that can be shared by all 
  8342.    processes in the system that refer to the module name. 
  8343.  
  8344.  global file-name character - Either a question mark (?) or an asterisk (*) 
  8345.    used as a variable in a file name or file name extension when referring to a 
  8346.    particular file or group of files. 
  8347.  
  8348.  glyph - A graphic symbol whose appearance conveys information. 
  8349.  
  8350.  GPI - Graphics programming interface. 
  8351.  
  8352.  graphic primitive - In computer graphics, a basic element, such as an arc or a 
  8353.    line, that is not made up of smaller parts and that is used to create 
  8354.    diagrams and pictures. See also graphics segment. 
  8355.  
  8356.  graphics - (1) A picture defined in terms of graphic primitives and graphics 
  8357.    attributes. (2) (D of C) The making of charts and pictures. (3) Pertaining 
  8358.    to charts, tables, and their creation. (4) See computer graphics, coordinate 
  8359.    graphics, fixed-image graphics, interactive graphics, passive graphics, 
  8360.    raster graphics. 
  8361.  
  8362.  graphics attributes - Attributes that apply to graphic primitives. Examples 
  8363.    are color, line type, and shading-pattern definition. See also segment 
  8364.    attributes. 
  8365.  
  8366.  graphics field - The clipping boundary that defines the visible part of the 
  8367.    presentation-page contents. 
  8368.  
  8369.  graphics mode - One of several states of a display. The mode determines the 
  8370.    resolution and color content of the screen. 
  8371.  
  8372.  graphics model space - The conceptual coordinate space in which a picture is 
  8373.    constructed after any model transforms have been applied. Also known as 
  8374.    model space. 
  8375.  
  8376.  Graphics programming interface - The formally defined programming language 
  8377.    that is between an IBM graphics program and the user of the program. 
  8378.  
  8379.  graphics segment - A sequence of related graphic primitives and graphics 
  8380.    attributes. See also graphic primitive. 
  8381.  
  8382.  graying - The indication that a choice on a pull-down is unavailable. 
  8383.  
  8384.  group - A collection of logically connected controls. For example, the buttons 
  8385.    controlling paper size for a printer could be called a group. See also 
  8386.    program group. 
  8387.  
  8388.  
  8389. ΓòÉΓòÉΓòÉ <hidden> Glossary - H ΓòÉΓòÉΓòÉ
  8390.  
  8391.  handle - (1) An identifier that represents an object, such as a device or 
  8392.    window, to the Presentation Interface. (2) (D of C) In the Advanced DOS and 
  8393.    OS/2 operating systems, a binary value created by the system that identifies 
  8394.    a drive, directory, and file so that the file can be found and opened. 
  8395.  
  8396.  hard error - An error condition on a network that requires either that the 
  8397.    system be reconfigured or that the source of the error be removed before the 
  8398.    system can resume reliable operation. 
  8399.  
  8400.  header - (1) System-defined control information that precedes user data. (2) 
  8401.    The portion of a message that contains control information for the message, 
  8402.    such as one or more destination fields, name of the originating station, 
  8403.    input sequence number, character string indicating the type of message, and 
  8404.    priority level for the message. 
  8405.  
  8406.  heading tags - A document element that enables information to be displayed in 
  8407.    windows, and that controls entries in the contents window controls placement 
  8408.    of push buttons in a window, and defines the shape and size of windows. 
  8409.  
  8410.  heap - An area of free storage available for dynamic allocation by an 
  8411.    application. Its size varies according to the storage requirements of the 
  8412.    application. 
  8413.  
  8414.  help function - (1) A function that provides information about a specific 
  8415.    field, an application panel, or information about the help facility. (2) (D 
  8416.    of C) One or more display images that describe how to use application 
  8417.    software or how to do a system operation. 
  8418.  
  8419.  Help index - In SAA Common User Access architecture, a help action that 
  8420.    provides an index of the help information available for an application. 
  8421.  
  8422.  help panel - A panel with information to assist users that is displayed in 
  8423.    response to a help request from the user. 
  8424.  
  8425.  help window - A Common-User-Access-defined secondary window that displays 
  8426.    information when the user requests help. 
  8427.  
  8428.  hidden file - An operating system file that is not displayed by a directory 
  8429.    listing. 
  8430.  
  8431.  hide button - In the OS/2 operating system, a small, square button located in 
  8432.    the right-hand corner of the title bar of a window that, when selected, 
  8433.    removes from the screen all the windows associated with that window. 
  8434.    Contrast with maximize button. See also restore button. 
  8435.  
  8436.  hierarchical inheritance - The relationship between parent and child classes. 
  8437.    An object that is lower in the inheritance hierarchy than another object, 
  8438.    inherits all the characteristics and behaviors of the objects above it in 
  8439.    the hierarchy. 
  8440.  
  8441.  hierarchy - A tree of segments beginning with the root segment and proceeding 
  8442.    downward to dependent segment types. 
  8443.  
  8444.  high-performance file system (HPFS) - In the OS/2 operating system, an 
  8445.    installable file system that uses high-speed buffer storage, known as a 
  8446.    cache, to provide fast access to large disk volumes. The file system also 
  8447.    supports the coexistence of multiple, active file systems on a single 
  8448.    personal computer, with the capability of multiple and different storage 
  8449.    devices. File names used with the HPFS can have as many as 254 characters. 
  8450.  
  8451.  hit testing - The means of identifying which window is associated with which 
  8452.    input device event. 
  8453.  
  8454.  hook - A point in a system-defined function where an application can supply 
  8455.    additional code that the system processes as though it were part of the 
  8456.    function. 
  8457.  
  8458.  hook chain - A sequence of hook procedures that are "chained" together so that 
  8459.    each event is passed, in turn, to each procedure in the chain. 
  8460.  
  8461.  hot spot - The part of the pointer that must touch an object before it can be 
  8462.    selected. This is usually the tip of the pointer. Contrast with action 
  8463.    point. 
  8464.  
  8465.  HPFS - high-performance file system. 
  8466.  
  8467.  hypergraphic link - A connection between one piece of information and another 
  8468.    through the use of graphics. 
  8469.  
  8470.  hypertext - A way of presenting information online with connections between 
  8471.    one piece of information and another, called hypertext links. See also 
  8472.    hypertext link. 
  8473.  
  8474.  hypertext link - A connection between one piece of information and another. 
  8475.  
  8476.  
  8477. ΓòÉΓòÉΓòÉ <hidden> Glossary - I ΓòÉΓòÉΓòÉ
  8478.  
  8479.  I/O operation - An input operation to, or output operation from a device 
  8480.    attached to a computer. 
  8481.  
  8482.  I-beam pointer - A pointer that indicates an area, such as an entry field in 
  8483.    which text can be edited. 
  8484.  
  8485.  icon - In SAA Advanced Common User Access architecture, a graphical 
  8486.    representation of an object, consisting of an image, image background, and a 
  8487.    label. Icons can represent items (such as a document file) that the user 
  8488.    wants to work on, and actions that the user wants to perform. In the 
  8489.    Presentation Manager, icons are used for data objects, system actions, and 
  8490.    minimized programs. 
  8491.  
  8492.  icon area - In the Presentation Manager, the area at the bottom of the screen 
  8493.    that is normally used to display the icons for minimized programs. 
  8494.  
  8495.  Icon Editor - The Presentation Manager-provided tool for creating icons. 
  8496.  
  8497.  IDL - Interface Definition Language. 
  8498.  
  8499.  image font - A set of symbols, each of which is described in a rectangular 
  8500.    array of pels. Some of the pels in the array are set to produce the image of 
  8501.    one of the symbols. Contrast with outline font. 
  8502.  
  8503.  implied metaclass - Subclassing the metaclass of a parent class without a 
  8504.    separate CSC for the resultant metaclass. 
  8505.  
  8506.  indirect manipulation - Interaction with an object through choices and 
  8507.    controls. 
  8508.  
  8509.  information device context - A logical description of a data destination other 
  8510.    than the screen (for example, a printer or plotter), but where no output 
  8511.    will occur. Its purpose is to satisfy queries. See also device context. 
  8512.  
  8513.  information panel - A defined panel type characterized by a body containing 
  8514.    only protected information. 
  8515.  
  8516.  Information Presentation Facility (IPF) - A facility provided by the OS/2 
  8517.    operating system, by which application developers can produce online 
  8518.    documentation and context-sensitive online help panels for their 
  8519.    applications. 
  8520.  
  8521.  inheritance - The technique of specifying the shape and behavior of one class 
  8522.    (called a subclass) as incremental differences from another class (called 
  8523.    the parent class or superclass). The subclass inherits the superclass' state 
  8524.    representation and methods, and can provide additional data elements and 
  8525.    methods. The subclass also can provide new functions with the same method 
  8526.    names used by the superclass. Such a subclass method is said to override the 
  8527.    superclass method, and will be selected automatically by method resolution 
  8528.    on subclass instances. An overriding method can elect to call upon the 
  8529.    superclass' method as part of its own implementation. 
  8530.  
  8531.  input focus - (1) The area of a window where user interaction is possible 
  8532.    using an input device, such as a mouse or the keyboard. (2) The position in 
  8533.    the active window where a user's normal interaction with the keyboard will 
  8534.    appear. 
  8535.  
  8536.  input router - An internal OS/2 process that removes messages from the system 
  8537.    queue. 
  8538.  
  8539.  input/output control - A device-specific command that requests a function of a 
  8540.    device driver. 
  8541.  
  8542.  installable file system (IFS) - A file system in which software is installed 
  8543.    when the operating system is started. 
  8544.  
  8545.  instance - (Or object instance). A specific object, as distinguished from the 
  8546.    abstract definition of an object referred to as its class. 
  8547.  
  8548.  instance method - A method valid for a particular object. 
  8549.  
  8550.  instruction pointer - In System/38, a pointer that provides addressability for 
  8551.    a machine interface instruction in a program. 
  8552.  
  8553.  integer atom - An atom that represents a predefined system constant and 
  8554.    carries no storage overhead. For example, names of window classes provided 
  8555.    by Presentation Manager are expressed as integer atoms. 
  8556.  
  8557.  interactive graphics - Graphics that can be moved or manipulated by a user at 
  8558.    a terminal. 
  8559.  
  8560.  interactive program - (1) A program that is running (active) and is ready to 
  8561.    receive (or is receiving) input from a user. (2) A running program that can 
  8562.    receive input from the keyboard or another input device. Compare with active 
  8563.    program and contrast with noninteractive program. 
  8564.  
  8565.    Also known as a foreground program. 
  8566.  
  8567.  interchange file - A file containing data that can be sent from one 
  8568.    Presentation Manager interface application to another. 
  8569.  
  8570.  Interface Definition Language (IDL) - Language-neutral interface specification 
  8571.    for a SOM class. 
  8572.  
  8573.  interpreter - A program that translates and executes each instruction of a 
  8574.    high-level programming language before it translates and executes. 
  8575.  
  8576.  interprocess communication (IPC) - In the OS/2 operating system, the exchange 
  8577.    of information between processes or threads through semaphores, pipes, 
  8578.    queues, and shared memory. 
  8579.  
  8580.  interval timer - (1) A timer that provides program interruptions on a 
  8581.    program-controlled basis. (2) An electronic counter that counts intervals of 
  8582.    time under program control. 
  8583.  
  8584.  IOCtl - Input/output control. 
  8585.  
  8586.  IOPL - Input/output privilege level. 
  8587.  
  8588.  IOPL code segment - An IOPL executable section of programming code that 
  8589.    enables an application to directly manipulate hardware interrupts and ports 
  8590.    without replacing the device driver. See also privilege level. 
  8591.  
  8592.  IPC - Interprocess communication. 
  8593.  
  8594.  IPF - Information Presentation Facility. 
  8595.  
  8596.  IPF compiler - A text compiler that interpret tags in a source file and 
  8597.    converts the information into the specified format. 
  8598.  
  8599.  IPF tag language - A markup language that provides the instructions for 
  8600.    displaying online information. 
  8601.  
  8602.  item - A data object that can be passed in a DDE transaction. 
  8603.  
  8604.  
  8605. ΓòÉΓòÉΓòÉ <hidden> Glossary - J ΓòÉΓòÉΓòÉ
  8606.  
  8607.  journal - A special-purpose file that is used to record changes made in the 
  8608.    system. 
  8609.  
  8610.  
  8611. ΓòÉΓòÉΓòÉ <hidden> Glossary - K ΓòÉΓòÉΓòÉ
  8612.  
  8613.  Kanji - A graphic character set used in Japanese ideographic alphabets. 
  8614.  
  8615.  KBD$ - Character-device name reserved for the keyboard. 
  8616.  
  8617.  kernel - The part of an operating system that performs basic functions, such 
  8618.    as allocating hardware resources. 
  8619.  
  8620.  kerning - The design of graphics characters so that their character boxes 
  8621.    overlap. Used to space text proportionally. 
  8622.  
  8623.  keyboard accelerator - A keystroke that generates a command message for an 
  8624.    application. 
  8625.  
  8626.  keyboard augmentation - A function that enables a user to press a keyboard key 
  8627.    while pressing a mouse button. 
  8628.  
  8629.  keyboard focus - A temporary attribute of a window. The window that has a 
  8630.    keyboard focus receives all keyboard input until the focus changes to a 
  8631.    different window. 
  8632.  
  8633.  Keys help - In SAA Common User Access architecture, a help action that 
  8634.    provides a listing of the application keys and their assigned functions. 
  8635.  
  8636.  
  8637. ΓòÉΓòÉΓòÉ <hidden> Glossary - L ΓòÉΓòÉΓòÉ
  8638.  
  8639.  label - In a graphics segment, an identifier of one or more elements that is 
  8640.    used when editing the segment. 
  8641.  
  8642.  LAN - Local area network. 
  8643.  
  8644.  language support procedure - A function provided by the Presentation Manager 
  8645.    Interface for applications that do not, or cannot (as in the case of COBOL 
  8646.    and FORTRAN programs), provide their own dialog or window procedures. 
  8647.  
  8648.  lazy drag - See pickup and drop. 
  8649.  
  8650.  lazy drag set - See pickup set. 
  8651.  
  8652.  LDT - In the OS/2 operating system, Local Descriptor Table. 
  8653.  
  8654.  LIFO stack - A stack from which data is retrieved in last-in, first-out order. 
  8655.  
  8656.  linear address - A unique value that identifies the memory object. 
  8657.  
  8658.  linked list - Synonym for chained list. 
  8659.  
  8660.  list box - In SAA Advanced Common User Access architecture, a control that 
  8661.    contains scrollable choices from which a user can select one choice. 
  8662.  
  8663.    Note:  In CUA architecture, this is a programmer term. The end user term is 
  8664.    selection list. 
  8665.  
  8666.  list button - A button labeled with an underlined down-arrow that presents a 
  8667.    list of valid objects or choices that can be selected for that field. 
  8668.  
  8669.  list panel - A defined panel type that displays a list of items from which 
  8670.    users can select one or more choices and then specify one or more actions to 
  8671.    work on those choices. 
  8672.  
  8673.  load time - The point in time at which a program module is loaded into main 
  8674.    storage for execution. 
  8675.  
  8676.  load-on-call - A function of a linkage editor that allows selected segments of 
  8677.    the module to be disk resident while other segments are executing. Disk 
  8678.    resident segments are loaded for execution and given control when any entry 
  8679.    point that they contain is called. 
  8680.  
  8681.  local area network (LAN) - (1) A computer network located on a user's premises 
  8682.    within a limited geographical area. Communication within a local area 
  8683.    network is not subject to external regulations;  however, communication 
  8684.    across the LAN boundary may be subject to some form of regulation. (T)
  8685.  
  8686.    Note:  A LAN does not use store and forward techniques. (2) A network in 
  8687.    which a set of devices are connected to one another for communication and 
  8688.    that can be connected to a larger network. 
  8689.  
  8690.  Local Descriptor Table (LDT) - Defines code and data segments specific to a 
  8691.    single task. 
  8692.  
  8693.  lock - A serialization mechanism by means of which a resource is restricted 
  8694.    for use by the holder of the lock. 
  8695.  
  8696.  logical storage device - A device that the user can map to a physical (actual) 
  8697.    device. 
  8698.  
  8699.  LPT1, LPT2, LPT3 - Character-device names reserved for parallel printers 1 
  8700.    through 3. 
  8701.  
  8702.  
  8703. ΓòÉΓòÉΓòÉ <hidden> Glossary - M ΓòÉΓòÉΓòÉ
  8704.  
  8705.  main window - The window that is positioned relative to the desktop window. 
  8706.  
  8707.  manipulation button - The button on a pointing device a user presses to 
  8708.    directly manipulate an object. 
  8709.  
  8710.  map - (1) A set of values having a defined correspondence with the quantities 
  8711.    or values of another set. (I)  (A)  (2) To establish a set of values having 
  8712.    a defined correspondence with the quantities or values of another set. (I)
  8713.  
  8714.  marker box - In computer graphics, the boundary that defines, in world 
  8715.    coordinates, the horizontal and vertical space occupied by a single marker 
  8716.    from a marker set. 
  8717.  
  8718.  marker symbol - A symbol centered on a point. Graphs and charts can use marker 
  8719.    symbols to indicate the plotted points. 
  8720.  
  8721.  marquee box - The rectangle that appears during a selection technique in which 
  8722.    a user selects objects by drawing a box around them with a pointing device. 
  8723.  
  8724.  Master Help Index - In the OS/2 operating system, an alphabetic list of help 
  8725.    topics related to using the operating system. 
  8726.  
  8727.  maximize - To enlarge a window to its largest possible size. 
  8728.  
  8729.  media window - The part of the physical device (display, printer, or plotter) 
  8730.    on which a picture is presented. 
  8731.  
  8732.  memory block - Part memory within a heap. 
  8733.  
  8734.  memory device context - A logical description of a data destination that is a 
  8735.    memory bit map. See also device context. 
  8736.  
  8737.  memory management - A feature of the operating system for allocating, sharing, 
  8738.    and freeing main storage. 
  8739.  
  8740.  memory object - Logical unit of memory requested by an application, which 
  8741.    forms the granular unit of memory manipulation from the application 
  8742.    viewpoint. 
  8743.  
  8744.  menu - In SAA Advanced Common User Access architecture, an extension of the 
  8745.    menu bar that displays a list of choices available for a selected choice in 
  8746.    the menu bar. After a user selects a choice in menu bar, the corresponding 
  8747.    menu appears. Additional pop-up windows can appear from menu choices. 
  8748.  
  8749.  menu bar - In SAA Advanced Common User Access architecture, the area near the 
  8750.    top of a window, below the title bar and above the rest of the window, that 
  8751.    contains choices that provide access to other menus. 
  8752.  
  8753.  menu button - The button on a pointing device that a user presses to view a 
  8754.    pop-up menu associated with an object. 
  8755.  
  8756.  message - (1) In the Presentation Manager, a packet of data used for 
  8757.    communication between the Presentation Manager interface and Presentation 
  8758.    Manager applications (2) In a user interface, information not requested by 
  8759.    users but presented to users by the computer in response to a user action or 
  8760.    internal process. 
  8761.  
  8762.  message box - (1) A dialog window predefined by the system and used as a 
  8763.    simple interface for applications, without the necessity of creating 
  8764.    dialog-template resources or dialog procedures. (2) (D of C) In SAA Advanced 
  8765.    Common User Access architecture, a type of window that shows messages to 
  8766.    users. See also dialog box, primary window, secondary window. 
  8767.  
  8768.  message filter - The means of selecting which messages from a specific window 
  8769.    will be handled by the application. 
  8770.  
  8771.  message queue - A sequenced collection of messages to be read by the 
  8772.    application. 
  8773.  
  8774.  message stream mode - A method of operation in which data is treated as a 
  8775.    stream of messages.  Contrast with  byte stream. 
  8776.  
  8777.  metacharacter - See global file-name character. 
  8778.  
  8779.  metaclass - A class whose instances are all classes. In SOM, any class 
  8780.    descended from SOMClass is a metaclass. The methods of a metaclass are 
  8781.    sometimes called "class" methods. 
  8782.  
  8783.  metafile - A file containing a series of attributes that set color, shape and 
  8784.    size, usually of a picture or a drawing. Using a program that can interpret 
  8785.    these attributes, a user can view the assembled image. 
  8786.  
  8787.  metafile device context - A logical description of a data destination that is 
  8788.    a metafile, which is used for graphics interchange. See also device context. 
  8789.  
  8790.  metalanguage - A language used to specify another language. For example, data 
  8791.    types can be described using a metalanguage so as to make the descriptions 
  8792.    independent of any one computer language. 
  8793.  
  8794.  method - One of the units that makes up the behavior of an object. A method is 
  8795.    a combination of a function and a name, such that many different functions 
  8796.    can have the same name. Which function the name refers to at any point in 
  8797.    time depends on the object that is to execute the method and is the subject 
  8798.    of method resolution. 
  8799.  
  8800.  method override - The replacement, by a child class, of the implementation of 
  8801.    a method inherited from a parent and an ancestor class. 
  8802.  
  8803.  mickey - A unit of measurement for physical mouse motion whose value depends 
  8804.    on the mouse device driver currently loaded. 
  8805.  
  8806.  micro presentation space - A graphics presentation space in which a restricted 
  8807.    set of the GPI function calls is available. 
  8808.  
  8809.  minimize - To remove from the screen all windows associated with an 
  8810.    application and replace them with an icon that represents the application. 
  8811.  
  8812.  mix - An attribute that determines how the foreground of a graphic primitive 
  8813.    is combined with the existing color of graphics output. Also known as 
  8814.    foreground mix. Contrast with background mix. 
  8815.  
  8816.  mixed character string - A string containing a mixture of one-byte and Kanji 
  8817.    or Hangeul (two-byte) characters. 
  8818.  
  8819.  mnemonic - (1) A method of selecting an item on a pull-down by means of typing 
  8820.    the highlighted letter in the menu item. (2) (D of C) In SAA Advanced Common 
  8821.    User Access architecture, usually a single character, within the text of a 
  8822.    choice, identified by an underscore beneath the character. If all characters 
  8823.    in a choice already serve as mnemonics for other choices, another character, 
  8824.    placed in parentheses immediately following the choice, can be used. When a 
  8825.    user types the mnemonic for a choice, the choice is either selected or the 
  8826.    cursor is moved to that choice. 
  8827.  
  8828.  modal dialog box - In SAA Advanced Common User Access architecture, a type of 
  8829.    movable window, fixed in size, that requires a user to enter information 
  8830.    before continuing to work in the application window from which it was 
  8831.    displayed. Contrast with modeless dialog box. Also known as a serial dialog 
  8832.    box. Contrast with parallel dialog box. 
  8833.  
  8834.    Note:  In CUA architecture, this is a programmer term. The end user term is 
  8835.    pop-up window. 
  8836.  
  8837.  model space - See graphics model space. 
  8838.  
  8839.  modeless dialog box - In SAA Advanced Common User Access architecture, a type 
  8840.    of movable window, fixed in size, that allows users to continue their dialog 
  8841.    with the application without entering information in the dialog box. Also 
  8842.    known as a parallel dialog box. Contrast with modal dialog box. 
  8843.  
  8844.    Note:  In CUA architecture, this is a programmer term. The end user term is 
  8845.    pop-up window. 
  8846.  
  8847.  module definition file - A file that describes the code segments within a load 
  8848.    module. For example, it indicates whether a code segment is loadable before 
  8849.    module execution begins (preload), or loadable only when referred to at run 
  8850.    time (load-on-call). 
  8851.  
  8852.  mouse - In SAA usage, a device that a user moves on a flat surface to position 
  8853.    a pointer on the screen. It allows a user to select a choice o function to 
  8854.    be performed or to perform operations on the screen, such as dragging or 
  8855.    drawing lines from one position to another. 
  8856.  
  8857.  MOUSE$ - Character-device name reserved for a mouse. 
  8858.  
  8859.  multiple-choice selection - In SAA Basic Common User Access architecture, a 
  8860.    type of field from which a user can select one or more choices or select 
  8861.    none. See also check box. Contrast with extended-choice selection. 
  8862.  
  8863.  multiple-line entry field - In SAA Advanced Common User Access architecture, a 
  8864.    control into which a user types more than one line of information. See also 
  8865.    single-line entry field. 
  8866.  
  8867.  multitasking - The concurrent processing of applications or parts of 
  8868.    applications. A running application and its data are protected from other 
  8869.    concurrently running applications. 
  8870.  
  8871.  mutex semaphore - (Mutual exclusion semaphore). A semaphore that enables 
  8872.    threads to serialize their access to resources. Only the thread that 
  8873.    currently owns the mutex semaphore can gain access to the resource, thus 
  8874.    preventing one thread from interrupting operations being performed by 
  8875.    another. 
  8876.  
  8877.  muxwait semaphore - (Multiple wait semaphore). A semaphore that enables a 
  8878.    thread to wait either for multiple event semaphores to be posted or for 
  8879.    multiple mutex semaphores to be released. Alternatively, a muxwait semaphore 
  8880.    can be set to enable a thread to wait for any ONE of the event or mutex 
  8881.    semaphores in the muxwait semaphore's list to be posted or released. 
  8882.  
  8883.  
  8884. ΓòÉΓòÉΓòÉ <hidden> Glossary - N ΓòÉΓòÉΓòÉ
  8885.  
  8886.  named pipe - A named buffer that provides client-to-server, server-to-client, 
  8887.    or full duplex communication between unrelated processes. Contrast with 
  8888.    unnamed pipe. 
  8889.  
  8890.  national language support (NLS) - The modification or conversion of a United 
  8891.    States English product to conform to the requirements of another language or 
  8892.    country. This can include the enabling or retrofitting of a product and the 
  8893.    translation of nomenclature, MRI, or documentation of a product. 
  8894.  
  8895.  nested list - A list that is contained within another list. 
  8896.  
  8897.  NLS - national language support. 
  8898.  
  8899.  non-8.3 file-name format - A file-naming convention in which file names can 
  8900.    consist of up to 255 characters. See also 8.3 file-name format. 
  8901.  
  8902.  noncritical extended attribute - An extended attribute that is not necessary 
  8903.    for the function of an application. 
  8904.  
  8905.  nondestructive read - Reading that does not erase the data in the source 
  8906.    location. (T)
  8907.  
  8908.  noninteractive program - A running program that cannot receive input from the 
  8909.    keyboard or other input device. Compare with active program, and contrast 
  8910.    with interactive program. 
  8911.  
  8912.  nonretained graphics - Graphic primitives that are not remembered by the 
  8913.    Presentation Manager interface when they have been drawn. Contrast with 
  8914.    retained graphics. 
  8915.  
  8916.  null character (NUL) - (1) Character-device name reserved for a nonexistent 
  8917.    (dummy) device. (2) (D of C) A control character that is used to accomplish 
  8918.    media-fill or time-fill and that may be inserted into or removed from a 
  8919.    sequence of characters without affecting the meaning of the sequence; 
  8920.    however, the control of equipment or the format may be affected by this 
  8921.    character. (I)  (A)
  8922.  
  8923.  null-terminated string - A string of (n+1) characters where the (n+1)th 
  8924.    character is the 'null' character (0x00) Also known as 'zero-terminated' 
  8925.    string and 'ASCIIZ' string. 
  8926.  
  8927.  
  8928. ΓòÉΓòÉΓòÉ <hidden> Glossary - O ΓòÉΓòÉΓòÉ
  8929.  
  8930.  object - The elements of data and function that programs create, manipulate, 
  8931.    pass as arguments, and so forth. An object is a way of associating specific 
  8932.    data values with a specific set of named functions (called methods) for a 
  8933.    period of time (referred to as the lifetime of the object). The data values 
  8934.    of an object are referred to as its state. In SOM, objects are created by 
  8935.    other objects called classes. The specification of what comprises the set of 
  8936.    functions and data elements that make up an object is referred to as the 
  8937.    definition of a class. 
  8938.  
  8939.    SOM objects offer a high degree of encapsulation. This property permits many 
  8940.    aspects of the implementation of an object to change without affecting 
  8941.    client programs that depend on the object's behavior. 
  8942.  
  8943.  object definition - See class. 
  8944.  
  8945.  object instance - See instance. 
  8946.  
  8947.  Object Interface Definition Language (OIDL) - Specification language used in 
  8948.    SOM Version 1 for defining classes. Replaced by Interface Definition 
  8949.    Language (IDL). 
  8950.  
  8951.  object window - A window that does not have a parent but which might have 
  8952.    child windows. An object window cannot be presented on a device. 
  8953.  
  8954.  OIDL - Object Interface Definition Language. 
  8955.  
  8956.  open - To start working with a file, directory, or other object. 
  8957.  
  8958.  ordered list - Vertical arrangements of items, with each item in the list 
  8959.    preceded by a number or letter. 
  8960.  
  8961.  outline font - A set of symbols, each of which is created as a series of lines 
  8962.    and curves.  Synonymous with vector font. Contrast with image font. 
  8963.  
  8964.  output area - An area of storage reserved for output. (A)
  8965.  
  8966.  owner window - A window into which specific events that occur in another 
  8967.    (owned) window are reported. 
  8968.  
  8969.  ownership - The determination of how windows communicate using messages. 
  8970.  
  8971.  owning process - The process that owns the resources that might be shared with 
  8972.    other processes. 
  8973.  
  8974.  
  8975. ΓòÉΓòÉΓòÉ <hidden> Glossary - P ΓòÉΓòÉΓòÉ
  8976.  
  8977.  page - (1) A 4KB segment of contiguous physical memory. (2) (D of C) A defined 
  8978.    unit of space on a storage medium. 
  8979.  
  8980.  page viewport - A boundary in device coordinates that defines the area of the 
  8981.    output device in which graphics are to be displayed. The presentation-page 
  8982.    contents are transformed automatically to the page viewport in device space. 
  8983.  
  8984.  paint - (1) The action of drawing or redrawing the contents of a window. (2) 
  8985.    In computer graphics, to shade an area of a display image;  for example, 
  8986.    with crosshatching or color. 
  8987.  
  8988.  panel - In SAA Basic Common User Access architecture, a particular arrangement 
  8989.    of information that is presented in a window or pop-up. If some of the 
  8990.    information is not visible, a user can scroll through the information. 
  8991.  
  8992.  panel area - An area within a panel that contains related information. The 
  8993.    three major Common User Access-defined panel areas are the action bar, the 
  8994.    function key area, and the panel body. 
  8995.  
  8996.  panel area separator - In SAA Basic Common User Access architecture, a solid, 
  8997.    dashed, or blank line that provides a visual distinction between two 
  8998.    adjacent areas of a panel. 
  8999.  
  9000.  panel body - The portion of a panel not occupied by the action bar, function 
  9001.    key area, title or scroll bars. The panel body can contain protected 
  9002.    information, selection fields, and entry fields. The layout and content of 
  9003.    the panel body determine the panel type. 
  9004.  
  9005.  panel body area - See client area. 
  9006.  
  9007.  panel definition - A description of the contents and characteristics of a 
  9008.    panel. A panel definition is the application developer's mechanism for 
  9009.    predefining the format to be presented to users in a window. 
  9010.  
  9011.  panel ID - In SAA Basic Common User Access architecture, a panel identifier, 
  9012.    located in the upper-left corner of a panel.  A user can choose whether to 
  9013.    display the panel ID. 
  9014.  
  9015.  panel title - In SAA Basic Common User Access architecture, a particular 
  9016.    arrangement of information that is presented in a window or pop-up. If some 
  9017.    of the information is not visible, a user can scroll through the 
  9018.    information. 
  9019.  
  9020.  paper size - The size of paper, defined in either standard U.S. or European 
  9021.    names (for example, A, B, A4), and measured in inches or millimeters 
  9022.    respectively. 
  9023.  
  9024.  parallel dialog box - See modeless dialog box. 
  9025.  
  9026.  parameter list - A list of values that provides a means of associating 
  9027.    addressability of data defined in a called program with data in the calling 
  9028.    program. It contains parameter names and the order in which they are to be 
  9029.    associated in the calling and called program. 
  9030.  
  9031.  parent class - See inheritance. 
  9032.  
  9033.  parent process - In the OS/2 operating system, a process that creates other 
  9034.    processes. Contrast with child process. 
  9035.  
  9036.  parent window - In the OS/2 operating system, a window that creates a child 
  9037.    window. The child window is drawn within the parent window. If the parent 
  9038.    window is moved, resized, or destroyed, the child window also will be moved, 
  9039.    resized, or destroyed. However, the child window can be moved and resized 
  9040.    independently from the parent window, within the boundaries of the parent 
  9041.    window. Contrast with child window. 
  9042.  
  9043.  partition - (1) A fixed-size division of storage. (2) On an IBM personal 
  9044.    computer fixed disk, one of four possible storage areas of variable size; 
  9045.    one may be accessed by DOS, and each of the others may be assigned to 
  9046.    another operating system. 
  9047.  
  9048.  Paste - A choice in the Edit pull-down that a user selects to move the 
  9049.    contents of the clipboard into a preselected location. See also Copy and 
  9050.    Cut. 
  9051.  
  9052.  path - The route used to locate files; the storage location of a file. A fully 
  9053.    qualified path lists the drive identifier, directory name, subdirectory name 
  9054.    (if any), and file name with the associated extension. 
  9055.  
  9056.  PDD - Physical device driver. 
  9057.  
  9058.  peeking - An action taken by any thread in the process that owns the queue to 
  9059.    examine queue elements without removing them. 
  9060.  
  9061.  pel - (1) The smallest area of a display screen capable of being addressed and 
  9062.    switched between visible and invisible states. Synonym for display point, 
  9063.    pixel, and picture element. (2) (D of C) Picture element. 
  9064.  
  9065.  persistent object - An object whose instance data and state are preserved 
  9066.    between system shutdown and system startup. 
  9067.  
  9068.  physical device driver (PDD) - A system interface that handles hardware 
  9069.    interrupts and supports a set of input and output functions. 
  9070.  
  9071.  pick - To select part of a displayed object using the pointer. 
  9072.  
  9073.  pickup - To add an object or set of objects to the pickup set. 
  9074.  
  9075.  pickup and drop - A drag operation that does not require the direct 
  9076.    manipulation button to be pressed for the duration of the drag. 
  9077.  
  9078.  pickup set - The set of objects that have been picked up as part of a pickup 
  9079.    and drop operation. 
  9080.  
  9081.  picture chain - See segment chain. 
  9082.  
  9083.  picture element - (1) Synonym for pel. (2) (D of C) In computer graphics, the 
  9084.    smallest element of a display surface that can be independently assigned 
  9085.    color and intensity. (T)  . (3) The area of the finest detail that can be 
  9086.    reproduced effectively on the recording medium. 
  9087.  
  9088.  PID - Process identification. 
  9089.  
  9090.  pipe - (1) A named or unnamed buffer used to pass data between processes. A 
  9091.    process reads from or writes to a pipe as if the pipe were a standard-input 
  9092.    or standard-output file. See also named pipe and unnamed pipe. (2) (D of C) 
  9093.    To direct data so that the output from one process becomes the input to 
  9094.    another process. The standard output of one command can be connected to the 
  9095.    standard input of another with the pipe operator (|). 
  9096.  
  9097.  pixel - (1) Synonym for pel. (2) (D of C) Picture element. 
  9098.  
  9099.  plotter - An output unit that directly produces a hardcopy record of data on a 
  9100.    removable medium, in the form of a two-dimensional graphic representation. (T)
  9101.  
  9102.  PM - Presentation Manager. 
  9103.  
  9104.  pointer - (1) The symbol displayed on the screen that is moved by a pointing 
  9105.    device, such as a mouse. The pointer is used to point at items that users 
  9106.    can select. Contrast with cursor. (2) A data element that indicates the 
  9107.    location of another data element. (T)
  9108.  
  9109.  POINTER$ - Character-device name reserved for a pointer device (mouse screen 
  9110.    support). 
  9111.  
  9112.  pointing device - In SAA Advanced Common User Access architecture, an 
  9113.    instrument, such as a mouse, trackball, or joystick, used to move a pointer 
  9114.    on the screen. 
  9115.  
  9116.  pointings - Pairs of x-y coordinates produced by an operator defining 
  9117.    positions on a screen with a pointing device, such as a mouse. 
  9118.  
  9119.  polyfillet - A curve based on a sequence of lines. The curve is tangential to 
  9120.    the end points of the first and last lines, and tangential also to the 
  9121.    midpoints of all other lines. See also fillet. 
  9122.  
  9123.  polygon - One or more closed figures that can be drawn filled, outlined, or 
  9124.    filled and outlined. 
  9125.  
  9126.  polyline - A sequence of adjoining lines. 
  9127.  
  9128.  polymorphism - The ability to have different implementations of the same 
  9129.    method for two or more classes of objects. 
  9130.  
  9131.  pop - To retrieve an item from a last-in-first-out stack of items. Contrast 
  9132.    with push. 
  9133.  
  9134.  pop-up menu - A menu that lists the actions that a user can perform on an 
  9135.    object. The contents of the pop-up menu can vary depending on the context, 
  9136.    or state, of the object. 
  9137.  
  9138.  pop-up window - (1) A window that appears on top of another window in a 
  9139.    dialog. Each pop-up window must be completed before returning to the 
  9140.    underlying window. (2) (D of C) In SAA Advanced Common User Access 
  9141.    architecture, a movable window, fixed in size, in which a user provides 
  9142.    information required by an application so that it can continue to process a 
  9143.    user request. 
  9144.  
  9145.  presentation drivers - Special purpose I/O routines that handle field 
  9146.    device-independent I/O requests from the PM and its applications. 
  9147.  
  9148.  Presentation Manager (PM) - The interface of the OS/2 operating system that 
  9149.    presents, in windows a graphics-based interface to applications and files 
  9150.    installed and running under the OS/2 operating system. 
  9151.  
  9152.  presentation page - The coordinate space in which a picture is assembled for 
  9153.    display. 
  9154.  
  9155.  presentation space (PS) - (1) Contains the device-independent definition of a 
  9156.    picture. (2) (D of C) The display space on a display device. 
  9157.  
  9158.  primary window - In SAA Common User Access architecture, the window in which 
  9159.    the main interaction between the user and the application takes place. In a 
  9160.    multiprogramming environment, each application starts in its own primary 
  9161.    window. The primary window remains for the duration of the application, 
  9162.    although the panel displayed will change as the user's dialog moves forward. 
  9163.    See also secondary window. 
  9164.  
  9165.  primitive - In computer graphics, one of several simple functions for drawing 
  9166.    on the screen, including, for example, the rectangle, line, ellipse, 
  9167.    polygon, and so on. 
  9168.  
  9169.  primitive attribute - A specifiable characteristic of a graphic primitive. See 
  9170.    graphics attributes. 
  9171.  
  9172.  print job - The result of sending a document or picture to be printed. 
  9173.  
  9174.  Print Manager - In the Presentation Manager, the part of the spooler that 
  9175.    manages the spooling process. It also allows users to view print queues and 
  9176.    to manipulate print jobs. 
  9177.  
  9178.  privilege level - A protection level imposed by the hardware architecture of 
  9179.    the IBM personal computer.  There are four privilege levels (number 0 
  9180.    through 3).  Only certain types of programs are allowed to execute at each 
  9181.    privilege level.  See also IOPL code segment. 
  9182.  
  9183.  procedure call - In programming languages, a language construct for invoking 
  9184.    execution of a procedure. 
  9185.  
  9186.  process - An instance of an executing application and the resources it is 
  9187.    using. 
  9188.  
  9189.  program - A sequence of instructions that a computer can interpret and 
  9190.    execute. 
  9191.  
  9192.  program details - Information about a program that is specified in the Program 
  9193.    Manager window and is used when the program is started. 
  9194.  
  9195.  program group - In the Presentation Manager, several programs that can be 
  9196.    acted upon as a single entity. 
  9197.  
  9198.  program name - The full file specification of a program. Contrast with program 
  9199.    title. 
  9200.  
  9201.  program title - The name of a program as it is listed in the Program Manager 
  9202.    window. Contrast with program name. 
  9203.  
  9204.  prompt - A displayed symbol or message that requests input from the user or 
  9205.    gives operational information; for example, on the display screen of an IBM 
  9206.    personal computer, the DOS A> prompt. The user must respond to the prompt in 
  9207.    order to proceed. 
  9208.  
  9209.  protect mode - A method of program operation that limits or prevents access to 
  9210.    certain instructions or areas of storage. Contrast with real mode. 
  9211.  
  9212.  protocol - A set of semantic and syntactic rules that determines the behavior 
  9213.    of functional units in achieving communication. (I)
  9214.  
  9215.  pseudocode - An artificial language used to describe computer program 
  9216.    algorithms without using the syntax of any particular programming language. (A)
  9217.  
  9218.  pull-down - (1) An action bar extension that displays a list of choices 
  9219.    available for a selected action bar choice. After users select an action bar 
  9220.    choice, the pull-down appears with the list of choices. Additional pop-up 
  9221.    windows may appear from pull-down choices to further extend the actions 
  9222.    available to users. (2) (D of C) In SAA Common User Access architecture, 
  9223.    pertaining to a choice in an action bar pull-down. 
  9224.  
  9225.  push - To add an item to a last-in-first-out stack of items. Contrast with 
  9226.    pop. 
  9227.  
  9228.  push button - In SAA Advanced Common User Access architecture, a rectangle 
  9229.    with text inside. Push buttons are used in windows for actions that occur 
  9230.    immediately when the push button is selected. 
  9231.  
  9232.  putback - To remove an object or set of objects from the lazy drag set. This 
  9233.    has the effect of undoing the pickup operation for those objects 
  9234.  
  9235.  putdown - To drop the objects in the lazy drag set on the target object. 
  9236.  
  9237.  
  9238. ΓòÉΓòÉΓòÉ <hidden> Glossary - Q ΓòÉΓòÉΓòÉ
  9239.  
  9240.  queue - (1) A linked list of elements waiting to be processed in FIFO order. 
  9241.    For example, a queue may be a list of print jobs waiting to be printed. (2) 
  9242.    (D of C) A line or list of items waiting to be processed; for example, work 
  9243.    to be performed or messages to be displayed. 
  9244.  
  9245.  queued device context - A logical description of a data destination (for 
  9246.    example, a printer or plotter) where the output is to go through the 
  9247.    spooler. See also device context. 
  9248.  
  9249.  
  9250. ΓòÉΓòÉΓòÉ <hidden> Glossary - R ΓòÉΓòÉΓòÉ
  9251.  
  9252.  radio button - (1) A control window, shaped like a round button on the screen, 
  9253.    that can be in a checked or unchecked state. It is used to select a single 
  9254.    item from a list. Contrast with check box. (2) In SAA Advanced Common User 
  9255.    Access architecture, a circle with text beside it. Radio buttons are 
  9256.    combined to show a user a fixed set of choices from which only one can be 
  9257.    selected. The circle is partially filled when a choice is selected. 
  9258.  
  9259.  RAS - Reliability, availability, and serviceability. 
  9260.  
  9261.  raster - (1) In computer graphics, a predetermined pattern of lines that 
  9262.    provides uniform coverage of a display space. (T)  (2) The coordinate grid 
  9263.    that divides the display area of a display device.  (A)
  9264.  
  9265.  read-only file - A file that can be read from but not written to. 
  9266.  
  9267.  real mode - A method of program operation that does not limit or prevent 
  9268.    access to any instructions or areas of storage.  The operating system loads 
  9269.    the entire program into storage and gives the program access to all system 
  9270.    resources. Contrast with protect mode. 
  9271.  
  9272.  realize - To cause the system to ensure, wherever possible, that the physical 
  9273.    color table of a device is set to the closest possible match in the logical 
  9274.    color table. 
  9275.  
  9276.  recursive routine - A routine that can call itself, or be called by another 
  9277.    routine that was called by the recursive routine. 
  9278.  
  9279.  reentrant - The attribute of a program or routine that allows the same copy of 
  9280.    the program or routine to be used concurrently by two or more tasks. 
  9281.  
  9282.  reference phrase - (1) A word or phrase that is emphasized in a 
  9283.    device-dependent manner to inform the user that additional information for 
  9284.    the word or phrase is available. (2) (D of C) In hypertext, text that is 
  9285.    highlighted and preceded by a single-character input field used to signify 
  9286.    the existence of a hypertext link. 
  9287.  
  9288.  reference phrase help - In SAA Common User Access architecture, highlighted 
  9289.    words or phrases within help information that a user selects to get 
  9290.    additional information. 
  9291.  
  9292.  refresh - To update a window, with changed information, to its current status. 
  9293.  
  9294.  region - A clipping boundary in device space. 
  9295.  
  9296.  register - A part of internal storage having a specified storage capacity and 
  9297.    usually intended for a specific purpose. (T)
  9298.  
  9299.  remote file system - A file-system driver that gains access to a remote system 
  9300.    without a block device driver. 
  9301.  
  9302.  resource - The means of providing extra information used in the definition of 
  9303.    a window. A resource can contain definitions of fonts, templates, 
  9304.    accelerators, and mnemonics; the definitions are held in a resource file. 
  9305.  
  9306.  resource file - A file containing information used in the definition of a 
  9307.    window. Definitions can be of fonts, templates, accelerators, and mnemonics. 
  9308.  
  9309.  restore - To return a window to its original size or position following a 
  9310.    sizing or moving action. 
  9311.  
  9312.  retained graphics - Graphic primitives that are remembered by the Presentation 
  9313.    Manager interface after they have been drawn. Contrast with nonretained 
  9314.    graphics. 
  9315.  
  9316.  return code - (1) A value returned to a program to indicate the results of an 
  9317.    operation requested by that program. (2) A code used to influence the 
  9318.    execution of succeeding instructions.(A) 
  9319.  
  9320.  reverse video - (1) A form of highlighting a character, field, or cursor by 
  9321.    reversing the color of the character, field, or cursor with its background; 
  9322.    for example, changing a red character on a black background to a black 
  9323.    character on a red background. (2) In SAA Basic Common User Access 
  9324.    architecture, a screen emphasis feature that interchanges the foreground and 
  9325.    background colors of an item. 
  9326.  
  9327.  REXX Language - Restructured Extended Executor. A procedural language that 
  9328.    provides batch language functions along with structured programming 
  9329.    constructs such as loops; conditional testing and subroutines. 
  9330.  
  9331.  RGB - (1) Color coding in which the brightness of the additive primary colors 
  9332.    of light, red, green, and blue, are specified as three distinct values of 
  9333.    white light. (2) Pertaining to a color display that accepts signals 
  9334.    representing red, green, and blue. 
  9335.  
  9336.  roman - Relating to a type style with upright characters. 
  9337.  
  9338.  root segment - In a hierarchical database, the highest segment in the tree 
  9339.    structure. 
  9340.  
  9341.  round-robin scheduling - A process that allows each thread to run for a 
  9342.    specified amount of time. 
  9343.  
  9344.  run time - (1) Any instant at which the execution of a particular computer 
  9345.    program takes place. (T)  (2) The amount of time needed for the execution of 
  9346.    a particular computer program. (T)  (3) The time during which an instruction 
  9347.    in an instruction register is decoded and performed. Synonym for execution 
  9348.    time. 
  9349.  
  9350.  
  9351. ΓòÉΓòÉΓòÉ <hidden> Glossary - S ΓòÉΓòÉΓòÉ
  9352.  
  9353.  SAA - Systems Application Architecture. 
  9354.  
  9355.  SBCS - Single-byte character set. 
  9356.  
  9357.  scheduler - A computer program designed to perform functions such as 
  9358.    scheduling, initiation, and termination of jobs. 
  9359.  
  9360.  screen - In SAA Basic Common User Access architecture, the physical surface of 
  9361.    a display device upon which information is shown to a user. 
  9362.  
  9363.  screen device context - A logical description of a data destination that is a 
  9364.    particular window on the screen. See also device context. 
  9365.  
  9366.  SCREEN$ - Character-device name reserved for the display screen. 
  9367.  
  9368.  scroll bar - In SAA Advanced Common User Access architecture, a part of a 
  9369.    window, associated with a scrollable area, that a user interacts with to see 
  9370.    information that is not currently allows visible. 
  9371.  
  9372.  scrollable entry field - An entry field larger than the visible field. 
  9373.  
  9374.  scrollable selection field - A selection field that contains more choices than 
  9375.    are visible. 
  9376.  
  9377.  scrolling - Moving a display image vertically or horizontally in a manner such 
  9378.    that new data appears at one edge, as existing data disappears at the 
  9379.    opposite edge. 
  9380.  
  9381.  secondary window - A window that contains information that is dependent on 
  9382.    information in a primary window and is used to supplement the interaction in 
  9383.    the primary window. 
  9384.  
  9385.  sector - On disk or diskette storage, an addressable subdivision of a track 
  9386.    used to record one block of a program or data. 
  9387.  
  9388.  segment - See graphics segment. 
  9389.  
  9390.  segment attributes - Attributes that apply to the segment as an entity, as 
  9391.    opposed to the individual primitives within the segment. For example, the 
  9392.    visibility or detectability of a segment. 
  9393.  
  9394.  segment chain - All segments in a graphics presentation space that are defined 
  9395.    with the 'chained' attribute. Synonym for picture chain. 
  9396.  
  9397.  segment priority - The order in which segments are drawn. 
  9398.  
  9399.  segment store - An area in a normal graphics presentation space where retained 
  9400.    graphics segments are stored. 
  9401.  
  9402.  select - To mark or choose an item. Note that select means to mark or type in 
  9403.    a choice on the screen; enter means to send all selected choices to the 
  9404.    computer for processing. 
  9405.  
  9406.  select button - The button on a pointing device, such as a mouse, that is 
  9407.    pressed to select a menu choice.  Also known as button 1. 
  9408.  
  9409.  selection cursor - In SAA Advanced Common User Access architecture, a visual 
  9410.    indication that a user has selected a choice. It is represented by outlining 
  9411.    the choice with a dotted box. See also text cursor. 
  9412.  
  9413.  selection field - (1) In SAA Advanced Common User Access architecture, a set 
  9414.    of related choices. See also entry field. (2) In SAA Basic Common User 
  9415.    Access architecture, an area of a panel that cannot be scrolled and contains 
  9416.    a fixed number of choices. 
  9417.  
  9418.  semantics - The relationships between symbols and their meanings. 
  9419.  
  9420.  semaphore - An object used by applications for signalling purposes and for 
  9421.    controlling access to serially reusable resources. 
  9422.  
  9423.  separator - In SAA Advanced Common User Access architecture, a line or color 
  9424.    boundary that provides a visual distinction between two adjacent areas. 
  9425.  
  9426.  serial dialog box - See modal dialog box. 
  9427.  
  9428.  serialization - The consecutive ordering of items. 
  9429.  
  9430.  serialize - To ensure that one or more events occur in a specified sequence. 
  9431.  
  9432.  serially reusable resource (SRR) - A logical resource or object that can be 
  9433.    accessed by only one task at a time. 
  9434.  
  9435.  session - (1) A routing mechanism for user interaction via the console; a 
  9436.    complete environment that determines how an application runs and how users 
  9437.    interact with the application. OS/2 can manage more than one session at a 
  9438.    time, and more than one process can run in a session. Each session has its 
  9439.    own set of environment variables that determine where OS/2 looks for 
  9440.    dynamic-link libraries and other important files. (2) (D of C) In the OS/2 
  9441.    operating system, one instance of a started program or command prompt. Each 
  9442.    session is separate from all other sessions that might be running on the 
  9443.    computer. The operating system is responsible for coordinating the resources 
  9444.    that each session uses, such as computer memory, allocation of processor 
  9445.    time, and windows on the screen. 
  9446.  
  9447.  Settings Notebook - A control window that is used to display the settings for 
  9448.    an object and to enable the user to change them. 
  9449.  
  9450.  shadow - An object that refers to another object. A shadow is not a copy of 
  9451.    another object, but is another representation of the object. 
  9452.  
  9453.  shadow box - The area on the screen that follows mouse movements and shows 
  9454.    what shape the window will take if the mouse button is released. 
  9455.  
  9456.  shared data - Data that is used by two or more programs. 
  9457.  
  9458.  shared memory - In the OS/2 operating system, a segment that can be used by 
  9459.    more than one program. 
  9460.  
  9461.  shear - In computer graphics, the forward or backward slant of a graphics 
  9462.    symbol or string of such symbols relative to a line perpendicular to the 
  9463.    baseline of the symbol. 
  9464.  
  9465.  shell - (1) A software interface between a user and the operating system of a 
  9466.    computer. Shell programs interpret commands and user interactions on devices 
  9467.    such as keyboards, pointing devices, and touch-sensitive screens, and 
  9468.    communicate them to the operating system. (2) Software that allows a kernel 
  9469.    program to run under different operating-system environments. 
  9470.  
  9471.  shutdown - The process of ending operation of a system or a subsystem, 
  9472.    following a defined procedure. 
  9473.  
  9474.  sibling processes - Child processes that have the same parent process. 
  9475.  
  9476.  sibling windows - Child windows that have the same parent window. 
  9477.  
  9478.  simple list - A list of like values; for example, a list of user names. 
  9479.    Contrast with mixed list. 
  9480.  
  9481.  single-byte character set (SBCS) - A character set in which each character is 
  9482.    represented by a one-byte code.  Contrast with double-byte character set. 
  9483.  
  9484.  slider box - In SAA Advanced Common User Access architecture: a part of the 
  9485.    scroll bar that shows the position and size of the visible information in a 
  9486.    window relative to the total amount of information available. Also known as 
  9487.    thumb mark. 
  9488.  
  9489.  SOM - System Object Model. 
  9490.  
  9491.  source file - A file that contains source statements for items such as 
  9492.    high-level language programs and data description specifications. 
  9493.  
  9494.  source statement - A statement written in a programming language. 
  9495.  
  9496.  specific dynamic-link module - A dynamic-link module created for the exclusive 
  9497.    use of an application. 
  9498.  
  9499.  spin button - In SAA Advanced Common User Access architecture, a type of entry 
  9500.    field that shows a scrollable ring of choices from which a user can select a 
  9501.    choice. After the last choice is displayed, the first choice is displayed 
  9502.    again.  A user can also type a choice from the scrollable ring into the 
  9503.    entry field without interacting with the spin button. 
  9504.  
  9505.  spline - A sequence of one or more B╨Æzier curves. 
  9506.  
  9507.  spooler - A program that intercepts the data going to printer devices and 
  9508.    writes it to disk. The data is printed or plotted when it is complete and 
  9509.    the required device is available.  The spooler prevents output from 
  9510.    different sources from being intermixed. 
  9511.  
  9512.  stack - A list constructed and maintained so that the next data element to be 
  9513.    retrieved is the most recently stored. This method is characterized as 
  9514.    last-in-first-out (LIFO). 
  9515.  
  9516.  standard window - A collection of window elements that form a panel. The 
  9517.    standard window can include one or more of the following window elements: 
  9518.    sizing borders, system menu icon, title bar, maximize/minimize/restore 
  9519.    icons, action bar and pull-downs, scroll bars, and client area. 
  9520.  
  9521.  static control - The means by which the application presents descriptive 
  9522.    information (for example, headings and descriptors) to the user. The user 
  9523.    cannot change this information. 
  9524.  
  9525.  static storage - (1) A read/write storage unit in which data is retained in 
  9526.    the absence of control signals. (A)  Static storage may use dynamic 
  9527.    addressing or sensing circuits. (2) Storage other than dynamic storage. (A)
  9528.  
  9529.  style - See window style. 
  9530.  
  9531.  subclass - A class that inherits from another class. See also Inheritance. 
  9532.  
  9533.  subdirectory - In an IBM personal computer, a file referred to in a root 
  9534.    directory that contains the names of other files stored on the diskette or 
  9535.    fixed disk. 
  9536.  
  9537.  superclass - A class from which another class inherits. See also inheritance. 
  9538.  
  9539.  swapping - (1) A process that interchanges the contents of an area of real 
  9540.    storage with the contents of an area in auxiliary storage. (I)  (A)  (2) In 
  9541.    a system with virtual storage, a paging technique that writes the active 
  9542.    pages of a job to auxiliary storage and reads pages of another job from 
  9543.    auxiliary storage into real storage. (3) The process of temporarily removing 
  9544.    an active job from main storage, saving it on disk, and processing another 
  9545.    job in the area of main storage formerly occupied by the first job. 
  9546.  
  9547.  switch - (1) In SAA usage, to move the cursor from one point of interest to 
  9548.    another;  for example, to move from one screen or window to another or from 
  9549.    a place within a displayed image to another place on the same displayed 
  9550.    image. (2) In a computer program, a conditional instruction and an indicator 
  9551.    to be interrogated by that instruction. (3) A device or programming 
  9552.    technique for making a selection, for example, a toggle, a conditional jump. 
  9553.  
  9554.  switch list - See Task List. 
  9555.  
  9556.  symbolic identifier - A text string that equates to an integer value in an 
  9557.    include file, which is used to identify a programming object. 
  9558.  
  9559.  symbols - In Information Presentation Facility, a document element used to 
  9560.    produce characters that cannot be entered from the keyboard. 
  9561.  
  9562.  synchronous - Pertaining to two or more processes that depend upon the 
  9563.    occurrence of specific events such as common timing signals. (T)  See also 
  9564.    asynchronous. 
  9565.  
  9566.  System Menu - In the Presentation Manager, the pull-down in the top left 
  9567.    corner of a window that allows it to be moved and sized with the keyboard. 
  9568.  
  9569.  System Object Model (SOM) - A mechanism for language-neutral, object-oriented 
  9570.    programming in the OS/2 environment. 
  9571.  
  9572.  system queue - The master queue for all pointer device or keyboard events. 
  9573.  
  9574.  system-defined messages - Messages that control the operations of applications 
  9575.    and provides input an other information for applications to process. 
  9576.  
  9577.  Systems Application Architecture (SAA) - A set of IBM software interfaces, 
  9578.    conventions, and protocols that provide a framework for designing and 
  9579.    developing applications that are consistent across systems. 
  9580.  
  9581.  
  9582. ΓòÉΓòÉΓòÉ <hidden> Glossary - T ΓòÉΓòÉΓòÉ
  9583.  
  9584.  table tags - In Information Presentation Facility, a document element that 
  9585.    formats text in an arrangement of rows and columns. 
  9586.  
  9587.  tag - (1) One or more characters attached to a set of data that contain 
  9588.    information about the set, including its identification. (I)  (A)  (2) In 
  9589.    Generalized Markup Language markup, a name for a type of document or 
  9590.    document element that is entered in the source document to identify it. 
  9591.  
  9592.  target object - An object to which the user is transferring information. 
  9593.  
  9594.  Task List - In the Presentation Manager, the list of programs that are active. 
  9595.    The list can be used to switch to a program and to stop programs. 
  9596.  
  9597.  terminate-and-stay-resident (TSR) - Pertaining to an application that modifies 
  9598.    an operating system interrupt vector to point to its own location (known as 
  9599.    hooking an interrupt). 
  9600.  
  9601.  text - Characters or symbols. 
  9602.  
  9603.  text cursor - A symbol displayed in an entry field that indicates where typed 
  9604.    input will appear. 
  9605.  
  9606.  text window - Also known as the VIO window. 
  9607.  
  9608.  text-windowed application - The environment in which the operating system 
  9609.    performs advanced-video input and output operations. 
  9610.  
  9611.  thread - A unit of execution within a process. It uses the resources of the 
  9612.    process. 
  9613.  
  9614.  thumb mark - The portion of the scroll bar that describes the range and 
  9615.    properties of the data that is currently visible in a window. Also known as 
  9616.    a slider box. 
  9617.  
  9618.  thunk - Term used to describe the process of address conversion, stack and 
  9619.    structure realignment, etc., necessary when passing control between 16-bit 
  9620.    and 32-bit modules. 
  9621.  
  9622.  tilde - A mark used to denote the character that is to be used as a mnemonic 
  9623.    when selecting text items within a menu. 
  9624.  
  9625.  time slice - (1) An interval of time on the processing unit allocated for use 
  9626.    in performing a task. After the interval has expired, processing-unit time 
  9627.    is allocated to another task, so a task cannot monopolize processing-unit 
  9628.    time beyond a fixed limit. (2) In systems with time sharing, a segment of 
  9629.    time allocated to a terminal job. 
  9630.  
  9631.  time-critical process - A process that must be performed within a specified 
  9632.    time after an event has occurred. 
  9633.  
  9634.  timer - A facility provided under the Presentation Manager, whereby 
  9635.    Presentation Manager will dispatch a message of class WM_TIMER to a 
  9636.    particular window at specified intervals. This capability may be used by an 
  9637.    application to perform a specific processing task at predetermined 
  9638.    intervals, without the necessity for the application to explicitly keep 
  9639.    track of the passage of time. 
  9640.  
  9641.  timer tick - See clock tick. 
  9642.  
  9643.  title bar - In SAA Advanced Common User Access architecture, the area at the 
  9644.    top of each window that contains the window title and system menu icon. When 
  9645.    appropriate, it also contains the minimize, maximize, and restore icons. 
  9646.    Contrast with panel title. 
  9647.  
  9648.  TLB - Translation lookaside buffer. 
  9649.  
  9650.  transaction - An exchange between a workstation and another device that 
  9651.    accomplishes a particular action or result. 
  9652.  
  9653.  transform - (1) The action of modifying a picture by scaling, shearing, 
  9654.    reflecting, rotating, or translating. (2) The object that performs or 
  9655.    defines such a modification; also referred to as a transformation. 
  9656.  
  9657.  Translation lookaside buffer (TLB) - A hardware-based address caching 
  9658.    mechanism for paging information. 
  9659.  
  9660.  Tree - In the Presentation Manager, the window in the File Manager that shows 
  9661.    the organization of drives and directories. 
  9662.  
  9663.  truncate - (1) To terminate a computational process in accordance with some 
  9664.    rule (A)  (2) To remove the beginning or ending elements of a string. (3) To 
  9665.    drop data that cannot be printed or displayed in the line width specified or 
  9666.    available. (4) To shorten a field or statement to a specified length. 
  9667.  
  9668.  TSR - Terminate-and-stay-resident. 
  9669.  
  9670.  
  9671. ΓòÉΓòÉΓòÉ <hidden> Glossary - U ΓòÉΓòÉΓòÉ
  9672.  
  9673.  unnamed pipe - A circular buffer, created in memory, used by related processes 
  9674.    to communicate with one another. Contrast with named pipe. 
  9675.  
  9676.  unordered list - In Information Presentation Facility, a vertical arrangement 
  9677.    of items in a list, with each item in the list preceded by a special 
  9678.    character or bullet. 
  9679.  
  9680.  update region - A system-provided area of dynamic storage containing one or 
  9681.    more (not necessarily contiguous) rectangular areas of a window that are 
  9682.    visually invalid or incorrect, and therefore are in need of repainting. 
  9683.  
  9684.  user interface - Hardware, software, or both that allows a user to interact 
  9685.    with and perform operations on a system, program, or device. 
  9686.  
  9687.  User Shell - A component of OS/2 that uses a graphics-based, windowed 
  9688.    interface to allow the user to manage applications and files installed and 
  9689.    running under OS/2. 
  9690.  
  9691.  utility program - (1) A computer program in general support of computer 
  9692.    processes; for example, a diagnostic program, a trace program, a sort 
  9693.    program. (T)  (2) A program designed to perform an everyday task such as 
  9694.    copying data from one storage device to another. (A)
  9695.  
  9696.  
  9697. ΓòÉΓòÉΓòÉ <hidden> Glossary - V ΓòÉΓòÉΓòÉ
  9698.  
  9699.  value set control - A visual component that enables a user to select one 
  9700.    choice from a group of mutually exclusive choices. 
  9701.  
  9702.  vector font - A set of symbols, each of which is created as a series of lines 
  9703.    and curves. Synonymous with outline font. Contrast with image font. 
  9704.  
  9705.  VGA - Video graphics array. 
  9706.  
  9707.  view - A way of looking at an object's information. 
  9708.  
  9709.  viewing pipeline - The series of transformations applied to a graphic object 
  9710.    to map the object to the device on which it is to be presented. 
  9711.  
  9712.  viewing window - A clipping boundary that defines the visible part of model 
  9713.    space. 
  9714.  
  9715.  VIO - Video Input/Output. 
  9716.  
  9717.  virtual memory (VM) - Synonymous with virtual storage. 
  9718.  
  9719.  virtual storage - (1) The storage space that may be regarded as addressable 
  9720.    main storage by the user of a computer system in which virtual addresses are 
  9721.    mapped into real addresses. The size of virtual storage is limited by the 
  9722.    addressing scheme of the computer system and by the amount of auxiliary 
  9723.    storage available, not by the actual number of main storage 
  9724.    locations. (I)  (A)  (2) Addressable space that is apparent to the user as 
  9725.    the processor storage space, from which the instructions and the data are 
  9726.    mapped into the processor storage locations. (3) Synonymous with virtual 
  9727.    memory. 
  9728.  
  9729.  visible region - A window's presentation space, clipped to the boundary of the 
  9730.    window and the boundaries of any overlying window. 
  9731.  
  9732.  volume - (1) A file-system driver that uses a block device driver for input 
  9733.    and output operations to a local or remote device. (I)  (2) A portion of 
  9734.    data, together with its data carrier, that can be handled conveniently as a 
  9735.    unit. 
  9736.  
  9737.  
  9738. ΓòÉΓòÉΓòÉ <hidden> Glossary - W ΓòÉΓòÉΓòÉ
  9739.  
  9740.  wildcard character - Synonymous with global file-name character. 
  9741.  
  9742.  window - (1) A portion of a display surface in which display images pertaining 
  9743.    to a particular application can be presented. Different applications can be 
  9744.    displayed simultaneously in different windows. (A)  (2) An area of the 
  9745.    screen with visible boundaries within which information is displayed. A 
  9746.    window can be smaller than or the same size as the screen. Windows can 
  9747.    appear to overlap on the screen. 
  9748.  
  9749.  window class - The grouping of windows whose processing needs conform to the 
  9750.    services provided by one window procedure. 
  9751.  
  9752.  window coordinates - A set of coordinates by which a window position or size 
  9753.    is defined; measured in device units, or pels. 
  9754.  
  9755.  window handle - Unique identifier of a window, generated by Presentation 
  9756.    Manager when the window is created, and used by applications to direct 
  9757.    messages to the window. 
  9758.  
  9759.  window procedure - Code that is activated in response to a message. The 
  9760.    procedure controls the appearance and behavior of its associated windows. 
  9761.  
  9762.  window rectangle - The means by which the size and position of a window is 
  9763.    described in relation to the desktop window. 
  9764.  
  9765.  window resource - A read-only data segment stored in the .EXE file of an 
  9766.    application o the .DLL file of a dynamic link library. 
  9767.  
  9768.  window style - The set of properties that influence how events related to a 
  9769.    particular window will be processed. 
  9770.  
  9771.  window title - In SAA Advanced Common User Access architecture, the area in 
  9772.    the title bar that contains the name of the application and the OS/2 
  9773.    operating system file name, if applicable. 
  9774.  
  9775.  Workplace Shell - The OS/2 object-oriented, graphical user interface. 
  9776.  
  9777.  workstation - (1) A display screen together with attachments such as a 
  9778.    keyboard, a local copy device, or a tablet. (2) (D of C) One or more 
  9779.    programmable or nonprogrammable devices that allow a user to do work. 
  9780.  
  9781.  world coordinates - A device-independent Cartesian coordinate system used by 
  9782.    the application program for specifying graphical input and output. (I)  (A)
  9783.  
  9784.  world-coordinate space - Coordinate space in which graphics are defined before 
  9785.    transformations are applied. 
  9786.  
  9787.  WYSIWYG - What-You-See-Is-What-You-Get. A capability of a text editor to 
  9788.    continually display pages exactly as they will be printed. 
  9789.  
  9790.  
  9791. ΓòÉΓòÉΓòÉ <hidden> Glossary - X ΓòÉΓòÉΓòÉ
  9792.  
  9793. There are no glossary terms for this starting letter. 
  9794.  
  9795.  
  9796. ΓòÉΓòÉΓòÉ <hidden> Glossary - Y ΓòÉΓòÉΓòÉ
  9797.  
  9798. There are no glossary terms for this starting letter. 
  9799.  
  9800.  
  9801. ΓòÉΓòÉΓòÉ <hidden> Glossary - Z ΓòÉΓòÉΓòÉ
  9802.  
  9803.  z-order - The order in which sibling windows are presented. The topmost 
  9804.    sibling window obscures any portion of the siblings that it overlaps; the 
  9805.    same effect occurs down through the order of lower sibling windows. 
  9806.  
  9807.  zooming - The progressive scaling of an entire display image in order to give 
  9808.    the visual impression of movement of all or part of a display group toward 
  9809.    or away from an observer. (I)  (A)
  9810.  
  9811.  8.3 file-name format - A file-naming convention in which file names are 
  9812.    limited to eight characters before and three characters after a single dot. 
  9813.    Usually pronounced "eight-dot-three." See also non-8.3 file-name format. 
  9814.  
  9815.  
  9816. ΓòÉΓòÉΓòÉ 10. Notices ΓòÉΓòÉΓòÉ
  9817.  
  9818. November 1996 
  9819.  
  9820. The following paragraph does not apply to the United Kingdom or any country 
  9821. where such provisions are inconsistent with local law:  INTERNATIONAL BUSINESS 
  9822. MACHINES CORPORATION PROVIDES THIS PUBLICATION "AS IS" WITHOUT WARRANTY OF ANY 
  9823. KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  9824. WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Some states 
  9825. do not allow disclaimer of express or implied warranties in certain 
  9826. transactions, therefore, this statement may not apply to you. 
  9827.  
  9828. This publication could include technical inaccuracies or typographical errors. 
  9829. Changes are periodically made to the information herein; these changes will be 
  9830. incorporated in new editions of the publication. IBM may make improvements 
  9831. and/or changes in the product(s) and/or the program(s) described in this 
  9832. publication at any time. 
  9833.  
  9834. It is possible that this publication may contain reference to, or information 
  9835. about, IBM products (machines and programs), programming, or services that are 
  9836. not announced in your country.  Such references or information must not be 
  9837. construed to mean that IBM intends to announce such IBM products, programming, 
  9838. or services in your country. 
  9839.  
  9840. Requests for technical information about IBM products should be made to your 
  9841. IBM reseller or IBM marketing representative. 
  9842.  
  9843.  
  9844. ΓòÉΓòÉΓòÉ 10.1. Copyright Notices ΓòÉΓòÉΓòÉ
  9845.  
  9846. COPYRIGHT LICENSE: This publication contains printed sample application 
  9847. programs in source language, which illustrate OS/2 programming techniques. You 
  9848. may copy, modify, and distribute these sample programs in any form without 
  9849. payment to IBM, for the purposes of developing, using, marketing or 
  9850. distributing application programs conforming to the OS/2 application 
  9851. programming interface. 
  9852.  
  9853. Each copy of any portion of these sample programs or any derivative work, which 
  9854. is distributed to others, must include a copyright notice as follows: "(C) 
  9855. (your company name) (year).  All rights reserved." 
  9856.  
  9857. (C) Copyright International Business Machines Corporation 1994,1996. All rights 
  9858. reserved. 
  9859. Note to U.S. Government Users - Documentation related to restricted rights - 
  9860. Use, duplication or disclosure is subject to restrictions set forth in GSA ADP 
  9861. Schedule Contract with IBM Corp. 
  9862.  
  9863.  
  9864. ΓòÉΓòÉΓòÉ 10.2. Disclaimers ΓòÉΓòÉΓòÉ
  9865.  
  9866. References in this publication to IBM products, programs, or services do not 
  9867. imply that IBM intends to make these available in all countries in which IBM 
  9868. operates. Any reference to an IBM product, program, or service is not intended 
  9869. to state or imply that only that IBM product, program, or service may be used. 
  9870. Subject to IBM's valid intellectual property or other legally protectable 
  9871. rights, any functionally equivalent product, program, or service may be used 
  9872. instead of the IBM product, program, or service. The evaluation and 
  9873. verification of operation in conjunction with other products, except those 
  9874. expressly designated by IBM, are the responsibility of the user. 
  9875.  
  9876. IBM may have patents or pending patent applications covering subject matter in 
  9877. this document. The furnishing of this document does not give you any license to 
  9878. these patents. You can send license inquiries, in writing, to: 
  9879.  
  9880.       IBM Director of Licensing 
  9881.       IBM Corporation 
  9882.       500 Columbus Avenue 
  9883.       Thornwood, NY  10594 
  9884.       U.S.A. 
  9885.  
  9886.  
  9887. ΓòÉΓòÉΓòÉ 10.3. Trademarks ΓòÉΓòÉΓòÉ
  9888.  
  9889. The following terms are trademarks of the IBM Corporation in the United States 
  9890. or other countries or both: 
  9891.  
  9892. AT
  9893. Common User Access
  9894. CUA
  9895. IBM
  9896. IBM PC AT
  9897. OS/2
  9898. Personal System/2
  9899. Presentation Manager
  9900. PS/2
  9901. SAA
  9902. Systems Application Architecture
  9903.  
  9904. The following terms are trademarks of other companies: 
  9905.  
  9906.  Intel                    Intel Corporation 
  9907.