Annotation of kernel/bsd/dev/ppc/drvApple96_SCSI/Timestamp.c, revision 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.