⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 latency.c

📁 用于TM1300/PNX1300系列DSP(主要用于视频处理)的动态下载程序源码。
💻 C
字号:
/* NOTE: copied from latency sampling demo */


/*
 * Copyright (c) 1995,2000 TriMedia Technologies Inc.     
 *
 * +------------------------------------------------------------------+
 * | This software is furnished under a license and may only be used  |
 * | and copied in accordance with the terms and conditions of  such  |
 * | a license and with the inclusion of this copyright notice. This  |
 * | software or any other copies of this software may not be provided|
 * | or otherwise made available to any other person.  The ownership  |
 * | and title of this software is not transferred.                   |
 * |                                                                  |
 * | The information in this software is subject  to change without   |
 * | any  prior notice and should not be construed as a commitment by |
 * | TriMedia Technologies.                                           |
 * |                                                                  |
 * | this code and information is provided "as is" without any        |
 * | warranty of any kind, either expressed or implied, including but |
 * | not limited to the implied warranties of merchantability and/or  |
 * | fitness for any particular purpose.                              |
 * +------------------------------------------------------------------+
 *
 *  Module name              : latency.c    1.8
 *
 *  Last update              : 17:07:14 - 00/06/16
 *
 *  Description              :
 *
 *
 *  Revision                 :
 *        Built for the TCS 1.1 release
 *
 *
 *
 * Overview:
 * ========
 *
 * This is the source of a demonstration library which can be
 * linked against an application to sample its interrupt latencies.
 *
 * A 'latency' of an interrupt is the difference in time between the
 * moment at which the interrupt is asserted and the moment at which
 * its handler starts executing. Any (noticeable) latency is
 * caused by the application, by having disabled the particular
 * interrupt.
 *
 * Longer latencies in an application may be harmful, since they
 * reduce real time response. This may result in overrun errors
 * of input devices, in which captured data is lost because the
 * processor was notified to late to timely read it away and process
 * it; or it may result in output device underrun errors in which
 * no new output data has been made available in time because the
 * processor has been too slow in reacting on a previous device
 * notification.
 *
 * Depending on the characteristics of the application, either
 * a worst case, or the average case interrupt latency is the issue:
 * in a video application, an occasional `bad' latency might
 * temporarily reduce the video quality, which need not be a problem.
 * A disconnecting modem, even only occasionally, is next to
 * unusable.
 *
 *
 * Reasons for interrupt disabling:
 * ===============================
 *
 * Clearing the IEN:
 * ----------------
 *
 * Disabling of an interrupt may be achieved by clearing the IE bit in
 * the PCSW. Massively disabling all interrupts in this way, and
 * later enabling them again is the usual way to achieve without much
 * overhead a critical section in which a device, or global data
 * structure can be accessed without the danger of a task context
 * switch or a new intervening interrupt.
 * Two compiler- supported mechanisms provide an effect similar to
 * clearing the IEN bit:
 *
 * 1) Defining an interupt handler as a `TCS_handler` (in contrast to
 *    a `TCS_interruptible_handler`). The generated code for such a
 *    handler clears the IEN at the start, to be enabled at the end
 *    of the handler.
 * 2) Defining a function or handler as a 'TCS_atomic'. For these
 *    functions, the compiler will generate non-interruptible jumps
 *    (on the TM1, interrupts and exceptions are only served at
 *    'interruptible jumps).
 *    NOTE that explicit use of non-interruptible jumps in handcoded
 *         assembly also locks out interrupts.
 *
 * As a general rule, applications should not run with a cleared IEN
 * PCSW bit for more than 10 micro seconds. The IEN can be cleared,
 * set and restored by means of functions intClearIEN, intSetIEN and
 * intRestoreIEN from the tmInterrupts library.
 *
 * Changing the global interupt priority:
 * -------------------------------------
 *
 * Although less common, interrupt disabling can also be achieved by
 * raising the global interrupt priority to a value higher than the
 * interrupt priority. This mechanism is generally used in interrupt
 * handlers, to let serving not be disturbed by 'less urgent`
 * interrupts, while still allowing 'more urgent' ones. So while the
 * IEN is generally used to achieve atomicity, disabling based
 * on interrupt priority is used to (temporarily) allocate processor
 * cycles only to a certain minimal urgency. The global interrupt
 * priority can be modified by means of a call to intSetPriority
 * from the tmInterrupts library.
 *
 * Individual disabling:
 * --------------------
 *
 * Interrupts can also be individually disabled. For instance, using
 * a call to intInstanceSetup from the tmInterrupts library, interrupt
 * intVIDEOIN can be individually disabled; regardless of its priority,
 * and it has no effect on other interrupts.
 *
 *
 * Sampling method used:
 * ====================
 *
 * The latency sampler in this example records the interrupt latencies
 * of a periodic interrupt whose handler runs at interrupt priority 0.
 * Since it runs at the lowest interrupt priority, its latencies are
 * always larger than or equal to those of any other interrupt which
 * is not individually disabled. Because of this, the provided samples
 * can be considered as lower bounds of the latencies over all interrupts
 * which are not individually disabled; on the other hand, the samples
 * can *not* be used for obtaining any latency information of interrupts
 * which have been individually disabled.
 *
 * Sampling is timer based: a periodic interrupt is generated and
 * the difference between timer elapse and actual invokation
 * of its interrupt handler is measured and recorded. This means that
 * this sampler can only be used when at least one of the three TM1
 * timers is available for sample timing.
 * The samples themselves are recorded in an array of buckets of which
 * entry i contains the number of sampled latencies between i * 2^LOGS
 * and (i+1) * 2^LOGS for 0<(i<NROF_BUCKETS-1). Entry NROF_BUCKETS-1
 * contains the number of samples latencies larger than
 * (NROF_BUCKETS-1) * 2^LOGS.
 *
 *
 * Using the sampler:
 * =================
 *
 * Sampling must be started by calling function init_latency. This
 * function clears the bucket array, allocates a timer, and starts
 * sampling. Upon successful initialisation, it returns True, False
 * otherwise. Function term_latency stops sampling, frees the used timer,
 * and prints the contents of all non- empty buckets to the standard
 * output.
 *
 *
 * Detection of latency violators:
 * ==============================
 *
 * Upon any sampled latency larger than NROF_BUCKETS * 2^LOGS,
 * the function LATENCY_VIOLATOR_DETECTED is called. This can be
 * used to detect the part of the application which was responsible
 * for this long latency, by placing a breakpoint in this function
 * using tmdbg. When hitting this breakpoint, a stack traversal
 * will reveal the function which performed a too late interrupt
 * enable.
 *
 *
 *
 * Sample output:
 * =============
 *
 * A sample output after a PSOS benchmark which in a loop
 * invokes all pSOS functions to measure their performance
 * is as follows (NROF_BUCKETS= 1000, LOGS=4, SAMPLE_PERIOD=500,
 * host is Mac):
 *
 *      32 :     711
 *      48 :      29
 *      64 :      24
 *      80 :      20
 *      96 :      26
 *     112 :       8
 *     128 :       2
 *     144 :       2
 *     176 :       1
 *     192 :       1
 *     208 :       1
 *     288 :       1
 *     384 :       2
 *     496 :       1
 *     560 :       1
 *     720 :       1
 *     992 :       1
 *    1248 :       1
 *
 * On the 80MHz processor used, this meant that the maximal
 * latency measured was 15us, with an average latency below 1 us.
 *
 */

/*----------------------------- includes ------------------------------------*/

#include <tm1/tmTimers.h>
#include <tm1/tmTimersmmio.h>
#include <tm1/mmio.h>
#include <stdio.h>
#include <stdlib.h>

/*------------------------- local definitions -------------------------------*/

#define NROF_BUCKETS      1000    /* number of sample buckets               */
#define LOGS                 4    /* binary logarithm of sample bucket size */
#define SAMPLE_PERIOD     1000    /* cycles                                 */


static Int buckets[NROF_BUCKETS];
static Int  sample_timer;
static Int last_tick;

/*------------------------- utility functions -------------------------------*/



LATENCY_VIOLATOR_DETECTED()
{
    intClearIEN();

/* Place a breakpoint here */

    intSetIEN();
}



static void
sampler(void)
{
#pragma TCS_handler
    Int         now                 = cycles();
    Int         sample_timer_value  = timGetVALUE(sample_timer);
    Int         this_tick           = now - sample_timer_value;
    Int         latency             = now - last_tick - SAMPLE_PERIOD;
    Int         bucket_nr           = latency >> LOGS;

    last_tick = this_tick;

    if (bucket_nr >= NROF_BUCKETS) {
        buckets[NROF_BUCKETS - 1]++;
        LATENCY_VIOLATOR_DETECTED();
    }
    else if (bucket_nr < 0) {
        buckets[0]++;
    }
    else {
        buckets[bucket_nr]++;
    }
}





Bool
init_latency()
{
    timInstanceSetup_t setup;

    if (timOpen(&sample_timer) != TMLIBDEV_OK) {
        return False;
    }
    else {

        memset((Pointer) buckets, 0, sizeof (buckets));

        last_tick = cycles();

        setup.source     = timCLOCK;
        setup.prescale   = 1;
        setup.modulus    = SAMPLE_PERIOD;
        setup.running    = True;
        setup.handler    = sampler;
        setup.priority   = intPRIO_0;

        timInstanceSetup(sample_timer, &setup);

        return True;
    }
}


void
term_latency()
{
    Int        i;

    timClose(sample_timer);

    for (i = 0; i < NROF_BUCKETS; i++) {
        if (buckets[i]) {
            printf(" %7d : %7d\n", i << LOGS, buckets[i]);
        }
    }
}


#include "sys_conf.h"



main(Int argc, String argv[])
{
    Int         seconds = 10;

    if (argc == 2) {
        seconds = atoi(argv[1]);
    }
    else if (argc > 2) {
        printf("Usage: latency [ nrof_seconds ]\n");
        exit(-1);
    }

    if (!init_latency()) {
        printf("Error: no available timer for sampling.\n");
        exit(-1);
    }

    tm_wkafter(seconds * KC_TICKS2SEC);

    term_latency();

    exit(0);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -