Changeset 44 for trunk/src


Ignore:
Timestamp:
Mar 8, 2001, 8:28:45 PM (24 years ago)
Author:
umoeller
Message:

Misc. changes.

Location:
trunk/src/helpers
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/helpers/procstat.c

    r14 r44  
    114114VOID prc16FreeInfo(PQPROCSTAT16 pInfo)
    115115{
    116     free(pInfo);
     116    if (pInfo)
     117        free(pInfo);
    117118}
    118119
     
    133134    PQPROCESS16 pProcess,
    134135                pReturn = NULL;
    135     for ( pProcess = (PQPROCESS16)PTR(pInfo->ulProcesses, 0);
    136           pProcess->ulType != 3;
    137           pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,
    138                                       pProcess->usThreads * sizeof(QTHREAD16))
    139         )
    140     {
    141         CHAR    szModuleName[CCHMAXPATH];
    142         if (DosQueryModuleName(pProcess->usHModule,
    143                                sizeof(szModuleName),
    144                                szModuleName)
    145                 == NO_ERROR)
    146         {
    147             // the module name is fully qualified, so find the
    148             // file name (after the last backslash)
    149             PSZ pLastBackslash = strrchr(szModuleName, '\\');
    150             if (pLastBackslash)
    151                 // found:
    152                 if (stricmp(pLastBackslash + 1, pcszName) == 0)
    153                 {
    154                     // matches:
    155                     pReturn = pProcess;
    156                     break;
    157                 }
     136    if (pInfo)
     137    {
     138        for ( pProcess = (PQPROCESS16)PTR(pInfo->ulProcesses, 0);
     139              pProcess->ulType != 3;
     140              pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,
     141                                          pProcess->usThreads * sizeof(QTHREAD16))
     142            )
     143        {
     144            CHAR    szModuleName[CCHMAXPATH];
     145            if (DosQueryModuleName(pProcess->usHModule,
     146                                   sizeof(szModuleName),
     147                                   szModuleName)
     148                    == NO_ERROR)
     149            {
     150                // the module name is fully qualified, so find the
     151                // file name (after the last backslash)
     152                PSZ pLastBackslash = strrchr(szModuleName, '\\');
     153                if (pLastBackslash)
     154                    // found:
     155                    if (stricmp(pLastBackslash + 1, pcszName) == 0)
     156                    {
     157                        // matches:
     158                        pReturn = pProcess;
     159                        break;
     160                    }
     161            }
    158162        }
    159163    }
     
    178182    PQPROCESS16 pProcess,
    179183                pReturn = NULL;
    180     for ( pProcess = (PQPROCESS16)PTR(pInfo->ulProcesses, 0);
    181           pProcess->ulType != 3;
    182           pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,
    183                                       pProcess->usThreads * sizeof(QTHREAD16))
    184         )
    185     {
    186         if (pProcess->usPID == ulPID)
    187         {
    188             pReturn = pProcess;
    189             break;
     184    if (pInfo)
     185    {
     186        for ( pProcess = (PQPROCESS16)PTR(pInfo->ulProcesses, 0);
     187              pProcess->ulType != 3;
     188              pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,
     189                                          pProcess->usThreads * sizeof(QTHREAD16))
     190            )
     191        {
     192            if (pProcess->usPID == ulPID)
     193            {
     194                pReturn = pProcess;
     195                break;
     196            }
    190197        }
    191198    }
     
    207214VOID prcReport16(PQPROCESS16 pProcess, PPRCPROCESS pprcp)
    208215{
    209     // USHORT usPriority = 0;
    210     PQTHREAD16 pThread;
    211     int i;
    212 
    213     DosQueryModuleName(pProcess->usHModule,
    214                        sizeof(pprcp->szModuleName),
    215                        pprcp->szModuleName);
    216     // DosGetPrty(PRTYS_PROCESS, &(pprcp->usPriority), pProcess->usPID);
    217 
    218     // sum up CPU time for process
    219     for (pprcp->ulCPU = 0,
    220                 i = 0,
    221                 pThread = (PQTHREAD16)PTR(pProcess->ulThreadList, 0);
    222          i < pProcess->usThreads;
    223          i++, pThread++ )
    224     {
    225         pprcp->ulCPU += (pThread->ulSysTime + pThread->ulUserTime);
    226     }
    227 
    228     pprcp->usPID            = pProcess->usPID;
    229     pprcp->usParentPID      = pProcess->usParentPID;
    230     pprcp->usThreads        = pProcess->usThreads;
    231     pprcp->ulSID            = pProcess->ulSID;
    232     pprcp->ulSessionType    = pProcess->ulSessionType;
    233     pprcp->ulStatus         = pProcess->ulStatus;
     216    if (pProcess)
     217    {
     218        PQTHREAD16 pThread;
     219        int i;
     220
     221        DosQueryModuleName(pProcess->usHModule,
     222                           sizeof(pprcp->szModuleName),
     223                           pprcp->szModuleName);
     224        // DosGetPrty(PRTYS_PROCESS, &(pprcp->usPriority), pProcess->usPID);
     225
     226        // sum up CPU time for process
     227        for (pprcp->ulCPU = 0,
     228                    i = 0,
     229                    pThread = (PQTHREAD16)PTR(pProcess->ulThreadList, 0);
     230             i < pProcess->usThreads;
     231             i++, pThread++ )
     232        {
     233            pprcp->ulCPU += (pThread->ulSysTime + pThread->ulUserTime);
     234        }
     235
     236        pprcp->usPID            = pProcess->usPID;
     237        pprcp->usParentPID      = pProcess->usParentPID;
     238        pprcp->usThreads        = pProcess->usThreads;
     239        pprcp->ulSID            = pProcess->ulSID;
     240        pprcp->ulSessionType    = pProcess->ulSessionType;
     241        pprcp->ulStatus         = pProcess->ulStatus;
     242    }
    234243}
    235244
     
    243252 */
    244253
    245 BOOL prc16QueryProcessInfo(USHORT usPID,  // in: PID to query
    246                            PPRCPROCESS pprcp) // out: process info
     254BOOL prc16QueryProcessInfo(PQPROCSTAT16 pps,    // in: from prc16GetInfo
     255                           USHORT usPID,        // in: PID to query
     256                           PPRCPROCESS pprcp)   // out: process info
    247257{
    248258    BOOL rc = FALSE;
    249     PQPROCESS16 pProcess;
    250     PQPROCSTAT16 pps = (PQPROCSTAT16)malloc(0x8000);
    251     DosQProcStatus(pps, 0x8000);
    252 
    253     for ( pProcess = (PQPROCESS16)PTR(pps->ulProcesses, 0);
    254           pProcess->ulType != 3;
    255           pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,
    256                                       pProcess->usThreads * sizeof(QTHREAD16))
    257         )
    258     {
    259         if (pProcess->usPID == usPID)
    260         {
    261             prcReport16(pProcess, pprcp);
    262             rc = TRUE;
    263             break;
    264         }
    265     }
    266 
    267     free(pps);
     259    if (pps)
     260    {
     261        PQPROCESS16 pProcess;
     262
     263        for ( pProcess = (PQPROCESS16)PTR(pps->ulProcesses, 0);
     264              pProcess->ulType != 3;
     265              pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,
     266                                          pProcess->usThreads * sizeof(QTHREAD16))
     267            )
     268        {
     269            if (pProcess->usPID == usPID)
     270            {
     271                prcReport16(pProcess, pprcp);
     272                rc = TRUE;
     273                break;
     274            }
     275        }
     276    }
     277
    268278    return (rc);
    269279}
     
    315325 *      in the given process. If pid == 0, the
    316326 *      total thread count for the system is returned.
    317  */
    318 
    319 ULONG prc16QueryThreadCount(USHORT usPID)
     327 *
     328 *@@changed V0.9.9 (2001-03-07) [umoeller]: added pps param
     329 */
     330
     331ULONG prc16QueryThreadCount(PQPROCSTAT16 pps, // in: from prc16GetInfo
     332                            USHORT usPID)
    320333{
    321334    ULONG       ulrc = 0;
    322     PQPROCSTAT16  pps = (PQPROCSTAT16)malloc(0x8000);
    323     DosQProcStatus(pps, 0x8000);
    324 
    325     if (usPID)
    326     {
    327         // process query:
     335
     336    if (pps)
     337    {
     338        if (usPID)
     339        {
     340            // process query:
     341            PQPROCESS16 pProcess;
     342            for ( pProcess = (PQPROCESS16)PTR(pps->ulProcesses, 0);
     343                  pProcess->ulType != 3;
     344                  pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,
     345                                              pProcess->usThreads * sizeof(QTHREAD16))
     346                )
     347            {
     348                if (pProcess->usPID == usPID)
     349                {
     350                    ulrc = pProcess->usThreads;
     351                    break;
     352                }
     353            }
     354        }
     355        else
     356        {
     357            // global query:
     358            PQGLOBAL16   pg;
     359            pg = (PQGLOBAL16)PTR(pps->ulGlobal, 0);
     360            ulrc = pg->ulThreads;
     361        }
     362    }
     363
     364    return (ulrc);
     365}
     366
     367/*
     368 *@@ prc16QueryThreadInfo:
     369 *      this searches for a given thread in a given process
     370 *      and fills a given PRCTHREAD structure with lots of
     371 *      information about that thread.
     372 *
     373 *      Returns FALSE upon errors.
     374 *
     375 *      Note: This function loops thru all processes which
     376 *      are currently running and is therefore not terribly
     377 *      fast. Use economically.
     378 *
     379 *@@changed V0.9.9 (2001-03-07) [umoeller]: added pps param
     380 */
     381
     382BOOL prc16QueryThreadInfo(PQPROCSTAT16 pps, // in: from prc16GetInfo
     383                          USHORT usPID,
     384                          USHORT usTID,
     385                          PPRCTHREAD pprct)
     386{
     387    BOOL        brc = FALSE;
     388    if (pps)
     389    {
    328390        PQPROCESS16 pProcess;
     391
     392        // find process:
    329393        for ( pProcess = (PQPROCESS16)PTR(pps->ulProcesses, 0);
    330394              pProcess->ulType != 3;
     
    335399            if (pProcess->usPID == usPID)
    336400            {
    337                 ulrc = pProcess->usThreads;
    338                 break;
     401                PQTHREAD16 pThread;
     402                int i;
     403                // process found: find thread
     404                for ( i = 0, pThread = (PQTHREAD16)PTR(pProcess->ulThreadList, 0);
     405                      i < pProcess->usThreads;
     406                      i++, pThread++ )
     407                {
     408                    if (pThread->usTID == usTID)
     409                    {
     410                        // thread found:
     411                        pprct->usTID          = pThread->usTID;
     412                        pprct->usThreadSlotID = pThread->usThreadSlotID;
     413                        pprct->ulBlockID      = pThread->ulBlockID;
     414                        pprct->ulPriority     = pThread->ulPriority;
     415                        pprct->ulSysTime      = pThread->ulSysTime;
     416                        pprct->ulUserTime     = pThread->ulUserTime;
     417                        pprct->ucStatus       = pThread->ucStatus;
     418
     419                        brc = TRUE;
     420
     421                        break; // thread-for loop
     422                    }
     423                } // end for thread
     424                break; // process-for loop
    339425            }
    340         }
    341     }
    342     else
    343     {
    344         // global query:
    345         PQGLOBAL16   pg;
    346         pg = (PQGLOBAL16)PTR(pps->ulGlobal, 0);
    347         ulrc = pg->ulThreads;
    348     }
    349 
    350     free(pps);
    351     return (ulrc);
    352 }
    353 
    354 /*
    355  *@@ prc16QueryThreadInfo:
    356  *      this searches for a given thread in a given process
    357  *      and fills a given PRCTHREAD structure with lots of
    358  *      information about that thread.
    359  *
    360  *      Returns FALSE upon errors.
     426        } // end for process
     427    }
     428
     429    return (brc);
     430}
     431
     432/*
     433 *@@ prcQueryPriority:
     434 *      shortcut to prc16QueryThreadInfo if you want the priority only.
     435 *
     436 *      Returns -1 upon errors.
    361437 *
    362438 *      Note: This function loops thru all processes which
    363439 *      are currently running and is therefore not terribly
    364440 *      fast. Use economically.
    365  */
    366 
    367 BOOL prc16QueryThreadInfo(USHORT usPID, USHORT usTID, PPRCTHREAD pprct)
    368 {
    369     BOOL        brc = FALSE;
    370     PQPROCSTAT16  pps = (PQPROCSTAT16)malloc(0x8000);
    371     PQPROCESS16 pProcess;
    372     DosQProcStatus(pps, 0x8000);
    373 
    374     // find process:
    375     for ( pProcess = (PQPROCESS16)PTR(pps->ulProcesses, 0);
    376           pProcess->ulType != 3;
    377           pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,
    378                                       pProcess->usThreads * sizeof(QTHREAD16))
    379         )
    380     {
    381         if (pProcess->usPID == usPID)
    382         {
    383             PQTHREAD16 pThread;
    384             int i;
    385             // process found: find thread
    386             for ( i = 0, pThread = (PQTHREAD16)PTR(pProcess->ulThreadList, 0);
    387                   i < pProcess->usThreads;
    388                   i++, pThread++ )
    389             {
    390                 if (pThread->usTID == usTID)
    391                 {
    392                     // thread found:
    393                     pprct->usTID          = pThread->usTID;
    394                     pprct->usThreadSlotID = pThread->usThreadSlotID;
    395                     pprct->ulBlockID      = pThread->ulBlockID;
    396                     pprct->ulPriority     = pThread->ulPriority;
    397                     pprct->ulSysTime      = pThread->ulSysTime;
    398                     pprct->ulUserTime     = pThread->ulUserTime;
    399                     pprct->ucStatus       = pThread->ucStatus;
    400 
    401                     brc = TRUE;
    402 
    403                     break; // thread-for loop
    404                 }
    405             } // end for thread
    406             break; // process-for loop
    407         }
    408     } // end for process
    409 
    410     free(pps);
    411     return (brc);
    412 }
    413 
    414 /*
    415  *@@ prcQueryPriority:
    416  *      shortcut to prc16QueryThreadInfo if you want the priority only.
    417  *
    418  *      Returns -1 upon errors.
    419  *
    420  *      Note: This function loops thru all processes which
    421  *      are currently running and is therefore not terribly
    422  *      fast. Use economically.
    423  */
    424 
    425 ULONG prc16QueryThreadPriority(USHORT usPID,
     441 *
     442 *@@changed V0.9.9 (2001-03-07) [umoeller]: added pps param
     443 */
     444
     445ULONG prc16QueryThreadPriority(PQPROCSTAT16 pps, // in: from prc16GetInfo
     446                               USHORT usPID,
    426447                               USHORT usTID)
    427448{
    428449    PRCTHREAD prct;
    429450    ULONG ulrc = -1;
    430     if (prc16QueryThreadInfo(usPID, usTID, &prct))
     451    if (prc16QueryThreadInfo(pps, usPID, usTID, &prct))
    431452        ulrc = prct.ulPriority;
    432453    return (ulrc);
  • trunk/src/helpers/threads.c

    r38 r44  
    5050#include "setup.h"                      // code generation and debugging options
    5151
     52#include "helpers\linklist.h"
    5253#include "helpers\threads.h"
    5354
     
    5859 *      see threads.c.
    5960 */
     61
     62/* ******************************************************************
     63 *
     64 *   Global variables
     65 *
     66 ********************************************************************/
     67
     68LINKLIST        G_llThreadInfos;
     69            // linked list of all THREADINFOS ever created...
     70            // no auto-free
     71HMTX            G_hmtxThreadInfos = NULLHANDLE;
     72
     73/* ******************************************************************
     74 *
     75 *   Functions
     76 *
     77 ********************************************************************/
     78
     79/*
     80 *@@ LockThreadInfos:
     81 *
     82 *@@added V0.9.9 (2001-03-07) [umoeller]
     83 */
     84
     85BOOL LockThreadInfos(VOID)
     86{
     87    APIRET arc = NO_ERROR;
     88
     89    if (G_hmtxThreadInfos == NULLHANDLE)
     90    {
     91        // first call:
     92        arc = DosCreateMutexSem(NULL,     // unnamed
     93                                &G_hmtxThreadInfos,
     94                                0,        // unshared
     95                                TRUE);        // request!
     96        lstInit(&G_llThreadInfos, FALSE);
     97    }
     98    else
     99    {
     100        arc = DosRequestMutexSem(G_hmtxThreadInfos,
     101                                 SEM_INDEFINITE_WAIT);
     102    }
     103
     104    return (arc == NO_ERROR);
     105}
     106
     107/*
     108 *@@ UnlockThreadInfos:
     109 *
     110 *@@added V0.9.9 (2001-03-07) [umoeller]
     111 */
     112
     113VOID UnlockThreadInfos(VOID)
     114{
     115    DosReleaseMutexSem(G_hmtxThreadInfos);
     116}
    60117
    61118/*
     
    108165            DosCloseEventSem(pti->hevRunning);
    109166
     167        // V0.9.9 (2001-03-07) [umoeller]
     168        // remove thread from global list
     169        if (LockThreadInfos())
     170        {
     171            lstRemoveItem(&G_llThreadInfos, pti);
     172            UnlockThreadInfos();
     173        }
     174
    110175        // (2000-12-18) [lafaix] clean up pti if thread is transient.
    111176        if (pti->flFlags & THRF_TRANSIENT)
     
    128193/*
    129194 *@@ thrCreate:
    130  *      this function fills a THREADINFO structure in *pti
    131  *      and starts a new thread using _beginthread.
     195 *      this function fills a THREADINFO structure and starts
     196 *      a new thread using _beginthread.
    132197 *
    133198 *      You must pass the thread function in pfn, which will
     
    144209 *      function is prototyped somewhere, VAC will automatically
    145210 *      modify the function's linkage, and you'll run into
    146  *      compiler warnings.
    147  *
    148  *      ptiMyself is then a pointer to the THREADINFO structure.
     211 *      crashes.
     212 *
     213 *      The thread's ptiMyself is then a pointer to the
     214 *      THREADINFO structure passed to this function.
    149215 *      ulData may be obtained like this:
    150  +          ULONG ulData = ((PTHREADINFO)ptiMyself)->ulData;
     216 *
     217 +          ULONG ulData = ptiMyself->ulData;
     218 *
     219 *      The THREADINFO structure passed to this function must
     220 *      be accessible all the time while the thread is running
     221 *      because the thr* functions will use it for maintenance.
     222 *
     223 *      This function does NOT check whether a thread is
     224 *      already running in *pti. Do not use the same THREADINFO
     225 *      for several threads.
     226 *
     227 *      If you do not want to manage the structure yourself,
     228 *      you can pass the THRF_TRANSIENT flag (see below).
    151229 *
    152230 *      thrCreate does not call your thread func directly,
     
    156234 *      explicitly, because this would skip the exit processing
    157235 *      (cleanup) in thr_fntGeneric. Instead, just fall out of
    158  *      your thread function.
    159  *
    160  *      This function does NOT check whether a thread is
    161  *      already running in *pti. If it is, that information
    162  *      will be lost.
     236 *      your thread function, or return().
    163237 *
    164238 *      flFlags can be any combination of the following:
     
    194268 *@@changed V0.9.7 (2000-12-18) [lafaix]: THRF_TRANSIENT support added
    195269 *@@changed V0.9.9 (2001-02-06) [umoeller]: now returning TID
     270 *@@changed V0.9.9 (2001-03-07) [umoeller]: added pcszThreadName
    196271 */
    197272
     
    200275                PBOOL pfRunning,     // out: variable set to TRUE while thread is running;
    201276                                     // ptr can be NULL
     277                const char *pcszThreadName, // in: thread name (for identification)
    202278                ULONG flFlags,       // in: THRF_* flags
    203279                ULONG ulData)        // in: user data to be stored in THREADINFO
     
    209285    {
    210286        if (pti == NULL)
    211             pti = (PTHREADINFO) malloc(sizeof(THREADINFO));
     287            pti = (PTHREADINFO)malloc(sizeof(THREADINFO));
     288                    // cleaned up by thr_fntGeneric on exit
    212289    }
    213290
    214291    if (pti)
    215292    {
    216         // we arrive here if *ppti was NULL or (*ppti->tid == NULLHANDLE),
    217         // i.e. the thread is not already running.
    218         // _beginthread is contained both in the VAC++ and EMX
    219         // C libraries with this syntax.
    220293        memset(pti, 0, sizeof(THREADINFO));
    221294        pti->cbStruct = sizeof(THREADINFO);
    222295        pti->pThreadFunc = (PVOID)pfn;
    223296        pti->pfRunning = pfRunning;
     297        pti->pcszThreadName = pcszThreadName; // V0.9.9 (2001-03-07) [umoeller]
    224298        pti->flFlags = flFlags;
    225299        pti->ulData = ulData;
     
    251325
    252326            if (ulrc)
     327            {
     328                if (LockThreadInfos())
     329                {
     330                    lstAppendItem(&G_llThreadInfos, pti);
     331                    UnlockThreadInfos();
     332                }
     333
    253334                if (flFlags & THRF_WAIT)
    254335                {
     
    258339                                    SEM_INDEFINITE_WAIT);
    259340                }
     341            }
    260342        }
    261343    }
     
    281363 *
    282364 *@@added V0.9.5 (2000-08-26) [umoeller]
     365 *@@changed V0.9.9 (2001-03-07) [umoeller]: added pcszThreadName
    283366 */
    284367
    285368ULONG thrRunSync(HAB hab,               // in: anchor block of calling thread
    286                  PTHREADFUNC pfn,       // in: thread function
    287                  ULONG ulData)          // in: data for thread function
     369                 PTHREADFUNC pfn,       // in: passed to thrCreate
     370                 const char *pcszThreadName, // in: passed to thrCreate
     371                 ULONG ulData)          // in: passed to thrCreate
    288372{
    289373    ULONG ulrc = 0;
     
    306390                  pfn,
    307391                  NULL,
     392                  pcszThreadName,
    308393                  THRF_PMMSGQUEUE,
    309394                  ulData);
     
    336421
    337422    return (ulrc);
     423}
     424
     425/*
     426 *@@ thrListThreads:
     427 *      returns an array of THREADINFO structures
     428 *      for all threads that have been started using
     429 *      thrCreate (or thrRunSync).
     430 *
     431 *      If no threads are running yet, this returns
     432 *      NULL.
     433 *
     434 *      Otherwise, this returns the pointer to the
     435 *      first array item, and *pcThreads receives
     436 *      the array item count (NOT the total array
     437 *      size). The array is a copied snapshot of all
     438 *      current THREADINFO's and must be free()'d
     439 *      by the caller.
     440 *
     441 *@@added V0.9.9 (2001-03-07) [umoeller]
     442 */
     443
     444PTHREADINFO thrListThreads(PULONG pcThreads)
     445{
     446    PTHREADINFO pArray = 0;
     447
     448    if (LockThreadInfos())
     449    {
     450        PTHREADINFO pThis;
     451        PLISTNODE pNode;
     452        *pcThreads = lstCountItems(&G_llThreadInfos);
     453        _Pmpf((__FUNCTION__ ": got %d threads", *pcThreads));
     454        pArray = (PTHREADINFO)malloc(*pcThreads * sizeof(THREADINFO));
     455        pThis = pArray;
     456
     457        pNode = lstQueryFirstNode(&G_llThreadInfos);
     458        while (pNode)
     459        {
     460            memcpy(pThis,
     461                   (PTHREADINFO)pNode->pItemData,
     462                   sizeof(THREADINFO));
     463            pThis++;
     464            pNode = pNode->pNext;
     465        }
     466
     467        UnlockThreadInfos();
     468    }
     469
     470    return (pArray);
     471}
     472
     473/*
     474 *@@ thrFindThread:
     475 *      attempts to find the thread with the specified
     476 *      TID; if found, returns TRUE and copies its
     477 *      THREADINFO into *pti.
     478 *
     479 *@@added V0.9.9 (2001-03-07) [umoeller]
     480 */
     481
     482BOOL thrFindThread(PTHREADINFO pti,
     483                   ULONG tid)
     484{
     485    BOOL brc = FALSE;
     486    if (LockThreadInfos())
     487    {
     488        PLISTNODE pNode = lstQueryFirstNode(&G_llThreadInfos);
     489        while (pNode)
     490        {
     491            PTHREADINFO ptiThis = (PTHREADINFO)pNode->pItemData;
     492            if (ptiThis->tid == tid)
     493            {
     494                memcpy(pti, ptiThis, sizeof(THREADINFO));
     495                brc = TRUE;
     496                break;
     497            }
     498            pNode = pNode->pNext;
     499        }
     500
     501        UnlockThreadInfos();
     502    }
     503
     504    return (brc);
    338505}
    339506
  • trunk/src/helpers/timer.c

    r41 r44  
    55 *      timer usage.
    66 *
    7  *      These timers operate similar to PM timers started
    8  *      with WinStartTimer. These are implemented thru a
    9  *      separate thread (fntTimersThread) which posts
    10  *      WM_TIMER messages regularly.
    11  *
    12  *      Instead of WinStartTimer, use tmrStartXTimer.
    13  *      Instead of WinStopTimer, use tmrStopXTimer.
     7 *      The functions here allow you to share a single PM
     8 *      timer for many windows on the same thread. Basically,
     9 *      these start a "master PM timer", to whose WM_TIMER
     10 *      message your window procedure must respond by calling
     11 *      tmrTimerTick, which will "distribute" the timer tick
     12 *      to those XTimers which have elapsed.
     13 *
     14 *      So to use XTimers, do the following:
     15 *
     16 *      1.  Create a timer set with tmrCreateSet. Specify
     17 *          an owner window and the timer ID of the master
     18 *          PM timer.
     19 *
     20 *      2.  You can then start and stop XTimers for windows
     21 *          on the same thread by calling tmrStartXTimer and
     22 *          tmrStopXTimer, respectively.
     23 *
     24 *      3.  In the window proc of the owner window, respond
     25 *          to WM_TIMER for the master PM timer by calling
     26 *          tmrTimerTick. This will call the window procs
     27 *          of those windows with WM_TIMER messages directly
     28 *          whose XTimers have elapsed.
    1429 *
    1530 *      The main advantage of the XTimers is that these
     
    2742 *          running.
    2843 *
    29  *      --  XTimers post WM_TIMER messages regardless of
    30  *          whether previous WM_TIMER messages have already
    31  *          been processed. For this reason, be careful with
    32  *          small timer timeouts, this might flood the
    33  *          message queue.
     44 *      --  tmrTimerTick (which you must call when the
     45 *          "master" WM_TIMER comes in) does not post WM_TIMER
     46 *          messages to the windows specified in the subtimers,
     47 *          but calls the window procedure of the target window
     48 *          directly. This makes sure that timers work even if
     49 *          some thread is hogging the SIQ.
     50 *
     51 *          This however requires that all XTimers must run on
     52 *          the same thread as the owner window of the master
     53 *          timer which was specified with tmrCreateSet.
    3454 *
    3555 *      --  Queue timers (with HWND == NULLHANDLE) are not
    3656 *          supported.
    3757 *
    38  *      --  When a window is deleted, its timers are not
    39  *          automatically cleaned up. The timer thread does
     58 *      --  When a window is destroyed, its timers are not
     59 *          automatically cleaned up. tmrTimerTick does
    4060 *          detect invalid windows and removes them from the
    4161 *          timers list before posting, but to be on the safe
     
    106126 *@@ XTIMER:
    107127 *      one of these represents an XTimer.
    108  *      These are stored in a global linked list.
     128 *      These are stored in a linked list in
     129 *      an _XTIMERSET.
    109130 */
    110131
     
    221242 */
    222243
    223 PXTIMER FindTimer(PXTIMERSET pSet,
    224                   HWND hwnd,
    225                   USHORT usTimerID)
     244PXTIMER FindTimer(PXTIMERSET pSet,          // in: timer set (from tmrCreateSet)
     245                  HWND hwnd,                // in: timer target window
     246                  USHORT usTimerID)         // in: timer ID
    226247{
    227248    if (pSet && pSet->pvllXTimers)
     
    252273 *
    253274 *      Internal function.
    254  *
    255  *      Preconditions:
    256  *
    257  *      -- The caller must call LockTimers() first.
    258  */
    259 
    260 VOID RemoveTimer(PXTIMERSET pSet,
    261                  PXTIMER pTimer)
     275 */
     276
     277VOID RemoveTimer(PXTIMERSET pSet,       // in: timer set (from tmrCreateSet)
     278                 PXTIMER pTimer)        // in: timer to remove.
    262279{
    263280    if (pSet && pSet->pvllXTimers)
     
    266283        lstRemoveItem(pllXTimers,
    267284                      pTimer);       // auto-free!
    268         /* if (lstCountItems(&G_llTimers) == 0)
    269             // no more timers left:
    270             // stop the main timer
    271             thrClose(&G_tiTimers); */
    272285    }
    273286}
     
    284297 *      This is the first step if you want to use the XTimers.
    285298 *
     299 *      hwndOwner must specify the "owner window", the target
     300 *      window for the master PM timer. This window must respond
     301 *      to a WM_TIMER message with the specified usPMTimerID and
     302 *      invoke tmrTimerTick then.
     303 *
     304 *      Note that the master timer is not started until an XTimer
     305 *      is started.
     306 *
    286307 *      Use tmrDestroySet to free all resources again.
    287308 *
     
    289310 */
    290311
    291 PXTIMERSET tmrCreateSet(HWND hwndOwner,
     312PXTIMERSET tmrCreateSet(HWND hwndOwner,         // in: owner window
    292313                        USHORT usPMTimerID)
    293314{
    294315    PXTIMERSET pSet = NULL;
    295 
    296     // _Pmpf((__FUNCTION__ ": entering"));
    297316
    298317    pSet = (PXTIMERSET)malloc(sizeof(*pSet));
     
    303322        pSet->idPMTimer = usPMTimerID;
    304323        pSet->idPMTimerRunning = 0;
     324        pSet->ulPMTimeout = 0;
    305325
    306326        pSet->pvllXTimers = (PVOID)lstCreate(TRUE);
    307327    }
    308 
    309     // _Pmpf((__FUNCTION__ ": leaving, returning 0x%lX", pSet));
    310328
    311329    return (pSet);
     
    323341 */
    324342
    325 VOID tmrDestroySet(PXTIMERSET pSet)
    326 {
    327     // _Pmpf((__FUNCTION__ ": entering"));
    328 
     343VOID tmrDestroySet(PXTIMERSET pSet)     // in: timer set (from tmrCreateSet)
     344{
    329345    if (pSet)
    330346    {
     
    344360        }
    345361
     362        if (pSet->idPMTimerRunning)
     363            WinStopTimer(pSet->hab,
     364                         pSet->hwndOwner,
     365                         pSet->idPMTimer);
     366
    346367        free(pSet);
    347368    }
    348 
    349     // _Pmpf((__FUNCTION__ ": leaving"));
     369}
     370
     371/*
     372 *@@ AdjustPMTimer:
     373 *      goes thru all XTimers in the sets and starts
     374 *      or stops the PM timer with a decent frequency.
     375 *
     376 *@@added V0.9.9 (2001-03-07) [umoeller]
     377 */
     378
     379VOID AdjustPMTimer(PXTIMERSET pSet)
     380{
     381    PLINKLIST pllXTimers = (PLINKLIST)pSet->pvllXTimers;
     382    PLISTNODE pNode = lstQueryFirstNode(pllXTimers);
     383    if (!pNode)
     384    {
     385        // no XTimers running:
     386        if (pSet->idPMTimerRunning)
     387        {
     388            // but PM timer running:
     389            // stop it
     390            WinStopTimer(pSet->hab,
     391                         pSet->hwndOwner,
     392                         pSet->idPMTimer);
     393            pSet->idPMTimerRunning = 0;
     394        }
     395
     396        pSet->ulPMTimeout = 0;
     397    }
     398    else
     399    {
     400        // we have timers:
     401        ULONG ulOldPMTimeout = pSet->ulPMTimeout;
     402        pSet->ulPMTimeout = 1000;
     403
     404        while (pNode)
     405        {
     406            PXTIMER pTimer = (PXTIMER)pNode->pItemData;
     407
     408            if ( (pTimer->ulTimeout / 2) < pSet->ulPMTimeout )
     409                pSet->ulPMTimeout = pTimer->ulTimeout / 2;
     410
     411            pNode = pNode->pNext;
     412        }
     413
     414        if (    (pSet->idPMTimerRunning == 0)       // timer not running?
     415             || (pSet->ulPMTimeout != ulOldPMTimeout) // timeout changed?
     416           )
     417            // start or restart PM timer
     418            pSet->idPMTimerRunning = WinStartTimer(pSet->hab,
     419                                                   pSet->hwndOwner,
     420                                                   pSet->idPMTimer,
     421                                                   pSet->ulPMTimeout);
     422    }
    350423}
    351424
     
    364437 */
    365438
    366 VOID tmrTimerTick(PXTIMERSET pSet)
    367 {
    368     // _Pmpf((__FUNCTION__ ": entering"));
    369 
     439VOID tmrTimerTick(PXTIMERSET pSet)      // in: timer set (from tmrCreateSet)
     440{
    370441    if (pSet && pSet->pvllXTimers)
    371442    {
     
    376447        PLISTNODE pTimerNode = lstQueryFirstNode(pllXTimers);
    377448
    378         // stop the PM timer for now; we'll restart it later
    379         WinStopTimer(pSet->hab,
    380                      pSet->hwndOwner,
    381                      pSet->idPMTimer);
    382         pSet->idPMTimerRunning = 0;
    383 
    384         if (pTimerNode)
     449        if (!pTimerNode)
     450        {
     451            // no timers left:
     452            if (pSet->idPMTimerRunning)
     453            {
     454                // but PM timer running:
     455                // stop it
     456                WinStopTimer(pSet->hab,
     457                             pSet->hwndOwner,
     458                             pSet->idPMTimer);
     459                pSet->idPMTimerRunning = 0;
     460            }
     461
     462            pSet->ulPMTimeout = 0;
     463        }
     464        else
    385465        {
    386466            // we have timers:
    387467            BOOL    fFoundInvalid = FALSE;
    388468
    389             ULONG   ulInterval = 100,
     469            ULONG   // ulInterval = 100,
    390470                    ulTimeNow = 0;
    391471
     
    432512                } // end if (pTimer->ulNextFire < ulTimeNow)
    433513
    434                 // adjust DosSleep interval
    435                 if (pTimer->ulTimeout < ulInterval)
    436                     ulInterval = pTimer->ulTimeout;
    437 
    438514                // next timer
    439515                pTimerNode = pTimerNode->pNext;
     
    452528                }
    453529                lstClear(&llInvalidTimers);
    454             }
    455 
    456             if (lstCountItems(pllXTimers))
    457             {
    458                 // any timers left:
    459                 // restart timer with the timeout calculated above
    460                 pSet->idPMTimerRunning = WinStartTimer(pSet->hab,
    461                                                        pSet->hwndOwner,
    462                                                        pSet->idPMTimer,
    463                                                        ulInterval);
    464                 /* _Pmpf(("  %d timers left, restarted PM timer == %d, interval %d",
    465                             lstCountItems(pllXTimers),
    466                             pSet->idPMTimerRunning,
    467                             ulInterval));
    468                 _Pmpf(("  pSet->hab: 0x%lX, hwndOwner = 0x%lX, usPMTimerID = %d",
    469                         pSet->hab,
    470                         pSet->hwndOwner,
    471                         pSet->idPMTimer)); */
     530
     531                AdjustPMTimer(pSet);
    472532            }
    473533        } // end else if (!pTimerNode)
    474534    }
    475 
    476     // _Pmpf((__FUNCTION__ ": leaving"));
    477535}
    478536
     
    496554 */
    497555
    498 USHORT XWPENTRY tmrStartXTimer(PXTIMERSET pSet,
    499                                HWND hwnd,
    500                                USHORT usTimerID,
    501                                ULONG ulTimeout)
     556USHORT XWPENTRY tmrStartXTimer(PXTIMERSET pSet, // in: timer set (from tmrCreateSet)
     557                               HWND hwnd,       // in: target window for XTimer
     558                               USHORT usTimerID, // in: timer ID for XTimer's WM_TIMER
     559                               ULONG ulTimeout) // in: XTimer's timeout
    502560{
    503561    USHORT  usrc = 0;
     
    525583                pTimer->ulNextFire = ulTimeNow + ulTimeout;
    526584                usrc = pTimer->usTimerID;
    527                 // _Pmpf(("  timer existed, reset"));
    528585            }
    529586            else
     
    544601                                  pTimer);
    545602                    usrc = pTimer->usTimerID;
    546 
    547                     // _Pmpf(("  new timer created"));
    548603                }
    549604            }
     
    552607            {
    553608                // timer created or reset:
    554                 // start main PM timer
    555                 pSet->idPMTimerRunning = WinStartTimer(pSet->hab,
    556                                                        pSet->hwndOwner,
    557                                                        pSet->idPMTimer,
    558                                                        100);
    559                 // _Pmpf(("  started PM timer %d", pSet->idPMTimerRunning));
     609                AdjustPMTimer(pSet);
    560610            }
    561611        } // if ((hwnd) && (ulTimeout))
     
    577627 */
    578628
    579 BOOL XWPENTRY tmrStopXTimer(PXTIMERSET pSet,
     629BOOL XWPENTRY tmrStopXTimer(PXTIMERSET pSet,    // in: timer set (from tmrCreateSet)
    580630                            HWND hwnd,
    581631                            USHORT usTimerID)
     
    593643        {
    594644            RemoveTimer(pSet, pTimer);
     645            // recalculate
     646            AdjustPMTimer(pSet);
    595647            brc = TRUE;
    596648        }
Note: See TracChangeset for help on using the changeset viewer.