Annotation of kernel/bsd/dev/ppc/drvApple96_SCSI/Timestamp.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /*
                     26:        File:           Timestamp.c
                     27: 
                     28:     Contains:  Low-impact event timing function library
                     29: 
                     30:     Copyright: 1995-1997 by Apple Computer, Inc., all rights reserved.
                     31: 
                     32:     Version:   1.1
                     33: 
                     34:     Written by: Martin Minow
                     35: 
                     36:     Change History (most recent first):
                     37: 
                     38:         <1>    04/14/97    MM      Conversion for Rhapsody SCSI from Copland Timestamp.c;8.
                     39:         <2>    97.07.17    MM      Radar 1669061 Convert PPC tick to nanoseconds for vector return, too.
                     40: 
                     41: */
                     42: 
                     43: #define USE_RAW_PPC_CLOCK   1
                     44: 
                     45: #include "Timestamp.h"
                     46: #import <kernserv/prototypes.h>
                     47: #if USE_RAW_PPC_CLOCK
                     48: #include <machdep/ppc/powermac.h>
                     49: extern long long read_processor_clock(void);
                     50: #endif /* USE_RAW_PPC_CLOCK */
                     51: #ifndef FALSE
                     52: #define FALSE  0
                     53: #define TRUE   1
                     54: #endif
                     55: #ifndef NULL
                     56: #define NULL   0
                     57: #endif
                     58: 
                     59: /*
                     60:  * Values for the flags variable in the LogDataRecord. These are private to the
                     61:  * LogData library and dcmd display routine.
                     62:  */
                     63: enum {
                     64:     kTimestampEnabledMask      = (1L <<  0),   /* Enable logging if set            */
                     65:     kTimestampPreserveFirstMask = (1L <<  1),  /* Preserve first entry if set      */
                     66:     kTimestampWrapAroundMask   = (1L <<  2)    /* Record has wrapped around once   */
                     67: };
                     68: 
                     69: struct TimestampRecord {
                     70:     volatile UInt32    semaphore;          /* In critical section if non-zero      */
                     71:     volatile UInt32    lostLockCounter;    /* Can't enter critical section         */
                     72:     volatile UInt32    flags;              /* Logging & lost data flags            */
                     73:     volatile UInt32    entryPutIndex;      /* Where to store the next record       */
                     74:     volatile UInt32    entryGetIndex;      /* Where to retrieve the next record    */
                     75:     volatile UInt32    entryMaxIndex;      /* Actual number of log entries         */
                     76:     TimestampDataRecord entries[1];        /* Ring buffer of log entries           */
                     77: };
                     78: typedef struct TimestampRecord TimestampRecord, *TimestampRecordPtr;
                     79: 
                     80: 
                     81: 
                     82: #if 1  /* TEMP TEMP TEMP */
                     83: /*
                     84:  * Temporary atomic instruction implementations
                     85:  */
                     86: static inline SInt32 IncrementAtomicAligned(
                     87:                volatile SInt32         *theValue
                     88:     )
                     89: {
                     90:                SInt32                          result = *theValue;
                     91:                ++(*theValue);
                     92:                return (result);
                     93: }
                     94: static inline UInt32 BitAndAtomicAligned(
                     95:                UInt32                          theMask,
                     96:                volatile UInt32         *theValue
                     97:     )
                     98: {
                     99:                SInt32                          result = *theValue;
                    100:                *theValue &= theMask;
                    101:                return (result);
                    102: }
                    103: static inline Boolean CompareAndSwapAligned(
                    104:                UInt32                          oldValue,
                    105:                UInt32                          newValue,
                    106:                volatile UInt32         *theValue
                    107:     )
                    108: {
                    109:                if (oldValue != (*theValue)) {
                    110:                        return (FALSE);                 /* False */
                    111:                }
                    112:                else {
                    113:                        *theValue = newValue;
                    114:                        return (TRUE);
                    115:                }
                    116: }
                    117: 
                    118: #endif
                    119: 
                    120: typedef union TimestampTime {
                    121:     long               d[2];
                    122:     long long          ppcClock;
                    123:     ns_time_t          nsecTime;
                    124: } TimestampTime;
                    125: 
                    126: static void                                    StoreRawTimestamp(
                    127:        UInt32                  timestampTag,
                    128:                UInt32                                  timestampValue,
                    129:                const TimestampTime             *timestampTime
                    130:     );
                    131: 
                    132: #if TIMESTAMP
                    133: static TimestampRecordPtr                      gTimestampRecordPtr;
                    134: #define LOG (*gTimestampRecordPtr)
                    135: 
                    136: void
                    137: MakeTimestampRecord(
                    138:                UInt32                                  nEntries
                    139:     )
                    140: {
                    141:                UInt32                                  areaSize;
                    142:                UInt32                                  pageSize;
                    143: 
                    144:                if (gTimestampRecordPtr == NULL) {
                    145:                        areaSize = (nEntries * sizeof (TimestampDataRecord))
                    146:                                         + sizeof (TimestampRecord)
                    147:                                         - sizeof (TimestampDataRecord)
                    148:                                ;
                    149:                        /*
                    150:                         * Round up areaSize to a page size.
                    151:                         */
                    152:                        pageSize = 4096;
                    153:                        areaSize = (areaSize + pageSize - 1) & ~(pageSize - 1);
                    154:                        /*
                    155:                         * Recompute nEntries.
                    156:                         */
                    157:                        nEntries = (areaSize - sizeof (TimestampRecord))
                    158:                                         / sizeof (TimestampDataRecord);
                    159:                        nEntries += 1;
                    160:            gTimestampRecordPtr = (TimestampRecordPtr)  kalloc(areaSize);
                    161:                        if (gTimestampRecordPtr != NULL) {
                    162:                                LOG.entryMaxIndex = nEntries;
                    163:                                LOG.flags = ( (1 * kTimestampEnabledMask)               /* Enabled                      */
                    164:                            | (0 * kTimestampPreserveFirstMask) /* Save last        */
                    165:                                                        | (0 * kTimestampWrapAroundMask)        /* Always zero          */
                    166:                                                        );
                    167:                                LOG.entryPutIndex = 0;
                    168:                                LOG.entryGetIndex = 0;
                    169:                        } /* If we created the area */
                    170: #if 0  /* Temp for initial debugging */
                    171:                        {
                    172:                                int                             i;
                    173:                                TimestampTime   t;
                    174:                                TimestampTime   x;
                    175:                                for (i = 0; i < 10; i++) {
                    176:                                        t.ppcClock = read_processor_clock();
                    177:                                        x.ppcClock = t.ppcClock;
                    178:                                        x.ppcClock *= powermac_info.proc_clock_to_nsec_numerator;
                    179:                                        x.ppcClock /= powermac_info.proc_clock_to_nsec_denominator;
                    180:                                        IOLog("clock numerator %u, clock denominator %u, value %u %u -> %u %u\n", 
                    181:                                                powermac_info.proc_clock_to_nsec_numerator,
                    182:                                                powermac_info.proc_clock_to_nsec_denominator,
                    183:                                                t.d[0],
                    184:                                                t.d[1],
                    185:                                                x.d[0],
                    186:                                                x.d[1]
                    187:                                        );
                    188:                                }
                    189:                        }
                    190: #endif
                    191:                } /* gTimestampRecordPtr == NULL */
                    192: }
                    193: 
                    194: 
                    195: void
                    196: StoreNSecTimestamp(
                    197:        UInt32                  timestampTag,
                    198:                UInt32                                  timestampValue,
                    199:                ns_time_t                               timestampEvent
                    200:     )
                    201: {
                    202:                TimestampTime                   timestampTime;
                    203: 
                    204:                timestampTime.nsecTime = timestampEvent;
                    205: #if USE_RAW_PPC_CLOCK
                    206:                timestampTime.ppcClock *= powermac_info.proc_clock_to_nsec_denominator;
                    207:                timestampTime.ppcClock /= powermac_info.proc_clock_to_nsec_numerator;
                    208: #endif
                    209:                StoreRawTimestamp(
                    210:                        timestampTag,
                    211:                        timestampValue,
                    212:                        &timestampTime
                    213:                );
                    214: }
                    215: 
                    216: void
                    217: StoreTimestamp(
                    218:        UInt32                  timestampTag,
                    219:                UInt32                                  timestampValue
                    220:     )
                    221: {
                    222:                TimestampTime                   timestampTime;
                    223: #if USE_RAW_PPC_CLOCK
                    224:                timestampTime.ppcClock = read_processor_clock();
                    225: #else
                    226:                IOGetTimestamp(&timestampTime.nsecTime);
                    227: #endif
                    228:                StoreRawTimestamp(
                    229:                        timestampTag,
                    230:                        timestampValue,
                    231:                        &timestampTime
                    232:                );
                    233: }
                    234: 
                    235: static void
                    236: StoreRawTimestamp(
                    237:        UInt32                  timestampTag,
                    238:                UInt32                                  timestampValue,
                    239:                const TimestampTime             *timestampTime
                    240:     )
                    241: {
                    242:                UInt32                                  putIndex;
                    243:                UInt32                                  getIndex;
                    244:                TimestampDataPtr                entryPtr;
                    245: 
                    246:                if (gTimestampRecordPtr != NULL
                    247:                 && (LOG.flags & kTimestampEnabledMask) != 0) {
                    248:                        if (CompareAndSwapAligned(0, 1, (UInt32 *) &LOG.semaphore) == FALSE) {
                    249:                                IncrementAtomicAligned((volatile SInt32 *) &LOG.lostLockCounter);
                    250:                        }
                    251:            else {                                              /* Nope, we got it  */
                    252:                                /*
                    253:                                 * The ring buffer is designed so that put == get implies empty
                    254:                                 * and pointers are always incremented before use.
                    255:                                 */
                    256:                                putIndex = LOG.entryPutIndex + 1;
                    257:                                if (putIndex >= LOG.entryMaxIndex) {
                    258:                                        putIndex = 0;
                    259:                                        LOG.flags |= kTimestampWrapAroundMask;
                    260:                                }
                    261:                                if (putIndex == LOG.entryGetIndex) {            /* Did it fill?         */
                    262:                                        if ((LOG.flags & kTimestampPreserveFirstMask) != 0) {
                    263:                                                ;                                                                       /* Keeping first        */
                    264:                                        }
                    265:                                        else {
                    266:                                                /*
                    267:                                                 * We want to retain the latest entry. Do this by
                    268:                                                 * advancing the "get" pointer as if the earliest entry
                    269:                                                 * has been read. Then jump around the if bracket to store
                    270:                                                 * this datum.
                    271:                                                 */
                    272:                                                getIndex = LOG.entryGetIndex + 1;
                    273:                                                if (getIndex >= LOG.entryMaxIndex)
                    274:                                                        getIndex = 0;
                    275:                                                LOG.entryGetIndex = getIndex;
                    276:                                                goto storeDatum;
                    277:                                        }
                    278:                                }
                    279:                                else {
                    280: storeDatum:                    entryPtr = &LOG.entries[putIndex];
                    281:                                        LOG.entryPutIndex = putIndex;
                    282:                                        entryPtr->eventTime = timestampTime->nsecTime;
                    283:                                        entryPtr->timestampTag = timestampTag;
                    284:                                        entryPtr->timestampValue = timestampValue;
                    285:                                }
                    286:                LOG.semaphore = 0;                              /* Free semaphore   */
                    287:                        }
                    288:                }
                    289: }
                    290: 
                    291: /**
                    292:  * Returns the next timestamp, if any, in resultData.
                    293:  * @param   resultData     Where to store the data
                    294:  * @return  TRUE           Valid data returned
                    295:  *                     FALSE                   No data is available.
                    296:  */
                    297: Boolean
                    298: ReadTimestamp(
                    299:                TimestampDataPtr                resultData                              /* Result stored here           */
                    300:     )
                    301: {
                    302:                UInt32                                  getIndex;
                    303:                Boolean                                 result = FALSE;
                    304: 
                    305:                if (resultData != NULL && gTimestampRecordPtr != NULL) {
                    306:                        /*
                    307:                         * Try to grab the semaphore.
                    308:                         */
                    309:                        if (CompareAndSwapAligned(0, 1, (UInt32 *) &LOG.semaphore) == FALSE) {
                    310:                                IncrementAtomicAligned((volatile SInt32 *) &LOG.lostLockCounter);
                    311:                        }
                    312:                        else {                                                                                          /* Nope, we got it              */
                    313:                                getIndex = LOG.entryGetIndex;
                    314:                                if (getIndex != LOG.entryPutIndex) {                    /* Empty?                               */
                    315:                                        result = TRUE;                                                          /* No: get some data    */
                    316:                                        if (++getIndex >= LOG.entryMaxIndex)
                    317:                                                getIndex = 0;
                    318:                                        *resultData = LOG.entries[getIndex];
                    319:                                        LOG.entryGetIndex = getIndex;
                    320:                                }
                    321:                LOG.semaphore = 0;                              /* Free semaphore   */
                    322:                        }
                    323:                }
                    324: #if USE_RAW_PPC_CLOCK
                    325:                if (result) {
                    326:                        TimestampTime                   timestampTime;
                    327: 
                    328:                        timestampTime.nsecTime = resultData->eventTime;
                    329:                        timestampTime.ppcClock *= powermac_info.proc_clock_to_nsec_numerator;
                    330:                        timestampTime.ppcClock /= powermac_info.proc_clock_to_nsec_denominator;
                    331:                        resultData->eventTime = timestampTime.nsecTime;
                    332:                }
                    333: #endif
                    334:                return (result);
                    335: }
                    336: 
                    337: /**
                    338:  * Return a vector of timestamps.
                    339:  * @param   resultVector    Where to store the data
                    340:  * @param   count          On entrance, this has the maximum number of elements
                    341:  *                                                     to return. On exit, this will have the actual number
                    342:  *                                                     of elements that were returned.
                    343:  * Note that, if the semaphore is blocked, ReadTimestampVector will not return any
                    344:  * data. Data cannot be collected while ReadTimestampVector is copying data
                    345:  * to the user's buffer. Note that, since the user's buffer will typically be
                    346:  * in pageable memory, pageing I/O that might otherwise be timestamped will
                    347:  * be lost.
                    348:  */
                    349: void
                    350: ReadTimestampVector(
                    351:                TimestampDataPtr                resultVector,                   /* -> Result buffer                     */
                    352:        UInt32                  *count                  /* -> Max count, <-actual   */
                    353:     )
                    354: {
                    355:                UInt32                                  getIndex;
                    356:                UInt32                                  i;
                    357:                
                    358:                if (resultVector != NULL
                    359:                 && gTimestampRecordPtr != NULL
                    360:                 && count != NULL) {
                    361:                        i = 0;
                    362:                        if (CompareAndSwapAligned(0, 1, (UInt32 *) &LOG.semaphore) == FALSE) {
                    363:                                IncrementAtomicAligned((volatile SInt32 *) &LOG.lostLockCounter);
                    364:                        }
                    365:                        else {
                    366:                                getIndex = LOG.entryGetIndex;
                    367:                                for (; i < *count && getIndex != LOG.entryPutIndex; i++) {
                    368:                                        if (++getIndex >= LOG.entryMaxIndex)
                    369:                                                getIndex = 0;
                    370:                                        *resultVector = LOG.entries[getIndex];
                    371: #if USE_RAW_PPC_CLOCK
                    372:                                        resultVector->eventTime =
                    373:                                                (resultVector->eventTime * powermac_info.proc_clock_to_nsec_numerator)
                    374:                                                / powermac_info.proc_clock_to_nsec_denominator;
                    375: #endif
                    376:                                        resultVector++;
                    377:                                }
                    378:                                LOG.entryGetIndex = getIndex;
                    379:                                LOG.semaphore = 0;                                              /* Free semaphore                       */
                    380:                        }
                    381:                        *count = i;                                                                     /* Return actual count          */
                    382:                }
                    383: }
                    384: 
                    385: Boolean
                    386: EnableTimestamp(
                    387:                Boolean                                 enableTimestamp                 /* True to enable timestamp */
                    388:     )
                    389: {
                    390:                UInt32                                  newFlags;
                    391:                Boolean                                 timestampsWereEnabled;
                    392: 
                    393:                if (gTimestampRecordPtr == NULL) {
                    394:                        timestampsWereEnabled = FALSE;
                    395:                }
                    396:                else {
                    397:                        do {
                    398:                                timestampsWereEnabled = (LOG.flags & kTimestampEnabledMask) != 0;
                    399:                                if (enableTimestamp)
                    400:                                        newFlags = LOG.flags | kTimestampEnabledMask;
                    401:                                else {
                    402:                                        newFlags = LOG.flags & ~kTimestampEnabledMask;
                    403:                                }
                    404:                        } while (CompareAndSwapAligned(LOG.flags, newFlags, &LOG.flags) == FALSE);
                    405:                }
                    406:                return (timestampsWereEnabled);
                    407: }
                    408: 
                    409: Boolean
                    410: PreserveTimestamp(
                    411:        Boolean                 preserveFirst           /* TRUE to preserve start   */
                    412:     )
                    413: {
                    414:                UInt32                                  newFlags;
                    415:                Boolean                                 wasFirst;
                    416: 
                    417:                if (gTimestampRecordPtr == NULL) {
                    418:                        wasFirst = FALSE;
                    419:                }
                    420:                else {
                    421:                        do {
                    422:                                wasFirst = (LOG.flags & kTimestampPreserveFirstMask) != 0;
                    423:                                if (preserveFirst)
                    424:                                        newFlags = LOG.flags | kTimestampPreserveFirstMask;
                    425:                                else {
                    426:                                        newFlags = LOG.flags & kTimestampPreserveFirstMask;
                    427:                                }
                    428:                        } while (CompareAndSwapAligned(LOG.flags, newFlags, &LOG.flags) == FALSE);
                    429:                }
                    430:                return (wasFirst);
                    431: }
                    432: 
                    433: void
                    434: ResetTimestampIndex(void)
                    435: {
                    436:                if (gTimestampRecordPtr != NULL) {
                    437:                        BitAndAtomicAligned(0, &LOG.entryPutIndex);
                    438:                        BitAndAtomicAligned(0, &LOG.entryGetIndex);
                    439:                }
                    440: }
                    441: 
                    442: UInt32
                    443: GetTimestampSemaphoreLostCounter(void)
                    444: {
                    445:                UInt32                                  result;
                    446: 
                    447:                if (gTimestampRecordPtr == NULL) {
                    448:                        result = 0;
                    449:                }
                    450:                else {
                    451:                        do {
                    452:                                result = LOG.lostLockCounter;
                    453:                        } while (CompareAndSwapAligned(
                    454:                                        result, result, (UInt32 *) &LOG.lostLockCounter) == FALSE);
                    455:                }
                    456:                return (result);
                    457: }
                    458: #endif /* TIMESTAMP */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.