Changeset 14 for trunk/src/helpers/dosh.c
- Timestamp:
- Dec 9, 2000, 8:19:42 PM (25 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/helpers/dosh.c
r13 r14 31 31 /* 32 32 * This file Copyright (C) 1997-2000 Ulrich Mller. 33 * This file is part of the XWorkplacesource package.34 * XWorkplaceis free software; you can redistribute it and/or modify33 * This file is part of the "XWorkplace helpers" source package. 34 * This is free software; you can redistribute it and/or modify 35 35 * it under the terms of the GNU General Public License as published 36 36 * by the Free Software Foundation, in version 2 as it comes in the … … 47 47 // as unsigned char 48 48 49 #define INCL_DOS 49 #define INCL_DOSMODULEMGR 50 #define INCL_DOSPROCESS 51 #define INCL_DOSSESMGR 52 #define INCL_DOSQUEUES 53 #define INCL_DOSMISC 54 #define INCL_DOSDEVICES 50 55 #define INCL_DOSDEVIOCTL 51 56 #define INCL_DOSERRORS 57 52 58 #define INCL_KBD 53 59 #include <os2.h> 60 54 61 #include <stdlib.h> 55 62 #include <string.h> 56 63 #include <stdio.h> 57 // #include <ctype.h>58 64 59 65 #include "setup.h" // code generation and debugging options … … 70 76 71 77 /* ****************************************************************** 72 * *73 * Miscellaneous *74 * *78 * 79 * Miscellaneous 80 * 75 81 ********************************************************************/ 76 82 … … 172 178 173 179 return (s_brc); 180 } 181 182 /* 183 *@@ doshQueryAvailPhysMem: 184 * returns the amount of physical memory which 185 * is presently available (before the swapper 186 * would have to be expanded). 187 * 188 * This number is calculated by getting the 189 * total available memory (QSV_TOTRESMEM) 190 * and subtracting the free space on the 191 * drive with the swap file from it. 192 * 193 * As a result, you also need to specify 194 * the logical drive on which the swapper 195 * resides (3 = C, 4 = D, and so on). 196 * 197 *@@added V0.9.7 (2000-12-01) [umoeller] 198 */ 199 200 APIRET doshQueryAvailPhysMem(PULONG pulMem, 201 ULONG ulLogicalSwapDrive) 202 { 203 APIRET arc = DosQuerySysInfo(QSV_TOTAVAILMEM, 204 QSV_TOTAVAILMEM, 205 pulMem, 206 sizeof(*pulMem)); 207 if (arc == NO_ERROR) 208 { 209 double dFree = 0; 210 arc = doshQueryDiskFree(ulLogicalSwapDrive, 211 &dFree); 212 *pulMem -= (ULONG)dFree; 213 } 214 215 return (arc); 174 216 } 175 217 … … 213 255 214 256 /* ****************************************************************** 215 * *216 * Memory helpers *217 * *257 * 258 * Memory helpers 259 * 218 260 ********************************************************************/ 219 261 … … 283 325 284 326 /* ****************************************************************** 285 * *286 * Drive helpers *287 * *327 * 328 * Drive helpers 329 * 288 330 ********************************************************************/ 289 331 … … 417 459 { 418 460 ULONG ulBootDrive; 419 DosQuerySysInfo(5, 5, &ulBootDrive, sizeof(ulBootDrive)); 461 DosQuerySysInfo(QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, 462 &ulBootDrive, 463 sizeof(ulBootDrive)); 420 464 return (G_acDriveLetters[ulBootDrive]); 421 465 } … … 461 505 OPEN_FLAGS_DASD 462 506 | OPEN_FLAGS_FAIL_ON_ERROR 507 | OPEN_FLAGS_NOINHERIT // V0.9.6 (2000-11-25) [pr] 463 508 | OPEN_ACCESS_READONLY 464 509 | OPEN_SHARE_DENYNONE, … … 523 568 524 569 /* 570 *@@ doshSetLogicalMap: 571 * sets the mapping of logical floppy drives onto a single 572 * physical floppy drive. 573 * This means selecting either drive A: or drive B: to refer 574 * to the physical drive. 575 * 576 *@@added V0.9.6 (2000-11-24) [pr] 577 */ 578 579 APIRET doshSetLogicalMap(ULONG ulLogicalDrive) 580 { 581 CHAR name[3] = "?:"; 582 ULONG fd = 0, 583 action = 0, 584 paramsize = 0, 585 datasize = 0; 586 APIRET rc = NO_ERROR; 587 USHORT data, 588 param; 589 590 name[0] = doshQueryBootDrive(); 591 rc = DosOpen(name, 592 &fd, 593 &action, 594 0, 595 0, 596 OPEN_ACTION_FAIL_IF_NEW 597 | OPEN_ACTION_OPEN_IF_EXISTS, 598 OPEN_FLAGS_DASD 599 | OPEN_FLAGS_FAIL_ON_ERROR 600 | OPEN_FLAGS_NOINHERIT 601 | OPEN_ACCESS_READONLY 602 | OPEN_SHARE_DENYNONE, 603 0); 604 if (rc == NO_ERROR) 605 { 606 param = 0; 607 data = (USHORT)ulLogicalDrive; 608 paramsize = sizeof(param); 609 datasize = sizeof(data); 610 rc = DosDevIOCtl(fd, 611 IOCTL_DISK, DSK_SETLOGICALMAP, 612 ¶m, paramsize, ¶msize, 613 &data, datasize, &datasize); 614 DosClose(fd); 615 } 616 617 return(rc); 618 } 619 620 /* 525 621 *@@ doshQueryDiskFree: 526 622 * returns the number of bytes remaining on the disk 527 * specified by the given logical drive , or -1 upon errors.623 * specified by the given logical drive. 528 624 * 529 625 * Note: This returns a "double" value, because a ULONG … … 532 628 * 533 629 *@@changed V0.9.0 [umoeller]: fixed another > 4 GB bug (thanks to Rdiger Ihle) 534 */ 535 536 double doshQueryDiskFree(ULONG ulLogicalDrive) // in: 1 for A:, 2 for B:, 3 for C:, ... 537 { 630 *@@changed V0.9.7 (2000-12-01) [umoeller]: changed prototype 631 */ 632 633 APIRET doshQueryDiskFree(ULONG ulLogicalDrive, // in: 1 for A:, 2 for B:, 3 for C:, ... 634 double *pdFree) 635 { 636 APIRET arc = NO_ERROR; 538 637 FSALLOCATE fsa; 539 638 double dbl = -1; 540 639 541 if (ulLogicalDrive) 542 if (DosQueryFSInfo(ulLogicalDrive, FSIL_ALLOC, &fsa, sizeof(fsa)) 543 == NO_ERROR) 544 dbl = ((double)fsa.cSectorUnit * fsa.cbSector * fsa.cUnitAvail); 640 arc = DosQueryFSInfo(ulLogicalDrive, FSIL_ALLOC, &fsa, sizeof(fsa)); 641 if (arc == NO_ERROR) 642 *pdFree = ((double)fsa.cSectorUnit * fsa.cbSector * fsa.cUnitAvail); 545 643 // ^ fixed V0.9.0 546 644 547 return ( dbl);645 return (arc); 548 646 } 549 647 … … 779 877 780 878 /* ****************************************************************** 781 * *782 * File helpers *783 * *879 * 880 * File helpers 881 * 784 882 ********************************************************************/ 785 883 … … 1226 1324 1227 1325 /* ****************************************************************** 1228 * *1229 * Directory helpers *1230 * *1326 * 1327 * Directory helpers 1328 * 1231 1329 ********************************************************************/ 1232 1330 … … 1459 1557 1460 1558 /* 1559 *@@category: Helpers\Control program helpers\Performance (CPU load) helpers 1560 */ 1561 1562 /* ****************************************************************** 1563 * 1564 * Performance Counters (CPU Load) 1565 * 1566 ********************************************************************/ 1567 1568 /* 1569 *@@ doshPerfOpen: 1570 * initializes the OS/2 DosPerfSysCall API for 1571 * the calling thread. 1572 * 1573 * Note: This API is not supported on all OS/2 1574 * versions. I believe it came up with some Warp 4 1575 * fixpak. The API is resolved dynamically by 1576 * this function (using DosQueryProcAddr). Only 1577 * if NO_ERROR is returned, you may call doshPerfGet 1578 * afterwards. 1579 * 1580 * This properly initializes the internal counters 1581 * which the OS/2 kernel uses for this API. Apparently, 1582 * with newer kernels (FP13/14), IBM has chosen to no 1583 * longer do this automatically, which is the reason 1584 * why many "pulse" utilities display garbage with these 1585 * fixpaks. 1586 * 1587 * After NO_ERROR is returned, DOSHPERFSYS.cProcessors 1588 * contains the no. of processors found on the system. 1589 * All pointers in DOSHPERFSYS then point to arrays 1590 * which have exactly cProcessors array items. 1591 * 1592 * Call doshPerfClose to clean up resources allocated 1593 * by this function. 1594 * 1595 * Example code: 1596 * 1597 + PDOSHPERFSYS pPerf = NULL; 1598 + APIRET arc = doshPerfOpen(&pPerf); 1599 + if (arc == NO_ERROR) 1600 + { 1601 + // this should really be in a timer 1602 + ULONG ulCPU; 1603 + arc = doshPerfGet(&pPerf); 1604 + // go thru all CPUs 1605 + for (ulCPU = 0; ulCPU < pPerf->cProcessors; ulCPU++) 1606 + { 1607 + LONG lLoadThis = pPerf->palLoads[ulCPU]; 1608 + ... 1609 + } 1610 + 1611 + ... 1612 + 1613 + // clean up 1614 + doshPerfClose(&pPerf); 1615 + } 1616 + 1617 * 1618 *@@added V0.9.7 (2000-12-02) [umoeller] 1619 */ 1620 1621 APIRET doshPerfOpen(PDOSHPERFSYS *ppPerfSys) // out: new DOSHPERFSYS structure 1622 { 1623 APIRET arc = NO_ERROR; 1624 1625 // allocate DOSHPERFSYS structure 1626 *ppPerfSys = (PDOSHPERFSYS)malloc(sizeof(DOSHPERFSYS)); 1627 if (!*ppPerfSys) 1628 arc = ERROR_NOT_ENOUGH_MEMORY; 1629 else 1630 { 1631 // initialize structure 1632 PDOSHPERFSYS pPerfSys = *ppPerfSys; 1633 memset(pPerfSys, 0, sizeof(*pPerfSys)); 1634 1635 // resolve DosPerfSysCall API entry 1636 arc = DosLoadModule(NULL, 0, "DOSCALLS", &pPerfSys->hmod); 1637 if (arc == NO_ERROR) 1638 { 1639 arc = DosQueryProcAddr(pPerfSys->hmod, 1640 976, 1641 "DosPerfSysCall", 1642 (PFN*)(&pPerfSys->pDosPerfSysCall)); 1643 if (arc == NO_ERROR) 1644 { 1645 // OK, we got the API: initialize! 1646 arc = pPerfSys->pDosPerfSysCall(CMD_KI_ENABLE, 0, 0, 0); 1647 if (arc == NO_ERROR) 1648 { 1649 pPerfSys->fInitialized = TRUE; 1650 // call CMD_KI_DISABLE later 1651 1652 arc = pPerfSys->pDosPerfSysCall(CMD_PERF_INFO, 1653 0, 1654 (ULONG)(&pPerfSys->cProcessors), 1655 0); 1656 if (arc == NO_ERROR) 1657 { 1658 ULONG ul = 0; 1659 1660 // allocate arrays 1661 pPerfSys->paCPUUtils = (PCPUUTIL)calloc(pPerfSys->cProcessors, 1662 sizeof(CPUUTIL)); 1663 if (!pPerfSys->paCPUUtils) 1664 arc = ERROR_NOT_ENOUGH_MEMORY; 1665 else 1666 { 1667 pPerfSys->padBusyPrev = (double*)malloc(pPerfSys->cProcessors * sizeof(double)); 1668 if (!pPerfSys->padBusyPrev) 1669 arc = ERROR_NOT_ENOUGH_MEMORY; 1670 else 1671 { 1672 pPerfSys->padTimePrev 1673 = (double*)malloc(pPerfSys->cProcessors * sizeof(double)); 1674 if (!pPerfSys->padTimePrev) 1675 arc = ERROR_NOT_ENOUGH_MEMORY; 1676 else 1677 { 1678 pPerfSys->palLoads = (PLONG)malloc(pPerfSys->cProcessors * sizeof(LONG)); 1679 if (!pPerfSys->palLoads) 1680 arc = ERROR_NOT_ENOUGH_MEMORY; 1681 else 1682 { 1683 for (ul = 0; ul < pPerfSys->cProcessors; ul++) 1684 { 1685 pPerfSys->padBusyPrev[ul] = 0.0; 1686 pPerfSys->padTimePrev[ul] = 0.0; 1687 pPerfSys->palLoads[ul] = 0; 1688 } 1689 } 1690 } 1691 } 1692 } 1693 } 1694 } 1695 } // end if (arc == NO_ERROR) 1696 } // end if (arc == NO_ERROR) 1697 1698 if (arc != NO_ERROR) 1699 { 1700 doshPerfClose(ppPerfSys); 1701 } 1702 } // end else if (!*ppPerfSys) 1703 1704 return (arc); 1705 } 1706 1707 /* 1708 *@@ doshPerfGet: 1709 * calculates a current snapshot of the system load, 1710 * compared with the load which was calculated on 1711 * the previous call. 1712 * 1713 * If you want to continually measure the system CPU 1714 * load, this is the function you will want to call 1715 * regularly -- e.g. with a timer once per second. 1716 * 1717 * Call this ONLY if doshPerfOpen returned NO_ERROR, 1718 * or you'll get crashes. 1719 * 1720 * If this call returns NO_ERROR, you get a LONG 1721 * CPU load for each CPU in the system in the 1722 * DOSHPERFSYS.palLoads array (in per-mille, 0-1000). 1723 * 1724 * For example, if there are two CPUs, after this call, 1725 * 1726 * -- DOSHPERFSYS.palLoads[0] contains the load of 1727 * the first CPU, 1728 * 1729 * -- DOSHPERFSYS.palLoads[1] contains the load of 1730 * the second CPU. 1731 * 1732 * See doshPerfOpen for example code. 1733 * 1734 *@@added V0.9.7 (2000-12-02) [umoeller] 1735 */ 1736 1737 APIRET doshPerfGet(PDOSHPERFSYS pPerfSys) 1738 { 1739 APIRET arc = NO_ERROR; 1740 if (!pPerfSys->pDosPerfSysCall) 1741 arc = ERROR_INVALID_PARAMETER; 1742 else 1743 { 1744 arc = pPerfSys->pDosPerfSysCall(CMD_KI_RDCNT, 1745 (ULONG)pPerfSys->paCPUUtils, 1746 0, 0); 1747 if (arc == NO_ERROR) 1748 { 1749 // go thru all processors 1750 ULONG ul = 0; 1751 for (; ul < pPerfSys->cProcessors; ul++) 1752 { 1753 PCPUUTIL pCPUUtilThis = &pPerfSys->paCPUUtils[ul]; 1754 1755 double dTime = LL2F(pCPUUtilThis->ulTimeHigh, 1756 pCPUUtilThis->ulTimeLow); 1757 double dBusy = LL2F(pCPUUtilThis->ulBusyHigh, 1758 pCPUUtilThis->ulBusyLow); 1759 1760 double *pdBusyPrevThis = &pPerfSys->padBusyPrev[ul]; 1761 double *pdTimePrevThis = &pPerfSys->padTimePrev[ul]; 1762 1763 // avoid division by zero 1764 double dTimeDelta = (dTime - *pdTimePrevThis); 1765 if (dTimeDelta) 1766 pPerfSys->palLoads[ul] 1767 = (LONG)( (double)( (dBusy - *pdBusyPrevThis) 1768 / dTimeDelta 1769 * 1000.0 1770 ) 1771 ); 1772 else 1773 pPerfSys->palLoads[ul] = 0; 1774 1775 *pdTimePrevThis = dTime; 1776 *pdBusyPrevThis = dBusy; 1777 } 1778 } 1779 } 1780 1781 return (arc); 1782 } 1783 1784 /* 1785 *@@ doshPerfClose: 1786 * frees all resources allocated by doshPerfOpen. 1787 * 1788 *@@added V0.9.7 (2000-12-02) [umoeller] 1789 */ 1790 1791 APIRET doshPerfClose(PDOSHPERFSYS *ppPerfSys) 1792 { 1793 APIRET arc = NO_ERROR; 1794 PDOSHPERFSYS pPerfSys = *ppPerfSys; 1795 if (!pPerfSys) 1796 arc = ERROR_INVALID_PARAMETER; 1797 else 1798 { 1799 if (pPerfSys->fInitialized) 1800 pPerfSys->pDosPerfSysCall(CMD_KI_DISABLE, 1801 0, 0, 0); 1802 1803 if (pPerfSys->paCPUUtils) 1804 free(pPerfSys->paCPUUtils); 1805 if (pPerfSys->padBusyPrev) 1806 free(pPerfSys->padBusyPrev); 1807 if (pPerfSys->padTimePrev) 1808 free(pPerfSys->padTimePrev); 1809 1810 if (pPerfSys->hmod) 1811 DosFreeModule(pPerfSys->hmod); 1812 free(pPerfSys); 1813 *ppPerfSys = NULL; 1814 } 1815 1816 return (arc); 1817 } 1818 1819 /* 1461 1820 *@@category: Helpers\Control program helpers\Process management 1462 1821 */ 1463 1822 1464 1823 /* ****************************************************************** 1465 * *1466 * Process helpers *1467 * *1824 * 1825 * Process helpers 1826 * 1468 1827 ********************************************************************/ 1469 1828
Note:
See TracChangeset
for help on using the changeset viewer.