/* * $Id$ * * :ts=4 * * Portable ISO 'C' (1994) runtime library for the Amiga computer * Copyright (c) 2002-2015 by Olaf Barthel * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Neither the name of Olaf Barthel nor the names of contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include static struct Interrupt CounterInt; static struct PerformanceMonitorIFace *IPM; static struct IntData { struct PerformanceMonitorIFace *IPM; uint16 *Buffer; uint32 BufferSize; uint32 Offset; uint32 Scale; uint32 CounterStart; } ProfileData; uint32 GetCounterStart(void); uint32 CounterIntFn(struct ExceptionContext *, struct ExecBase *, struct IntData *); uint32 GetCounterStart(void) { uint64 fsb; double bit0time; uint32 count; GetCPUInfoTags( GCIT_FrontsideSpeed, &fsb, TAG_DONE); /* Timebase ticks at 1/4 of FSB */ bit0time = 8.0 / (double)fsb; count = (uint32)(0.01 / bit0time); return 0x80000000 - count; } uint32 CounterIntFn(struct ExceptionContext *ctx, struct ExecBase *ExecBase, struct IntData *ProfileData) { uint32 sia = (uint32)ProfileData->IPM->GetSampledAddress(); /* Silence compiler */ (void)ExecBase; (void)ctx; sia = ((sia - ProfileData->Offset) * ProfileData->Scale) >> 16; if (sia <= (ProfileData->BufferSize>>1)) { //if (ProfileData->Buffer[sia] != 0xffff) ProfileData->Buffer[sia]++; } IPM->CounterControl(1, ProfileData->CounterStart, PMCI_Transition); return 1; } int profil(unsigned short *buffer, size_t bufSize, size_t offset, unsigned int scale) { APTR Stack; if (buffer == 0) { Stack = SuperState(); IPM->EventControlTags( PMECT_Disable, PMEC_MasterInterrupt, TAG_DONE); IPM->SetInterruptVector(1, 0); IPM->Unmark(0); IPM->Release(); if (Stack) UserState(Stack); return 0; } IPM = (struct PerformanceMonitorIFace *) OpenResource("performancemonitor.resource"); if (!IPM || IPM->Obtain() != 1) { return 0; } Stack = SuperState(); /* Init IntData */ ProfileData.IPM = IPM; ProfileData.Buffer = buffer; ProfileData.BufferSize = bufSize; ProfileData.Offset = offset; ProfileData.Scale = scale; ProfileData.CounterStart = GetCounterStart(); /* Set interrupt vector */ CounterInt.is_Code = (void (*)(void))CounterIntFn; CounterInt.is_Data = &ProfileData; IPM->SetInterruptVector(1, &CounterInt); /* Prepare Performance Monitor */ IPM->MonitorControlTags( PMMCT_FreezeCounters, PMMC_Unmarked, PMMCT_RTCBitSelect, PMMC_BIT0, TAG_DONE); IPM->CounterControl(1, ProfileData.CounterStart, PMCI_Transition); IPM->EventControlTags( PMECT_Enable, 1, PMECT_Enable, PMEC_MasterInterrupt, TAG_DONE); IPM->Mark(0); if (Stack) UserState(Stack); return 0; }