home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: SysTools / SysTools.zip / taman002.zip / TASKMANA.ZIP / src / kQuerySysState.c < prev    next >
C/C++ Source or Header  |  2000-04-29  |  18KB  |  542 lines

  1. /* $Id: kQuerySysState.c,v 1.1 2000/04/29 19:06:35 stknut Exp $
  2.  *
  3.  * QuerySysState - system interface and data storage location.
  4.  *
  5.  * Copyright (c) 2000 knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
  6.  *
  7.  */
  8.  
  9. /*******************************************************************************
  10. *   Defined Constants And Macros                                               *
  11. *******************************************************************************/
  12. #define INCL_DOSERRORS
  13. #define INCL_DOSPROCESS
  14.  
  15. /*******************************************************************************
  16. *   Header Files                                                               *
  17. *******************************************************************************/
  18. #include <os2.h>
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include <malloc.h>
  22. #include <assert.h>
  23.  
  24. #include "kQuerySysState.h"
  25.  
  26. /*******************************************************************************
  27. *   Global Variables                                                           *
  28. *******************************************************************************/
  29. static PPROCESSDATA     pProcFirst = NULL;
  30. static PPROCESSDATA     pProcLast = NULL;
  31. static PPROCESSDATA     pProcCur = NULL;
  32. static qsLrec_t *       pMTEs = NULL;
  33. static qsS16Headrec_t * p16Sems = NULL;
  34. static qsS32rec_t *     p32Sems = NULL;
  35. static qsMrec_t *       pMemRecs = NULL;
  36. static qsMrec_t *       pShrMemRecs = NULL;
  37. static qsFrec_t *       pFSRecs = NULL;
  38. static qsGrec_t *       pGlobalRec = NULL;
  39. static unsigned         cBuffers = 2;
  40. static unsigned         cbBuffer = 1024*1024;
  41. static char             achBuffer[2][1024*1024];
  42. static unsigned         iCurBuffer = 1;
  43.  
  44.  
  45. /**
  46.  * Updates the status data.
  47.  * @returns   TRUE - success
  48.  *            FALSE - failure.
  49.  * @status
  50.  * @author    knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
  51.  * @remark    Single threaded!
  52.  */
  53. BOOL            QSUpdateStateData(void)
  54. {
  55.     APIRET      rc;
  56.  
  57.     /*
  58.      * Find correct buffer, Zero it, and query sys stata.
  59.      */
  60.     iCurBuffer = (iCurBuffer + 1) % cBuffers;
  61.     memset(achBuffer[iCurBuffer], 0, cbBuffer);
  62.     rc = DosQuerySysState(QS_PROCESS | QS_SEMAPHORE | QS_MTE | QS_FILESYS | QS_SHMEMORY, /* information requested */
  63.                           QS_MTE,                   /* Object info for MTEs */
  64.                           0UL,                      /* PID. 0 is all processes. */
  65.                           0UL,                      /* TID. 0 is all threads. (PID=0 too) */
  66.                           achBuffer[iCurBuffer],    /* Pointer to databuffer. */
  67.                           cbBuffer);                /* Size of databuffer. */
  68.     if (rc == NO_ERROR)
  69.     {
  70.         qsPtrRec_t *    pPtrRec;        /* Pointer to pointer record at buffer start. */
  71.         qsPrec_t *      pProcRec;       /* Current process record. */
  72.         PPROCESSDATA    pProcData;
  73.  
  74.         /*
  75.          * Local data
  76.          */
  77.         pPtrRec = (qsPtrRec_t*)achBuffer[iCurBuffer];
  78.         pProcRec = pPtrRec->pProcRec;
  79.  
  80.         /*
  81.          * Global data
  82.          */
  83.         pMTEs = pPtrRec->pLibRec;
  84.         p16Sems = pPtrRec->p16SemRec;
  85.         p32Sems = pPtrRec->p32SemRec;
  86.         pMemRecs = pPtrRec->pMemRec;
  87.         pShrMemRecs = pPtrRec->pShrMemRec;
  88.         pFSRecs = pPtrRec->pFSRec;
  89.         pGlobalRec = pPtrRec->pGlobalRec;
  90.  
  91.         /*
  92.          * Set dead flag before starting to update and add processes.
  93.          * When a process have been found in the new stat data, the
  94.          * dead flag is cleared.
  95.          */
  96.         for (pProcData = pProcFirst; pProcData != NULL; pProcData = pProcData->pNext)
  97.             pProcData->fDead = TRUE;
  98.  
  99.         /*
  100.          * Loop thru all processes which was found and update or add
  101.          * data to the linked list of processes.
  102.          */
  103.         while (pProcRec != NULL && pProcRec->RecType == QS_PROCESS)
  104.         {
  105.             unsigned long ulSysTime;    /* Used when calculating total time in system code. */
  106.             unsigned long ulUserTime;   /* Used when calculating total time in user code. */
  107.             unsigned      cbProcRec;    /* Size of qsPrec (with all additional data!) */
  108.             int           i;            /* Loop counter (threads) */
  109.  
  110.             pProcData = QSGetProcessData(pProcRec->pid);
  111.             if (pProcData == NULL)
  112.             {   /*
  113.                  * New process.
  114.                  * Allocate a new process data struct and set to following:
  115.                  *    usPid        to Pid number
  116.                  *    fDirty       to TRUE
  117.                  *    pProcRec     is NULL (indiactes a new process)
  118.                  *    cbProcRec    is 0
  119.                  *    pvRecordCore is NULL (indicates a new process)
  120.                  * And insert the process data.
  121.                  */
  122.                 pProcData = (PPROCESSDATA)calloc(sizeof(PROCESSDATA), 1);
  123.                 assert(pProcData != NULL); if (pProcData == NULL) break;
  124.                 pProcData->usPid = pProcRec->pid;
  125.                 pProcData->fDirty = TRUE;
  126.                 QSInsertProcessData(pProcData);
  127.             }
  128.             /* This process is not dead! fDead to false! */
  129.             pProcData->fDead = FALSE;
  130.  
  131.             /*
  132.              * Calc record size for the new data and see if it matches the size
  133.              * of the old data for this process. If is doesn't match, something have been changed!
  134.              */
  135.             cbProcRec = (unsigned)(pProcRec->pThrdRec + pProcRec->cTCB) - (unsigned)pProcRec;
  136.             if (pProcData->cbProcRec != cbProcRec)
  137.             {
  138.                 pProcData->cbProcRec = cbProcRec;
  139.                 pProcData->fDirty = TRUE;
  140.             }
  141.  
  142.             /*
  143.              * Count total times and evt. update the pProcData struct.
  144.              */
  145.             for (i = 0, ulSysTime = ulUserTime = 0; i < pProcRec->cTCB; i++)
  146.             {
  147.                 ulUserTime += pProcRec->pThrdRec[i].usertime;
  148.                 ulSysTime  += pProcRec->pThrdRec[i].systime;
  149.             }
  150.             if (pProcData->ulSysTime != ulSysTime || pProcData->ulUserTime != ulUserTime)
  151.             {
  152.                 pProcData->fDirty = TRUE;
  153.                 pProcData->ulSysTime = ulSysTime;
  154.                 pProcData->ulUserTime = ulUserTime;
  155.             }
  156.  
  157.             /*
  158.              * Dirty check. If not allready dirty.
  159.              */
  160.             if (!pProcData->fDirty)
  161.             {
  162.                 pProcData->fDirty =
  163.                     pProcData->pProcRec->cTCB != pProcRec->cTCB
  164.                     /* ||  FIXME */
  165.                     ;
  166.             }
  167.  
  168.             /*
  169.              * Set Record pointer
  170.              */
  171.             pProcData->pProcRec = pProcRec;
  172.  
  173.             /* next - DEPENDS on the ThrdRecs to be last */
  174.             pProcRec = (qsPrec_t*)(unsigned)(pProcRec->pThrdRec + pProcRec->cTCB);
  175.         }
  176.     }
  177.  
  178.     memset(achBuffer[(iCurBuffer+1) % cBuffers], 0, cbBuffer);
  179.  
  180.     return rc == NO_ERROR;
  181. }
  182.  
  183.  
  184. /**
  185.  * Inserts a process data node.
  186.  * @param     pProcData  Pointer to the node which is to inserted.
  187.  * @status    completely  implemented.
  188.  * @author    knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
  189.  * @remark    The pProcData doubly-linked list is sorted on usPid.
  190.  */
  191. VOID            QSInsertProcessData(PPROCESSDATA pProcData)
  192. {
  193.     PPROCESSDATA pCur;
  194.     BOOL         fDir;                  /* TRUE: Start --> End; FALSE: End --> Start*/
  195.     assert(pProcData != NULL);
  196.  
  197.     /*
  198.      * Semi optimized start location.
  199.      */
  200.     if (pProcCur == NULL)
  201.         pCur = pProcLast;
  202.     else
  203.         pCur = pProcCur;
  204.  
  205.     /*
  206.      * Find the right place for the new node in the list.
  207.      */
  208.     if (pCur != NULL)
  209.     {
  210.         if (pCur->usPid <= pProcData->usPid)
  211.         {
  212.             fDir = TRUE;
  213.             while (pCur != NULL && pCur->usPid < pProcData->usPid)
  214.                 pCur = pCur->pNext;
  215.         }
  216.         else
  217.         {
  218.             fDir = FALSE;
  219.             while (pCur != NULL && pCur->usPid >= pProcData->usPid)
  220.                 pCur = pCur->pPrev;
  221.  
  222.             /* insert before, so we'll have to goback one node */
  223.             if (pCur != NULL)
  224.                 pCur = pCur->pNext;
  225.         }
  226.         assert(pCur == NULL || pCur->usPid != pProcData->usPid);
  227.     }
  228.  
  229.     /*
  230.      * case pCur == NULL && fDir:
  231.      *      Last in the list. (or empty list)
  232.      * case pCur == NULL && !fDir:
  233.      *      First in the list. (or empty list)
  234.      * case pCur != NULL:
  235.      *      Insert before pCur
  236.      */
  237.     if (pCur == NULL)
  238.     {
  239.         if (fDir)
  240.         {   /* last */
  241.             pProcData->pNext = NULL;
  242.             pProcData->pPrev = pProcLast;
  243.             if (pProcLast != NULL)
  244.                 pProcLast->pNext = pProcData;
  245.             else
  246.                 pProcFirst = pProcData;
  247.             pProcLast = pProcData;
  248.         }
  249.         else
  250.         {   /* first */
  251.             pProcData->pNext = pProcFirst;
  252.             pProcData->pPrev = NULL;
  253.             if (pProcFirst != NULL)
  254.                 pProcFirst->pPrev = pProcData;
  255.             else
  256.                 pProcLast = pProcData;
  257.             pProcFirst = pProcData;
  258.         }
  259.     }
  260.     else
  261.     {   /* before */
  262.         pProcData->pNext = pCur;
  263.         pProcData->pPrev = pCur->pPrev;
  264.         if (pCur->pPrev != NULL)
  265.             pCur->pPrev->pNext = pProcData;
  266.         else
  267.             pProcFirst = pProcData;
  268.         pCur->pPrev = pProcData;
  269.     }
  270.  
  271.     /*
  272.      * Set the last found node as this might optimize next access to the list.
  273.      */
  274.     pProcCur = pProcData;
  275. }
  276.  
  277.  
  278. /**
  279.  * Removes a processdata node.
  280.  * This function will free the memory occupied by pProcData!
  281.  * @param     pProcData  Process data node
  282.  * @status
  283.  * @author    knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
  284.  * @remark
  285.  */
  286. VOID            QSRemoveProcessData(PPROCESSDATA pProcData)
  287. {
  288.     if (pProcData->pPrev != NULL)
  289.         pProcData->pPrev->pNext = pProcData->pNext;
  290.     else
  291.         pProcFirst = pProcData->pNext;
  292.     if (pProcData->pNext != NULL)
  293.         pProcData->pNext->pPrev = pProcData->pPrev;
  294.     else
  295.         pProcLast = pProcData->pPrev;
  296.     if (pProcCur == pProcData)
  297.         pProcCur = pProcData->pPrev;
  298.     free(pProcData);
  299. }
  300.  
  301.  
  302.  
  303. /**
  304.  * Finds a process data node by PID number.
  305.  * @returns   NULL if not found. Pointer to node if found.
  306.  * @param     usPid  Process identificator to find.
  307.  * @status
  308.  * @author    knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
  309.  * @remark
  310.  */
  311. PPROCESSDATA    QSGetProcessData(USHORT usPid)
  312. {
  313.     PPROCESSDATA pCur;
  314.  
  315.     /*
  316.      * Semi optimized start location.
  317.      */
  318.     if (pProcCur == NULL)
  319.         pCur = pProcLast;
  320.     else
  321.         pCur = pProcCur;
  322.  
  323.     /*
  324.      * Find the right place for the new node in the list.
  325.      */
  326.     if (pCur != NULL)
  327.     {
  328.         if (pCur->usPid <= usPid)
  329.         {
  330.             while (pCur != NULL && pCur->usPid < usPid)
  331.                 pCur = pCur->pNext;
  332.         }
  333.         else
  334.         {
  335.             while (pCur != NULL && pCur->usPid > usPid)
  336.                 pCur = pCur->pPrev;
  337.         }
  338.     }
  339.  
  340.     return pCur != NULL && pCur->usPid == usPid ? pCur : NULL;
  341. }
  342.  
  343.  
  344. /**
  345.  * Gets the first node in the process data list.
  346.  * @returns   Pointer ot the first node in the process data list.
  347.  *            If empty list, NULL is returned.
  348.  * @author    knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
  349.  */
  350. PPROCESSDATA    QSGetFirstProcessDataNode(VOID)
  351. {
  352.     return pProcFirst;
  353. }
  354.  
  355.  
  356. /**
  357.  * Gets a given MTE (library) record from the data returned from DosQuerySysState.
  358.  * @returns   NULL if not found (or error). Pointer to MTE record if found.
  359.  * @param     USHORT  hMTE.
  360.  * @author    knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
  361.  */
  362. qsLrec_t *      QSGetMteData(register USHORT hMTE)
  363. {
  364.     /*
  365.      * Searches lineary (no other option) thru the linked list of
  366.      * Mte (Library) records returned by DosQuerySysState.
  367.      */
  368.     register qsLrec_t *pLrec = pMTEs;
  369.     while (pLrec != NULL)
  370.     {
  371.  
  372.         /*
  373.          * Bug detected in OS/2 FP13. Probably a problem which occurs
  374.          * in _LDRSysMteInfo when qsCheckCache is calle before writing
  375.          * object info. The result is that the cache flushed and the
  376.          * attempt of updating the qsLrec_t next and object pointer is
  377.          * not done. This used to work earlier and on Aurora AFAIK.
  378.          *
  379.          * The fix for this problem is to check if the pObjInfo is NULL
  380.          * while the number of objects isn't 0 and correct this. pNextRec
  381.          * will also be NULL at this time. This will be have to corrected
  382.          * before we exit the loop or moves to the next record.
  383.          * There is also a nasty alignment of the object info... Hope
  384.          * I got it right. (This aligment seems new to FP13.)
  385.          */
  386.         if (pLrec->pObjInfo == NULL /*&& pLrec->pNextRec == NULL*/ && pLrec->ctObj > 0)
  387.             {
  388.             pLrec->pObjInfo = (qsLObjrec_t*)(
  389.                 (char*)pLrec
  390.                 + ((sizeof(qsLrec_t)                     /* size of the lib record */
  391.                    + pLrec->ctImpMod * sizeof(short)    /* size of the array of imported modules */
  392.                    + strlen((char*)pLrec->pName) + 1    /* size of the filename */
  393.                    + 3) & ~3));                          /* the size is align on 4 bytes boundrary */
  394.             pLrec->pNextRec = (qsLrec_t*)((char*)pLrec->pObjInfo
  395.                                            + sizeof(qsLObjrec_t) * pLrec->ctObj);
  396.             }
  397.         if (pLrec->hmte == hMTE)
  398.             break;
  399.  
  400.         pLrec = pLrec->pNextRec;
  401.     }
  402.     return pLrec;
  403. }
  404.  
  405.  
  406. /**
  407.  * Get the starting MTE data record.
  408.  * @returns   Pointer to the first MTE data record.
  409.  * @author    knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
  410.  */
  411. qsLrec_t *      QSGetMteFirstData(VOID)
  412. {
  413.     return pMTEs;
  414. }
  415.  
  416.  
  417. /**
  418.  * Get the first filesystem record.
  419.  * @returns   NULL pointer if found or error.
  420.  *            Pointer to FS record on success.
  421.  * @author    knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
  422.  */
  423. qsFrec_t *      QSGetFSFirstData(VOID)
  424. {
  425.     return pFSRecs;
  426. }
  427.  
  428.  
  429. /**
  430.  * Get the FS record for the given system file number.
  431.  * @returns   NULL pointer if found or error.
  432.  *            Pointer to FS record on success.
  433.  * @param     usSFN  System File number.
  434.  * @author    knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
  435.  */
  436. qsFrec_t *      QSGetSfnData(USHORT usSFN)
  437. {
  438.     /*
  439.      * Searches lineary (no other option) thru the linked list of
  440.      * FS records returned by DosQuerySysState.
  441.      */
  442.     register qsFrec_t * pCur = pFSRecs;
  443.     while (pCur != NULL && pCur->RecType == QS_FILESYS)
  444.     {
  445.         register int i;
  446.         for (i = 0; i < pCur->ctSft; i++)
  447.             if (pCur->pSft[i].sfn == usSFN)
  448.                 return pCur;
  449.         /* next */
  450.         pCur = pCur->pNextRec;
  451.     }
  452.  
  453.  
  454.     return NULL;
  455. }
  456.  
  457.  
  458. /**
  459.  * Debug function which dumps the process list.
  460.  * @author    knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
  461.  */
  462. VOID            QSDumpProcessData(VOID)
  463. {
  464.     PPROCESSDATA pProcData = pProcFirst;
  465.  
  466.         printf("pid   ppid  cTCB  SysTime   UserTime  Dirty  Dead  Name\n");
  467.     while (pProcData != NULL)
  468.     {
  469.         int i;
  470.         qsLrec_t *pMTE = QSGetMteData(pProcData->pProcRec->hMte);
  471.  
  472.         printf("%04x  %04x  %04x  %000008x  %000008x  %-4d   %-4d  %s\n",
  473.                pProcData->pProcRec->pid,
  474.                pProcData->pProcRec->ppid,
  475.                pProcData->pProcRec->cTCB,
  476.                pProcData->ulSysTime,
  477.                pProcData->ulUserTime,
  478.                pProcData->fDirty,
  479.                pProcData->fDead,
  480.                pMTE != NULL && pMTE->pName != NULL ? pMTE->pName : "<not found>"
  481.                );
  482.         if (pProcData->pProcRec->pFSRec
  483.             && pProcData->pProcRec->cFH > 0)
  484.             for (i = 0; i < pProcData->pProcRec->cFH; i++)
  485.             {
  486.                 qsFrec_t * pFSRec = QSGetSfnData(pProcData->pProcRec->pFSRec[i]);
  487.                 printf("    sfn %#06x  %s\n", pProcData->pProcRec->pFSRec[i],
  488.                        pFSRec != NULL ? (char*)(pFSRec + 1) : "<not found>"
  489.                        );
  490.             }
  491.  
  492.         /* next */
  493.         pProcData = pProcData->pNext;
  494.     }
  495. }
  496.  
  497.  
  498. /**
  499.  * Debug function which dumps the MFS list.
  500.  * @author    knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
  501.  */
  502. VOID            QSDumpFileSystemData(VOID)
  503. {
  504.     qsFrec_t *pCur = pFSRecs;
  505.  
  506.     while (pCur != NULL && pCur->RecType == QS_FILESYS)
  507.     {
  508.         int i;
  509.         printf("%s  (",
  510.                pCur + 1
  511.                );
  512.         for (i = 0; i < pCur->ctSft; i++)
  513.             printf("%d,", pCur->pSft[i].sfn);
  514.         printf(")\n");
  515.         /* next */
  516.         pCur = pCur->pNextRec;
  517.     }
  518.  
  519.     pCur = pFSRecs;
  520.     while (pCur != NULL && pCur->RecType == QS_FILESYS)
  521.     {
  522.         int i;
  523.         for (i = 0; i < pCur->ctSft; i++)
  524.             printf("sfn 0x%04x  %s\n", pCur->pSft[i].sfn, pCur + 1);
  525.  
  526.         /* next */
  527.         pCur = pCur->pNextRec;
  528.     }
  529.  
  530. }
  531.  
  532.  
  533. #if 0
  534. void main(void)
  535. {
  536.     QSUpdateStateData();
  537.     QSDumpProcessData();
  538.     QSDumpFileSystemData();
  539. }
  540. #endif
  541.  
  542.