+++ /dev/null
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-XML_H := $(shell cd $(LOCAL_PATH) && make events_xml.h defaults_xml.h)
-
-LOCAL_CFLAGS += -Wall -O3 -mthumb-interwork -fno-exceptions -DETCDIR=\"/etc\" -Ilibsensors
-
-LOCAL_SRC_FILES := \
- Buffer.cpp \
- CapturedXML.cpp \
- Child.cpp \
- ConfigurationXML.cpp \
- Driver.cpp \
- DriverSource.cpp \
- DynBuf.cpp \
- EventsXML.cpp \
- ExternalSource.cpp \
- Fifo.cpp \
- Hwmon.cpp \
- KMod.cpp \
- LocalCapture.cpp \
- Logging.cpp \
- main.cpp \
- Monitor.cpp \
- OlySocket.cpp \
- OlyUtility.cpp \
- PerfBuffer.cpp \
- PerfDriver.cpp \
- PerfGroup.cpp \
- PerfSource.cpp \
- Proc.cpp \
- Sender.cpp \
- SessionData.cpp \
- SessionXML.cpp \
- Source.cpp \
- StreamlineSetup.cpp \
- UEvent.cpp \
- UserSpaceSource.cpp \
- libsensors/access.c \
- libsensors/conf-lex.c \
- libsensors/conf-parse.c \
- libsensors/data.c \
- libsensors/error.c \
- libsensors/general.c \
- libsensors/init.c \
- libsensors/sysfs.c \
- mxml/mxml-attr.c \
- mxml/mxml-entity.c \
- mxml/mxml-file.c \
- mxml/mxml-get.c \
- mxml/mxml-index.c \
- mxml/mxml-node.c \
- mxml/mxml-private.c \
- mxml/mxml-search.c \
- mxml/mxml-set.c \
- mxml/mxml-string.c
-
-LOCAL_C_INCLUDES := $(LOCAL_PATH)
-
-LOCAL_MODULE := gatord
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_EXECUTABLE)
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "Buffer.h"
-
-#include "Logging.h"
-#include "Sender.h"
-#include "SessionData.h"
-
-#define mask (mSize - 1)
-
-enum {
- CODE_PEA = 1,
- CODE_KEYS = 2,
- CODE_FORMAT = 3,
- CODE_MAPS = 4,
- CODE_COMM = 5,
-};
-
-// Summary Frame Messages
-enum {
- MESSAGE_SUMMARY = 1,
- MESSAGE_CORE_NAME = 3,
-};
-
-// From gator_marshaling.c
-#define NEWLINE_CANARY \
- /* Unix */ \
- "1\n" \
- /* Windows */ \
- "2\r\n" \
- /* Mac OS */ \
- "3\r" \
- /* RISC OS */ \
- "4\n\r" \
- /* Add another character so the length isn't 0x0a bytes */ \
- "5"
-
-Buffer::Buffer(const int32_t core, const int32_t buftype, const int size, sem_t *const readerSem) : mCore(core), mBufType(buftype), mSize(size), mReadPos(0), mWritePos(0), mCommitPos(0), mAvailable(true), mIsDone(false), mBuf(new char[mSize]), mCommitTime(gSessionData->mLiveRate), mReaderSem(readerSem) {
- if ((mSize & mask) != 0) {
- logg->logError(__FILE__, __LINE__, "Buffer size is not a power of 2");
- handleException();
- }
- frame();
-}
-
-Buffer::~Buffer() {
- delete [] mBuf;
-}
-
-void Buffer::write(Sender *const sender) {
- if (!commitReady()) {
- return;
- }
-
- // determine the size of two halves
- int length1 = mCommitPos - mReadPos;
- char *buffer1 = mBuf + mReadPos;
- int length2 = 0;
- char *buffer2 = mBuf;
- if (length1 < 0) {
- length1 = mSize - mReadPos;
- length2 = mCommitPos;
- }
-
- logg->logMessage("Sending data length1: %i length2: %i", length1, length2);
-
- // start, middle or end
- if (length1 > 0) {
- sender->writeData(buffer1, length1, RESPONSE_APC_DATA);
- }
-
- // possible wrap around
- if (length2 > 0) {
- sender->writeData(buffer2, length2, RESPONSE_APC_DATA);
- }
-
- mReadPos = mCommitPos;
-}
-
-bool Buffer::commitReady() const {
- return mCommitPos != mReadPos;
-}
-
-int Buffer::bytesAvailable() const {
- int filled = mWritePos - mReadPos;
- if (filled < 0) {
- filled += mSize;
- }
-
- int remaining = mSize - filled;
-
- if (mAvailable) {
- // Give some extra room; also allows space to insert the overflow error packet
- remaining -= 200;
- } else {
- // Hysteresis, prevents multiple overflow messages
- remaining -= 2000;
- }
-
- return remaining;
-}
-
-bool Buffer::checkSpace(const int bytes) {
- const int remaining = bytesAvailable();
-
- if (remaining < bytes) {
- mAvailable = false;
- } else {
- mAvailable = true;
- }
-
- return mAvailable;
-}
-
-int Buffer::contiguousSpaceAvailable() const {
- int remaining = bytesAvailable();
- int contiguous = mSize - mWritePos;
- if (remaining < contiguous) {
- return remaining;
- } else {
- return contiguous;
- }
-}
-
-void Buffer::commit(const uint64_t time) {
- // post-populate the length, which does not include the response type length nor the length itself, i.e. only the length of the payload
- const int typeLength = gSessionData->mLocalCapture ? 0 : 1;
- int length = mWritePos - mCommitPos;
- if (length < 0) {
- length += mSize;
- }
- length = length - typeLength - sizeof(int32_t);
- for (size_t byte = 0; byte < sizeof(int32_t); byte++) {
- mBuf[(mCommitPos + typeLength + byte) & mask] = (length >> byte * 8) & 0xFF;
- }
-
- logg->logMessage("Committing data mReadPos: %i mWritePos: %i mCommitPos: %i", mReadPos, mWritePos, mCommitPos);
- mCommitPos = mWritePos;
-
- if (gSessionData->mLiveRate > 0) {
- while (time > mCommitTime) {
- mCommitTime += gSessionData->mLiveRate;
- }
- }
-
- if (!mIsDone) {
- frame();
- }
-
- // send a notification that data is ready
- sem_post(mReaderSem);
-}
-
-void Buffer::check(const uint64_t time) {
- int filled = mWritePos - mCommitPos;
- if (filled < 0) {
- filled += mSize;
- }
- if (filled >= ((mSize * 3) / 4) || (gSessionData->mLiveRate > 0 && time >= mCommitTime)) {
- commit(time);
- }
-}
-
-void Buffer::packInt(int32_t x) {
- int packedBytes = 0;
- int more = true;
- while (more) {
- // low order 7 bits of x
- char b = x & 0x7f;
- x >>= 7;
-
- if ((x == 0 && (b & 0x40) == 0) || (x == -1 && (b & 0x40) != 0)) {
- more = false;
- } else {
- b |= 0x80;
- }
-
- mBuf[(mWritePos + packedBytes) & mask] = b;
- packedBytes++;
- }
-
- mWritePos = (mWritePos + packedBytes) & mask;
-}
-
-void Buffer::packInt64(int64_t x) {
- int packedBytes = 0;
- int more = true;
- while (more) {
- // low order 7 bits of x
- char b = x & 0x7f;
- x >>= 7;
-
- if ((x == 0 && (b & 0x40) == 0) || (x == -1 && (b & 0x40) != 0)) {
- more = false;
- } else {
- b |= 0x80;
- }
-
- mBuf[(mWritePos + packedBytes) & mask] = b;
- packedBytes++;
- }
-
- mWritePos = (mWritePos + packedBytes) & mask;
-}
-
-void Buffer::writeBytes(const void *const data, size_t count) {
- size_t i;
- for (i = 0; i < count; ++i) {
- mBuf[(mWritePos + i) & mask] = static_cast<const char *>(data)[i];
- }
-
- mWritePos = (mWritePos + i) & mask;
-}
-
-void Buffer::writeString(const char *const str) {
- const int len = strlen(str);
- packInt(len);
- writeBytes(str, len);
-}
-
-void Buffer::frame() {
- if (!gSessionData->mLocalCapture) {
- packInt(RESPONSE_APC_DATA);
- }
- // Reserve space for the length
- mWritePos += sizeof(int32_t);
- packInt(mBufType);
- packInt(mCore);
-}
-
-void Buffer::summary(const int64_t timestamp, const int64_t uptime, const int64_t monotonicDelta, const char *const uname) {
- packInt(MESSAGE_SUMMARY);
- writeString(NEWLINE_CANARY);
- packInt64(timestamp);
- packInt64(uptime);
- packInt64(monotonicDelta);
- writeString("uname");
- writeString(uname);
- writeString("");
- check(1);
-}
-
-void Buffer::coreName(const int core, const int cpuid, const char *const name) {
- if (checkSpace(3 * MAXSIZE_PACK32 + 0x100)) {
- packInt(MESSAGE_CORE_NAME);
- packInt(core);
- packInt(cpuid);
- writeString(name);
- }
- check(1);
-}
-
-bool Buffer::eventHeader(const uint64_t curr_time) {
- bool retval = false;
- if (checkSpace(MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
- packInt(0); // key of zero indicates a timestamp
- packInt64(curr_time);
- retval = true;
- }
-
- return retval;
-}
-
-bool Buffer::eventTid(const int tid) {
- bool retval = false;
- if (checkSpace(2 * MAXSIZE_PACK32)) {
- packInt(1); // key of 1 indicates a tid
- packInt(tid);
- retval = true;
- }
-
- return retval;
-}
-
-void Buffer::event(const int32_t key, const int32_t value) {
- if (checkSpace(2 * MAXSIZE_PACK32)) {
- packInt(key);
- packInt(value);
- }
-}
-
-void Buffer::event64(const int64_t key, const int64_t value) {
- if (checkSpace(2 * MAXSIZE_PACK64)) {
- packInt64(key);
- packInt64(value);
- }
-}
-
-void Buffer::pea(const struct perf_event_attr *const pea, int key) {
- if (checkSpace(2 * MAXSIZE_PACK32 + pea->size)) {
- packInt(CODE_PEA);
- writeBytes(pea, pea->size);
- packInt(key);
- } else {
- logg->logError(__FILE__, __LINE__, "Ran out of buffer space for perf attrs");
- handleException();
- }
- // Don't know the real perf time so use 1 as it will work for now
- check(1);
-}
-
-void Buffer::keys(const int count, const __u64 *const ids, const int *const keys) {
- if (checkSpace(2 * MAXSIZE_PACK32 + count * (MAXSIZE_PACK32 + MAXSIZE_PACK64))) {
- packInt(CODE_KEYS);
- packInt(count);
- for (int i = 0; i < count; ++i) {
- packInt64(ids[i]);
- packInt(keys[i]);
- }
- } else {
- logg->logError(__FILE__, __LINE__, "Ran out of buffer space for perf attrs");
- handleException();
- }
- check(1);
-}
-
-void Buffer::format(const int length, const char *const format) {
- if (checkSpace(MAXSIZE_PACK32 + length + 1)) {
- packInt(CODE_FORMAT);
- writeBytes(format, length + 1);
- } else {
- logg->logError(__FILE__, __LINE__, "Ran out of buffer space for perf attrs");
- handleException();
- }
- check(1);
-}
-
-void Buffer::maps(const int pid, const int tid, const char *const maps) {
- const int mapsLen = strlen(maps) + 1;
- if (checkSpace(3 * MAXSIZE_PACK32 + mapsLen)) {
- packInt(CODE_MAPS);
- packInt(pid);
- packInt(tid);
- writeBytes(maps, mapsLen);
- } else {
- logg->logError(__FILE__, __LINE__, "Ran out of buffer space for perf attrs");
- handleException();
- }
- check(1);
-}
-
-void Buffer::comm(const int pid, const int tid, const char *const image, const char *const comm) {
- const int imageLen = strlen(image) + 1;
- const int commLen = strlen(comm) + 1;
- if (checkSpace(3 * MAXSIZE_PACK32 + imageLen + commLen)) {
- packInt(CODE_COMM);
- packInt(pid);
- packInt(tid);
- writeBytes(image, imageLen);
- writeBytes(comm, commLen);
- } else {
- logg->logError(__FILE__, __LINE__, "Ran out of buffer space for perf attrs");
- handleException();
- }
- check(1);
-}
-
-void Buffer::setDone() {
- mIsDone = true;
- commit(0);
-}
-
-bool Buffer::isDone() const {
- return mIsDone && mReadPos == mCommitPos && mCommitPos == mWritePos;
-}
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef BUFFER_H
-#define BUFFER_H
-
-#include <stdint.h>
-#include <semaphore.h>
-
-#include "k/perf_event.h"
-
-class Sender;
-
-enum {
- FRAME_SUMMARY = 1,
- FRAME_BLOCK_COUNTER = 5,
- FRAME_EXTERNAL = 10,
- FRAME_PERF_ATTRS = 11,
- FRAME_PERF = 12,
-};
-
-class Buffer {
-public:
- static const size_t MAXSIZE_PACK32 = 5;
- static const size_t MAXSIZE_PACK64 = 10;
-
- Buffer(int32_t core, int32_t buftype, const int size, sem_t *const readerSem);
- ~Buffer();
-
- void write(Sender *sender);
-
- int bytesAvailable() const;
- int contiguousSpaceAvailable() const;
- void commit(const uint64_t time);
- void check(const uint64_t time);
-
- void frame();
-
- // Summary messages
- void summary(const int64_t timestamp, const int64_t uptime, const int64_t monotonicDelta, const char *const uname);
- void coreName(const int core, const int cpuid, const char *const name);
-
- // Block Counter messages
- bool eventHeader(uint64_t curr_time);
- bool eventTid(int tid);
- void event(int32_t key, int32_t value);
- void event64(int64_t key, int64_t value);
-
- // Perf Attrs messages
- void pea(const struct perf_event_attr *const pea, int key);
- void keys(const int count, const __u64 *const ids, const int *const keys);
- void format(const int length, const char *const format);
- void maps(const int pid, const int tid, const char *const maps);
- void comm(const int pid, const int tid, const char *const image, const char *const comm);
-
- void setDone();
- bool isDone() const;
-
- // Prefer a new member to using these functions if possible
- char *getWritePos() { return mBuf + mWritePos; }
- void advanceWrite(int bytes) { mWritePos = (mWritePos + bytes) & /*mask*/(mSize - 1); }
-
- static void writeLEInt(unsigned char *buf, int v) {
- buf[0] = (v >> 0) & 0xFF;
- buf[1] = (v >> 8) & 0xFF;
- buf[2] = (v >> 16) & 0xFF;
- buf[3] = (v >> 24) & 0xFF;
- }
-
-private:
- bool commitReady() const;
- bool checkSpace(int bytes);
-
- void packInt(int32_t x);
- void packInt64(int64_t x);
- void writeBytes(const void *const data, size_t count);
- void writeString(const char *const str);
-
- const int32_t mCore;
- const int32_t mBufType;
- const int mSize;
- int mReadPos;
- int mWritePos;
- int mCommitPos;
- bool mAvailable;
- bool mIsDone;
- char *const mBuf;
- uint64_t mCommitTime;
- sem_t *const mReaderSem;
-
- // Intentionally unimplemented
- Buffer(const Buffer &);
- Buffer &operator=(const Buffer &);
-};
-
-#endif // BUFFER_H
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "CapturedXML.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <dirent.h>
-
-#include "SessionData.h"
-#include "Logging.h"
-#include "OlyUtility.h"
-
-CapturedXML::CapturedXML() {
-}
-
-CapturedXML::~CapturedXML() {
-}
-
-mxml_node_t* CapturedXML::getTree(bool includeTime) {
- mxml_node_t *xml;
- mxml_node_t *captured;
- mxml_node_t *target;
- int x;
-
- xml = mxmlNewXML("1.0");
-
- captured = mxmlNewElement(xml, "captured");
- mxmlElementSetAttr(captured, "version", "1");
- if (gSessionData->perf.isSetup()) {
- mxmlElementSetAttr(captured, "type", "Perf");
- }
- mxmlElementSetAttrf(captured, "protocol", "%d", PROTOCOL_VERSION);
- if (includeTime) { // Send the following only after the capture is complete
- if (time(NULL) > 1267000000) { // If the time is reasonable (after Feb 23, 2010)
- mxmlElementSetAttrf(captured, "created", "%lu", time(NULL)); // Valid until the year 2038
- }
- }
-
- target = mxmlNewElement(captured, "target");
- mxmlElementSetAttr(target, "name", gSessionData->mCoreName);
- mxmlElementSetAttrf(target, "sample_rate", "%d", gSessionData->mSampleRate);
- mxmlElementSetAttrf(target, "cores", "%d", gSessionData->mCores);
- mxmlElementSetAttrf(target, "cpuid", "0x%x", gSessionData->mMaxCpuId);
-
- if (!gSessionData->mOneShot && (gSessionData->mSampleRate > 0)) {
- mxmlElementSetAttr(target, "supports_live", "yes");
- }
-
- if (gSessionData->mLocalCapture) {
- mxmlElementSetAttr(target, "local_capture", "yes");
- }
-
- mxml_node_t *counters = NULL;
- for (x = 0; x < MAX_PERFORMANCE_COUNTERS; x++) {
- const Counter & counter = gSessionData->mCounters[x];
- if (counter.isEnabled()) {
- if (counters == NULL) {
- counters = mxmlNewElement(captured, "counters");
- }
- mxml_node_t *const node = mxmlNewElement(counters, "counter");
- mxmlElementSetAttrf(node, "key", "0x%x", counter.getKey());
- mxmlElementSetAttr(node, "type", counter.getType());
- mxmlElementSetAttrf(node, "event", "0x%x", counter.getEvent());
- if (counter.getCount() > 0) {
- mxmlElementSetAttrf(node, "count", "%d", counter.getCount());
- }
- }
- }
-
- return xml;
-}
-
-char* CapturedXML::getXML(bool includeTime) {
- char* xml_string;
- mxml_node_t *xml = getTree(includeTime);
- xml_string = mxmlSaveAllocString(xml, mxmlWhitespaceCB);
- mxmlDelete(xml);
- return xml_string;
-}
-
-void CapturedXML::write(char* path) {
- char file[PATH_MAX];
-
- // Set full path
- snprintf(file, PATH_MAX, "%s/captured.xml", path);
-
- char* xml = getXML(true);
- if (util->writeToDisk(file, xml) < 0) {
- logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify the path.", file);
- handleException();
- }
-
- free(xml);
-}
-
-// whitespace callback utility function used with mini-xml
-const char * mxmlWhitespaceCB(mxml_node_t *node, int loc) {
- const char *name;
-
- name = mxmlGetElement(node);
-
- if (loc == MXML_WS_BEFORE_OPEN) {
- // Single indentation
- if (!strcmp(name, "target") || !strcmp(name, "counters"))
- return("\n ");
-
- // Double indentation
- if (!strcmp(name, "counter"))
- return("\n ");
-
- // Avoid a carriage return on the first line of the xml file
- if (!strncmp(name, "?xml", 4))
- return(NULL);
-
- // Default - no indentation
- return("\n");
- }
-
- if (loc == MXML_WS_BEFORE_CLOSE) {
- // No indentation
- if (!strcmp(name, "captured"))
- return("\n");
-
- // Single indentation
- if (!strcmp(name, "counters"))
- return("\n ");
-
- // Default - no carriage return
- return(NULL);
- }
-
- return(NULL);
-}
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __CAPTURED_XML_H__
-#define __CAPTURED_XML_H__
-
-#include "mxml/mxml.h"
-
-class CapturedXML {
-public:
- CapturedXML();
- ~CapturedXML();
- char* getXML(bool includeTime); // the string should be freed by the caller
- void write(char* path);
-private:
- mxml_node_t* getTree(bool includeTime);
-};
-
-const char * mxmlWhitespaceCB(mxml_node_t *node, int where);
-
-#endif //__CAPTURED_XML_H__
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "Child.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <signal.h>
-#include <unistd.h>
-#include <sys/prctl.h>
-
-#include "Logging.h"
-#include "CapturedXML.h"
-#include "SessionData.h"
-#include "LocalCapture.h"
-#include "Sender.h"
-#include "OlyUtility.h"
-#include "OlySocket.h"
-#include "StreamlineSetup.h"
-#include "ConfigurationXML.h"
-#include "Driver.h"
-#include "PerfSource.h"
-#include "DriverSource.h"
-#include "UserSpaceSource.h"
-#include "ExternalSource.h"
-
-static sem_t haltPipeline, senderThreadStarted, startProfile, senderSem; // Shared by Child and spawned threads
-static Source *primarySource = NULL;
-static Source *userSpaceSource = NULL;
-static Source *externalSource = NULL;
-static Sender* sender = NULL; // Shared by Child.cpp and spawned threads
-Child* child = NULL; // shared by Child.cpp and main.cpp
-
-extern void cleanUp();
-void handleException() {
- if (child && child->numExceptions++ > 0) {
- // it is possible one of the below functions itself can cause an exception, thus allow only one exception
- logg->logMessage("Received multiple exceptions, terminating the child");
- exit(1);
- }
- fprintf(stderr, "%s", logg->getLastError());
-
- if (child && child->socket) {
- if (sender) {
- // send the error, regardless of the command sent by Streamline
- sender->writeData(logg->getLastError(), strlen(logg->getLastError()), RESPONSE_ERROR);
-
- // cannot close the socket before Streamline issues the command, so wait for the command before exiting
- if (gSessionData->mWaitingOnCommand) {
- char discard;
- child->socket->receiveNBytes(&discard, 1);
- }
-
- // Ensure all data is flushed
- child->socket->shutdownConnection();
-
- // this indirectly calls close socket which will ensure the data has been sent
- delete sender;
- }
- }
-
- if (gSessionData->mLocalCapture)
- cleanUp();
-
- exit(1);
-}
-
-// CTRL C Signal Handler for child process
-static void child_handler(int signum) {
- static bool beenHere = false;
- if (beenHere == true) {
- logg->logMessage("Gator is being forced to shut down.");
- exit(1);
- }
- beenHere = true;
- logg->logMessage("Gator is shutting down.");
- if (signum == SIGALRM || !primarySource) {
- exit(1);
- } else {
- child->endSession();
- alarm(5); // Safety net in case endSession does not complete within 5 seconds
- }
-}
-
-static void *durationThread(void *) {
- prctl(PR_SET_NAME, (unsigned long)&"gatord-duration", 0, 0, 0);
- sem_wait(&startProfile);
- if (gSessionData->mSessionIsActive) {
- // Time out after duration seconds
- // Add a second for host-side filtering
- sleep(gSessionData->mDuration + 1);
- if (gSessionData->mSessionIsActive) {
- logg->logMessage("Duration expired.");
- child->endSession();
- }
- }
- logg->logMessage("Exit duration thread");
- return 0;
-}
-
-static void *stopThread(void *) {
- OlySocket* socket = child->socket;
-
- prctl(PR_SET_NAME, (unsigned long)&"gatord-stopper", 0, 0, 0);
- while (gSessionData->mSessionIsActive) {
- // This thread will stall until the APC_STOP or PING command is received over the socket or the socket is disconnected
- unsigned char header[5];
- const int result = socket->receiveNBytes((char*)&header, sizeof(header));
- const char type = header[0];
- const int length = (header[1] << 0) | (header[2] << 8) | (header[3] << 16) | (header[4] << 24);
- if (result == -1) {
- child->endSession();
- } else if (result > 0) {
- if ((type != COMMAND_APC_STOP) && (type != COMMAND_PING)) {
- logg->logMessage("INVESTIGATE: Received unknown command type %d", type);
- } else {
- // verify a length of zero
- if (length == 0) {
- if (type == COMMAND_APC_STOP) {
- logg->logMessage("Stop command received.");
- child->endSession();
- } else {
- // Ping is used to make sure gator is alive and requires an ACK as the response
- logg->logMessage("Ping command received.");
- sender->writeData(NULL, 0, RESPONSE_ACK);
- }
- } else {
- logg->logMessage("INVESTIGATE: Received stop command but with length = %d", length);
- }
- }
- }
- }
-
- logg->logMessage("Exit stop thread");
- return 0;
-}
-
-static void *senderThread(void *) {
- char end_sequence[] = {RESPONSE_APC_DATA, 0, 0, 0, 0};
-
- sem_post(&senderThreadStarted);
- prctl(PR_SET_NAME, (unsigned long)&"gatord-sender", 0, 0, 0);
- sem_wait(&haltPipeline);
-
- while (!primarySource->isDone() || (userSpaceSource != NULL && !userSpaceSource->isDone()) || (externalSource != NULL && !externalSource->isDone())) {
- sem_wait(&senderSem);
-
- primarySource->write(sender);
- if (userSpaceSource != NULL) {
- userSpaceSource->write(sender);
- }
- if (externalSource != NULL) {
- externalSource->write(sender);
- }
- }
-
- // write end-of-capture sequence
- if (!gSessionData->mLocalCapture) {
- sender->writeData(end_sequence, sizeof(end_sequence), RESPONSE_APC_DATA);
- }
-
- logg->logMessage("Exit sender thread");
- return 0;
-}
-
-Child::Child() {
- initialization();
- gSessionData->mLocalCapture = true;
-}
-
-Child::Child(OlySocket* sock, int conn) {
- initialization();
- socket = sock;
- mNumConnections = conn;
-}
-
-Child::~Child() {
-}
-
-void Child::initialization() {
- // Set up different handlers for signals
- gSessionData->mSessionIsActive = true;
- signal(SIGINT, child_handler);
- signal(SIGTERM, child_handler);
- signal(SIGABRT, child_handler);
- signal(SIGALRM, child_handler);
- socket = NULL;
- numExceptions = 0;
- mNumConnections = 0;
-
- // Initialize semaphores
- sem_init(&senderThreadStarted, 0, 0);
- sem_init(&startProfile, 0, 0);
- sem_init(&senderSem, 0, 0);
-}
-
-void Child::endSession() {
- gSessionData->mSessionIsActive = false;
- primarySource->interrupt();
- sem_post(&haltPipeline);
-}
-
-void Child::run() {
- LocalCapture* localCapture = NULL;
- pthread_t durationThreadID, stopThreadID, senderThreadID;
-
- prctl(PR_SET_NAME, (unsigned long)&"gatord-child", 0, 0, 0);
-
- // Disable line wrapping when generating xml files; carriage returns and indentation to be added manually
- mxmlSetWrapMargin(0);
-
- // Instantiate the Sender - must be done first, after which error messages can be sent
- sender = new Sender(socket);
-
- if (mNumConnections > 1) {
- logg->logError(__FILE__, __LINE__, "Session already in progress");
- handleException();
- }
-
- // Populate gSessionData with the configuration
- { ConfigurationXML configuration; }
-
- // Set up the driver; must be done after gSessionData->mPerfCounterType[] is populated
- if (!gSessionData->perf.isSetup()) {
- primarySource = new DriverSource(&senderSem, &startProfile);
- } else {
- primarySource = new PerfSource(&senderSem, &startProfile);
- }
-
- // Initialize all drivers
- for (Driver *driver = Driver::getHead(); driver != NULL; driver = driver->getNext()) {
- driver->resetCounters();
- }
-
- // Set up counters using the associated driver's setup function
- for (int i = 0; i < MAX_PERFORMANCE_COUNTERS; i++) {
- Counter & counter = gSessionData->mCounters[i];
- if (counter.isEnabled()) {
- counter.getDriver()->setupCounter(counter);
- }
- }
-
- // Start up and parse session xml
- if (socket) {
- // Respond to Streamline requests
- StreamlineSetup ss(socket);
- } else {
- char* xmlString;
- xmlString = util->readFromDisk(gSessionData->mSessionXMLPath);
- if (xmlString == 0) {
- logg->logError(__FILE__, __LINE__, "Unable to read session xml file: %s", gSessionData->mSessionXMLPath);
- handleException();
- }
- gSessionData->parseSessionXML(xmlString);
- localCapture = new LocalCapture();
- localCapture->createAPCDirectory(gSessionData->mTargetPath);
- localCapture->copyImages(gSessionData->mImages);
- localCapture->write(xmlString);
- sender->createDataFile(gSessionData->mAPCDir);
- free(xmlString);
- }
-
- // Must be after session XML is parsed
- if (!primarySource->prepare()) {
- logg->logError(__FILE__, __LINE__, "Unable to prepare for capture");
- handleException();
- }
-
- // Sender thread shall be halted until it is signaled for one shot mode
- sem_init(&haltPipeline, 0, gSessionData->mOneShot ? 0 : 2);
-
- // Create the duration, stop, and sender threads
- bool thread_creation_success = true;
- if (gSessionData->mDuration > 0 && pthread_create(&durationThreadID, NULL, durationThread, NULL)) {
- thread_creation_success = false;
- } else if (socket && pthread_create(&stopThreadID, NULL, stopThread, NULL)) {
- thread_creation_success = false;
- } else if (pthread_create(&senderThreadID, NULL, senderThread, NULL)){
- thread_creation_success = false;
- }
-
- if (gSessionData->hwmon.countersEnabled()) {
- userSpaceSource = new UserSpaceSource(&senderSem);
- if (!userSpaceSource->prepare()) {
- logg->logError(__FILE__, __LINE__, "Unable to prepare for capture");
- handleException();
- }
- userSpaceSource->start();
- }
- if (access("/tmp/gator", F_OK) == 0) {
- externalSource = new ExternalSource(&senderSem);
- if (!externalSource->prepare()) {
- logg->logError(__FILE__, __LINE__, "Unable to prepare for capture");
- handleException();
- }
- externalSource->start();
- }
-
- if (!thread_creation_success) {
- logg->logError(__FILE__, __LINE__, "Failed to create gator threads");
- handleException();
- }
-
- // Wait until thread has started
- sem_wait(&senderThreadStarted);
-
- // Start profiling
- primarySource->run();
-
- if (externalSource != NULL) {
- externalSource->join();
- }
- if (userSpaceSource != NULL) {
- userSpaceSource->join();
- }
-
- // Wait for the other threads to exit
- pthread_join(senderThreadID, NULL);
-
- // Shutting down the connection should break the stop thread which is stalling on the socket recv() function
- if (socket) {
- logg->logMessage("Waiting on stop thread");
- socket->shutdownConnection();
- pthread_join(stopThreadID, NULL);
- }
-
- // Write the captured xml file
- if (gSessionData->mLocalCapture) {
- CapturedXML capturedXML;
- capturedXML.write(gSessionData->mAPCDir);
- }
-
- logg->logMessage("Profiling ended.");
-
- delete externalSource;
- delete userSpaceSource;
- delete primarySource;
- delete sender;
- delete localCapture;
-}
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __CHILD_H__
-#define __CHILD_H__
-
-class OlySocket;
-
-class Child {
-public:
- Child();
- Child(OlySocket* sock, int numConnections);
- ~Child();
- void run();
- OlySocket *socket;
- void endSession();
- int numExceptions;
-private:
- int mNumConnections;
-
- void initialization();
-
- // Intentionally unimplemented
- Child(const Child &);
- Child &operator=(const Child &);
-};
-
-#endif //__CHILD_H__
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef CONFIG_H
-#define CONFIG_H
-
-#define ARRAY_LENGTH(A) static_cast<int>(sizeof(A)/sizeof((A)[0]))
-
-#define MAX_PERFORMANCE_COUNTERS 50
-#define NR_CPUS 16
-
-#endif // CONFIG_H
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "ConfigurationXML.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <dirent.h>
-
-#include "Driver.h"
-#include "Logging.h"
-#include "OlyUtility.h"
-#include "SessionData.h"
-
-static const char* ATTR_COUNTER = "counter";
-static const char* ATTR_REVISION = "revision";
-static const char* ATTR_EVENT = "event";
-static const char* ATTR_COUNT = "count";
-
-ConfigurationXML::ConfigurationXML() {
- const char * configuration_xml;
- unsigned int configuration_xml_len;
- getDefaultConfigurationXml(configuration_xml, configuration_xml_len);
-
- char path[PATH_MAX];
-
- getPath(path);
- mConfigurationXML = util->readFromDisk(path);
-
- for (int retryCount = 0; retryCount < 2; ++retryCount) {
- if (mConfigurationXML == NULL) {
- logg->logMessage("Unable to locate configuration.xml, using default in binary");
- // null-terminate configuration_xml
- mConfigurationXML = (char*)malloc(configuration_xml_len + 1);
- memcpy(mConfigurationXML, (const void*)configuration_xml, configuration_xml_len);
- mConfigurationXML[configuration_xml_len] = 0;
- }
-
- int ret = parse(mConfigurationXML);
- if (ret == 1) {
- remove();
-
- // Free the current configuration and reload
- free((void*)mConfigurationXML);
- mConfigurationXML = NULL;
- continue;
- }
-
- break;
- }
-
- validate();
-}
-
-ConfigurationXML::~ConfigurationXML() {
- if (mConfigurationXML) {
- free((void*)mConfigurationXML);
- }
-}
-
-int ConfigurationXML::parse(const char* configurationXML) {
- mxml_node_t *tree, *node;
- int ret;
-
- // clear counter overflow
- gSessionData->mCounterOverflow = 0;
- gSessionData->mIsEBS = false;
- mIndex = 0;
-
- // disable all counters prior to parsing the configuration xml
- for (int i = 0; i < MAX_PERFORMANCE_COUNTERS; i++) {
- gSessionData->mCounters[i].setEnabled(false);
- }
-
- tree = mxmlLoadString(NULL, configurationXML, MXML_NO_CALLBACK);
-
- node = mxmlGetFirstChild(tree);
- while (node && mxmlGetType(node) != MXML_ELEMENT)
- node = mxmlWalkNext(node, tree, MXML_NO_DESCEND);
-
- ret = configurationsTag(node);
-
- node = mxmlGetFirstChild(node);
- while (node) {
- if (mxmlGetType(node) != MXML_ELEMENT) {
- node = mxmlWalkNext(node, tree, MXML_NO_DESCEND);
- continue;
- }
- configurationTag(node);
- node = mxmlWalkNext(node, tree, MXML_NO_DESCEND);
- }
-
- mxmlDelete(tree);
-
- return ret;
-}
-
-void ConfigurationXML::validate(void) {
- for (int i = 0; i < MAX_PERFORMANCE_COUNTERS; i++) {
- const Counter & counter = gSessionData->mCounters[i];
- if (counter.isEnabled()) {
- if (strcmp(counter.getType(), "") == 0) {
- logg->logError(__FILE__, __LINE__, "Invalid required attribute in configuration.xml:\n counter=\"%s\"\n event=%d\n", counter.getType(), counter.getEvent());
- handleException();
- }
-
- // iterate through the remaining enabled performance counters
- for (int j = i + 1; j < MAX_PERFORMANCE_COUNTERS; j++) {
- const Counter & counter2 = gSessionData->mCounters[j];
- if (counter2.isEnabled()) {
- // check if the types are the same
- if (strcmp(counter.getType(), counter2.getType()) == 0) {
- logg->logError(__FILE__, __LINE__, "Duplicate performance counter type in configuration.xml: %s", counter.getType());
- handleException();
- }
- }
- }
- }
- }
-}
-
-#define CONFIGURATION_REVISION 3
-int ConfigurationXML::configurationsTag(mxml_node_t *node) {
- const char* revision_string;
-
- revision_string = mxmlElementGetAttr(node, ATTR_REVISION);
- if (!revision_string) {
- return 1; //revision issue;
- }
-
- int revision = strtol(revision_string, NULL, 10);
- if (revision < CONFIGURATION_REVISION) {
- return 1; // revision issue
- }
-
- // A revision >= CONFIGURATION_REVISION is okay
- // Greater than can occur when Streamline is newer than gator
-
- return 0;
-}
-
-void ConfigurationXML::configurationTag(mxml_node_t *node) {
- // handle all other performance counters
- if (mIndex >= MAX_PERFORMANCE_COUNTERS) {
- mIndex++;
- gSessionData->mCounterOverflow = mIndex;
- return;
- }
-
- // read attributes
- Counter & counter = gSessionData->mCounters[mIndex];
- counter.clear();
- if (mxmlElementGetAttr(node, ATTR_COUNTER)) counter.setType(mxmlElementGetAttr(node, ATTR_COUNTER));
- if (mxmlElementGetAttr(node, ATTR_EVENT)) counter.setEvent(strtol(mxmlElementGetAttr(node, ATTR_EVENT), NULL, 16));
- if (mxmlElementGetAttr(node, ATTR_COUNT)) counter.setCount(strtol(mxmlElementGetAttr(node, ATTR_COUNT), NULL, 10));
- if (counter.getCount() > 0) {
- gSessionData->mIsEBS = true;
- }
- counter.setEnabled(true);
-
- // Associate a driver with each counter
- for (Driver *driver = Driver::getHead(); driver != NULL; driver = driver->getNext()) {
- if (driver->claimCounter(counter)) {
- if (counter.getDriver() != NULL) {
- logg->logError(__FILE__, __LINE__, "More than one driver has claimed %s:%i", counter.getType(), counter.getEvent());
- handleException();
- }
- counter.setDriver(driver);
- }
- }
-
- // If no driver is associated with the counter, disable it
- if (counter.getDriver() == NULL) {
- logg->logMessage("No driver has claimed %s:%i", counter.getType(), counter.getEvent());
- counter.setEnabled(false);
- }
-
- if (counter.isEnabled()) {
- // update counter index
- mIndex++;
- }
-}
-
-void ConfigurationXML::getDefaultConfigurationXml(const char * & xml, unsigned int & len) {
-#include "defaults_xml.h" // defines and initializes char defaults_xml[] and int defaults_xml_len
- xml = (const char *)defaults_xml;
- len = defaults_xml_len;
-}
-
-void ConfigurationXML::getPath(char* path) {
- if (gSessionData->mConfigurationXMLPath) {
- strncpy(path, gSessionData->mConfigurationXMLPath, PATH_MAX);
- } else {
- if (util->getApplicationFullPath(path, PATH_MAX) != 0) {
- logg->logMessage("Unable to determine the full path of gatord, the cwd will be used");
- }
- strncat(path, "configuration.xml", PATH_MAX - strlen(path) - 1);
- }
-}
-
-void ConfigurationXML::remove() {
- char path[PATH_MAX];
- getPath(path);
-
- if (::remove(path) != 0) {
- logg->logError(__FILE__, __LINE__, "Invalid configuration.xml file detected and unable to delete it. To resolve, delete configuration.xml on disk");
- handleException();
- }
- logg->logMessage("Invalid configuration.xml file detected and removed");
-}
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef COUNTERS_H
-#define COUNTERS_H
-
-#include "mxml/mxml.h"
-
-class ConfigurationXML {
-public:
- static void getDefaultConfigurationXml(const char * & xml, unsigned int & len);
- static void getPath(char* path);
- static void remove();
-
- ConfigurationXML();
- ~ConfigurationXML();
- const char* getConfigurationXML() {return mConfigurationXML;}
- void validate(void);
-
-private:
- char* mConfigurationXML;
- int mIndex;
-
- int parse(const char* xmlFile);
- int configurationsTag(mxml_node_t *node);
- void configurationTag(mxml_node_t *node);
-
- // Intentionally unimplemented
- ConfigurationXML(const ConfigurationXML &);
- ConfigurationXML &operator=(const ConfigurationXML &);
-};
-
-#endif // COUNTERS_H
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef COUNTER_H
-#define COUNTER_H
-
-#include <string.h>
-
-class Driver;
-
-class Counter {
-public:
- static const size_t MAX_STRING_LEN = 80;
- static const size_t MAX_DESCRIPTION_LEN = 400;
-
- Counter () {
- clear();
- }
-
- void clear () {
- mType[0] = '\0';
- mEnabled = false;
- mEvent = -1;
- mCount = 0;
- mKey = 0;
- mDriver = NULL;
- }
-
- void setType(const char *const type) { strncpy(mType, type, sizeof(mType)); mType[sizeof(mType) - 1] = '\0'; }
- void setEnabled(const bool enabled) { mEnabled = enabled; }
- void setEvent(const int event) { mEvent = event; }
- void setCount(const int count) { mCount = count; }
- void setKey(const int key) { mKey = key; }
- void setDriver(Driver *const driver) { mDriver = driver; }
-
- const char *getType() const { return mType;}
- bool isEnabled() const { return mEnabled; }
- int getEvent() const { return mEvent; }
- int getCount() const { return mCount; }
- int getKey() const { return mKey; }
- Driver *getDriver() const { return mDriver; }
-
-private:
- // Intentionally unimplemented
- Counter(const Counter &);
- Counter & operator=(const Counter &);
-
- char mType[MAX_STRING_LEN];
- bool mEnabled;
- int mEvent;
- int mCount;
- int mKey;
- Driver *mDriver;
-};
-
-#endif // COUNTER_H
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "Driver.h"
-
-Driver *Driver::head = NULL;
-
-Driver::Driver() : next(head) {
- head = this;
-}
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef DRIVER_H
-#define DRIVER_H
-
-#include "mxml/mxml.h"
-
-class Counter;
-
-class Driver {
-public:
- static Driver *getHead() { return head; }
-
- virtual ~Driver() {}
-
- // Returns true if this driver can manage the counter
- virtual bool claimCounter(const Counter &counter) const = 0;
- // Clears and disables all counters
- virtual void resetCounters() = 0;
- // Enables and prepares the counter for capture
- virtual void setupCounter(Counter &counter) = 0;
-
- // Emits available counters
- virtual int writeCounters(mxml_node_t *root) const = 0;
- // Emits possible dynamically generated events/counters
- virtual void writeEvents(mxml_node_t *) const {}
-
- Driver *getNext() const { return next; }
-
-protected:
- Driver ();
-
-private:
- static Driver *head;
- Driver *next;
-
- // Intentionally unimplemented
- Driver(const Driver &);
- Driver &operator=(const Driver &);
-};
-
-#endif // DRIVER_H
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#define __STDC_FORMAT_MACROS
-
-#include "DriverSource.h"
-
-#include <fcntl.h>
-#include <inttypes.h>
-#include <unistd.h>
-
-#include "Child.h"
-#include "Fifo.h"
-#include "Logging.h"
-#include "Sender.h"
-#include "SessionData.h"
-
-extern Child *child;
-
-DriverSource::DriverSource(sem_t *senderSem, sem_t *startProfile) : mFifo(NULL), mSenderSem(senderSem), mStartProfile(startProfile), mBufferSize(0), mBufferFD(0), mLength(1) {
- int driver_version = 0;
-
- if (readIntDriver("/dev/gator/version", &driver_version) == -1) {
- logg->logError(__FILE__, __LINE__, "Error reading gator driver version");
- handleException();
- }
-
- // Verify the driver version matches the daemon version
- if (driver_version != PROTOCOL_VERSION) {
- if ((driver_version > PROTOCOL_DEV) || (PROTOCOL_VERSION > PROTOCOL_DEV)) {
- // One of the mismatched versions is development version
- logg->logError(__FILE__, __LINE__,
- "DEVELOPMENT BUILD MISMATCH: gator driver version \"%d\" is not in sync with gator daemon version \"%d\".\n"
- ">> The following must be synchronized from engineering repository:\n"
- ">> * gator driver\n"
- ">> * gator daemon\n"
- ">> * Streamline", driver_version, PROTOCOL_VERSION);
- handleException();
- } else {
- // Release version mismatch
- logg->logError(__FILE__, __LINE__,
- "gator driver version \"%d\" is different than gator daemon version \"%d\".\n"
- ">> Please upgrade the driver and daemon to the latest versions.", driver_version, PROTOCOL_VERSION);
- handleException();
- }
- }
-
- int enable = -1;
- if (readIntDriver("/dev/gator/enable", &enable) != 0 || enable != 0) {
- logg->logError(__FILE__, __LINE__, "Driver already enabled, possibly a session is already in progress.");
- handleException();
- }
-
- readIntDriver("/dev/gator/cpu_cores", &gSessionData->mCores);
- if (gSessionData->mCores == 0) {
- gSessionData->mCores = 1;
- }
-
- if (readIntDriver("/dev/gator/buffer_size", &mBufferSize) || mBufferSize <= 0) {
- logg->logError(__FILE__, __LINE__, "Unable to read the driver buffer size");
- handleException();
- }
-}
-
-DriverSource::~DriverSource() {
- delete mFifo;
-
- // Write zero for safety, as a zero should have already been written
- writeDriver("/dev/gator/enable", "0");
-
- // Calls event_buffer_release in the driver
- if (mBufferFD) {
- close(mBufferFD);
- }
-}
-
-bool DriverSource::prepare() {
- // Create user-space buffers, add 5 to the size to account for the 1-byte type and 4-byte length
- logg->logMessage("Created %d MB collector buffer with a %d-byte ragged end", gSessionData->mTotalBufferSize, mBufferSize);
- mFifo = new Fifo(mBufferSize + 5, gSessionData->mTotalBufferSize*1024*1024, mSenderSem);
-
- return true;
-}
-
-void DriverSource::run() {
- // Get the initial pointer to the collect buffer
- char *collectBuffer = mFifo->start();
- int bytesCollected = 0;
-
- logg->logMessage("********** Profiling started **********");
-
- // Set the maximum backtrace depth
- if (writeReadDriver("/dev/gator/backtrace_depth", &gSessionData->mBacktraceDepth)) {
- logg->logError(__FILE__, __LINE__, "Unable to set the driver backtrace depth");
- handleException();
- }
-
- // open the buffer which calls userspace_buffer_open() in the driver
- mBufferFD = open("/dev/gator/buffer", O_RDONLY);
- if (mBufferFD < 0) {
- logg->logError(__FILE__, __LINE__, "The gator driver did not set up properly. Please view the linux console or dmesg log for more information on the failure.");
- handleException();
- }
-
- // set the tick rate of the profiling timer
- if (writeReadDriver("/dev/gator/tick", &gSessionData->mSampleRate) != 0) {
- logg->logError(__FILE__, __LINE__, "Unable to set the driver tick");
- handleException();
- }
-
- // notify the kernel of the response type
- int response_type = gSessionData->mLocalCapture ? 0 : RESPONSE_APC_DATA;
- if (writeDriver("/dev/gator/response_type", response_type)) {
- logg->logError(__FILE__, __LINE__, "Unable to write the response type");
- handleException();
- }
-
- // Set the live rate
- if (writeReadDriver("/dev/gator/live_rate", &gSessionData->mLiveRate)) {
- logg->logError(__FILE__, __LINE__, "Unable to set the driver live rate");
- handleException();
- }
-
- logg->logMessage("Start the driver");
-
- // This command makes the driver start profiling by calling gator_op_start() in the driver
- if (writeDriver("/dev/gator/enable", "1") != 0) {
- logg->logError(__FILE__, __LINE__, "The gator driver did not start properly. Please view the linux console or dmesg log for more information on the failure.");
- handleException();
- }
-
- lseek(mBufferFD, 0, SEEK_SET);
-
- sem_post(mStartProfile);
-
- // Collect Data
- do {
- // This command will stall until data is received from the driver
- // Calls event_buffer_read in the driver
- errno = 0;
- bytesCollected = read(mBufferFD, collectBuffer, mBufferSize);
-
- // If read() returned due to an interrupt signal, re-read to obtain the last bit of collected data
- if (bytesCollected == -1 && errno == EINTR) {
- bytesCollected = read(mBufferFD, collectBuffer, mBufferSize);
- }
-
- // return the total bytes written
- logg->logMessage("Driver read of %d bytes", bytesCollected);
-
- // In one shot mode, stop collection once all the buffers are filled
- if (gSessionData->mOneShot && gSessionData->mSessionIsActive) {
- if (bytesCollected == -1 || mFifo->willFill(bytesCollected)) {
- logg->logMessage("One shot");
- child->endSession();
- }
- }
- collectBuffer = mFifo->write(bytesCollected);
- } while (bytesCollected > 0);
-
- logg->logMessage("Exit collect data loop");
-}
-
-void DriverSource::interrupt() {
- // This command should cause the read() function in collect() to return and stop the driver from profiling
- if (writeDriver("/dev/gator/enable", "0") != 0) {
- logg->logMessage("Stopping kernel failed");
- }
-}
-
-bool DriverSource::isDone() {
- return mLength <= 0;
-}
-
-void DriverSource::write(Sender *sender) {
- char *data = mFifo->read(&mLength);
- if (data != NULL) {
- sender->writeData(data, mLength, RESPONSE_APC_DATA);
- mFifo->release();
- }
-}
-
-int DriverSource::readIntDriver(const char *fullpath, int *value) {
- char data[40]; // Sufficiently large to hold any integer
- const int fd = open(fullpath, O_RDONLY);
- if (fd < 0) {
- return -1;
- }
-
- const ssize_t bytes = read(fd, data, sizeof(data) - 1);
- close(fd);
- if (bytes < 0) {
- return -1;
- }
- data[bytes] = '\0';
-
- char *endptr;
- errno = 0;
- *value = strtol(data, &endptr, 10);
- if (errno != 0 || *endptr != '\n') {
- logg->logMessage("Invalid value in file %s", fullpath);
- return -1;
- }
-
- return 0;
-}
-
-int DriverSource::readInt64Driver(const char *fullpath, int64_t *value) {
- char data[40]; // Sufficiently large to hold any integer
- const int fd = open(fullpath, O_RDONLY);
- if (fd < 0) {
- return -1;
- }
-
- const ssize_t bytes = read(fd, data, sizeof(data) - 1);
- close(fd);
- if (bytes < 0) {
- return -1;
- }
- data[bytes] = '\0';
-
- char *endptr;
- errno = 0;
- *value = strtoll(data, &endptr, 10);
- if (errno != 0 || *endptr != '\n') {
- logg->logMessage("Invalid value in file %s", fullpath);
- return -1;
- }
-
- return 0;
-}
-
-int DriverSource::writeDriver(const char *fullpath, const char *data) {
- int fd = open(fullpath, O_WRONLY);
- if (fd < 0) {
- return -1;
- }
- if (::write(fd, data, strlen(data)) < 0) {
- close(fd);
- logg->logMessage("Opened but could not write to %s", fullpath);
- return -1;
- }
- close(fd);
- return 0;
-}
-
-int DriverSource::writeDriver(const char *path, int value) {
- char data[40]; // Sufficiently large to hold any integer
- snprintf(data, sizeof(data), "%d", value);
- return writeDriver(path, data);
-}
-
-int DriverSource::writeDriver(const char *path, int64_t value) {
- char data[40]; // Sufficiently large to hold any integer
- snprintf(data, sizeof(data), "%" PRIi64, value);
- return writeDriver(path, data);
-}
-
-int DriverSource::writeReadDriver(const char *path, int *value) {
- if (writeDriver(path, *value) || readIntDriver(path, value)) {
- return -1;
- }
- return 0;
-}
-
-int DriverSource::writeReadDriver(const char *path, int64_t *value) {
- if (writeDriver(path, *value) || readInt64Driver(path, value)) {
- return -1;
- }
- return 0;
-}
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef DRIVERSOURCE_H
-#define DRIVERSOURCE_H
-
-#include <semaphore.h>
-#include <stdint.h>
-
-#include "Source.h"
-
-class Fifo;
-
-class DriverSource : public Source {
-public:
- DriverSource(sem_t *senderSem, sem_t *startProfile);
- ~DriverSource();
-
- bool prepare();
- void run();
- void interrupt();
-
- bool isDone();
- void write(Sender *sender);
-
- static int readIntDriver(const char *fullpath, int *value);
- static int readInt64Driver(const char *fullpath, int64_t *value);
- static int writeDriver(const char *fullpath, const char *data);
- static int writeDriver(const char *path, int value);
- static int writeDriver(const char *path, int64_t value);
- static int writeReadDriver(const char *path, int *value);
- static int writeReadDriver(const char *path, int64_t *value);
-
-private:
- Fifo *mFifo;
- sem_t *const mSenderSem;
- sem_t *const mStartProfile;
- int mBufferSize;
- int mBufferFD;
- int mLength;
-
- // Intentionally unimplemented
- DriverSource(const DriverSource &);
- DriverSource &operator=(const DriverSource &);
-};
-
-#endif // DRIVERSOURCE_H
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "DynBuf.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include "Logging.h"
-
-// Pick an aggressive size as buffer is primarily used for disk IO
-#define MIN_BUFFER_FREE (1 << 12)
-
-int DynBuf::resize(const size_t minCapacity) {
- size_t scaledCapacity = 2 * capacity;
- if (scaledCapacity < minCapacity) {
- scaledCapacity = minCapacity;
- }
- if (scaledCapacity < 2 * MIN_BUFFER_FREE) {
- scaledCapacity = 2 * MIN_BUFFER_FREE;
- }
- capacity = scaledCapacity;
-
- buf = static_cast<char *>(realloc(buf, capacity));
- if (buf == NULL) {
- return -errno;
- }
-
- return 0;
-}
-
-bool DynBuf::read(const char *const path) {
- int result = false;
-
- const int fd = open(path, O_RDONLY);
- if (fd < 0) {
- logg->logMessage("%s(%s:%i): open failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
-
- length = 0;
-
- for (;;) {
- const size_t minCapacity = length + MIN_BUFFER_FREE + 1;
- if (capacity < minCapacity) {
- if (resize(minCapacity) != 0) {
- logg->logMessage("%s(%s:%i): DynBuf::resize failed", __FUNCTION__, __FILE__, __LINE__);
- goto fail;
- }
- }
-
- const ssize_t bytes = ::read(fd, buf + length, capacity - length - 1);
- if (bytes < 0) {
- logg->logMessage("%s(%s:%i): read failed", __FUNCTION__, __FILE__, __LINE__);
- goto fail;
- } else if (bytes == 0) {
- break;
- }
- length += bytes;
- }
-
- buf[length] = '\0';
- result = true;
-
- fail:
- close(fd);
-
- return result;
-}
-
-int DynBuf::readlink(const char *const path) {
- ssize_t bytes = MIN_BUFFER_FREE;
-
- for (;;) {
- if (static_cast<size_t>(bytes) >= capacity) {
- const int err = resize(2 * bytes);
- if (err != 0) {
- return err;
- }
- }
- bytes = ::readlink(path, buf, capacity);
- if (bytes < 0) {
- return -errno;
- } else if (static_cast<size_t>(bytes) < capacity) {
- break;
- }
- }
-
- length = bytes;
- buf[bytes] = '\0';
-
- return 0;
-}
-
-bool DynBuf::printf(const char *format, ...) {
- va_list ap;
-
- if (capacity <= 0) {
- if (resize(2 * MIN_BUFFER_FREE) != 0) {
- logg->logMessage("%s(%s:%i): DynBuf::resize failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
- }
-
- va_start(ap, format);
- int bytes = vsnprintf(buf, capacity, format, ap);
- va_end(ap);
- if (bytes < 0) {
- logg->logMessage("%s(%s:%i): fsnprintf failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
-
- if (static_cast<size_t>(bytes) > capacity) {
- if (resize(bytes + 1) != 0) {
- logg->logMessage("%s(%s:%i): DynBuf::resize failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
-
- va_start(ap, format);
- bytes = vsnprintf(buf, capacity, format, ap);
- va_end(ap);
- if (bytes < 0) {
- logg->logMessage("%s(%s:%i): fsnprintf failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
- }
-
- length = bytes;
-
- return true;
-}
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef DYNBUF_H
-#define DYNBUF_H
-
-#include <stdlib.h>
-
-class DynBuf {
-public:
- DynBuf() : capacity(0), length(0), buf(NULL) {}
- ~DynBuf() {
- reset();
- }
-
- inline void reset() {
- capacity = 0;
- length = 0;
- if (buf != NULL) {
- free(buf);
- buf = NULL;
- }
- }
-
- bool read(const char *const path);
- // On error instead of printing the error and returning false, this returns -errno
- int readlink(const char *const path);
- __attribute__ ((format(printf, 2, 3)))
- bool printf(const char *format, ...);
-
- size_t getLength() const { return length; }
- const char *getBuf() const { return buf; }
- char *getBuf() { return buf; }
-
-private:
- int resize(const size_t minCapacity);
-
- size_t capacity;
- size_t length;
- char *buf;
-
- // Intentionally undefined
- DynBuf(const DynBuf &);
- DynBuf &operator=(const DynBuf &);
-};
-
-#endif // DYNBUF_H
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "EventsXML.h"
-
-#include "CapturedXML.h"
-#include "Logging.h"
-#include "OlyUtility.h"
-#include "SessionData.h"
-
-char* EventsXML::getXML() {
-#include "events_xml.h" // defines and initializes char events_xml[] and int events_xml_len
- char path[PATH_MAX];
- mxml_node_t *xml;
- FILE *fl;
-
- // Avoid unused variable warning
- (void)events_xml_len;
-
- // Load the provided or default events xml
- if (gSessionData->mEventsXMLPath) {
- strncpy(path, gSessionData->mEventsXMLPath, PATH_MAX);
- } else {
- util->getApplicationFullPath(path, PATH_MAX);
- strncat(path, "events.xml", PATH_MAX - strlen(path) - 1);
- }
- fl = fopen(path, "r");
- if (fl) {
- xml = mxmlLoadFile(NULL, fl, MXML_NO_CALLBACK);
- fclose(fl);
- } else {
- logg->logMessage("Unable to locate events.xml, using default");
- xml = mxmlLoadString(NULL, (const char *)events_xml, MXML_NO_CALLBACK);
- }
-
- // Add dynamic events from the drivers
- mxml_node_t *events = mxmlFindElement(xml, xml, "events", NULL, NULL, MXML_DESCEND);
- if (!events) {
- logg->logMessage("Unable to find <events> node in the events.xml");
- handleException();
- }
- for (Driver *driver = Driver::getHead(); driver != NULL; driver = driver->getNext()) {
- driver->writeEvents(events);
- }
-
- char* string = mxmlSaveAllocString(xml, mxmlWhitespaceCB);
- mxmlDelete(xml);
-
- return string;
-}
-
-void EventsXML::write(const char* path) {
- char file[PATH_MAX];
-
- // Set full path
- snprintf(file, PATH_MAX, "%s/events.xml", path);
-
- char* buf = getXML();
- if (util->writeToDisk(file, buf) < 0) {
- logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify the path.", file);
- handleException();
- }
-
- free(buf);
-}
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef EVENTS_XML
-#define EVENTS_XML
-
-class EventsXML {
-public:
- char* getXML();
- void write(const char* path);
-};
-
-#endif // EVENTS_XML
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "ExternalSource.h"
-
-#include <sys/prctl.h>
-
-#include "Logging.h"
-#include "OlySocket.h"
-#include "SessionData.h"
-
-ExternalSource::ExternalSource(sem_t *senderSem) : mBuffer(0, FRAME_EXTERNAL, 1024, senderSem), mSock("/tmp/gator") {
-}
-
-ExternalSource::~ExternalSource() {
-}
-
-bool ExternalSource::prepare() {
- return true;
-}
-
-void ExternalSource::run() {
- prctl(PR_SET_NAME, (unsigned long)&"gatord-uds", 0, 0, 0);
-
- while (gSessionData->mSessionIsActive) {
- // Will be aborted when the socket is closed at the end of the capture
- int length = mSock.receive(mBuffer.getWritePos(), mBuffer.contiguousSpaceAvailable());
- if (length <= 0) {
- break;
- }
-
- mBuffer.advanceWrite(length);
- mBuffer.check(0);
- }
-
- mBuffer.setDone();
-}
-
-void ExternalSource::interrupt() {
- // Do nothing
-}
-
-bool ExternalSource::isDone() {
- return mBuffer.isDone();
-}
-
-void ExternalSource::write(Sender *sender) {
- if (!mBuffer.isDone()) {
- mBuffer.write(sender);
- }
-}
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef EXTERNALSOURCE_H
-#define EXTERNALSOURCE_H
-
-#include <semaphore.h>
-
-#include "Buffer.h"
-#include "OlySocket.h"
-#include "Source.h"
-
-// Unix domain socket counters from external sources like graphics drivers
-class ExternalSource : public Source {
-public:
- ExternalSource(sem_t *senderSem);
- ~ExternalSource();
-
- bool prepare();
- void run();
- void interrupt();
-
- bool isDone();
- void write(Sender *sender);
-
-private:
- Buffer mBuffer;
- OlySocket mSock;
-
- // Intentionally unimplemented
- ExternalSource(const ExternalSource &);
- ExternalSource &operator=(const ExternalSource &);
-};
-
-#endif // EXTERNALSOURCE_H
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "Fifo.h"
-
-#include <stdlib.h>
-#ifdef WIN32
-#define valloc malloc
-#endif
-
-#include "Logging.h"
-
-// bufferSize is the amount of data to be filled
-// singleBufferSize is the maximum size that may be filled during a single write
-// (bufferSize + singleBufferSize) will be allocated
-Fifo::Fifo(int singleBufferSize, int bufferSize, sem_t* readerSem) {
- mWrite = mRead = mReadCommit = mRaggedEnd = 0;
- mWrapThreshold = bufferSize;
- mSingleBufferSize = singleBufferSize;
- mReaderSem = readerSem;
- mBuffer = (char*)valloc(bufferSize + singleBufferSize);
- mEnd = false;
-
- if (mBuffer == NULL) {
- logg->logError(__FILE__, __LINE__, "failed to allocate %d bytes", bufferSize + singleBufferSize);
- handleException();
- }
-
- if (sem_init(&mWaitForSpaceSem, 0, 0)) {
- logg->logError(__FILE__, __LINE__, "sem_init() failed");
- handleException();
- }
-}
-
-Fifo::~Fifo() {
- free(mBuffer);
- sem_destroy(&mWaitForSpaceSem);
-}
-
-int Fifo::numBytesFilled() const {
- return mWrite - mRead + mRaggedEnd;
-}
-
-char* Fifo::start() const {
- return mBuffer;
-}
-
-bool Fifo::isEmpty() const {
- return mRead == mWrite && mRaggedEnd == 0;
-}
-
-bool Fifo::isFull() const {
- return willFill(0);
-}
-
-// Determines if the buffer will fill assuming 'additional' bytes will be added to the buffer
-// 'full' means there is less than singleBufferSize bytes available contiguously; it does not mean there are zero bytes available
-bool Fifo::willFill(int additional) const {
- if (mWrite > mRead) {
- if (numBytesFilled() + additional < mWrapThreshold) {
- return false;
- }
- } else {
- if (numBytesFilled() + additional < mWrapThreshold - mSingleBufferSize) {
- return false;
- }
- }
- return true;
-}
-
-// This function will stall until contiguous singleBufferSize bytes are available
-char* Fifo::write(int length) {
- if (length <= 0) {
- length = 0;
- mEnd = true;
- }
-
- // update the write pointer
- mWrite += length;
-
- // handle the wrap-around
- if (mWrite >= mWrapThreshold) {
- mRaggedEnd = mWrite;
- mWrite = 0;
- }
-
- // send a notification that data is ready
- sem_post(mReaderSem);
-
- // wait for space
- while (isFull()) {
- sem_wait(&mWaitForSpaceSem);
- }
-
- return &mBuffer[mWrite];
-}
-
-void Fifo::release() {
- // update the read pointer now that the data has been handled
- mRead = mReadCommit;
-
- // handle the wrap-around
- if (mRead >= mWrapThreshold) {
- mRaggedEnd = mRead = mReadCommit = 0;
- }
-
- // send a notification that data is free (space is available)
- sem_post(&mWaitForSpaceSem);
-}
-
-// This function will return null if no data is available
-char* Fifo::read(int *const length) {
- // wait for data
- if (isEmpty() && !mEnd) {
- return NULL;
- }
-
- // obtain the length
- do {
- mReadCommit = mRaggedEnd ? mRaggedEnd : mWrite;
- *length = mReadCommit - mRead;
- } while (*length < 0); // plugs race condition without using semaphores
-
- return &mBuffer[mRead];
-}
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __FIFO_H__
-#define __FIFO_H__
-
-#ifdef WIN32
-#include <windows.h>
-#define sem_t HANDLE
-#define sem_init(sem, pshared, value) ((*(sem) = CreateSemaphore(NULL, value, LONG_MAX, NULL)) == NULL)
-#define sem_wait(sem) WaitForSingleObject(*(sem), INFINITE)
-#define sem_post(sem) ReleaseSemaphore(*(sem), 1, NULL)
-#define sem_destroy(sem) CloseHandle(*(sem))
-#else
-#include <semaphore.h>
-#endif
-
-class Fifo {
-public:
- Fifo(int singleBufferSize, int totalBufferSize, sem_t* readerSem);
- ~Fifo();
- int numBytesFilled() const;
- bool isEmpty() const;
- bool isFull() const;
- bool willFill(int additional) const;
- char* start() const;
- char* write(int length);
- void release();
- char* read(int *const length);
-
-private:
- int mSingleBufferSize, mWrite, mRead, mReadCommit, mRaggedEnd, mWrapThreshold;
- sem_t mWaitForSpaceSem;
- sem_t* mReaderSem;
- char* mBuffer;
- bool mEnd;
-
- // Intentionally unimplemented
- Fifo(const Fifo &);
- Fifo &operator=(const Fifo &);
-};
-
-#endif //__FIFO_H__
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "Hwmon.h"
-
-#include "libsensors/sensors.h"
-
-#include "Buffer.h"
-#include "Counter.h"
-#include "Logging.h"
-#include "SessionData.h"
-
-class HwmonCounter {
-public:
- HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, const sensors_feature *feature);
- ~HwmonCounter();
-
- HwmonCounter *getNext() const { return next; }
- int getKey() const { return key; }
- bool isEnabled() const { return enabled; }
- const char *getName() const { return name; }
- const char *getLabel() const { return label; }
- const char *getTitle() const { return title; }
- bool isDuplicate() const { return duplicate; }
- const char *getDisplay() const { return display; }
- const char *getUnit() const { return unit; }
- int getModifier() const { return modifier; }
-
- void setEnabled(const bool enabled) {
- this->enabled = enabled;
- // canRead will clear enabled if the counter is not readable
- canRead();
- }
-
- double read();
- bool canRead();
-
-private:
- void init(const sensors_chip_name *chip, const sensors_feature *feature);
-
- HwmonCounter *const next;
- const int key;
- int polled : 1,
- readable : 1,
- enabled : 1,
- monotonic: 1,
- duplicate : 1;
-
- const sensors_chip_name *chip;
- const sensors_feature *feature;
-
- char *name;
- char *label;
- const char *title;
- const char *display;
- const char *unit;
- int modifier;
- double previous_value;
-
- sensors_subfeature_type input;
-
- // Intentionally unimplemented
- HwmonCounter(const HwmonCounter &);
- HwmonCounter &operator=(const HwmonCounter &);
-};
-
-HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, const sensors_feature *feature) : next(next), key(getEventKey()), polled(false), readable(false), enabled(false), duplicate(false), chip(chip), feature(feature) {
-
- int len = sensors_snprintf_chip_name(NULL, 0, chip) + 1;
- char *chip_name = new char[len];
- sensors_snprintf_chip_name(chip_name, len, chip);
-
- len = snprintf(NULL, 0, "hwmon_%s_%d", chip_name, feature->number) + 1;
- name = new char[len];
- snprintf(name, len, "hwmon_%s_%d", chip_name, feature->number);
-
- delete [] chip_name;
-
- label = sensors_get_label(chip, feature);
-
- switch (feature->type) {
- case SENSORS_FEATURE_IN:
- title = "Voltage";
- input = SENSORS_SUBFEATURE_IN_INPUT;
- display = "average";
- unit = "V";
- modifier = 1000;
- monotonic = false;
- break;
- case SENSORS_FEATURE_FAN:
- title = "Fan";
- input = SENSORS_SUBFEATURE_FAN_INPUT;
- display = "average";
- unit = "RPM";
- modifier = 1;
- monotonic = false;
- break;
- case SENSORS_FEATURE_TEMP:
- title = "Temperature";
- input = SENSORS_SUBFEATURE_TEMP_INPUT;
- display = "maximum";
- unit = "°C";
- modifier = 1000;
- monotonic = false;
- break;
- case SENSORS_FEATURE_POWER:
- title = "Power";
- input = SENSORS_SUBFEATURE_POWER_INPUT;
- display = "average";
- unit = "W";
- modifier = 1000000;
- monotonic = false;
- break;
- case SENSORS_FEATURE_ENERGY:
- title = "Energy";
- input = SENSORS_SUBFEATURE_ENERGY_INPUT;
- display = "accumulate";
- unit = "J";
- modifier = 1000000;
- monotonic = true;
- break;
- case SENSORS_FEATURE_CURR:
- title = "Current";
- input = SENSORS_SUBFEATURE_CURR_INPUT;
- display = "average";
- unit = "A";
- modifier = 1000;
- monotonic = false;
- break;
- case SENSORS_FEATURE_HUMIDITY:
- title = "Humidity";
- input = SENSORS_SUBFEATURE_HUMIDITY_INPUT;
- display = "average";
- unit = "%";
- modifier = 1000;
- monotonic = false;
- break;
- default:
- logg->logError(__FILE__, __LINE__, "Unsupported hwmon feature %i", feature->type);
- handleException();
- }
-
- for (HwmonCounter * counter = next; counter != NULL; counter = counter->getNext()) {
- if (strcmp(label, counter->getLabel()) == 0 && strcmp(title, counter->getTitle()) == 0) {
- duplicate = true;
- counter->duplicate = true;
- break;
- }
- }
-}
-
-HwmonCounter::~HwmonCounter() {
- free((void *)label);
- delete [] name;
-}
-
-double HwmonCounter::read() {
- double value;
- double result;
- const sensors_subfeature *subfeature;
-
- // Keep in sync with canRead
- subfeature = sensors_get_subfeature(chip, feature, input);
- if (!subfeature) {
- logg->logError(__FILE__, __LINE__, "No input value for hwmon sensor %s", label);
- handleException();
- }
-
- if (sensors_get_value(chip, subfeature->number, &value) != 0) {
- logg->logError(__FILE__, __LINE__, "Can't get input value for hwmon sensor %s", label);
- handleException();
- }
-
- result = (monotonic ? value - previous_value : value);
- previous_value = value;
-
- return result;
-}
-
-bool HwmonCounter::canRead() {
- if (!polled) {
- double value;
- const sensors_subfeature *subfeature;
- bool result = true;
-
- subfeature = sensors_get_subfeature(chip, feature, input);
- if (!subfeature) {
- result = false;
- } else {
- result = sensors_get_value(chip, subfeature->number, &value) == 0;
- }
-
- polled = true;
- readable = result;
- }
-
- enabled &= readable;
-
- return readable;
-}
-
-Hwmon::Hwmon() : counters(NULL) {
-}
-
-Hwmon::~Hwmon() {
- while (counters != NULL) {
- HwmonCounter * counter = counters;
- counters = counter->getNext();
- delete counter;
- }
- sensors_cleanup();
-}
-
-void Hwmon::setup() {
- // hwmon does not currently work with perf
- if (gSessionData->perf.isSetup()) {
- return;
- }
-
- int err = sensors_init(NULL);
- if (err) {
- logg->logMessage("Failed to initialize libsensors! (%d)", err);
- return;
- }
- sensors_sysfs_no_scaling = 1;
-
- int chip_nr = 0;
- const sensors_chip_name *chip;
- while ((chip = sensors_get_detected_chips(NULL, &chip_nr))) {
- int feature_nr = 0;
- const sensors_feature *feature;
- while ((feature = sensors_get_features(chip, &feature_nr))) {
- counters = new HwmonCounter(counters, chip, feature);
- }
- }
-}
-
-HwmonCounter *Hwmon::findCounter(const Counter &counter) const {
- for (HwmonCounter * hwmonCounter = counters; hwmonCounter != NULL; hwmonCounter = hwmonCounter->getNext()) {
- if (hwmonCounter->canRead() && strcmp(hwmonCounter->getName(), counter.getType()) == 0) {
- return hwmonCounter;
- }
- }
-
- return NULL;
-}
-
-bool Hwmon::claimCounter(const Counter &counter) const {
- return findCounter(counter) != NULL;
-}
-
-bool Hwmon::countersEnabled() const {
- for (HwmonCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
- if (counter->isEnabled()) {
- return true;
- }
- }
- return false;
-}
-
-void Hwmon::resetCounters() {
- for (HwmonCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
- counter->setEnabled(false);
- }
-}
-
-void Hwmon::setupCounter(Counter &counter) {
- HwmonCounter *const hwmonCounter = findCounter(counter);
- if (hwmonCounter == NULL) {
- counter.setEnabled(false);
- return;
- }
- hwmonCounter->setEnabled(true);
- counter.setKey(hwmonCounter->getKey());
-}
-
-int Hwmon::writeCounters(mxml_node_t *root) const {
- int count = 0;
- for (HwmonCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
- if (!counter->canRead()) {
- continue;
- }
- mxml_node_t *node = mxmlNewElement(root, "counter");
- mxmlElementSetAttr(node, "name", counter->getName());
- ++count;
- }
-
- return count;
-}
-
-void Hwmon::writeEvents(mxml_node_t *root) const {
- root = mxmlNewElement(root, "category");
- mxmlElementSetAttr(root, "name", "hwmon");
-
- char buf[1024];
- for (HwmonCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
- if (!counter->canRead()) {
- continue;
- }
- mxml_node_t *node = mxmlNewElement(root, "event");
- mxmlElementSetAttr(node, "counter", counter->getName());
- mxmlElementSetAttr(node, "title", counter->getTitle());
- if (counter->isDuplicate()) {
- mxmlElementSetAttrf(node, "name", "%s (0x%x)", counter->getLabel(), counter->getKey());
- } else {
- mxmlElementSetAttr(node, "name", counter->getLabel());
- }
- mxmlElementSetAttr(node, "display", counter->getDisplay());
- mxmlElementSetAttr(node, "units", counter->getUnit());
- if (counter->getModifier() != 1) {
- mxmlElementSetAttrf(node, "modifier", "%d", counter->getModifier());
- }
- if (strcmp(counter->getDisplay(), "average") == 0 || strcmp(counter->getDisplay(), "maximum") == 0) {
- mxmlElementSetAttr(node, "average_selection", "yes");
- }
- snprintf(buf, sizeof(buf), "libsensors %s sensor %s (%s)", counter->getTitle(), counter->getLabel(), counter->getName());
- mxmlElementSetAttr(node, "description", buf);
- }
-}
-
-void Hwmon::start() {
- for (HwmonCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
- if (!counter->isEnabled()) {
- continue;
- }
- counter->read();
- }
-}
-
-void Hwmon::read(Buffer * const buffer) {
- for (HwmonCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
- if (!counter->isEnabled()) {
- continue;
- }
- buffer->event(counter->getKey(), counter->read());
- }
-}
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef HWMON_H
-#define HWMON_H
-
-#include "Driver.h"
-
-class Buffer;
-class HwmonCounter;
-
-class Hwmon : public Driver {
-public:
- Hwmon();
- ~Hwmon();
-
- void setup();
-
- bool claimCounter(const Counter &counter) const;
- bool countersEnabled() const;
- void resetCounters();
- void setupCounter(Counter &counter);
-
- int writeCounters(mxml_node_t *root) const;
- void writeEvents(mxml_node_t *root) const;
-
- void start();
- void read(Buffer * buffer);
-
-private:
- HwmonCounter *findCounter(const Counter &counter) const;
-
- HwmonCounter *counters;
-
- // Intentionally unimplemented
- Hwmon(const Hwmon &);
- Hwmon &operator=(const Hwmon &);
-};
-
-#endif // HWMON_H
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "KMod.h"
-
-#include <sys/types.h>
-#include <dirent.h>
-#include <unistd.h>
-
-#include "ConfigurationXML.h"
-#include "Counter.h"
-#include "DriverSource.h"
-#include "Logging.h"
-
-// Claim all the counters in /dev/gator/events
-bool KMod::claimCounter(const Counter &counter) const {
- char text[128];
- snprintf(text, sizeof(text), "/dev/gator/events/%s", counter.getType());
- return access(text, F_OK) == 0;
-}
-
-void KMod::resetCounters() {
- char base[128];
- char text[128];
-
- // Initialize all perf counters in the driver, i.e. set enabled to zero
- struct dirent *ent;
- DIR* dir = opendir("/dev/gator/events");
- if (dir) {
- while ((ent = readdir(dir)) != NULL) {
- // skip hidden files, current dir, and parent dir
- if (ent->d_name[0] == '.')
- continue;
- snprintf(base, sizeof(base), "/dev/gator/events/%s", ent->d_name);
- snprintf(text, sizeof(text), "%s/enabled", base);
- DriverSource::writeDriver(text, 0);
- snprintf(text, sizeof(text), "%s/count", base);
- DriverSource::writeDriver(text, 0);
- }
- closedir(dir);
- }
-}
-
-void KMod::setupCounter(Counter &counter) {
- char base[128];
- char text[128];
- snprintf(base, sizeof(base), "/dev/gator/events/%s", counter.getType());
-
- snprintf(text, sizeof(text), "%s/enabled", base);
- int enabled = true;
- if (DriverSource::writeReadDriver(text, &enabled) || !enabled) {
- counter.setEnabled(false);
- return;
- }
-
- snprintf(text, sizeof(text), "%s/key", base);
- int key = 0;
- DriverSource::readIntDriver(text, &key);
- counter.setKey(key);
-
- snprintf(text, sizeof(text), "%s/event", base);
- DriverSource::writeDriver(text, counter.getEvent());
- snprintf(text, sizeof(text), "%s/count", base);
- if (access(text, F_OK) == 0) {
- int count = counter.getCount();
- if (DriverSource::writeReadDriver(text, &count) && counter.getCount() > 0) {
- logg->logError(__FILE__, __LINE__, "Cannot enable EBS for %s:%i with a count of %d\n", counter.getType(), counter.getEvent(), counter.getCount());
- handleException();
- }
- counter.setCount(count);
- } else if (counter.getCount() > 0) {
- ConfigurationXML::remove();
- logg->logError(__FILE__, __LINE__, "Event Based Sampling is only supported with kernel versions 3.0.0 and higher with CONFIG_PERF_EVENTS=y, and CONFIG_HW_PERF_EVENTS=y. The invalid configuration.xml has been removed.\n");
- handleException();
- }
-}
-
-int KMod::writeCounters(mxml_node_t *root) const {
- struct dirent *ent;
- mxml_node_t *counter;
-
- // counters.xml is simply a file listing of /dev/gator/events
- DIR* dir = opendir("/dev/gator/events");
- if (dir == NULL) {
- return 0;
- }
-
- int count = 0;
- while ((ent = readdir(dir)) != NULL) {
- // skip hidden files, current dir, and parent dir
- if (ent->d_name[0] == '.')
- continue;
- counter = mxmlNewElement(root, "counter");
- mxmlElementSetAttr(counter, "name", ent->d_name);
- ++count;
- }
- closedir(dir);
-
- return count;
-}
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef KMOD_H
-#define KMOD_H
-
-#include "Driver.h"
-
-// Driver for the gator kernel module
-class KMod : public Driver {
-public:
- KMod() {}
- ~KMod() {}
-
- bool claimCounter(const Counter &counter) const;
- void resetCounters();
- void setupCounter(Counter &counter);
-
- int writeCounters(mxml_node_t *root) const;
-};
-
-#endif // KMOD_H
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "LocalCapture.h"
-
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <dirent.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "SessionData.h"
-#include "Logging.h"
-#include "OlyUtility.h"
-#include "EventsXML.h"
-
-LocalCapture::LocalCapture() {}
-
-LocalCapture::~LocalCapture() {}
-
-void LocalCapture::createAPCDirectory(char* target_path) {
- gSessionData->mAPCDir = createUniqueDirectory(target_path, ".apc");
- if ((removeDirAndAllContents(gSessionData->mAPCDir) != 0 || mkdir(gSessionData->mAPCDir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0)) {
- logg->logError(__FILE__, __LINE__, "Unable to create directory %s", gSessionData->mAPCDir);
- handleException();
- }
-}
-
-void LocalCapture::write(char* string) {
- char file[PATH_MAX];
-
- // Set full path
- snprintf(file, PATH_MAX, "%s/session.xml", gSessionData->mAPCDir);
-
- // Write the file
- if (util->writeToDisk(file, string) < 0) {
- logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify the path.", file);
- handleException();
- }
-
- // Write events XML
- EventsXML eventsXML;
- eventsXML.write(gSessionData->mAPCDir);
-}
-
-char* LocalCapture::createUniqueDirectory(const char* initialPath, const char* ending) {
- char* output;
- char path[PATH_MAX];
-
- // Ensure the path is an absolute path, i.e. starts with a slash
- if (initialPath == 0 || strlen(initialPath) == 0) {
- logg->logError(__FILE__, __LINE__, "Missing -o command line option required for a local capture.");
- handleException();
- } else if (initialPath[0] != '/') {
- if (getcwd(path, PATH_MAX) == 0) {
- logg->logMessage("Unable to retrieve the current working directory");
- }
- strncat(path, "/", PATH_MAX - strlen(path) - 1);
- strncat(path, initialPath, PATH_MAX - strlen(path) - 1);
- } else {
- strncpy(path, initialPath, PATH_MAX);
- path[PATH_MAX - 1] = 0; // strncpy does not guarantee a null-terminated string
- }
-
- // Add ending if it is not already there
- if (strcmp(&path[strlen(path) - strlen(ending)], ending) != 0) {
- strncat(path, ending, PATH_MAX - strlen(path) - 1);
- }
-
- output = strdup(path);
-
- return output;
-}
-
-int LocalCapture::removeDirAndAllContents(char* path) {
- int error = 0;
- struct stat mFileInfo;
- // Does the path exist?
- if (stat(path, &mFileInfo) == 0) {
- // Is it a directory?
- if (mFileInfo.st_mode & S_IFDIR) {
- DIR * dir = opendir(path);
- dirent* entry = readdir(dir);
- while (entry) {
- if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
- char* newpath = (char*)malloc(strlen(path) + strlen(entry->d_name) + 2);
- sprintf(newpath, "%s/%s", path, entry->d_name);
- error = removeDirAndAllContents(newpath);
- free(newpath);
- if (error) {
- break;
- }
- }
- entry = readdir(dir);
- }
- closedir(dir);
- if (error == 0) {
- error = rmdir(path);
- }
- } else {
- error = remove(path);
- }
- }
- return error;
-}
-
-void LocalCapture::copyImages(ImageLinkList* ptr) {
- char dstfilename[PATH_MAX];
-
- while (ptr) {
- strncpy(dstfilename, gSessionData->mAPCDir, PATH_MAX);
- dstfilename[PATH_MAX - 1] = 0; // strncpy does not guarantee a null-terminated string
- if (gSessionData->mAPCDir[strlen(gSessionData->mAPCDir) - 1] != '/') {
- strncat(dstfilename, "/", PATH_MAX - strlen(dstfilename) - 1);
- }
- strncat(dstfilename, util->getFilePart(ptr->path), PATH_MAX - strlen(dstfilename) - 1);
- if (util->copyFile(ptr->path, dstfilename)) {
- logg->logMessage("copied file %s to %s", ptr->path, dstfilename);
- } else {
- logg->logMessage("copy of file %s to %s failed", ptr->path, dstfilename);
- }
-
- ptr = ptr->next;
- }
-}
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __LOCAL_CAPTURE_H__
-#define __LOCAL_CAPTURE_H__
-
-struct ImageLinkList;
-
-class LocalCapture {
-public:
- LocalCapture();
- ~LocalCapture();
- void write(char* string);
- void copyImages(ImageLinkList* ptr);
- void createAPCDirectory(char* target_path);
-private:
- char* createUniqueDirectory(const char* path, const char* ending);
- int removeDirAndAllContents(char* path);
-};
-
-#endif //__LOCAL_CAPTURE_H__
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "Logging.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-
-#ifdef WIN32
-#define MUTEX_INIT() mLoggingMutex = CreateMutex(NULL, false, NULL);
-#define MUTEX_LOCK() WaitForSingleObject(mLoggingMutex, 0xFFFFFFFF);
-#define MUTEX_UNLOCK() ReleaseMutex(mLoggingMutex);
-#define snprintf _snprintf
-#else
-#include <pthread.h>
-#define MUTEX_INIT() pthread_mutex_init(&mLoggingMutex, NULL)
-#define MUTEX_LOCK() pthread_mutex_lock(&mLoggingMutex)
-#define MUTEX_UNLOCK() pthread_mutex_unlock(&mLoggingMutex)
-#endif
-
-// Global thread-safe logging
-Logging* logg = NULL;
-
-Logging::Logging(bool debug) {
- mDebug = debug;
- MUTEX_INIT();
-
- strcpy(mErrBuf, "Unknown Error");
- strcpy(mLogBuf, "Unknown Message");
-}
-
-Logging::~Logging() {
-}
-
-void Logging::logError(const char* file, int line, const char* fmt, ...) {
- va_list args;
-
- MUTEX_LOCK();
- if (mDebug) {
- snprintf(mErrBuf, sizeof(mErrBuf), "ERROR[%s:%d]: ", file, line);
- } else {
- mErrBuf[0] = 0;
- }
-
- va_start(args, fmt);
- vsnprintf(mErrBuf + strlen(mErrBuf), sizeof(mErrBuf) - 2 - strlen(mErrBuf), fmt, args); // subtract 2 for \n and \0
- va_end(args);
-
- if (strlen(mErrBuf) > 0) {
- strcat(mErrBuf, "\n");
- }
- MUTEX_UNLOCK();
-}
-
-void Logging::logMessage(const char* fmt, ...) {
- if (mDebug) {
- va_list args;
-
- MUTEX_LOCK();
- strcpy(mLogBuf, "INFO: ");
-
- va_start(args, fmt);
- vsnprintf(mLogBuf + strlen(mLogBuf), sizeof(mLogBuf) - 2 - strlen(mLogBuf), fmt, args); // subtract 2 for \n and \0
- va_end(args);
- strcat(mLogBuf, "\n");
-
- fprintf(stdout, "%s", mLogBuf);
- fflush(stdout);
- MUTEX_UNLOCK();
- }
-}
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __LOGGING_H__
-#define __LOGGING_H__
-
-#include <pthread.h>
-
-#define DRIVER_ERROR "\n Driver issue:\n >> gator.ko must be built against the current kernel version & configuration\n >> gator.ko should be co-located with gatord in the same directory\n >> OR insmod gator.ko prior to launching gatord"
-
-class Logging {
-public:
- Logging(bool debug);
- ~Logging();
- void logError(const char* file, int line, const char* fmt, ...);
- void logMessage(const char* fmt, ...);
- char* getLastError() {return mErrBuf;}
- char* getLastMessage() {return mLogBuf;}
-
-private:
- char mErrBuf[4096]; // Arbitrarily large buffer to hold a string
- char mLogBuf[4096]; // Arbitrarily large buffer to hold a string
- bool mDebug;
- pthread_mutex_t mLoggingMutex;
-};
-
-extern Logging* logg;
-
-extern void handleException() __attribute__ ((noreturn));
-
-#endif //__LOGGING_H__
+++ /dev/null
-#
-# Makefile for ARM Streamline - Gator Daemon
-#
-
-# Uncomment and define CROSS_COMPILE if it is not already defined
-# CROSS_COMPILE=/path/to/cross-compiler/arm-linux-gnueabihf-
-# NOTE: This toolchain uses the hardfloat abi by default. For non-hardfloat
-# targets run 'make SOFTFLOAT=1 SYSROOT=/path/to/sysroot', see
-# README_Streamline.txt for more details
-
-CPP = $(CROSS_COMPILE)g++
-GCC = $(CROSS_COMPILE)gcc
-
-# -mthumb-interwork is required for interworking to ARM or Thumb stdlibc
-CFLAGS += -mthumb-interwork
-
-ifeq ($(SOFTFLOAT),1)
- CFLAGS += -marm -march=armv4t -mfloat-abi=soft
- LDFLAGS += -marm -march=armv4t -mfloat-abi=soft
-endif
-ifneq ($(SYSROOT),)
- LDFLAGS += --sysroot=$(SYSROOT)
-endif
-
-include common.mk
+++ /dev/null
-#
-# Makefile for ARM Streamline - Gator Daemon
-# make -f Makefile_aarch64
-#
-
-# Uncomment and define CROSS_COMPILE if it is not already defined
-# CROSS_COMPILE=/path/to/cross-compiler/arm-linux-gnueabihf-
-# NOTE: This toolchain uses the hardfloat abi by default. For non-hardfloat
-# targets it is necessary to add options
-# '-marm -march=armv4t -mfloat-abi=soft'.
-
-CPP = $(CROSS_COMPILE)g++
-GCC = $(CROSS_COMPILE)gcc
-
-include common.mk
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "Monitor.h"
-
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "Logging.h"
-
-Monitor::Monitor() : mFd(-1) {
-}
-
-Monitor::~Monitor() {
- if (mFd >= -1) {
- close(mFd);
- }
-}
-
-bool Monitor::init() {
- mFd = epoll_create(16);
- if (mFd < 0) {
- logg->logMessage("%s(%s:%i): epoll_create1 failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
-
- return true;
-}
-
-bool Monitor::add(const int fd) {
- struct epoll_event event;
- memset(&event, 0, sizeof(event));
- event.data.fd = fd;
- event.events = EPOLLIN;
- if (epoll_ctl(mFd, EPOLL_CTL_ADD, fd, &event) != 0) {
- logg->logMessage("%s(%s:%i): epoll_ctl failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
-
- return true;
-}
-
-int Monitor::wait(struct epoll_event *const events, int maxevents, int timeout) {
- int result = epoll_wait(mFd, events, maxevents, timeout);
- if (result < 0) {
- // Ignore if the call was interrupted as this will happen when SIGINT is received
- if (errno == EINTR) {
- result = 0;
- } else {
- logg->logMessage("%s(%s:%i): epoll_wait failed", __FUNCTION__, __FILE__, __LINE__);
- }
- }
-
- return result;
-}
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef MONITOR_H
-#define MONITOR_H
-
-#include <sys/epoll.h>
-
-class Monitor {
-public:
- Monitor();
- ~Monitor();
-
- bool init();
- bool add(const int fd);
- int wait(struct epoll_event *const events, int maxevents, int timeout);
-
-private:
-
- int mFd;
-
- // Intentionally unimplemented
- Monitor(const Monitor &);
- Monitor &operator=(const Monitor &);
-};
-
-#endif // MONITOR_H
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "OlySocket.h"
-
-#include <stdio.h>
-#ifdef WIN32
-#include <Winsock2.h>
-#include <ws2tcpip.h>
-#else
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <unistd.h>
-#include <netdb.h>
-#endif
-
-#include "Logging.h"
-
-#ifdef WIN32
-#define CLOSE_SOCKET(x) closesocket(x)
-#define SHUTDOWN_RX_TX SD_BOTH
-#define snprintf _snprintf
-#else
-#define CLOSE_SOCKET(x) close(x)
-#define SHUTDOWN_RX_TX SHUT_RDWR
-#endif
-
-OlyServerSocket::OlyServerSocket(int port) {
-#ifdef WIN32
- WSADATA wsaData;
- if (WSAStartup(0x0202, &wsaData) != 0) {
- logg->logError(__FILE__, __LINE__, "Windows socket initialization failed");
- handleException();
- }
-#endif
-
- createServerSocket(port);
-}
-
-OlySocket::OlySocket(int port, const char* host) {
- createClientSocket(host, port);
-}
-
-OlySocket::OlySocket(int socketID) : mSocketID(socketID) {
-}
-
-#ifndef WIN32
-
-OlyServerSocket::OlyServerSocket(const char* path) {
- // Create socket
- mFDServer = socket(PF_UNIX, SOCK_STREAM, 0);
- if (mFDServer < 0) {
- logg->logError(__FILE__, __LINE__, "Error creating server socket");
- handleException();
- }
-
- unlink(path);
-
- // Create sockaddr_in structure, ensuring non-populated fields are zero
- struct sockaddr_un sockaddr;
- memset((void*)&sockaddr, 0, sizeof(sockaddr));
- sockaddr.sun_family = AF_UNIX;
- strncpy(sockaddr.sun_path, path, sizeof(sockaddr.sun_path) - 1);
- sockaddr.sun_path[sizeof(sockaddr.sun_path) - 1] = '\0';
-
- // Bind the socket to an address
- if (bind(mFDServer, (const struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0) {
- logg->logError(__FILE__, __LINE__, "Binding of server socket failed.");
- handleException();
- }
-
- // Listen for connections on this socket
- if (listen(mFDServer, 1) < 0) {
- logg->logError(__FILE__, __LINE__, "Listening of server socket failed");
- handleException();
- }
-}
-
-OlySocket::OlySocket(const char* path) {
- mSocketID = socket(PF_UNIX, SOCK_STREAM, 0);
- if (mSocketID < 0) {
- return;
- }
-
- // Create sockaddr_in structure, ensuring non-populated fields are zero
- struct sockaddr_un sockaddr;
- memset((void*)&sockaddr, 0, sizeof(sockaddr));
- sockaddr.sun_family = AF_UNIX;
- strncpy(sockaddr.sun_path, path, sizeof(sockaddr.sun_path) - 1);
- sockaddr.sun_path[sizeof(sockaddr.sun_path) - 1] = '\0';
-
- if (connect(mSocketID, (const struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0) {
- close(mSocketID);
- mSocketID = -1;
- return;
- }
-}
-
-#endif
-
-OlySocket::~OlySocket() {
- if (mSocketID > 0) {
- CLOSE_SOCKET(mSocketID);
- }
-}
-
-OlyServerSocket::~OlyServerSocket() {
- if (mFDServer > 0) {
- CLOSE_SOCKET(mFDServer);
- }
-}
-
-void OlySocket::shutdownConnection() {
- // Shutdown is primarily used to unblock other threads that are blocking on send/receive functions
- shutdown(mSocketID, SHUTDOWN_RX_TX);
-}
-
-void OlySocket::closeSocket() {
- // Used for closing an accepted socket but keeping the server socket active
- if (mSocketID > 0) {
- CLOSE_SOCKET(mSocketID);
- mSocketID = -1;
- }
-}
-
-void OlyServerSocket::closeServerSocket() {
- if (CLOSE_SOCKET(mFDServer) != 0) {
- logg->logError(__FILE__, __LINE__, "Failed to close server socket.");
- handleException();
- }
- mFDServer = 0;
-}
-
-void OlySocket::createClientSocket(const char* hostname, int portno) {
-#ifdef WIN32
- // TODO: Implement for Windows
-#else
- char buf[32];
- struct addrinfo hints, *res, *res0;
-
- snprintf(buf, sizeof(buf), "%d", portno);
- mSocketID = -1;
- memset((void*)&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
-
- if (getaddrinfo(hostname, buf, &hints, &res0)) {
- logg->logError(__FILE__, __LINE__, "Client socket failed to get address info for %s", hostname);
- handleException();
- }
- for (res=res0; res!=NULL; res = res->ai_next) {
- if ( res->ai_family != PF_INET || res->ai_socktype != SOCK_STREAM ) {
- continue;
- }
- mSocketID = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
- if (mSocketID < 0) {
- continue;
- }
- if (connect(mSocketID, res->ai_addr, res->ai_addrlen) < 0) {
- close(mSocketID);
- mSocketID = -1;
- }
- if (mSocketID > 0) {
- break;
- }
- }
- freeaddrinfo(res0);
- if (mSocketID <= 0) {
- logg->logError(__FILE__, __LINE__, "Could not connect to client socket. Ensure ARM Streamline is running.");
- handleException();
- }
-#endif
-}
-
-void OlyServerSocket::createServerSocket(int port) {
- int family = AF_INET6;
-
- // Create socket
- mFDServer = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
- if (mFDServer < 0) {
- family = AF_INET;
- mFDServer = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (mFDServer < 0) {
- logg->logError(__FILE__, __LINE__, "Error creating server socket");
- handleException();
- }
- }
-
- // Enable address reuse, another solution would be to create the server socket once and only close it when the object exits
- int on = 1;
- if (setsockopt(mFDServer, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) != 0) {
- logg->logError(__FILE__, __LINE__, "Setting server socket options failed");
- handleException();
- }
-
- // Create sockaddr_in structure, ensuring non-populated fields are zero
- struct sockaddr_in6 sockaddr;
- memset((void*)&sockaddr, 0, sizeof(sockaddr));
- sockaddr.sin6_family = family;
- sockaddr.sin6_port = htons(port);
- sockaddr.sin6_addr = in6addr_any;
-
- // Bind the socket to an address
- if (bind(mFDServer, (const struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0) {
- logg->logError(__FILE__, __LINE__, "Binding of server socket failed.\nIs an instance already running?");
- handleException();
- }
-
- // Listen for connections on this socket
- if (listen(mFDServer, 1) < 0) {
- logg->logError(__FILE__, __LINE__, "Listening of server socket failed");
- handleException();
- }
-}
-
-// mSocketID is always set to the most recently accepted connection
-// The user of this class should maintain the different socket connections, e.g. by forking the process
-int OlyServerSocket::acceptConnection() {
- int socketID;
- if (mFDServer <= 0) {
- logg->logError(__FILE__, __LINE__, "Attempting multiple connections on a single connection server socket or attempting to accept on a client socket");
- handleException();
- }
-
- // Accept a connection, note that this call blocks until a client connects
- socketID = accept(mFDServer, NULL, NULL);
- if (socketID < 0) {
- logg->logError(__FILE__, __LINE__, "Socket acceptance failed");
- handleException();
- }
- return socketID;
-}
-
-void OlySocket::send(const char* buffer, int size) {
- if (size <= 0 || buffer == NULL) {
- return;
- }
-
- while (size > 0) {
- int n = ::send(mSocketID, buffer, size, 0);
- if (n < 0) {
- logg->logError(__FILE__, __LINE__, "Socket send error");
- handleException();
- }
- size -= n;
- buffer += n;
- }
-}
-
-// Returns the number of bytes received
-int OlySocket::receive(char* buffer, int size) {
- if (size <= 0 || buffer == NULL) {
- return 0;
- }
-
- int bytes = recv(mSocketID, buffer, size, 0);
- if (bytes < 0) {
- logg->logError(__FILE__, __LINE__, "Socket receive error");
- handleException();
- } else if (bytes == 0) {
- logg->logMessage("Socket disconnected");
- return -1;
- }
- return bytes;
-}
-
-// Receive exactly size bytes of data. Note, this function will block until all bytes are received
-int OlySocket::receiveNBytes(char* buffer, int size) {
- int bytes = 0;
- while (size > 0 && buffer != NULL) {
- bytes = recv(mSocketID, buffer, size, 0);
- if (bytes < 0) {
- logg->logError(__FILE__, __LINE__, "Socket receive error");
- handleException();
- } else if (bytes == 0) {
- logg->logMessage("Socket disconnected");
- return -1;
- }
- buffer += bytes;
- size -= bytes;
- }
- return bytes;
-}
-
-// Receive data until a carriage return, line feed, or null is encountered, or the buffer fills
-int OlySocket::receiveString(char* buffer, int size) {
- int bytes_received = 0;
- bool found = false;
-
- if (buffer == 0) {
- return 0;
- }
-
- while (!found && bytes_received < size) {
- // Receive a single character
- int bytes = recv(mSocketID, &buffer[bytes_received], 1, 0);
- if (bytes < 0) {
- logg->logError(__FILE__, __LINE__, "Socket receive error");
- handleException();
- } else if (bytes == 0) {
- logg->logMessage("Socket disconnected");
- return -1;
- }
-
- // Replace carriage returns and line feeds with zero
- if (buffer[bytes_received] == '\n' || buffer[bytes_received] == '\r' || buffer[bytes_received] == '\0') {
- buffer[bytes_received] = '\0';
- found = true;
- }
-
- bytes_received++;
- }
-
- return bytes_received;
-}
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __OLY_SOCKET_H__
-#define __OLY_SOCKET_H__
-
-class OlySocket {
-public:
- OlySocket(int port, const char* hostname);
- OlySocket(int socketID);
-#ifndef WIN32
- OlySocket(const char* path);
-#endif
- ~OlySocket();
-
- void closeSocket();
- void shutdownConnection();
- void send(const char* buffer, int size);
- int receive(char* buffer, int size);
- int receiveNBytes(char* buffer, int size);
- int receiveString(char* buffer, int size);
-
- bool isValid() const { return mSocketID >= 0; }
-
-private:
- int mSocketID;
-
- void createClientSocket(const char* hostname, int port);
-};
-
-class OlyServerSocket {
-public:
- OlyServerSocket(int port);
-#ifndef WIN32
- OlyServerSocket(const char* path);
-#endif
- ~OlyServerSocket();
-
- int acceptConnection();
- void closeServerSocket();
-
-private:
- int mFDServer;
-
- void createServerSocket(int port);
-};
-
-#endif //__OLY_SOCKET_H__
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "OlyUtility.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#if defined(WIN32)
-#include <windows.h>
-#elif defined(__linux__)
-#include <unistd.h>
-#elif defined(DARWIN)
-#include <mach-o/dyld.h>
-#endif
-
-OlyUtility* util = NULL;
-
-bool OlyUtility::stringToBool(const char* string, bool defValue) {
- char value[32];
-
- if (string == NULL) {
- return defValue;
- }
-
- strncpy(value, string, sizeof(value));
- if (value[0] == 0) {
- return defValue;
- }
- value[sizeof(value) - 1] = 0; // strncpy does not guarantee a null-terminated string
-
- // Convert to lowercase
- int i = 0;
- while (value[i]) {
- value[i] = tolower(value[i]);
- i++;
- }
-
- if (strcmp(value, "true") == 0 || strcmp(value, "yes") == 0 || strcmp(value, "1") == 0 || strcmp(value, "on") == 0) {
- return true;
- } else if (strcmp(value, "false") == 0 || strcmp(value, "no") == 0 || strcmp(value, "0") == 0 || strcmp(value, "off") == 0) {
- return false;
- } else {
- return defValue;
- }
-}
-
-void OlyUtility::stringToLower(char* string) {
- if (string == NULL) {
- return;
- }
-
- while (*string) {
- *string = tolower(*string);
- string++;
- }
-}
-
-// Modifies fullpath with the path part including the trailing path separator
-int OlyUtility::getApplicationFullPath(char* fullpath, int sizeOfPath) {
- memset(fullpath, 0, sizeOfPath);
-#if defined(WIN32)
- int length = GetModuleFileName(NULL, fullpath, sizeOfPath);
-#elif defined(__linux__)
- int length = readlink("/proc/self/exe", fullpath, sizeOfPath);
-#elif defined(DARWIN)
- uint32_t length_u = (uint32_t)sizeOfPath;
- int length = sizeOfPath;
- if (_NSGetExecutablePath(fullpath, &length_u) == 0) {
- length = strlen(fullpath);
- }
-#endif
-
- if (length == sizeOfPath) {
- return -1;
- }
-
- fullpath[length] = 0;
- getPathPart(fullpath);
-
- return 0;
-}
-
-char* OlyUtility::readFromDisk(const char* file, unsigned int *size, bool appendNull) {
- // Open the file
- FILE* pFile = fopen(file, "rb");
- if (pFile==NULL) {
- return NULL;
- }
-
- // Obtain file size
- fseek(pFile , 0 , SEEK_END);
- unsigned int lSize = ftell(pFile);
- rewind(pFile);
-
- // Allocate memory to contain the whole file
- char* buffer = (char*)malloc(lSize + (int)appendNull);
- if (buffer == NULL) {
- fclose(pFile);
- return NULL;
- }
-
- // Copy the file into the buffer
- if (fread(buffer, 1, lSize, pFile) != lSize) {
- free(buffer);
- fclose(pFile);
- return NULL;
- }
-
- // Terminate
- fclose(pFile);
-
- if (appendNull) {
- buffer[lSize] = 0;
- }
-
- if (size) {
- *size = lSize;
- }
-
- return buffer;
-}
-
-int OlyUtility::writeToDisk(const char* path, const char* data) {
- // Open the file
- FILE* pFile = fopen(path, "wb");
- if (pFile == NULL) {
- return -1;
- }
-
- // Write the data to disk
- if (fwrite(data, 1, strlen(data), pFile) != strlen(data)) {
- fclose(pFile);
- return -1;
- }
-
- // Terminate
- fclose(pFile);
- return 0;
-}
-
-int OlyUtility::appendToDisk(const char* path, const char* data) {
- // Open the file
- FILE* pFile = fopen(path, "a");
- if (pFile == NULL) {
- return -1;
- }
-
- // Write the data to disk
- if (fwrite(data, 1, strlen(data), pFile) != strlen(data)) {
- fclose(pFile);
- return -1;
- }
-
- // Terminate
- fclose(pFile);
- return 0;
-}
-
-/**
- * Copies the srcFile into dstFile in 1kB chunks.
- * The dstFile will be overwritten if it exists.
- * 0 is returned on an error; otherwise 1.
- */
-#define TRANSFER_SIZE 1024
-int OlyUtility::copyFile(const char* srcFile, const char* dstFile) {
- char buffer[TRANSFER_SIZE];
- FILE * f_src = fopen(srcFile,"rb");
- if (!f_src) {
- return 0;
- }
- FILE * f_dst = fopen(dstFile,"wb");
- if (!f_dst) {
- fclose(f_src);
- return 0;
- }
- while (!feof(f_src)) {
- int num_bytes_read = fread(buffer, 1, TRANSFER_SIZE, f_src);
- if (num_bytes_read < TRANSFER_SIZE && !feof(f_src)) {
- fclose(f_src);
- fclose(f_dst);
- return 0;
- }
- int num_bytes_written = fwrite(buffer, 1, num_bytes_read, f_dst);
- if (num_bytes_written != num_bytes_read) {
- fclose(f_src);
- fclose(f_dst);
- return 0;
- }
- }
- fclose(f_src);
- fclose(f_dst);
- return 1;
-}
-
-const char* OlyUtility::getFilePart(const char* path) {
- const char* last_sep = strrchr(path, PATH_SEPARATOR);
-
- // in case path is not a full path
- if (last_sep == NULL) {
- return path;
- }
-
- return last_sep++;
-}
-
-// getPathPart may modify the contents of path
-// returns the path including the trailing path separator
-char* OlyUtility::getPathPart(char* path) {
- char* last_sep = strrchr(path, PATH_SEPARATOR);
-
- // in case path is not a full path
- if (last_sep == NULL) {
- return 0;
- }
- last_sep++;
- *last_sep = 0;
-
- return (path);
-}
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef OLY_UTILITY_H
-#define OLY_UTILITY_H
-
-#include <stddef.h>
-
-#ifdef WIN32
-#define PATH_SEPARATOR '\\'
-#define CAIMAN_PATH_MAX MAX_PATH
-#define snprintf _snprintf
-#else
-#include <limits.h>
-#define PATH_SEPARATOR '/'
-#define CAIMAN_PATH_MAX PATH_MAX
-#endif
-
-class OlyUtility {
-public:
- OlyUtility() {};
- ~OlyUtility() {};
- bool stringToBool(const char* string, bool defValue);
- void stringToLower(char* string);
- int getApplicationFullPath(char* path, int sizeOfPath);
- char* readFromDisk(const char* file, unsigned int *size = NULL, bool appendNull = true);
- int writeToDisk(const char* path, const char* file);
- int appendToDisk(const char* path, const char* file);
- int copyFile(const char* srcFile, const char* dstFile);
- const char* getFilePart(const char* path);
- char* getPathPart(char* path);
-private:
-};
-
-extern OlyUtility* util;
-
-#endif // OLY_UTILITY_H
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "PerfBuffer.h"
-
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-
-#include "Buffer.h"
-#include "Logging.h"
-#include "Sender.h"
-#include "SessionData.h"
-
-PerfBuffer::PerfBuffer() {
- for (int cpu = 0; cpu < ARRAY_LENGTH(mBuf); ++cpu) {
- mBuf[cpu] = MAP_FAILED;
- mDiscard[cpu] = false;
- }
-}
-
-PerfBuffer::~PerfBuffer() {
- for (int cpu = ARRAY_LENGTH(mBuf) - 1; cpu >= 0; --cpu) {
- if (mBuf[cpu] != MAP_FAILED) {
- munmap(mBuf[cpu], gSessionData->mPageSize + BUF_SIZE);
- }
- }
-}
-
-bool PerfBuffer::useFd(const int cpu, const int fd, const int groupFd) {
- if (fd == groupFd) {
- if (mBuf[cpu] != MAP_FAILED) {
- logg->logMessage("%s(%s:%i): cpu %i already online or not correctly cleaned up", __FUNCTION__, __FILE__, __LINE__, cpu);
- return false;
- }
-
- // The buffer isn't mapped yet
- mBuf[cpu] = mmap(NULL, gSessionData->mPageSize + BUF_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- if (mBuf[cpu] == MAP_FAILED) {
- logg->logMessage("%s(%s:%i): mmap failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
-
- // Check the version
- struct perf_event_mmap_page *pemp = static_cast<struct perf_event_mmap_page *>(mBuf[cpu]);
- if (pemp->compat_version != 0) {
- logg->logMessage("%s(%s:%i): Incompatible perf_event_mmap_page compat_version", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
- } else {
- if (mBuf[cpu] == MAP_FAILED) {
- logg->logMessage("%s(%s:%i): cpu already online or not correctly cleaned up", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
-
- if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, groupFd) < 0) {
- logg->logMessage("%s(%s:%i): ioctl failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
- }
-
- return true;
-}
-
-void PerfBuffer::discard(const int cpu) {
- if (mBuf[cpu] != MAP_FAILED) {
- mDiscard[cpu] = true;
- }
-}
-
-bool PerfBuffer::isEmpty() {
- for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) {
- if (mBuf[cpu] != MAP_FAILED) {
- // Take a snapshot of the positions
- struct perf_event_mmap_page *pemp = static_cast<struct perf_event_mmap_page *>(mBuf[cpu]);
- const __u64 head = pemp->data_head;
- const __u64 tail = pemp->data_tail;
-
- if (head != tail) {
- return false;
- }
- }
- }
-
- return true;
-}
-
-bool PerfBuffer::send(Sender *const sender) {
- for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) {
- if (mBuf[cpu] == MAP_FAILED) {
- continue;
- }
-
- // Take a snapshot of the positions
- struct perf_event_mmap_page *pemp = static_cast<struct perf_event_mmap_page *>(mBuf[cpu]);
- const __u64 head = pemp->data_head;
- const __u64 tail = pemp->data_tail;
-
- if (head > tail) {
- const uint8_t *const b = static_cast<uint8_t *>(mBuf[cpu]) + gSessionData->mPageSize;
- const int offset = gSessionData->mLocalCapture ? 1 : 0;
- unsigned char header[7];
- header[0] = RESPONSE_APC_DATA;
- Buffer::writeLEInt(header + 1, head - tail + sizeof(header) - 5);
- // Should use real packing functions
- header[5] = FRAME_PERF;
- header[6] = cpu;
-
- // Write header
- sender->writeData(reinterpret_cast<const char *>(&header) + offset, sizeof(header) - offset, RESPONSE_APC_DATA);
-
- // Write data
- if ((head & ~BUF_MASK) == (tail & ~BUF_MASK)) {
- // Not wrapped
- sender->writeData(reinterpret_cast<const char *>(b + (tail & BUF_MASK)), head - tail, RESPONSE_APC_DATA);
- } else {
- // Wrapped
- sender->writeData(reinterpret_cast<const char *>(b + (tail & BUF_MASK)), BUF_SIZE - (tail & BUF_MASK), RESPONSE_APC_DATA);
- sender->writeData(reinterpret_cast<const char *>(b), head & BUF_MASK, RESPONSE_APC_DATA);
- }
-
- // Update tail with the data read
- pemp->data_tail = head;
- }
-
- if (mDiscard[cpu]) {
- munmap(mBuf[cpu], gSessionData->mPageSize + BUF_SIZE);
- mBuf[cpu] = MAP_FAILED;
- mDiscard[cpu] = false;
- logg->logMessage("%s(%s:%i): Unmaped cpu %i", __FUNCTION__, __FILE__, __LINE__, cpu);
- }
- }
-
- return true;
-}
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef PERF_BUFFER
-#define PERF_BUFFER
-
-#include "Config.h"
-
-#define BUF_SIZE (gSessionData->mTotalBufferSize * 1024 * 1024)
-#define BUF_MASK (BUF_SIZE - 1)
-
-class Sender;
-
-class PerfBuffer {
-public:
- PerfBuffer();
- ~PerfBuffer();
-
- bool useFd(const int cpu, const int fd, const int groupFd);
- void discard(const int cpu);
- bool isEmpty();
- bool send(Sender *const sender);
-
-private:
- void *mBuf[NR_CPUS];
- // After the buffer is flushed it should be unmaped
- bool mDiscard[NR_CPUS];
-
- // Intentionally undefined
- PerfBuffer(const PerfBuffer &);
- PerfBuffer &operator=(const PerfBuffer &);
-};
-
-#endif // PERF_BUFFER
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "PerfDriver.h"
-
-#include <dirent.h>
-#include <sys/utsname.h>
-#include <time.h>
-
-#include "Buffer.h"
-#include "Config.h"
-#include "ConfigurationXML.h"
-#include "Counter.h"
-#include "DriverSource.h"
-#include "DynBuf.h"
-#include "Logging.h"
-#include "PerfGroup.h"
-#include "SessionData.h"
-
-#define PERF_DEVICES "/sys/bus/event_source/devices"
-
-#define TYPE_DERIVED ~0U
-
-// From gator.h
-struct gator_cpu {
- const int cpuid;
- // Human readable name
- const char core_name[32];
- // gatorfs event and Perf PMU name
- const char *const pmnc_name;
- const int pmnc_counters;
-};
-
-// From gator_main.c
-static const struct gator_cpu gator_cpus[] = {
- { 0xb36, "ARM1136", "ARM_ARM11", 3 },
- { 0xb56, "ARM1156", "ARM_ARM11", 3 },
- { 0xb76, "ARM1176", "ARM_ARM11", 3 },
- { 0xb02, "ARM11MPCore", "ARM_ARM11MPCore", 3 },
- { 0xc05, "Cortex-A5", "ARMv7_Cortex_A5", 2 },
- { 0xc07, "Cortex-A7", "ARMv7_Cortex_A7", 4 },
- { 0xc08, "Cortex-A8", "ARMv7_Cortex_A8", 4 },
- { 0xc09, "Cortex-A9", "ARMv7_Cortex_A9", 6 },
- { 0xc0d, "Cortex-A12", "ARMv7_Cortex_A12", 6 },
- { 0xc0f, "Cortex-A15", "ARMv7_Cortex_A15", 6 },
- { 0xc0e, "Cortex-A17", "ARMv7_Cortex_A17", 6 },
- { 0x00f, "Scorpion", "Scorpion", 4 },
- { 0x02d, "ScorpionMP", "ScorpionMP", 4 },
- { 0x049, "KraitSIM", "Krait", 4 },
- { 0x04d, "Krait", "Krait", 4 },
- { 0x06f, "Krait S4 Pro", "Krait", 4 },
- { 0xd03, "Cortex-A53", "ARM_Cortex-A53", 6 },
- { 0xd07, "Cortex-A57", "ARM_Cortex-A57", 6 },
- { 0xd0f, "AArch64", "ARM_AArch64", 6 },
-};
-
-static const char OLD_PMU_PREFIX[] = "ARMv7 Cortex-";
-static const char NEW_PMU_PREFIX[] = "ARMv7_Cortex_";
-
-class PerfCounter {
-public:
- PerfCounter(PerfCounter *next, const char *name, uint32_t type, uint64_t config) : mNext(next), mName(name), mType(type), mCount(0), mKey(getEventKey()), mConfig(config), mEnabled(false) {}
- ~PerfCounter() {
- delete [] mName;
- }
-
- PerfCounter *getNext() const { return mNext; }
- const char *getName() const { return mName; }
- uint32_t getType() const { return mType; }
- int getCount() const { return mCount; }
- void setCount(const int count) { mCount = count; }
- int getKey() const { return mKey; }
- uint64_t getConfig() const { return mConfig; }
- void setConfig(const uint64_t config) { mConfig = config; }
- bool isEnabled() const { return mEnabled; }
- void setEnabled(const bool enabled) { mEnabled = enabled; }
-
-private:
- PerfCounter *const mNext;
- const char *const mName;
- const uint32_t mType;
- int mCount;
- const int mKey;
- uint64_t mConfig;
- bool mEnabled;
-};
-
-PerfDriver::PerfDriver() : mCounters(NULL), mIsSetup(false) {
-}
-
-PerfDriver::~PerfDriver() {
- while (mCounters != NULL) {
- PerfCounter *counter = mCounters;
- mCounters = counter->getNext();
- delete counter;
- }
-}
-
-void PerfDriver::addCpuCounters(const char *const counterName, const int type, const int numCounters) {
- int len = snprintf(NULL, 0, "%s_ccnt", counterName) + 1;
- char *name = new char[len];
- snprintf(name, len, "%s_ccnt", counterName);
- mCounters = new PerfCounter(mCounters, name, type, -1);
-
- for (int j = 0; j < numCounters; ++j) {
- len = snprintf(NULL, 0, "%s_cnt%d", counterName, j) + 1;
- name = new char[len];
- snprintf(name, len, "%s_cnt%d", counterName, j);
- mCounters = new PerfCounter(mCounters, name, type, -1);
- }
-}
-
-// From include/generated/uapi/linux/version.h
-#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
-
-bool PerfDriver::setup() {
- // Check the kernel version
- struct utsname utsname;
- if (uname(&utsname) != 0) {
- logg->logMessage("%s(%s:%i): uname failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
-
- int release[3] = { 0, 0, 0 };
- int part = 0;
- char *ch = utsname.release;
- while (*ch >= '0' && *ch <= '9' && part < ARRAY_LENGTH(release)) {
- release[part] = 10*release[part] + *ch - '0';
-
- ++ch;
- if (*ch == '.') {
- ++part;
- ++ch;
- }
- }
-
- if (KERNEL_VERSION(release[0], release[1], release[2]) < KERNEL_VERSION(3, 12, 0)) {
- logg->logMessage("%s(%s:%i): Unsupported kernel version", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
-
- // Add supported PMUs
- bool foundCpu = false;
- DIR *dir = opendir(PERF_DEVICES);
- if (dir == NULL) {
- logg->logMessage("%s(%s:%i): opendif failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
-
- struct dirent *dirent;
- while ((dirent = readdir(dir)) != NULL) {
- for (int i = 0; i < ARRAY_LENGTH(gator_cpus); ++i) {
- // Do the names match exactly?
- if (strcmp(dirent->d_name, gator_cpus[i].pmnc_name) != 0 &&
- // Do these names match but have the old vs new prefix?
- (strncmp(dirent->d_name, OLD_PMU_PREFIX, sizeof(OLD_PMU_PREFIX) - 1) != 0 ||
- strncmp(gator_cpus[i].pmnc_name, NEW_PMU_PREFIX, sizeof(NEW_PMU_PREFIX) - 1) != 0 ||
- strcmp(dirent->d_name + sizeof(OLD_PMU_PREFIX) - 1, gator_cpus[i].pmnc_name + sizeof(NEW_PMU_PREFIX) - 1) != 0)) {
- continue;
- }
-
- int type;
- char buf[256];
- snprintf(buf, sizeof(buf), PERF_DEVICES "/%s/type", dirent->d_name);
- if (DriverSource::readIntDriver(buf, &type) != 0) {
- continue;
- }
-
- foundCpu = true;
- addCpuCounters(gator_cpus[i].pmnc_name, type, gator_cpus[i].pmnc_counters);
- }
- }
- closedir(dir);
-
- if (!foundCpu) {
- // If no cpu was found based on pmu names, try by cpuid
- for (int i = 0; i < ARRAY_LENGTH(gator_cpus); ++i) {
- if (gSessionData->mMaxCpuId != gator_cpus[i].cpuid) {
- continue;
- }
-
- foundCpu = true;
- addCpuCounters(gator_cpus[i].pmnc_name, PERF_TYPE_RAW, gator_cpus[i].pmnc_counters);
- }
- }
-
- /*
- if (!foundCpu) {
- // If all else fails, use the perf architected counters
- // 9 because that's how many are in events-Perf-Hardware.xml - assume they can all be enabled at once
- addCpuCounters("Perf_Hardware", PERF_TYPE_HARDWARE, 9);
- }
- */
-
- // Add supported software counters
- long long id;
- DynBuf printb;
-
- id = getTracepointId("irq/softirq_exit", &printb);
- if (id >= 0) {
- mCounters = new PerfCounter(mCounters, "Linux_irq_softirq", PERF_TYPE_TRACEPOINT, id);
- }
-
- id = getTracepointId("irq/irq_handler_exit", &printb);
- if (id >= 0) {
- mCounters = new PerfCounter(mCounters, "Linux_irq_irq", PERF_TYPE_TRACEPOINT, id);
- }
-
- //Linux_block_rq_wr
- //Linux_block_rq_rd
- //Linux_net_rx
- //Linux_net_tx
-
- id = getTracepointId(SCHED_SWITCH, &printb);
- if (id >= 0) {
- mCounters = new PerfCounter(mCounters, "Linux_sched_switch", PERF_TYPE_TRACEPOINT, id);
- }
-
- //Linux_meminfo_memused
- //Linux_meminfo_memfree
- //Linux_meminfo_bufferram
- //Linux_power_cpu_freq
- //Linux_power_cpu_idle
-
- mCounters = new PerfCounter(mCounters, "Linux_cpu_wait_contention", TYPE_DERIVED, -1);
-
- //Linux_cpu_wait_io
-
- mIsSetup = true;
- return true;
-}
-
-bool PerfDriver::summary(Buffer *const buffer) {
- struct utsname utsname;
- if (uname(&utsname) != 0) {
- logg->logMessage("%s(%s:%i): uname failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
-
- char buf[512];
- snprintf(buf, sizeof(buf), "%s %s %s %s %s GNU/Linux", utsname.sysname, utsname.nodename, utsname.release, utsname.version, utsname.machine);
-
- struct timespec ts;
- if (clock_gettime(CLOCK_REALTIME, &ts) != 0) {
- logg->logMessage("%s(%s:%i): clock_gettime failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
- const int64_t timestamp = (int64_t)ts.tv_sec * 1000000000L + ts.tv_nsec;
-
- if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
- logg->logMessage("%s(%s:%i): clock_gettime failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
- const int64_t uptime = (int64_t)ts.tv_sec * 1000000000L + ts.tv_nsec;
-
- buffer->summary(timestamp, uptime, 0, buf);
-
- for (int i = 0; i < gSessionData->mCores; ++i) {
- int j;
- for (j = 0; j < ARRAY_LENGTH(gator_cpus); ++j) {
- if (gator_cpus[j].cpuid == gSessionData->mCpuIds[i]) {
- break;
- }
- }
- if (gator_cpus[j].cpuid == gSessionData->mCpuIds[i]) {
- buffer->coreName(i, gSessionData->mCpuIds[i], gator_cpus[j].core_name);
- } else {
- snprintf(buf, sizeof(buf), "Unknown (0x%.3x)", gSessionData->mCpuIds[i]);
- buffer->coreName(i, gSessionData->mCpuIds[i], buf);
- }
- }
- buffer->commit(1);
-
- return true;
-}
-
-PerfCounter *PerfDriver::findCounter(const Counter &counter) const {
- for (PerfCounter * perfCounter = mCounters; perfCounter != NULL; perfCounter = perfCounter->getNext()) {
- if (strcmp(perfCounter->getName(), counter.getType()) == 0) {
- return perfCounter;
- }
- }
-
- return NULL;
-}
-
-bool PerfDriver::claimCounter(const Counter &counter) const {
- return findCounter(counter) != NULL;
-}
-
-void PerfDriver::resetCounters() {
- for (PerfCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) {
- counter->setEnabled(false);
- }
-}
-
-void PerfDriver::setupCounter(Counter &counter) {
- PerfCounter *const perfCounter = findCounter(counter);
- if (perfCounter == NULL) {
- counter.setEnabled(false);
- return;
- }
-
- // Don't use the config from counters XML if it's not set, ex: software counters
- if (counter.getEvent() != -1) {
- perfCounter->setConfig(counter.getEvent());
- }
- perfCounter->setCount(counter.getCount());
- perfCounter->setEnabled(true);
- counter.setKey(perfCounter->getKey());
-}
-
-int PerfDriver::writeCounters(mxml_node_t *root) const {
- int count = 0;
- for (PerfCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) {
- mxml_node_t *node = mxmlNewElement(root, "counter");
- mxmlElementSetAttr(node, "name", counter->getName());
- ++count;
- }
-
- return count;
-}
-
-bool PerfDriver::enable(PerfGroup *group, Buffer *const buffer) const {
- for (PerfCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) {
- if (counter->isEnabled() && (counter->getType() != TYPE_DERIVED)) {
- if (!group->add(buffer, counter->getKey(), counter->getType(), counter->getConfig(), counter->getCount(), 0, 0)) {
- logg->logMessage("%s(%s:%i): PerfGroup::add failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
- }
- }
-
- return true;
-}
-
-long long PerfDriver::getTracepointId(const char *const name, DynBuf *const printb) {
- if (!printb->printf(EVENTS_PATH "/%s/id", name)) {
- logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
- return -1;
- }
-
- int64_t result;
- if (DriverSource::readInt64Driver(printb->getBuf(), &result) != 0) {
- logg->logMessage("%s(%s:%i): DriverSource::readInt64Driver failed", __FUNCTION__, __FILE__, __LINE__);
- return -1;
- }
-
- return result;
-}
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef PERFDRIVER_H
-#define PERFDRIVER_H
-
-#include "Driver.h"
-
-// If debugfs is not mounted at /sys/kernel/debug, update DEBUGFS_PATH
-#define DEBUGFS_PATH "/sys/kernel/debug"
-#define EVENTS_PATH DEBUGFS_PATH "/tracing/events"
-
-#define SCHED_SWITCH "sched/sched_switch"
-
-class Buffer;
-class DynBuf;
-class PerfCounter;
-class PerfGroup;
-
-class PerfDriver : public Driver {
-public:
- PerfDriver();
- ~PerfDriver();
-
- bool setup();
- bool summary(Buffer *const buffer);
- bool isSetup() const { return mIsSetup; }
-
- bool claimCounter(const Counter &counter) const;
- void resetCounters();
- void setupCounter(Counter &counter);
-
- int writeCounters(mxml_node_t *root) const;
-
- bool enable(PerfGroup *group, Buffer *const buffer) const;
-
- static long long getTracepointId(const char *const name, DynBuf *const printb);
-
-private:
- PerfCounter *findCounter(const Counter &counter) const;
- void addCpuCounters(const char *const counterName, const int type, const int numCounters);
-
- PerfCounter *mCounters;
- bool mIsSetup;
-
- // Intentionally undefined
- PerfDriver(const PerfDriver &);
- PerfDriver &operator=(const PerfDriver &);
-};
-
-#endif // PERFDRIVER_H
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "PerfGroup.h"
-
-#include <errno.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/syscall.h>
-#include <unistd.h>
-
-#include "Buffer.h"
-#include "Logging.h"
-#include "Monitor.h"
-#include "PerfBuffer.h"
-#include "SessionData.h"
-
-#define DEFAULT_PEA_ARGS(pea, additionalSampleType) \
- pea.size = sizeof(pea); \
- /* Emit time, read_format below, group leader id, and raw tracepoint info */ \
- pea.sample_type = PERF_SAMPLE_TIME | PERF_SAMPLE_READ | PERF_SAMPLE_IDENTIFIER | additionalSampleType; \
- /* Emit emit value in group format */ \
- pea.read_format = PERF_FORMAT_ID | PERF_FORMAT_GROUP; \
- /* start out disabled */ \
- pea.disabled = 1; \
- /* have a sampling interrupt happen when we cross the wakeup_watermark boundary */ \
- pea.watermark = 1; \
- /* Be conservative in flush size as only one buffer set is monitored */ \
- pea.wakeup_watermark = 3 * BUF_SIZE / 4
-
-static int sys_perf_event_open(struct perf_event_attr *const attr, const pid_t pid, const int cpu, const int group_fd, const unsigned long flags) {
- return syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags);
-}
-
-PerfGroup::PerfGroup(PerfBuffer *const pb) : mPb(pb) {
- memset(&mAttrs, 0, sizeof(mAttrs));
- memset(&mKeys, -1, sizeof(mKeys));
- memset(&mFds, -1, sizeof(mFds));
-}
-
-PerfGroup::~PerfGroup() {
- for (int pos = ARRAY_LENGTH(mFds) - 1; pos >= 0; --pos) {
- if (mFds[pos] >= 0) {
- close(mFds[pos]);
- }
- }
-}
-
-bool PerfGroup::add(Buffer *const buffer, const int key, const __u32 type, const __u64 config, const __u64 sample, const __u64 sampleType, const int flags) {
- int i;
- for (i = 0; i < ARRAY_LENGTH(mKeys); ++i) {
- if (mKeys[i] < 0) {
- break;
- }
- }
-
- if (i >= ARRAY_LENGTH(mKeys)) {
- logg->logMessage("%s(%s:%i): Too many counters", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
-
- DEFAULT_PEA_ARGS(mAttrs[i], sampleType);
- mAttrs[i].type = type;
- mAttrs[i].config = config;
- mAttrs[i].sample_period = sample;
- // always be on the CPU but only a group leader can be pinned
- mAttrs[i].pinned = (i == 0 ? 1 : 0);
- mAttrs[i].mmap = (flags & PERF_GROUP_MMAP ? 1 : 0);
- mAttrs[i].comm = (flags & PERF_GROUP_COMM ? 1 : 0);
- mAttrs[i].freq = (flags & PERF_GROUP_FREQ ? 1 : 0);
- mAttrs[i].task = (flags & PERF_GROUP_TASK ? 1 : 0);
- mAttrs[i].sample_id_all = (flags & PERF_GROUP_SAMPLE_ID_ALL ? 1 : 0);
-
- mKeys[i] = key;
-
- buffer->pea(&mAttrs[i], key);
-
- return true;
-}
-
-bool PerfGroup::prepareCPU(const int cpu) {
- logg->logMessage("%s(%s:%i): Onlining cpu %i", __FUNCTION__, __FILE__, __LINE__, cpu);
-
- for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) {
- if (mKeys[i] < 0) {
- continue;
- }
-
- const int offset = i * gSessionData->mCores;
- if (mFds[cpu + offset] >= 0) {
- logg->logMessage("%s(%s:%i): cpu already online or not correctly cleaned up", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
-
- logg->logMessage("%s(%s:%i): perf_event_open cpu: %i type: %lli config: %lli sample: %lli sample_type: %lli", __FUNCTION__, __FILE__, __LINE__, cpu, (long long)mAttrs[i].type, (long long)mAttrs[i].config, (long long)mAttrs[i].sample_period, (long long)mAttrs[i].sample_type);
- mFds[cpu + offset] = sys_perf_event_open(&mAttrs[i], -1, cpu, i == 0 ? -1 : mFds[cpu], i == 0 ? 0 : PERF_FLAG_FD_OUTPUT);
- if (mFds[cpu + offset] < 0) {
- logg->logMessage("%s(%s:%i): failed %s", __FUNCTION__, __FILE__, __LINE__, strerror(errno));
- continue;
- }
-
- if (!mPb->useFd(cpu, mFds[cpu + offset], mFds[cpu])) {
- logg->logMessage("%s(%s:%i): PerfBuffer::useFd failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
- }
-
- return true;
-}
-
-int PerfGroup::onlineCPU(const int cpu, const bool start, Buffer *const buffer, Monitor *const monitor) {
- __u64 ids[ARRAY_LENGTH(mKeys)];
- int coreKeys[ARRAY_LENGTH(mKeys)];
- int idCount = 0;
-
- for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) {
- const int fd = mFds[cpu + i * gSessionData->mCores];
- if (fd < 0) {
- continue;
- }
-
- coreKeys[idCount] = mKeys[i];
- if (ioctl(fd, PERF_EVENT_IOC_ID, &ids[idCount]) != 0) {
- logg->logMessage("%s(%s:%i): ioctl failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
- ++idCount;
- }
-
- if (!monitor->add(mFds[cpu])) {
- logg->logMessage("%s(%s:%i): Monitor::add failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
-
- buffer->keys(idCount, ids, coreKeys);
-
- if (start) {
- for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) {
- int offset = i * gSessionData->mCores + cpu;
- if (mFds[offset] >= 0 && ioctl(mFds[offset], PERF_EVENT_IOC_ENABLE) < 0) {
- logg->logMessage("%s(%s:%i): ioctl failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
- }
- }
-
- return idCount;
-}
-
-bool PerfGroup::offlineCPU(const int cpu) {
- logg->logMessage("%s(%s:%i): Offlining cpu %i", __FUNCTION__, __FILE__, __LINE__, cpu);
-
- for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) {
- int offset = i * gSessionData->mCores + cpu;
- if (mFds[offset] >= 0 && ioctl(mFds[offset], PERF_EVENT_IOC_DISABLE) < 0) {
- logg->logMessage("%s(%s:%i): ioctl failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
- }
-
- // Mark the buffer so that it will be released next time it's read
- mPb->discard(cpu);
-
- for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) {
- if (mKeys[i] < 0) {
- continue;
- }
-
- int offset = i * gSessionData->mCores + cpu;
- if (mFds[offset] >= 0) {
- close(mFds[offset]);
- mFds[offset] = -1;
- }
- }
-
- return true;
-}
-
-bool PerfGroup::start() {
- for (int pos = 0; pos < ARRAY_LENGTH(mFds); ++pos) {
- if (mFds[pos] >= 0 && ioctl(mFds[pos], PERF_EVENT_IOC_ENABLE) < 0) {
- logg->logMessage("%s(%s:%i): ioctl failed", __FUNCTION__, __FILE__, __LINE__);
- goto fail;
- }
- }
-
- return true;
-
- fail:
- stop();
-
- return false;
-}
-
-void PerfGroup::stop() {
- for (int pos = ARRAY_LENGTH(mFds) - 1; pos >= 0; --pos) {
- if (mFds[pos] >= 0) {
- ioctl(mFds[pos], PERF_EVENT_IOC_DISABLE);
- }
- }
-}
+++ /dev/null
- /**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef PERF_GROUP
-#define PERF_GROUP
-
-// Use a snapshot of perf_event.h as it may be more recent than what is on the target and if not newer features won't be supported anyways
-#include "k/perf_event.h"
-
-#include "Config.h"
-
-class Buffer;
-class Monitor;
-class PerfBuffer;
-
-enum PerfGroupFlags {
- PERF_GROUP_MMAP = 1 << 0,
- PERF_GROUP_COMM = 1 << 1,
- PERF_GROUP_FREQ = 1 << 2,
- PERF_GROUP_TASK = 1 << 3,
- PERF_GROUP_SAMPLE_ID_ALL = 1 << 4,
-};
-
-class PerfGroup {
-public:
- PerfGroup(PerfBuffer *const pb);
- ~PerfGroup();
-
- bool add(Buffer *const buffer, const int key, const __u32 type, const __u64 config, const __u64 sample, const __u64 sampleType, const int flags);
- // Safe to call concurrently
- bool prepareCPU(const int cpu);
- // Not safe to call concurrently. Returns the number of events enabled
- int onlineCPU(const int cpu, const bool start, Buffer *const buffer, Monitor *const monitor);
- bool offlineCPU(int cpu);
- bool start();
- void stop();
-
-private:
- // +1 for the group leader
- struct perf_event_attr mAttrs[MAX_PERFORMANCE_COUNTERS + 1];
- int mKeys[MAX_PERFORMANCE_COUNTERS + 1];
- int mFds[NR_CPUS * (MAX_PERFORMANCE_COUNTERS + 1)];
- PerfBuffer *const mPb;
-
- // Intentionally undefined
- PerfGroup(const PerfGroup &);
- PerfGroup &operator=(const PerfGroup &);
-};
-
-#endif // PERF_GROUP
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "PerfSource.h"
-
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "Child.h"
-#include "DynBuf.h"
-#include "Logging.h"
-#include "PerfDriver.h"
-#include "Proc.h"
-#include "SessionData.h"
-
-#define MS_PER_US 1000000
-
-extern Child *child;
-
-static bool sendTracepointFormat(Buffer *const buffer, const char *const name, DynBuf *const printb, DynBuf *const b) {
- if (!printb->printf(EVENTS_PATH "/%s/format", name)) {
- logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
- if (!b->read(printb->getBuf())) {
- logg->logMessage("%s(%s:%i): DynBuf::read failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
- buffer->format(b->getLength(), b->getBuf());
-
- return true;
-}
-
-PerfSource::PerfSource(sem_t *senderSem, sem_t *startProfile) : mSummary(0, FRAME_SUMMARY, 1024, senderSem), mBuffer(0, FRAME_PERF_ATTRS, 1024*1024, senderSem), mCountersBuf(), mCountersGroup(&mCountersBuf), mMonitor(), mUEvent(), mSenderSem(senderSem), mStartProfile(startProfile), mInterruptFd(-1), mIsDone(false) {
- long l = sysconf(_SC_PAGE_SIZE);
- if (l < 0) {
- logg->logError(__FILE__, __LINE__, "Unable to obtain the page size");
- handleException();
- }
- gSessionData->mPageSize = static_cast<int>(l);
-
- l = sysconf(_SC_NPROCESSORS_CONF);
- if (l < 0) {
- logg->logError(__FILE__, __LINE__, "Unable to obtain the number of cores");
- handleException();
- }
- gSessionData->mCores = static_cast<int>(l);
-}
-
-PerfSource::~PerfSource() {
-}
-
-struct PrepareParallelArgs {
- PerfGroup *pg;
- int cpu;
-};
-
-void *prepareParallel(void *arg) {
- const PrepareParallelArgs *const args = (PrepareParallelArgs *)arg;
- args->pg->prepareCPU(args->cpu);
- return NULL;
-}
-
-bool PerfSource::prepare() {
- DynBuf printb;
- DynBuf b1;
- DynBuf b2;
- DynBuf b3;
- long long schedSwitchId;
-
- if (0
- || !mMonitor.init()
- || !mUEvent.init()
- || !mMonitor.add(mUEvent.getFd())
-
- || (schedSwitchId = PerfDriver::getTracepointId(SCHED_SWITCH, &printb)) < 0
- || !sendTracepointFormat(&mBuffer, SCHED_SWITCH, &printb, &b1)
-
- // Only want RAW but not IP on sched_switch and don't want TID on SAMPLE_ID
- || !mCountersGroup.add(&mBuffer, 100/**/, PERF_TYPE_TRACEPOINT, schedSwitchId, 1, PERF_SAMPLE_RAW, PERF_GROUP_MMAP | PERF_GROUP_COMM | PERF_GROUP_TASK | PERF_GROUP_SAMPLE_ID_ALL)
-
- // Only want TID and IP but not RAW on timer
- || (gSessionData->mSampleRate > 0 && !gSessionData->mIsEBS && !mCountersGroup.add(&mBuffer, 99/**/, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK, 1000000000UL / gSessionData->mSampleRate, PERF_SAMPLE_TID | PERF_SAMPLE_IP, 0))
-
- || !gSessionData->perf.enable(&mCountersGroup, &mBuffer)
- || 0) {
- logg->logMessage("%s(%s:%i): perf setup failed, are you running Linux 3.12 or later?", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
-
- if (!gSessionData->perf.summary(&mSummary)) {
- logg->logMessage("%s(%s:%i): PerfDriver::summary failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
-
- {
- // Run prepareCPU in parallel as perf_event_open can take more than 1 sec in some cases
- pthread_t threads[NR_CPUS];
- PrepareParallelArgs args[NR_CPUS];
- for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) {
- args[cpu].pg = &mCountersGroup;
- args[cpu].cpu = cpu;
- if (pthread_create(&threads[cpu], NULL, prepareParallel, &args[cpu]) != 0) {
- logg->logMessage("%s(%s:%i): pthread_create failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
- }
- for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) {
- if (pthread_join(threads[cpu], NULL) != 0) {
- logg->logMessage("%s(%s:%i): pthread_join failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
- }
- }
-
- int numEvents = 0;
- for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) {
- numEvents += mCountersGroup.onlineCPU(cpu, false, &mBuffer, &mMonitor);
- }
- if (numEvents <= 0) {
- logg->logMessage("%s(%s:%i): PerfGroup::onlineCPU failed on all cores", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
-
- // Start events before reading proc to avoid race conditions
- if (!mCountersGroup.start()) {
- logg->logMessage("%s(%s:%i): PerfGroup::start failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
-
- if (!readProc(&mBuffer, &printb, &b1, &b2, &b3)) {
- logg->logMessage("%s(%s:%i): readProc failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
-
- mBuffer.commit(1);
-
- return true;
-}
-
-static const char CPU_DEVPATH[] = "/devices/system/cpu/cpu";
-
-void PerfSource::run() {
- int pipefd[2];
-
- if (pipe(pipefd) != 0) {
- logg->logError(__FILE__, __LINE__, "pipe failed");
- handleException();
- }
- mInterruptFd = pipefd[1];
-
- if (!mMonitor.add(pipefd[0])) {
- logg->logError(__FILE__, __LINE__, "Monitor::add failed");
- handleException();
- }
-
- int timeout = -1;
- if (gSessionData->mLiveRate > 0) {
- timeout = gSessionData->mLiveRate/MS_PER_US;
- }
-
- sem_post(mStartProfile);
-
- while (gSessionData->mSessionIsActive) {
- // +1 for uevents, +1 for pipe
- struct epoll_event events[NR_CPUS + 2];
- int ready = mMonitor.wait(events, ARRAY_LENGTH(events), timeout);
- if (ready < 0) {
- logg->logError(__FILE__, __LINE__, "Monitor::wait failed");
- handleException();
- }
-
- for (int i = 0; i < ready; ++i) {
- if (events[i].data.fd == mUEvent.getFd()) {
- if (!handleUEvent()) {
- logg->logError(__FILE__, __LINE__, "PerfSource::handleUEvent failed");
- handleException();
- }
- break;
- }
- }
-
- // send a notification that data is ready
- sem_post(mSenderSem);
-
- // In one shot mode, stop collection once all the buffers are filled
- // Assume timeout == 0 in this case
- if (gSessionData->mOneShot && gSessionData->mSessionIsActive) {
- logg->logMessage("%s(%s:%i): One shot", __FUNCTION__, __FILE__, __LINE__);
- child->endSession();
- }
- }
-
- mCountersGroup.stop();
- mBuffer.setDone();
- mIsDone = true;
-
- // send a notification that data is ready
- sem_post(mSenderSem);
-
- mInterruptFd = -1;
- close(pipefd[0]);
- close(pipefd[1]);
-}
-
-bool PerfSource::handleUEvent() {
- UEventResult result;
- if (!mUEvent.read(&result)) {
- logg->logMessage("%s(%s:%i): UEvent::Read failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
-
- if (strcmp(result.mSubsystem, "cpu") == 0) {
- if (strncmp(result.mDevPath, CPU_DEVPATH, sizeof(CPU_DEVPATH) - 1) != 0) {
- logg->logMessage("%s(%s:%i): Unexpected cpu DEVPATH format", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
- char *endptr;
- errno = 0;
- int cpu = strtol(result.mDevPath + sizeof(CPU_DEVPATH) - 1, &endptr, 10);
- if (errno != 0 || *endptr != '\0') {
- logg->logMessage("%s(%s:%i): strtol failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
- if (strcmp(result.mAction, "online") == 0) {
- // Only call onlineCPU if prepareCPU succeeded
- const bool result = mCountersGroup.prepareCPU(cpu) &&
- mCountersGroup.onlineCPU(cpu, true, &mBuffer, &mMonitor);
- mBuffer.commit(1);
- return result;
- } else if (strcmp(result.mAction, "offline") == 0) {
- return mCountersGroup.offlineCPU(cpu);
- }
- }
-
- return true;
-}
-
-void PerfSource::interrupt() {
- if (mInterruptFd >= 0) {
- int8_t c = 0;
- // Write to the pipe to wake the monitor which will cause mSessionIsActive to be reread
- if (::write(mInterruptFd, &c, sizeof(c)) != sizeof(c)) {
- logg->logError(__FILE__, __LINE__, "write failed");
- handleException();
- }
- }
-}
-
-bool PerfSource::isDone () {
- return mBuffer.isDone() && mIsDone && mCountersBuf.isEmpty();
-}
-
-void PerfSource::write (Sender *sender) {
- if (!mSummary.isDone()) {
- mSummary.write(sender);
- }
- if (!mBuffer.isDone()) {
- mBuffer.write(sender);
- }
- if (!mCountersBuf.send(sender)) {
- logg->logError(__FILE__, __LINE__, "PerfBuffer::send failed");
- handleException();
- }
-}
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef PERFSOURCE_H
-#define PERFSOURCE_H
-
-#include <semaphore.h>
-
-#include "Buffer.h"
-#include "Monitor.h"
-#include "PerfBuffer.h"
-#include "PerfGroup.h"
-#include "Source.h"
-#include "UEvent.h"
-
-class Sender;
-
-class PerfSource : public Source {
-public:
- PerfSource(sem_t *senderSem, sem_t *startProfile);
- ~PerfSource();
-
- bool prepare();
- void run();
- void interrupt();
-
- bool isDone();
- void write(Sender *sender);
-
-private:
- bool handleUEvent();
-
- Buffer mSummary;
- Buffer mBuffer;
- PerfBuffer mCountersBuf;
- PerfGroup mCountersGroup;
- Monitor mMonitor;
- UEvent mUEvent;
- sem_t *const mSenderSem;
- sem_t *const mStartProfile;
- int mInterruptFd;
- bool mIsDone;
-
- // Intentionally undefined
- PerfSource(const PerfSource &);
- PerfSource &operator=(const PerfSource &);
-};
-
-#endif // PERFSOURCE_H
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "Proc.h"
-
-#include <dirent.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "Buffer.h"
-#include "DynBuf.h"
-#include "Logging.h"
-
-struct ProcStat {
- // From linux-dev/include/linux/sched.h
-#define TASK_COMM_LEN 16
- // TASK_COMM_LEN may grow, so be ready for it to get larger
- char comm[2*TASK_COMM_LEN];
- long numThreads;
-};
-
-static bool readProcStat(ProcStat *const ps, const char *const pathname, DynBuf *const b) {
- if (!b->read(pathname)) {
- logg->logMessage("%s(%s:%i): DynBuf::read failed, likely because the thread exited", __FUNCTION__, __FILE__, __LINE__);
- // This is not a fatal error - the thread just doesn't exist any more
- return true;
- }
-
- char *comm = strchr(b->getBuf(), '(');
- if (comm == NULL) {
- logg->logMessage("%s(%s:%i): parsing stat failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
- ++comm;
- char *const str = strrchr(comm, ')');
- if (str == NULL) {
- logg->logMessage("%s(%s:%i): parsing stat failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
- *str = '\0';
- strncpy(ps->comm, comm, sizeof(ps->comm) - 1);
- ps->comm[sizeof(ps->comm) - 1] = '\0';
-
- const int count = sscanf(str + 2, " %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %ld", &ps->numThreads);
- if (count != 1) {
- logg->logMessage("%s(%s:%i): sscanf failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
-
- return true;
-}
-
-static bool readProcTask(Buffer *const buffer, const int pid, const char *const image, DynBuf *const printb, DynBuf *const b) {
- bool result = false;
-
- if (!b->printf("/proc/%i/task", pid)) {
- logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
- return result;
- }
- DIR *task = opendir(b->getBuf());
- if (task == NULL) {
- logg->logMessage("%s(%s:%i): opendir failed", __FUNCTION__, __FILE__, __LINE__);
- return result;
- }
-
- struct dirent *dirent;
- while ((dirent = readdir(task)) != NULL) {
- char *endptr;
- const int tid = strtol(dirent->d_name, &endptr, 10);
- if (*endptr != '\0') {
- // Ignore task items that are not integers like ., etc...
- continue;
- }
-
- if (!printb->printf("/proc/%i/task/%i/stat", pid, tid)) {
- logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
- goto fail;
- }
- ProcStat ps;
- if (!readProcStat(&ps, printb->getBuf(), b)) {
- logg->logMessage("%s(%s:%i): readProcStat failed", __FUNCTION__, __FILE__, __LINE__);
- goto fail;
- }
-
- buffer->comm(pid, tid, image, ps.comm);
- }
-
- result = true;
-
- fail:
- closedir(task);
-
- return result;
-}
-
-bool readProc(Buffer *const buffer, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2, DynBuf *const b3) {
- bool result = false;
-
- DIR *proc = opendir("/proc");
- if (proc == NULL) {
- logg->logMessage("%s(%s:%i): opendir failed", __FUNCTION__, __FILE__, __LINE__);
- return result;
- }
-
- struct dirent *dirent;
- while ((dirent = readdir(proc)) != NULL) {
- char *endptr;
- const int pid = strtol(dirent->d_name, &endptr, 10);
- if (*endptr != '\0') {
- // Ignore proc items that are not integers like ., cpuinfo, etc...
- continue;
- }
-
- if (!printb->printf("/proc/%i/stat", pid)) {
- logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
- goto fail;
- }
- ProcStat ps;
- if (!readProcStat(&ps, printb->getBuf(), b1)) {
- logg->logMessage("%s(%s:%i): readProcStat failed", __FUNCTION__, __FILE__, __LINE__);
- goto fail;
- }
-
- if (!printb->printf("/proc/%i/exe", pid)) {
- logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
- goto fail;
- }
- const int err = b1->readlink(printb->getBuf());
- const char *image;
- if (err == 0) {
- image = strrchr(b1->getBuf(), '/');
- if (image == NULL) {
- image = b1->getBuf();
- } else {
- ++image;
- }
- } else if (err == -ENOENT) {
- // readlink /proc/[pid]/exe returns ENOENT for kernel threads
- image = "\0";
- } else {
- logg->logMessage("%s(%s:%i): DynBuf::readlink failed", __FUNCTION__, __FILE__, __LINE__);
- goto fail;
- }
-
- if (!printb->printf("/proc/%i/maps", pid)) {
- logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
- goto fail;
- }
- if (!b2->read(printb->getBuf())) {
- logg->logMessage("%s(%s:%i): DynBuf::read failed, likely because the process exited", __FUNCTION__, __FILE__, __LINE__);
- // This is not a fatal error - the process just doesn't exist any more
- continue;
- }
-
- buffer->maps(pid, pid, b2->getBuf());
- if (ps.numThreads <= 1) {
- buffer->comm(pid, pid, image, ps.comm);
- } else {
- if (!readProcTask(buffer, pid, image, printb, b3)) {
- logg->logMessage("%s(%s:%i): readProcTask failed", __FUNCTION__, __FILE__, __LINE__);
- goto fail;
- }
- }
- }
-
- result = true;
-
- fail:
- closedir(proc);
-
- return result;
-}
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef PROC_H
-#define PROC_H
-
-class Buffer;
-class DynBuf;
-
-bool readProc(Buffer *const buffer, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2, DynBuf *const b3);
-
-#endif // PROC_H
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "Sender.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "Buffer.h"
-#include "Logging.h"
-#include "OlySocket.h"
-#include "SessionData.h"
-
-Sender::Sender(OlySocket* socket) {
- mDataFile = NULL;
- mDataSocket = NULL;
-
- // Set up the socket connection
- if (socket) {
- char streamline[64] = {0};
- mDataSocket = socket;
-
- // Receive magic sequence - can wait forever
- // Streamline will send data prior to the magic sequence for legacy support, which should be ignored for v4+
- while (strcmp("STREAMLINE", streamline) != 0) {
- if (mDataSocket->receiveString(streamline, sizeof(streamline)) == -1) {
- logg->logError(__FILE__, __LINE__, "Socket disconnected");
- handleException();
- }
- }
-
- // Send magic sequence - must be done first, after which error messages can be sent
- char magic[32];
- snprintf(magic, 32, "GATOR %i\n", PROTOCOL_VERSION);
- mDataSocket->send(magic, strlen(magic));
-
- gSessionData->mWaitingOnCommand = true;
- logg->logMessage("Completed magic sequence");
- }
-
- pthread_mutex_init(&mSendMutex, NULL);
-}
-
-Sender::~Sender() {
- // Just close it as the client socket is on the stack
- if (mDataSocket != NULL) {
- mDataSocket->closeSocket();
- mDataSocket = NULL;
- }
- if (mDataFile != NULL) {
- fclose(mDataFile);
- }
-}
-
-void Sender::createDataFile(char* apcDir) {
- if (apcDir == NULL) {
- return;
- }
-
- mDataFileName = (char*)malloc(strlen(apcDir) + 12);
- sprintf(mDataFileName, "%s/0000000000", apcDir);
- mDataFile = fopen(mDataFileName, "wb");
- if (!mDataFile) {
- logg->logError(__FILE__, __LINE__, "Failed to open binary file: %s", mDataFileName);
- handleException();
- }
-}
-
-template<typename T>
-inline T min(const T a, const T b) {
- return (a < b ? a : b);
-}
-
-void Sender::writeData(const char* data, int length, int type) {
- if (length < 0 || (data == NULL && length > 0)) {
- return;
- }
-
- // Multiple threads call writeData()
- pthread_mutex_lock(&mSendMutex);
-
- // Send data over the socket connection
- if (mDataSocket) {
- // Start alarm
- const int alarmDuration = 8;
- alarm(alarmDuration);
-
- // Send data over the socket, sending the type and size first
- logg->logMessage("Sending data with length %d", length);
- if (type != RESPONSE_APC_DATA) {
- // type and length already added by the Collector for apc data
- unsigned char header[5];
- header[0] = type;
- Buffer::writeLEInt(header + 1, length);
- mDataSocket->send((char*)&header, sizeof(header));
- }
-
- // 100Kbits/sec * alarmDuration sec / 8 bits/byte
- const int chunkSize = 100*1000 * alarmDuration / 8;
- int pos = 0;
- while (true) {
- mDataSocket->send((const char*)data + pos, min(length - pos, chunkSize));
- pos += chunkSize;
- if (pos >= length) {
- break;
- }
-
- // Reset the alarm
- alarm(alarmDuration);
- logg->logMessage("Resetting the alarm");
- }
-
- // Stop alarm
- alarm(0);
- }
-
- // Write data to disk as long as it is not meta data
- if (mDataFile && type == RESPONSE_APC_DATA) {
- logg->logMessage("Writing data with length %d", length);
- // Send data to the data file
- if (fwrite(data, 1, length, mDataFile) != (unsigned int)length) {
- logg->logError(__FILE__, __LINE__, "Failed writing binary file %s", mDataFileName);
- handleException();
- }
- }
-
- pthread_mutex_unlock(&mSendMutex);
-}
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __SENDER_H__
-#define __SENDER_H__
-
-#include <stdio.h>
-#include <pthread.h>
-
-class OlySocket;
-
-enum {
- RESPONSE_XML = 1,
- RESPONSE_APC_DATA = 3,
- RESPONSE_ACK = 4,
- RESPONSE_NAK = 5,
- RESPONSE_ERROR = 0xFF
-};
-
-class Sender {
-public:
- Sender(OlySocket* socket);
- ~Sender();
- void writeData(const char* data, int length, int type);
- void createDataFile(char* apcDir);
-private:
- OlySocket* mDataSocket;
- FILE* mDataFile;
- char* mDataFileName;
- pthread_mutex_t mSendMutex;
-
- // Intentionally unimplemented
- Sender(const Sender &);
- Sender &operator=(const Sender &);
-};
-
-#endif //__SENDER_H__
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "SessionData.h"
-
-#include <string.h>
-
-#include "SessionXML.h"
-#include "Logging.h"
-
-SessionData* gSessionData = NULL;
-
-SessionData::SessionData() {
- initialize();
-}
-
-SessionData::~SessionData() {
-}
-
-void SessionData::initialize() {
- mWaitingOnCommand = false;
- mSessionIsActive = false;
- mLocalCapture = false;
- mOneShot = false;
- readCpuInfo();
- mConfigurationXMLPath = NULL;
- mSessionXMLPath = NULL;
- mEventsXMLPath = NULL;
- mTargetPath = NULL;
- mAPCDir = NULL;
- mSampleRate = 0;
- mLiveRate = 0;
- mDuration = 0;
- mBacktraceDepth = 0;
- mTotalBufferSize = 0;
- // sysconf(_SC_NPROCESSORS_CONF) is unreliable on 2.6 Android, get the value from the kernel module
- mCores = 1;
- mPageSize = 0;
-}
-
-void SessionData::parseSessionXML(char* xmlString) {
- SessionXML session(xmlString);
- session.parse();
-
- // Set session data values - use prime numbers just below the desired value to reduce the chance of events firing at the same time
- if (strcmp(session.parameters.sample_rate, "high") == 0) {
- mSampleRate = 9973; // 10000
- } else if (strcmp(session.parameters.sample_rate, "normal") == 0) {
- mSampleRate = 997; // 1000
- } else if (strcmp(session.parameters.sample_rate, "low") == 0) {
- mSampleRate = 97; // 100
- } else if (strcmp(session.parameters.sample_rate, "none") == 0) {
- mSampleRate = 0;
- } else {
- logg->logError(__FILE__, __LINE__, "Invalid sample rate (%s) in session xml.", session.parameters.sample_rate);
- handleException();
- }
- mBacktraceDepth = session.parameters.call_stack_unwinding == true ? 128 : 0;
- mDuration = session.parameters.duration;
-
- // Determine buffer size (in MB) based on buffer mode
- mOneShot = true;
- if (strcmp(session.parameters.buffer_mode, "streaming") == 0) {
- mOneShot = false;
- mTotalBufferSize = 1;
- } else if (strcmp(session.parameters.buffer_mode, "small") == 0) {
- mTotalBufferSize = 1;
- } else if (strcmp(session.parameters.buffer_mode, "normal") == 0) {
- mTotalBufferSize = 4;
- } else if (strcmp(session.parameters.buffer_mode, "large") == 0) {
- mTotalBufferSize = 16;
- } else {
- logg->logError(__FILE__, __LINE__, "Invalid value for buffer mode in session xml.");
- handleException();
- }
-
- mImages = session.parameters.images;
- // Convert milli- to nanoseconds
- mLiveRate = session.parameters.live_rate * (int64_t)1000000;
- if (mLiveRate > 0 && mLocalCapture) {
- logg->logMessage("Local capture is not compatable with live, disabling live");
- mLiveRate = 0;
- }
-}
-
-void SessionData::readCpuInfo() {
- char temp[256]; // arbitrarily large amount
- strcpy(mCoreName, "unknown");
- memset(&mCpuIds, -1, sizeof(mCpuIds));
- mMaxCpuId = -1;
-
- FILE* f = fopen("/proc/cpuinfo", "r");
- if (f == NULL) {
- logg->logMessage("Error opening /proc/cpuinfo\n"
- "The core name in the captured xml file will be 'unknown'.");
- return;
- }
-
- bool foundCoreName = false;
- int processor = 0;
- while (fgets(temp, sizeof(temp), f)) {
- if (strlen(temp) > 0) {
- temp[strlen(temp) - 1] = 0; // Replace the line feed with a null
- }
-
- const bool foundHardware = strstr(temp, "Hardware") != 0;
- const bool foundCPUPart = strstr(temp, "CPU part") != 0;
- const bool foundProcessor = strstr(temp, "processor") != 0;
- if (foundHardware || foundCPUPart || foundProcessor) {
- char* position = strchr(temp, ':');
- if (position == NULL || (unsigned int)(position - temp) + 2 >= strlen(temp)) {
- logg->logMessage("Unknown format of /proc/cpuinfo\n"
- "The core name in the captured xml file will be 'unknown'.");
- return;
- }
- position += 2;
-
- if (foundHardware) {
- strncpy(mCoreName, position, sizeof(mCoreName));
- mCoreName[sizeof(mCoreName) - 1] = 0; // strncpy does not guarantee a null-terminated string
- foundCoreName = true;
- }
-
- if (foundCPUPart) {
- mCpuIds[processor] = strtol(position, NULL, 0);
- // If this does not have the full topology in /proc/cpuinfo, mCpuIds[0] may not have the 1 CPU part emitted - this guarantees it's in mMaxCpuId
- if (mCpuIds[processor] > mMaxCpuId) {
- mMaxCpuId = mCpuIds[processor];
- }
- }
-
- if (foundProcessor) {
- processor = strtol(position, NULL, 0);
- }
- }
- }
-
- if (!foundCoreName) {
- logg->logMessage("Could not determine core name from /proc/cpuinfo\n"
- "The core name in the captured xml file will be 'unknown'.");
- }
- fclose(f);
- }
-
-int getEventKey() {
- // key 0 is reserved as a timestamp
- // key 1 is reserved as the marker for thread specific counters
- // Odd keys are assigned by the driver, even keys by the daemon
- static int key = 2;
-
- const int ret = key;
- key += 2;
- return ret;
-}
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef SESSION_DATA_H
-#define SESSION_DATA_H
-
-#include <stdint.h>
-
-#include "Config.h"
-#include "Counter.h"
-#include "Hwmon.h"
-#include "PerfDriver.h"
-
-#define PROTOCOL_VERSION 18
-#define PROTOCOL_DEV 1000 // Differentiates development versions (timestamp) from release versions
-
-struct ImageLinkList {
- char* path;
- struct ImageLinkList *next;
-};
-
-class SessionData {
-public:
- static const size_t MAX_STRING_LEN = 80;
-
- SessionData();
- ~SessionData();
- void initialize();
- void parseSessionXML(char* xmlString);
-
- Hwmon hwmon;
- PerfDriver perf;
-
- char mCoreName[MAX_STRING_LEN];
- struct ImageLinkList *mImages;
- char* mConfigurationXMLPath;
- char* mSessionXMLPath;
- char* mEventsXMLPath;
- char* mTargetPath;
- char* mAPCDir;
-
- bool mWaitingOnCommand;
- bool mSessionIsActive;
- bool mLocalCapture;
- bool mOneShot; // halt processing of the driver data until profiling is complete or the buffer is filled
- bool mIsEBS;
-
- int mBacktraceDepth;
- int mTotalBufferSize; // number of MB to use for the entire collection buffer
- int mSampleRate;
- int64_t mLiveRate;
- int mDuration;
- int mCores;
- int mPageSize;
- int mCpuIds[NR_CPUS];
- int mMaxCpuId;
-
- // PMU Counters
- int mCounterOverflow;
- Counter mCounters[MAX_PERFORMANCE_COUNTERS];
-
-private:
- void readCpuInfo();
-
- // Intentionally unimplemented
- SessionData(const SessionData &);
- SessionData &operator=(const SessionData &);
-};
-
-extern SessionData* gSessionData;
-
-int getEventKey();
-
-#endif // SESSION_DATA_H
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "SessionXML.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <limits.h>
-
-#include "Logging.h"
-#include "OlyUtility.h"
-#include "SessionData.h"
-
-static const char* TAG_SESSION = "session";
-static const char* TAG_IMAGE = "image";
-
-static const char* ATTR_VERSION = "version";
-static const char* ATTR_CALL_STACK_UNWINDING = "call_stack_unwinding";
-static const char* ATTR_BUFFER_MODE = "buffer_mode";
-static const char* ATTR_SAMPLE_RATE = "sample_rate";
-static const char* ATTR_DURATION = "duration";
-static const char* ATTR_PATH = "path";
-static const char* ATTR_LIVE_RATE = "live_rate";
-
-SessionXML::SessionXML(const char *str) {
- parameters.buffer_mode[0] = 0;
- parameters.sample_rate[0] = 0;
- parameters.duration = 0;
- parameters.call_stack_unwinding = false;
- parameters.live_rate = 0;
- parameters.images = NULL;
- mPath = 0;
- mSessionXML = (const char *)str;
- logg->logMessage(mSessionXML);
-}
-
-SessionXML::~SessionXML() {
- if (mPath != 0) {
- free((char *)mSessionXML);
- }
-}
-
-void SessionXML::parse() {
- mxml_node_t *tree;
- mxml_node_t *node;
-
- tree = mxmlLoadString(NULL, mSessionXML, MXML_NO_CALLBACK);
- node = mxmlFindElement(tree, tree, TAG_SESSION, NULL, NULL, MXML_DESCEND);
-
- if (node) {
- sessionTag(tree, node);
- mxmlDelete(tree);
- return;
- }
-
- logg->logError(__FILE__, __LINE__, "No session tag found in the session.xml file");
- handleException();
-}
-
-void SessionXML::sessionTag(mxml_node_t *tree, mxml_node_t *node) {
- int version = 0;
- if (mxmlElementGetAttr(node, ATTR_VERSION)) version = strtol(mxmlElementGetAttr(node, ATTR_VERSION), NULL, 10);
- if (version != 1) {
- logg->logError(__FILE__, __LINE__, "Invalid session.xml version: %d", version);
- handleException();
- }
-
- // copy to pre-allocated strings
- if (mxmlElementGetAttr(node, ATTR_BUFFER_MODE)) {
- strncpy(parameters.buffer_mode, mxmlElementGetAttr(node, ATTR_BUFFER_MODE), sizeof(parameters.buffer_mode));
- parameters.buffer_mode[sizeof(parameters.buffer_mode) - 1] = 0; // strncpy does not guarantee a null-terminated string
- }
- if (mxmlElementGetAttr(node, ATTR_SAMPLE_RATE)) {
- strncpy(parameters.sample_rate, mxmlElementGetAttr(node, ATTR_SAMPLE_RATE), sizeof(parameters.sample_rate));
- parameters.sample_rate[sizeof(parameters.sample_rate) - 1] = 0; // strncpy does not guarantee a null-terminated string
- }
-
- // integers/bools
- parameters.call_stack_unwinding = util->stringToBool(mxmlElementGetAttr(node, ATTR_CALL_STACK_UNWINDING), false);
- if (mxmlElementGetAttr(node, ATTR_DURATION)) parameters.duration = strtol(mxmlElementGetAttr(node, ATTR_DURATION), NULL, 10);
- if (mxmlElementGetAttr(node, ATTR_LIVE_RATE)) parameters.live_rate = strtol(mxmlElementGetAttr(node, ATTR_LIVE_RATE), NULL, 10);
-
- // parse subtags
- node = mxmlGetFirstChild(node);
- while (node) {
- if (mxmlGetType(node) != MXML_ELEMENT) {
- node = mxmlWalkNext(node, tree, MXML_NO_DESCEND);
- continue;
- }
- if (strcmp(TAG_IMAGE, mxmlGetElement(node)) == 0) {
- sessionImage(node);
- }
- node = mxmlWalkNext(node, tree, MXML_NO_DESCEND);
- }
-}
-
-void SessionXML::sessionImage(mxml_node_t *node) {
- int length = strlen(mxmlElementGetAttr(node, ATTR_PATH));
- struct ImageLinkList *image;
-
- image = (struct ImageLinkList *)malloc(sizeof(struct ImageLinkList));
- image->path = (char*)malloc(length + 1);
- image->path = strdup(mxmlElementGetAttr(node, ATTR_PATH));
- image->next = parameters.images;
- parameters.images = image;
-}
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef SESSION_XML_H
-#define SESSION_XML_H
-
-#include "mxml/mxml.h"
-
-struct ImageLinkList;
-
-struct ConfigParameters {
- char buffer_mode[64]; // buffer mode, "streaming", "low", "normal", "high" defines oneshot and buffer size
- char sample_rate[64]; // capture mode, "high", "normal", or "low"
- int duration; // length of profile in seconds
- bool call_stack_unwinding; // whether stack unwinding is performed
- int live_rate;
- struct ImageLinkList *images; // linked list of image strings
-};
-
-class SessionXML {
-public:
- SessionXML(const char *str);
- ~SessionXML();
- void parse();
- ConfigParameters parameters;
-private:
- const char *mSessionXML;
- const char *mPath;
- void sessionTag(mxml_node_t *tree, mxml_node_t *node);
- void sessionImage(mxml_node_t *node);
-
- // Intentionally unimplemented
- SessionXML(const SessionXML &);
- SessionXML &operator=(const SessionXML &);
-};
-
-#endif // SESSION_XML_H
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "Source.h"
-
-#include "Logging.h"
-
-Source::Source() : mThreadID() {
-}
-
-Source::~Source() {
-}
-
-void Source::start() {
- if (pthread_create(&mThreadID, NULL, runStatic, this)) {
- logg->logError(__FILE__, __LINE__, "Failed to create source thread");
- handleException();
- }
-}
-
-void Source::join() {
- pthread_join(mThreadID, NULL);
-}
-
-void *Source::runStatic(void *arg) {
- static_cast<Source *>(arg)->run();
- return NULL;
-}
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef SOURCE_H
-#define SOURCE_H
-
-#include <pthread.h>
-
-class Sender;
-
-class Source {
-public:
- Source();
- virtual ~Source();
-
- virtual bool prepare() = 0;
- void start();
- virtual void run() = 0;
- virtual void interrupt() = 0;
- void join();
-
- virtual bool isDone() = 0;
- virtual void write(Sender *sender) = 0;
-
-private:
- static void *runStatic(void *arg);
-
- pthread_t mThreadID;
-
- // Intentionally undefined
- Source(const Source &);
- Source &operator=(const Source &);
-};
-
-#endif // SOURCE_H
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2011-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "StreamlineSetup.h"
-
-#include "Buffer.h"
-#include "CapturedXML.h"
-#include "ConfigurationXML.h"
-#include "Driver.h"
-#include "EventsXML.h"
-#include "Logging.h"
-#include "OlySocket.h"
-#include "OlyUtility.h"
-#include "Sender.h"
-#include "SessionData.h"
-
-static const char* TAG_SESSION = "session";
-static const char* TAG_REQUEST = "request";
-static const char* TAG_CONFIGURATIONS = "configurations";
-
-static const char* ATTR_TYPE = "type";
-static const char* VALUE_EVENTS = "events";
-static const char* VALUE_CONFIGURATION = "configuration";
-static const char* VALUE_COUNTERS = "counters";
-static const char* VALUE_CAPTURED = "captured";
-static const char* VALUE_DEFAULTS = "defaults";
-
-StreamlineSetup::StreamlineSetup(OlySocket* s) {
- bool ready = false;
- char* data = NULL;
- int type;
-
- mSocket = s;
-
- // Receive commands from Streamline (master)
- while (!ready) {
- // receive command over socket
- gSessionData->mWaitingOnCommand = true;
- data = readCommand(&type);
-
- // parse and handle data
- switch (type) {
- case COMMAND_REQUEST_XML:
- handleRequest(data);
- break;
- case COMMAND_DELIVER_XML:
- handleDeliver(data);
- break;
- case COMMAND_APC_START:
- logg->logMessage("Received apc start request");
- ready = true;
- break;
- case COMMAND_APC_STOP:
- logg->logMessage("Received apc stop request before apc start request");
- exit(0);
- break;
- case COMMAND_DISCONNECT:
- logg->logMessage("Received disconnect command");
- exit(0);
- break;
- case COMMAND_PING:
- logg->logMessage("Received ping command");
- sendData(NULL, 0, RESPONSE_ACK);
- break;
- default:
- logg->logError(__FILE__, __LINE__, "Target error: Unknown command type, %d", type);
- handleException();
- }
-
- free(data);
- }
-
- if (gSessionData->mCounterOverflow > 0) {
- logg->logError(__FILE__, __LINE__, "Only %i performance counters are permitted, %i are selected", MAX_PERFORMANCE_COUNTERS, gSessionData->mCounterOverflow);
- handleException();
- }
-}
-
-StreamlineSetup::~StreamlineSetup() {
-}
-
-char* StreamlineSetup::readCommand(int* command) {
- unsigned char header[5];
- char* data;
- int response;
-
- // receive type and length
- response = mSocket->receiveNBytes((char*)&header, sizeof(header));
-
- // After receiving a single byte, we are no longer waiting on a command
- gSessionData->mWaitingOnCommand = false;
-
- if (response < 0) {
- logg->logError(__FILE__, __LINE__, "Target error: Unexpected socket disconnect");
- handleException();
- }
-
- const char type = header[0];
- const int length = (header[1] << 0) | (header[2] << 8) | (header[3] << 16) | (header[4] << 24);
-
- // add artificial limit
- if ((length < 0) || length > 1024 * 1024) {
- logg->logError(__FILE__, __LINE__, "Target error: Invalid length received, %d", length);
- handleException();
- }
-
- // allocate memory to contain the xml file, size of zero returns a zero size object
- data = (char*)calloc(length + 1, 1);
- if (data == NULL) {
- logg->logError(__FILE__, __LINE__, "Unable to allocate memory for xml");
- handleException();
- }
-
- // receive data
- response = mSocket->receiveNBytes(data, length);
- if (response < 0) {
- logg->logError(__FILE__, __LINE__, "Target error: Unexpected socket disconnect");
- handleException();
- }
-
- // null terminate the data for string parsing
- if (length > 0) {
- data[length] = 0;
- }
-
- *command = type;
- return data;
-}
-
-void StreamlineSetup::handleRequest(char* xml) {
- mxml_node_t *tree, *node;
- const char * attr = NULL;
-
- tree = mxmlLoadString(NULL, xml, MXML_NO_CALLBACK);
- node = mxmlFindElement(tree, tree, TAG_REQUEST, ATTR_TYPE, NULL, MXML_DESCEND_FIRST);
- if (node) {
- attr = mxmlElementGetAttr(node, ATTR_TYPE);
- }
- if (attr && strcmp(attr, VALUE_EVENTS) == 0) {
- sendEvents();
- logg->logMessage("Sent events xml response");
- } else if (attr && strcmp(attr, VALUE_CONFIGURATION) == 0) {
- sendConfiguration();
- logg->logMessage("Sent configuration xml response");
- } else if (attr && strcmp(attr, VALUE_COUNTERS) == 0) {
- sendCounters();
- logg->logMessage("Sent counters xml response");
- } else if (attr && strcmp(attr, VALUE_CAPTURED) == 0) {
- CapturedXML capturedXML;
- char* capturedText = capturedXML.getXML(false);
- sendData(capturedText, strlen(capturedText), RESPONSE_XML);
- free(capturedText);
- logg->logMessage("Sent captured xml response");
- } else if (attr && strcmp(attr, VALUE_DEFAULTS) == 0) {
- sendDefaults();
- logg->logMessage("Sent default configuration xml response");
- } else {
- char error[] = "Unknown request";
- sendData(error, strlen(error), RESPONSE_NAK);
- logg->logMessage("Received unknown request:\n%s", xml);
- }
-
- mxmlDelete(tree);
-}
-
-void StreamlineSetup::handleDeliver(char* xml) {
- mxml_node_t *tree;
-
- // Determine xml type
- tree = mxmlLoadString(NULL, xml, MXML_NO_CALLBACK);
- if (mxmlFindElement(tree, tree, TAG_SESSION, NULL, NULL, MXML_DESCEND_FIRST)) {
- // Session XML
- gSessionData->parseSessionXML(xml);
- sendData(NULL, 0, RESPONSE_ACK);
- logg->logMessage("Received session xml");
- } else if (mxmlFindElement(tree, tree, TAG_CONFIGURATIONS, NULL, NULL, MXML_DESCEND_FIRST)) {
- // Configuration XML
- writeConfiguration(xml);
- sendData(NULL, 0, RESPONSE_ACK);
- logg->logMessage("Received configuration xml");
- } else {
- // Unknown XML
- logg->logMessage("Received unknown XML delivery type");
- sendData(NULL, 0, RESPONSE_NAK);
- }
-
- mxmlDelete(tree);
-}
-
-void StreamlineSetup::sendData(const char* data, uint32_t length, char type) {
- unsigned char header[5];
- header[0] = type;
- Buffer::writeLEInt(header + 1, length);
- mSocket->send((char*)&header, sizeof(header));
- mSocket->send((const char*)data, length);
-}
-
-void StreamlineSetup::sendEvents() {
- EventsXML eventsXML;
- char* string = eventsXML.getXML();
- sendString(string, RESPONSE_XML);
- free(string);
-}
-
-void StreamlineSetup::sendConfiguration() {
- ConfigurationXML xml;
-
- const char* string = xml.getConfigurationXML();
- sendData(string, strlen(string), RESPONSE_XML);
-}
-
-void StreamlineSetup::sendDefaults() {
- // Send the config built into the binary
- const char* xml;
- unsigned int size;
- ConfigurationXML::getDefaultConfigurationXml(xml, size);
-
- // Artificial size restriction
- if (size > 1024*1024) {
- logg->logError(__FILE__, __LINE__, "Corrupt default configuration file");
- handleException();
- }
-
- sendData(xml, size, RESPONSE_XML);
-}
-
-void StreamlineSetup::sendCounters() {
- mxml_node_t *xml;
- mxml_node_t *counters;
-
- xml = mxmlNewXML("1.0");
- counters = mxmlNewElement(xml, "counters");
- int count = 0;
- for (Driver *driver = Driver::getHead(); driver != NULL; driver = driver->getNext()) {
- count += driver->writeCounters(counters);
- }
-
- if (count == 0) {
- logg->logError(__FILE__, __LINE__, "No counters found, this could be because /dev/gator/events can not be read or because perf is not working correctly");
- handleException();
- }
-
- char* string = mxmlSaveAllocString(xml, mxmlWhitespaceCB);
- sendString(string, RESPONSE_XML);
-
- free(string);
- mxmlDelete(xml);
-}
-
-void StreamlineSetup::writeConfiguration(char* xml) {
- char path[PATH_MAX];
-
- ConfigurationXML::getPath(path);
-
- if (util->writeToDisk(path, xml) < 0) {
- logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify write permissions to this path.", path);
- handleException();
- }
-
- // Re-populate gSessionData with the configuration, as it has now changed
- { ConfigurationXML configuration; }
-
- if (gSessionData->mCounterOverflow > 0) {
- logg->logError(__FILE__, __LINE__, "Only %i performance counters counters are permitted, %i are selected", MAX_PERFORMANCE_COUNTERS, gSessionData->mCounterOverflow);
- handleException();
- }
-}
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __STREAMLINE_SETUP_H__
-#define __STREAMLINE_SETUP_H__
-
-#include <stdint.h>
-#include <string.h>
-
-class OlySocket;
-
-// Commands from Streamline
-enum {
- COMMAND_REQUEST_XML = 0,
- COMMAND_DELIVER_XML = 1,
- COMMAND_APC_START = 2,
- COMMAND_APC_STOP = 3,
- COMMAND_DISCONNECT = 4,
- COMMAND_PING = 5
-};
-
-class StreamlineSetup {
-public:
- StreamlineSetup(OlySocket *socket);
- ~StreamlineSetup();
-private:
- OlySocket* mSocket;
-
- char* readCommand(int*);
- void handleRequest(char* xml);
- void handleDeliver(char* xml);
- void sendData(const char* data, uint32_t length, char type);
- void sendString(const char* string, int type) {sendData(string, strlen(string), type);}
- void sendEvents();
- void sendConfiguration();
- void sendDefaults();
- void sendCounters();
- void writeConfiguration(char* xml);
-
- // Intentionally unimplemented
- StreamlineSetup(const StreamlineSetup &);
- StreamlineSetup &operator=(const StreamlineSetup &);
-};
-
-#endif //__STREAMLINE_SETUP_H__
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "UEvent.h"
-
-#include <sys/socket.h>
-#include <linux/netlink.h>
-#include <string.h>
-
-#include <unistd.h>
-
-#include "Logging.h"
-
-static const char EMPTY[] = "";
-static const char ACTION[] = "ACTION=";
-static const char DEVPATH[] = "DEVPATH=";
-static const char SUBSYSTEM[] = "SUBSYSTEM=";
-
-UEvent::UEvent() : mFd(-1) {
-}
-
-UEvent::~UEvent() {
- if (mFd >= 0) {
- close(mFd);
- }
-}
-
-bool UEvent::init() {
- mFd = socket(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);
- if (mFd < 0) {
- logg->logMessage("%s(%s:%i): socket failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
-
- struct sockaddr_nl sockaddr;
- memset(&sockaddr, 0, sizeof(sockaddr));
- sockaddr.nl_family = AF_NETLINK;
- sockaddr.nl_groups = 1; // bitmask: (1 << 0) == kernel events, (1 << 1) == udev events
- sockaddr.nl_pid = 0;
- if (bind(mFd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) != 0) {
- logg->logMessage("%s(%s:%i): bind failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
-
- return true;
-}
-
-bool UEvent::read(UEventResult *const result) {
- ssize_t bytes = recv(mFd, result->mBuf, sizeof(result->mBuf), 0);
- if (bytes <= 0) {
- logg->logMessage("%s(%s:%i): recv failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
-
- result->mAction = EMPTY;
- result->mDevPath = EMPTY;
- result->mSubsystem = EMPTY;
-
- for (int pos = 0; pos < bytes; pos += strlen(result->mBuf + pos) + 1) {
- char *const str = result->mBuf + pos;
- if (strncmp(str, ACTION, sizeof(ACTION) - 1) == 0) {
- result->mAction = str + sizeof(ACTION) - 1;
- } else if (strncmp(str, DEVPATH, sizeof(DEVPATH) - 1) == 0) {
- result->mDevPath = str + sizeof(DEVPATH) - 1;
- } else if (strncmp(str, SUBSYSTEM, sizeof(SUBSYSTEM) - 1) == 0) {
- result->mSubsystem = str + sizeof(SUBSYSTEM) - 1;
- }
- }
-
- return true;
-}
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef UEVENT_H
-#define UEVENT_H
-
-struct UEventResult {
- const char *mAction;
- const char *mDevPath;
- const char *mSubsystem;
- char mBuf[1<<13];
-};
-
-class UEvent {
-public:
- UEvent();
- ~UEvent();
-
- bool init();
- bool read(UEventResult *const result);
- int getFd() const { return mFd; }
-
-private:
- int mFd;
-
- // Intentionally undefined
- UEvent(const UEvent &);
- UEvent &operator=(const UEvent &);
-};
-
-#endif // UEVENT_H
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "UserSpaceSource.h"
-
-#include <sys/prctl.h>
-#include <unistd.h>
-
-#include "Child.h"
-#include "DriverSource.h"
-#include "Logging.h"
-#include "SessionData.h"
-
-#define NS_PER_S ((uint64_t)1000000000)
-#define NS_PER_US 1000
-
-extern Child *child;
-
-UserSpaceSource::UserSpaceSource(sem_t *senderSem) : mBuffer(0, FRAME_BLOCK_COUNTER, gSessionData->mTotalBufferSize*1024*1024, senderSem) {
-}
-
-UserSpaceSource::~UserSpaceSource() {
-}
-
-bool UserSpaceSource::prepare() {
- return true;
-}
-
-void UserSpaceSource::run() {
- prctl(PR_SET_NAME, (unsigned long)&"gatord-counters", 0, 0, 0);
-
- gSessionData->hwmon.start();
-
- int64_t monotonic_started = 0;
- while (monotonic_started <= 0) {
- usleep(10);
-
- if (DriverSource::readInt64Driver("/dev/gator/started", &monotonic_started) == -1) {
- logg->logError(__FILE__, __LINE__, "Error reading gator driver start time");
- handleException();
- }
- }
-
- uint64_t next_time = 0;
- while (gSessionData->mSessionIsActive) {
- struct timespec ts;
-#ifndef CLOCK_MONOTONIC_RAW
- // Android doesn't have this defined but it was added in Linux 2.6.28
-#define CLOCK_MONOTONIC_RAW 4
-#endif
- if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts) != 0) {
- logg->logError(__FILE__, __LINE__, "Failed to get uptime");
- handleException();
- }
- const uint64_t curr_time = (NS_PER_S*ts.tv_sec + ts.tv_nsec) - monotonic_started;
- // Sample ten times a second ignoring gSessionData->mSampleRate
- next_time += NS_PER_S/10;//gSessionData->mSampleRate;
- if (next_time < curr_time) {
- logg->logMessage("Too slow, curr_time: %lli next_time: %lli", curr_time, next_time);
- next_time = curr_time;
- }
-
- if (mBuffer.eventHeader(curr_time)) {
- gSessionData->hwmon.read(&mBuffer);
- // Only check after writing all counters so that time and corresponding counters appear in the same frame
- mBuffer.check(curr_time);
- }
-
- if (mBuffer.bytesAvailable() <= 0) {
- logg->logMessage("One shot (counters)");
- child->endSession();
- }
-
- usleep((next_time - curr_time)/NS_PER_US);
- }
-
- mBuffer.setDone();
-}
-
-void UserSpaceSource::interrupt() {
- // Do nothing
-}
-
-bool UserSpaceSource::isDone() {
- return mBuffer.isDone();
-}
-
-void UserSpaceSource::write(Sender *sender) {
- if (!mBuffer.isDone()) {
- mBuffer.write(sender);
- }
-}
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef USERSPACESOURCE_H
-#define USERSPACESOURCE_H
-
-#include <semaphore.h>
-
-#include "Buffer.h"
-#include "Source.h"
-
-// User space counters - currently just hwmon
-class UserSpaceSource : public Source {
-public:
- UserSpaceSource(sem_t *senderSem);
- ~UserSpaceSource();
-
- bool prepare();
- void run();
- void interrupt();
-
- bool isDone();
- void write(Sender *sender);
-
-private:
- Buffer mBuffer;
-
- // Intentionally unimplemented
- UserSpaceSource(const UserSpaceSource &);
- UserSpaceSource &operator=(const UserSpaceSource &);
-};
-
-#endif // USERSPACESOURCE_H
+++ /dev/null
-# -g produces debugging information
-# -O3 maximum optimization
-# -O0 no optimization, used for debugging
-# -Wall enables most warnings
-# -Werror treats warnings as errors
-# -std=c++0x is the planned new c++ standard
-# -std=c++98 is the 1998 c++ standard
-CFLAGS += -O3 -Wall -fno-exceptions -pthread -MMD -DETCDIR=\"/etc\" -Ilibsensors
-CXXFLAGS += -fno-rtti -Wextra # -Weffc++
-ifeq ($(WERROR),1)
- CFLAGS += -Werror
-endif
-# -s strips the binary of debug info
-LDFLAGS += -s
-TARGET = gatord
-C_SRC = $(wildcard mxml/*.c) $(wildcard libsensors/*.c)
-CPP_SRC = $(wildcard *.cpp)
-
-all: $(TARGET)
-
-events.xml: events_header.xml $(wildcard events-*.xml) events_footer.xml
- cat $^ > $@
-
-include $(wildcard *.d)
-include $(wildcard mxml/*.d)
-
-EventsXML.cpp: events_xml.h
-ConfigurationXML.cpp: defaults_xml.h
-
-# Don't regenerate conf-lex.c or conf-parse.c
-libsensors/conf-lex.c: ;
-libsensors/conf-parse.c: ;
-
-%_xml.h: %.xml escape
- ./escape $< > $@
-
-%.o: %.c
- $(GCC) -c $(CFLAGS) -o $@ $<
-
-%.o: %.cpp
- $(CPP) -c $(CFLAGS) $(CXXFLAGS) -o $@ $<
-
-$(TARGET): $(CPP_SRC:%.cpp=%.o) $(C_SRC:%.c=%.o)
- $(CPP) $(LDFLAGS) -o $@ $^ -lrt -pthread
-
-escape: escape.c
- gcc $^ -o $@
-
-clean:
- rm -f *.d *.o mxml/*.d mxml/*.o libsensors/*.d libsensors/*.o $(TARGET) escape events.xml events_xml.h defaults_xml.h
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<configurations revision="3">
- <configuration counter="ARM_ARM11_ccnt" event="0xff"/>
- <configuration counter="ARM_ARM11_cnt0" event="0x7"/>
- <configuration counter="ARM_ARM11_cnt1" event="0xb"/>
- <configuration counter="ARM_ARM11MPCore_ccnt" event="0xff"/>
- <configuration counter="ARM_ARM11MPCore_cnt0" event="0x08"/>
- <configuration counter="ARM_ARM11MPCore_cnt1" event="0x0b"/>
- <configuration counter="ARMv7_Cortex_A5_ccnt" event="0xff"/>
- <configuration counter="ARMv7_Cortex_A5_cnt0" event="0x8"/>
- <configuration counter="ARMv7_Cortex_A5_cnt1" event="0x1"/>
- <configuration counter="ARMv7_Cortex_A7_ccnt" event="0xff"/>
- <configuration counter="ARMv7_Cortex_A7_cnt0" event="0x08"/>
- <configuration counter="ARMv7_Cortex_A7_cnt1" event="0x10"/>
- <configuration counter="ARMv7_Cortex_A7_cnt2" event="0x16"/>
- <configuration counter="ARMv7_Cortex_A8_ccnt" event="0xff"/>
- <configuration counter="ARMv7_Cortex_A8_cnt0" event="0x8"/>
- <configuration counter="ARMv7_Cortex_A8_cnt1" event="0x44"/>
- <configuration counter="ARMv7_Cortex_A8_cnt2" event="0x43"/>
- <configuration counter="ARMv7_Cortex_A8_cnt3" event="0x10"/>
- <configuration counter="ARMv7_Cortex_A9_ccnt" event="0xff"/>
- <configuration counter="ARMv7_Cortex_A9_cnt0" event="0x68"/>
- <configuration counter="ARMv7_Cortex_A9_cnt1" event="0x06"/>
- <configuration counter="ARMv7_Cortex_A9_cnt2" event="0x07"/>
- <configuration counter="ARMv7_Cortex_A9_cnt3" event="0x03"/>
- <configuration counter="ARMv7_Cortex_A9_cnt4" event="0x04"/>
- <configuration counter="ARMv7_Cortex_A12_ccnt" event="0xff"/>
- <configuration counter="ARMv7_Cortex_A12_cnt0" event="0x08"/>
- <configuration counter="ARMv7_Cortex_A12_cnt1" event="0x16"/>
- <configuration counter="ARMv7_Cortex_A12_cnt2" event="0x10"/>
- <configuration counter="ARMv7_Cortex_A12_cnt3" event="0x19"/>
- <configuration counter="ARMv7_Cortex_A15_ccnt" event="0xff"/>
- <configuration counter="ARMv7_Cortex_A15_cnt0" event="0x8"/>
- <configuration counter="ARMv7_Cortex_A15_cnt1" event="0x16"/>
- <configuration counter="ARMv7_Cortex_A15_cnt2" event="0x10"/>
- <configuration counter="ARMv7_Cortex_A15_cnt3" event="0x19"/>
- <configuration counter="ARM_Cortex-A53_ccnt" event="0x11"/>
- <configuration counter="ARM_Cortex-A53_cnt0" event="0x8"/>
- <configuration counter="ARM_Cortex-A53_cnt1" event="0x16"/>
- <configuration counter="ARM_Cortex-A53_cnt2" event="0x10"/>
- <configuration counter="ARM_Cortex-A53_cnt3" event="0x19"/>
- <configuration counter="ARM_Cortex-A57_ccnt" event="0x11"/>
- <configuration counter="ARM_Cortex-A57_cnt0" event="0x8"/>
- <configuration counter="ARM_Cortex-A57_cnt1" event="0x16"/>
- <configuration counter="ARM_Cortex-A57_cnt2" event="0x10"/>
- <configuration counter="ARM_Cortex-A57_cnt3" event="0x19"/>
- <configuration counter="Scorpion_ccnt" event="0xff"/>
- <configuration counter="Scorpion_cnt0" event="0x08"/>
- <configuration counter="Scorpion_cnt1" event="0x10"/>
- <configuration counter="ScorpionMP_ccnt" event="0xff"/>
- <configuration counter="ScorpionMP_cnt0" event="0x08"/>
- <configuration counter="ScorpionMP_cnt1" event="0x10"/>
- <configuration counter="Krait_ccnt" event="0xff"/>
- <configuration counter="Krait_cnt0" event="0x08"/>
- <configuration counter="Krait_cnt1" event="0x10"/>
- <configuration counter="Linux_block_rq_wr"/>
- <configuration counter="Linux_block_rq_rd"/>
- <configuration counter="Linux_meminfo_memused"/>
- <configuration counter="Linux_meminfo_memfree"/>
- <configuration counter="Linux_power_cpu_freq"/>
- <configuration counter="L2C-310_cnt0" event="0x1"/>
-</configurations>
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/*
- * The Makefile in the daemon folder builds and executes 'escape'
- * 'escape' creates configuration_xml.h from configuration.xml and events_xml.h from events-*.xml
- * these genereated xml files are then #included and built as part of the gatord binary
- */
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-static void print_escaped_path(char *path) {
- if (isdigit(*path)) {
- printf("__");
- }
- for (; *path != '\0'; ++path) {
- printf("%c", isalnum(*path) ? *path : '_');
- }
-}
-
-int main(int argc, char *argv[]) {
- int i;
- char *path;
- FILE *in = NULL;
- int ch;
- unsigned int len = 0;
-
- for (i = 1; i < argc && argv[i][0] == '-'; ++i) ;
- if (i == argc) {
- fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
- return EXIT_FAILURE;
- }
- path = argv[i];
-
- errno = 0;
- if ((in = fopen(path, "r")) == NULL) {
- fprintf(stderr, "Unable to open '%s': %s\n", path, strerror(errno));
- return EXIT_FAILURE;
- }
-
- printf("static const unsigned char ");
- print_escaped_path(path);
- printf("[] = {");
- for (;;) {
- ch = fgetc(in);
- if (len != 0) {
- printf(",");
- }
- if (len % 12 == 0) {
- printf("\n ");
- }
- // Write out a null character after the contents of the file but do not increment len
- printf(" 0x%.2x", (ch == EOF ? 0 : ch));
- if (ch == EOF) {
- break;
- }
- ++len;
- }
- printf("\n};\nstatic const unsigned int ");
- print_escaped_path(path);
- printf("_len = %i;\n", len);
-
- fclose(in);
-
- return EXIT_SUCCESS;
-}
+++ /dev/null
- <counter_set name="ARM_ARM11_cnt" count="3"/>
- <category name="ARM11" counter_set="ARM_ARM11_cnt" per_cpu="yes">
- <event counter="ARM_ARM11_ccnt" event="0xff" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/>
- <event event="0x00" title="Cache" name="Inst miss" description="Instruction cache miss to a cacheable location, which requires a fetch from external memory"/>
- <event event="0x01" title="Pipeline" name="Instruction stall" description="Stall because instruction buffer cannot deliver an instruction"/>
- <event event="0x02" title="Pipeline" name="Data stall" description="Stall because of a data dependency"/>
- <event event="0x03" title="Cache" name="Inst micro TLB miss" description="Instruction MicroTLB miss (unused on ARM1156)"/>
- <event event="0x04" title="Cache" name="Data micro TLB miss" description="Data MicroTLB miss (unused on ARM1156)"/>
- <event event="0x05" title="Branch" name="Instruction executed" description="Branch instruction executed, branch might or might not have changed program flow"/>
- <event event="0x06" title="Branch" name="Mispredicted" description="Branch mis-predicted"/>
- <event event="0x07" title="Instruction" name="Executed" description="Instructions executed"/>
- <event event="0x09" title="Cache" name="Data access" description="Data cache access, not including Cache operations"/>
- <event event="0x0a" title="Cache" name="Data all access" description="Data cache access, not including Cache Operations regardless of whether or not the location is cacheable"/>
- <event event="0x0b" title="Cache" name="Data miss" description="Data cache miss, not including Cache Operations"/>
- <event event="0x0c" title="Cache" name="Write-back" description="Data cache write-back"/>
- <event event="0x0d" title="Program Counter" name="SW change" description="Software changed the PC"/>
- <event event="0x0f" title="Cache " name="TLB miss" description="Main TLB miss (unused on ARM1156)"/>
- <event event="0x10" title="External" name="Access" description="Explicit external data or peripheral access"/>
- <event event="0x11" title="Cache" name="Data miss" description="Stall because of Load Store Unit request queue being full"/>
- <event event="0x12" title="Write Buffer" name="Drains" description="The number of times the Write Buffer was drained because of a Data Synchronization Barrier command or Strongly Ordered operation"/>
- <event event="0x13" title="Disable Interrupts" name="FIQ" description="The number of cycles which FIQ interrupts are disabled (ARM1156 only)"/>
- <event event="0x14" title="Disable Interrupts" name="IRQ" description="The number of cycles which IRQ interrupts are disabled (ARM1156 only)"/>
- <event event="0x20" title="ETM" name="ETMEXTOUT[0]" description="ETMEXTOUT[0] signal was asserted for a cycle"/>
- <event event="0x21" title="ETM" name="ETMEXTOUT[1]" description="ETMEXTOUT[1] signal was asserted for a cycle"/>
- <event event="0x22" title="ETM" name="ETMEXTOUT[0,1]" description="ETMEXTOUT[0] or ETMEXTOUT[1] was asserted"/>
- <event event="0x23" title="Procedure" name="Calls" description="Procedure call instruction executed"/>
- <event event="0x24" title="Procedure" name="Returns" description="Procedure return instruction executed"/>
- <event event="0x25" title="Procedure" name="Return and predicted" description="Procedure return instruction executed and return address predicted"/>
- <event event="0x26" title="Procedure" name="Return and mispredicted" description="Procedure return instruction executed and return address predicted incorrectly"/>
- <event event="0x30" title="Cache" name="Inst tag or parity error" description="Instruction cache Tag or Valid RAM parity error (ARM1156 only)"/>
- <event event="0x31" title="Cache" name="Inst parity error" description="Instruction cache RAM parity error (ARM1156 only)"/>
- <event event="0x32" title="Cache" name="Data tag or parity error" description="Data cache Tag or Valid RAM parity error (ARM1156 only)"/>
- <event event="0x33" title="Cache" name="Data parity error" description="Data cache RAM parity error (ARM1156 only)"/>
- <event event="0x34" title="ITCM" name="Error" description="ITCM error (ARM1156 only)"/>
- <event event="0x35" title="DTCM" name="Error" description="DTCM error (ARM1156 only)"/>
- <event event="0x36" title="Procedure" name="Return address pop" description="Procedure return address popped off the return stack (ARM1156 only)"/>
- <event event="0x37" title="Procedure" name="Return address misprediction" description="Procedure return address popped off the return stack has been incorrectly predicted by the PFU (ARM1156 only)"/>
- <event event="0x38" title="Cache" name="Data dirty parity error" description="Data cache Dirty RAM parity error (ARM1156 only)"/>
- </category>
+++ /dev/null
- <counter_set name="ARM_ARM11MPCore_cnt" count="3"/>
- <category name="ARM11MPCore" counter_set="ARM_ARM11MPCore_cnt" per_cpu="yes">
- <event counter="ARM_ARM11MPCore_ccnt" event="0xff" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/>
- <event event="0x00" title="Cache" name="Inst miss" description="Instruction cache miss to a cacheable location, which requires a fetch from external memory"/>
- <event event="0x01" title="Pipeline" name="Instruction stall" description="Stall because instruction buffer cannot deliver an instruction"/>
- <event event="0x02" title="Pipeline" name="Data stall" description="Stall because of a data dependency"/>
- <event event="0x03" title="Cache" name="Inst micro TLB miss" description="Instruction MicroTLB miss (unused on ARM1156)"/>
- <event event="0x04" title="Cache" name="Data micro TLB miss" description="Data MicroTLB miss (unused on ARM1156)"/>
- <event event="0x05" title="Branch" name="Instruction executed" description="Branch instructions executed, branch might or might not have changed program flow"/>
- <event event="0x06" title="Branch" name="Not predicted" description="Branch not predicted"/>
- <event event="0x07" title="Branch" name="Mispredicted" description="Branch mispredicted"/>
- <event event="0x08" title="Core" name="Instructions" description="Instructions executed"/>
- <event event="0x09" title="Core" name="Folded Instructions" description="Folded instructions executed"/>
- <event event="0x0a" title="Cache" name="Data read access" description="Data cache read access, not including cache operations"/>
- <event event="0x0b" title="Cache" name="Data read miss" description="Data cache miss, not including Cache Operations"/>
- <event event="0x0c" title="Cache" name="Data write access" description="Data cache write access"/>
- <event event="0x0d" title="Cache" name="Data write miss" description="Data cache write miss"/>
- <event event="0x0e" title="Cache" name="Data line eviction" description="Data cache line eviction, not including cache operations"/>
- <event event="0x0f" title="Branch" name="PC change w/o mode change" description="Software changed the PC and there is not a mode change"/>
- <event event="0x10" title="Cache " name="TLB miss" description="Main TLB miss"/>
- <event event="0x11" title="External" name="External Memory request" description="External memory request (cache refill, noncachable, write-back)"/>
- <event event="0x12" title="Cache" name="Stall" description="Stall because of Load Store Unit request queue being full"/>
- <event event="0x13" title="Write Buffer" name="Drains" description="The number of times the Write Buffer was drained because of LSU ordering constraints or CP15 operations (Data Synchronization Barrier command) or Strongly Ordered operation"/>
- <event event="0x14" title="Write Buffer" name="Write Merges" description="Buffered write merged in a store buffer slot"/>
- <event event="0xFF" title="Core" name="Cycle counter" description="An increment each cycle"/>
- </category>
+++ /dev/null
- <counter_set name="cci-400_cnt" count="4"/>
- <category name="CCI-400" counter_set="cci-400_cnt" per_cpu="no" supports_event_based_sampling="yes">
- <event counter="cci-400_ccnt" event="0xff" title="CCI-400 Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
-
- <option_set name="Slave">
- <option event_delta="0x00" name="S0" description="Slave interface 0"/>
- <option event_delta="0x20" name="S1" description="Slave interface 1"/>
- <option event_delta="0x40" name="S2" description="Slave interface 2"/>
- <option event_delta="0x60" name="S3" description="Slave interface 3"/>
- <option event_delta="0x80" name="S4" description="Slave interface 4"/>
- </option_set>
-
- <event event="0x00" option_set="Slave" title="CCI-400" name="Read: any" description="Read request handshake: any"/>
- <event event="0x01" option_set="Slave" title="CCI-400" name="Read: transaction" description="Read request handshake: device transaction"/>
- <event event="0x02" option_set="Slave" title="CCI-400" name="Read: normal" description="Read request handshake: normal, non-shareable or system-shareable, but not barrier or cache maintenance operation"/>
- <event event="0x03" option_set="Slave" title="CCI-400" name="Read: shareable" description="Read request handshake: inner- or outer-shareable, but not barrier, DVM message or cache maintenance operation"/>
- <event event="0x04" option_set="Slave" title="CCI-400" name="Read: cache" description="Read request handshake: cache maintenance operation, CleanInvalid, CleanShared, MakeInvalid"/>
- <event event="0x05" option_set="Slave" title="CCI-400" name="Read: memory barrier" description="Read request handshake: memory barrier"/>
- <event event="0x06" option_set="Slave" title="CCI-400" name="Read: sync barrier" description="Read request handshake: synchronization barrier"/>
- <event event="0x07" option_set="Slave" title="CCI-400" name="Read: DVM message, no sync" description="Read request handshake: DVM message, not synchronization"/>
- <event event="0x08" option_set="Slave" title="CCI-400" name="Read: DVM message, sync" description="Read request handshake: DVM message, synchronization"/>
- <event event="0x09" option_set="Slave" title="CCI-400" name="Read: stall" description="Read request stall cycle because the transaction tracker is full. Increase SIx_R_MAX to avoid this stall"/>
- <event event="0x0a" option_set="Slave" title="CCI-400" name="Read data last handshake" description="Read data last handshake: data returned from the snoop instead of from downstream"/>
- <event event="0x0b" option_set="Slave" title="CCI-400" name="Read data stall cycle" description="Read data stall cycle: RVALIDS is HIGH, RREADYS is LOW"/>
- <event event="0x0c" option_set="Slave" title="CCI-400" name="Write: any" description="Write request handshake: any"/>
- <event event="0x0d" option_set="Slave" title="CCI-400" name="Write: transaction" description="Write request handshake: device transaction"/>
- <event event="0x0e" option_set="Slave" title="CCI-400" name="Write: normal" description="Write request handshake: normal, non-shareable, or system-shareable, but not barrier"/>
- <event event="0x0f" option_set="Slave" title="CCI-400" name="Write: shareable" description="Write request handshake: inner- or outer-shareable, WriteBack or WriteClean"/>
- <event event="0x10" option_set="Slave" title="CCI-400" name="Write: WriteUnique" description="Write request handshake: WriteUnique"/>
- <event event="0x11" option_set="Slave" title="CCI-400" name="Write: WriteLineUnique" description="Write request handshake: WriteLineUnique"/>
- <event event="0x12" option_set="Slave" title="CCI-400" name="Write: Evict" description="Write request handshake: Evict"/>
- <event event="0x13" option_set="Slave" title="CCI-400" name="Write stall: tracker full" description="Write request stall cycle because the transaction tracker is full. Increase SIx_W_MAX to avoid this stall"/>
-
- <option_set name="Master">
- <option event_delta="0xa0" name="M0" description="Master interface 0"/>
- <option event_delta="0xc0" name="M1" description="Master interface 1"/>
- <option event_delta="0xe0" name="M2" description="Master interface 2"/>
- </option_set>
-
- <event event="0x14" option_set="Master" title="CCI-400" name="Retry fetch" description="RETRY of speculative fetch transaction"/>
- <event event="0x15" option_set="Master" title="CCI-400" name="Read stall: address hazard" description="Read request stall cycle because of an address hazard"/>
- <event event="0x16" option_set="Master" title="CCI-400" name="Read stall: ID hazard" description="Read request stall cycle because of an ID hazard"/>
- <event event="0x17" option_set="Master" title="CCI-400" name="Read stall: tracker full" description="Read request stall cycle because the transaction tracker is full. Increase MIx_R_MAX to avoid this stall. See the CoreLink CCI-400 Cache Coherent Interconnect Integration Manual"/>
- <event event="0x18" option_set="Master" title="CCI-400" name="Read stall: barrier hazard" description="Read request stall cycle because of a barrier hazard"/>
- <event event="0x19" option_set="Master" title="CCI-400" name="Write stall: barrier hazard" description="Write request stall cycle because of a barrier hazard"/>
- <event event="0x1a" option_set="Master" title="CCI-400" name="Write stall: tracker full" description="Write request stall cycle because the transaction tracker is full. Increase MIx_W_MAX to avoid this stall. See the CoreLink CCI-400 Cache Coherent Interconnect Integration Manual"/>
- </category>
-
- <counter_set name="cci-400-r1_cnt" count="4"/>
- <category name="CCI-400" counter_set="cci-400-r1_cnt" per_cpu="no" supports_event_based_sampling="yes">
- <event counter="cci-400-r1_ccnt" event="0xff" title="CCI-400 Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
-
- <option_set name="Slave">
- <option event_delta="0x00" name="S0" description="Slave interface 0"/>
- <option event_delta="0x20" name="S1" description="Slave interface 1"/>
- <option event_delta="0x40" name="S2" description="Slave interface 2"/>
- <option event_delta="0x60" name="S3" description="Slave interface 3"/>
- <option event_delta="0x80" name="S4" description="Slave interface 4"/>
- </option_set>
-
- <event event="0x00" option_set="Slave" title="CCI-400" name="Read: any" description="Read request handshake: any"/>
- <event event="0x01" option_set="Slave" title="CCI-400" name="Read: transaction" description="Read request handshake: device transaction"/>
- <event event="0x02" option_set="Slave" title="CCI-400" name="Read: normal" description="Read request handshake: normal, non-shareable or system-shareable, but not barrier or cache maintenance operation"/>
- <event event="0x03" option_set="Slave" title="CCI-400" name="Read: shareable" description="Read request handshake: inner- or outer-shareable, but not barrier, DVM message or cache maintenance operation"/>
- <event event="0x04" option_set="Slave" title="CCI-400" name="Read: cache" description="Read request handshake: cache maintenance operation"/>
- <event event="0x05" option_set="Slave" title="CCI-400" name="Read: memory barrier" description="Read request handshake: memory barrier"/>
- <event event="0x06" option_set="Slave" title="CCI-400" name="Read: sync barrier" description="Read request handshake: synchronization barrier"/>
- <event event="0x07" option_set="Slave" title="CCI-400" name="Read: DVM message, no sync" description="Read request handshake: DVM message, not synchronization"/>
- <event event="0x08" option_set="Slave" title="CCI-400" name="Read: DVM message, sync" description="Read request handshake: DVM message, synchronization"/>
- <event event="0x09" option_set="Slave" title="CCI-400" name="Read: stall" description="Read request stall cycle because the transaction tracker is full. Increase SIx_R_MAX to avoid this stall"/>
- <event event="0x0a" option_set="Slave" title="CCI-400" name="Read data last handshake" description="Read data last handshake: data returned from the snoop instead of from downstream"/>
- <event event="0x0b" option_set="Slave" title="CCI-400" name="Read data stall cycle" description="Read data stall cycle: RVALIDS is HIGH, RREADYS is LOW"/>
- <event event="0x0c" option_set="Slave" title="CCI-400" name="Write: any" description="Write request handshake: any"/>
- <event event="0x0d" option_set="Slave" title="CCI-400" name="Write: transaction" description="Write request handshake: device transaction"/>
- <event event="0x0e" option_set="Slave" title="CCI-400" name="Write: normal" description="Write request handshake: normal, non-shareable, or system-shareable, but not barrier"/>
- <event event="0x0f" option_set="Slave" title="CCI-400" name="Write: shareable" description="Write request handshake: inner- or outer-shareable, WriteBack or WriteClean"/>
- <event event="0x10" option_set="Slave" title="CCI-400" name="Write: WriteUnique" description="Write request handshake: WriteUnique"/>
- <event event="0x11" option_set="Slave" title="CCI-400" name="Write: WriteLineUnique" description="Write request handshake: WriteLineUnique"/>
- <event event="0x12" option_set="Slave" title="CCI-400" name="Write: Evict" description="Write request handshake: Evict"/>
- <event event="0x13" option_set="Slave" title="CCI-400" name="Write stall: tracker full" description="Write request stall cycle because the transaction tracker is full. Increase SIx_W_MAX to avoid this stall"/>
- <event event="0x14" option_set="Slave" title="CCI-400" name="Read stall: slave hazard" description="Read request stall cycle because of a slave interface ID hazard"/>
-
- <option_set name="Master">
- <option event_delta="0xa0" name="M0" description="Master interface 0"/>
- <option event_delta="0xc0" name="M1" description="Master interface 1"/>
- <option event_delta="0xe0" name="M2" description="Master interface 2"/>
- </option_set>
-
- <event event="0x00" option_set="Master" title="CCI-400" name="Retry fetch" description="RETRY of speculative fetch transaction"/>
- <event event="0x01" option_set="Master" title="CCI-400" name="Read stall: address hazard" description="Stall cycle because of an address hazard. A read or write invalidation is stalled because of an outstanding transaction to an overlapping address"/>
- <event event="0x02" option_set="Master" title="CCI-400" name="Read stall: ID hazard" description="Read request stall cycle because of a master interface ID hazard"/>
- <event event="0x03" option_set="Master" title="CCI-400" name="Read stall: tracker full" description="A read request with a QoS value in the high priority group is stalled for a cycle because the read transaction queue is full. Increase MIx_R_MAX to avoid this stall"/>
- <event event="0x04" option_set="Master" title="CCI-400" name="Read stall: barrier hazard" description="Read request stall cycle because of a barrier hazard"/>
- <event event="0x05" option_set="Master" title="CCI-400" name="Write stall: barrier hazard" description="Write request stall cycle because of a barrier hazard"/>
- <event event="0x06" option_set="Master" title="CCI-400" name="Write stall: tracker full" description="A write request is stalled for a cycle because the write transaction tracker is full. Increase MIx_W_MAX to avoid this stall"/>
- <event event="0x07" option_set="Master" title="CCI-400" name="Read Stall: Low Priority" description="A read request with a QoS value in the low priority group is stalled for a cycle because there are no slots available in the read queue for the low priority group"/>
- <event event="0x08" option_set="Master" title="CCI-400" name="Read Stall: Medium Priority" description="A read request with a QoS value in the medium priority group is stalled for a cycle because there are no slots available in the read queue for the medium priority group"/>
- <event event="0x09" option_set="Master" title="CCI-400" name="Read Stall: VN0" description="A read request is stalled for a cycle while it was waiting for a QVN token on VN0"/>
- <event event="0x0a" option_set="Master" title="CCI-400" name="Read Stall: VN1" description="A read request is stalled for a cycle while it was waiting for a QVN token on VN1"/>
- <event event="0x0b" option_set="Master" title="CCI-400" name="Read Stall: VN2" description="A read request is stalled for a cycle while it was waiting for a QVN token on VN2"/>
- <event event="0x0c" option_set="Master" title="CCI-400" name="Read Stall: VN3" description="A read request is stalled for a cycle while it was waiting for a QVN token on VN3"/>
- <event event="0x0d" option_set="Master" title="CCI-400" name="Write Stall: VN0" description="A write request is stalled for a cycle while it was waiting for a QVN token on VN0"/>
- <event event="0x0e" option_set="Master" title="CCI-400" name="Write Stall: VN1" description="A write request is stalled for a cycle while it was waiting for a QVN token on VN1"/>
- <event event="0x0f" option_set="Master" title="CCI-400" name="Write Stall: VN2" description="A write request is stalled for a cycle while it was waiting for a QVN token on VN2"/>
- <event event="0x10" option_set="Master" title="CCI-400" name="Write Stall: VN" description="A write request is stalled for a cycle while it was waiting for a QVN token on VN"/>
- <event event="0x11" option_set="Master" title="CCI-400" name="WriteUnique or WriteLineUnique Stall" description="A WriteUnique or WriteLineUnique request is stalled for a cycle because of an address hazard"/>
- </category>
+++ /dev/null
- <counter_set name="CCN-504_cnt" count="4"/>
- <category name="CCN-504" counter_set="CCN-504_cnt">
- <event counter="CCN-504_ccnt" title="CCN-504 Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
-
- <option_set name="XP_Region">
- <option event_delta="0x400000" name="XP 0" description="Crosspoint 0"/>
- <option event_delta="0x410000" name="XP 1" description="Crosspoint 1"/>
- <option event_delta="0x420000" name="XP 2" description="Crosspoint 2"/>
- <option event_delta="0x430000" name="XP 3" description="Crosspoint 3"/>
- <option event_delta="0x440000" name="XP 4" description="Crosspoint 4"/>
- <option event_delta="0x450000" name="XP 5" description="Crosspoint 5"/>
- <option event_delta="0x460000" name="XP 6" description="Crosspoint 6"/>
- <option event_delta="0x470000" name="XP 7" description="Crosspoint 7"/>
- <option event_delta="0x480000" name="XP 8" description="Crosspoint 8"/>
- <option event_delta="0x490000" name="XP 9" description="Crosspoint 9"/>
- <option event_delta="0x4A0000" name="XP 10" description="Crosspoint 10"/>
- </option_set>
-
- <event event="0x0801" option_set="XP_Region" title="CCN-504" name="Bus 0: REQ: H-bit" description="Bus 0: REQ: Set H-bit, signaled when this XP sets the H-bit."/>
- <event event="0x0802" option_set="XP_Region" title="CCN-504" name="Bus 0: REQ: S-bit" description="Bus 0: REQ: Set S-bit, signaled when this XP sets the S-bit."/>
- <event event="0x0803" option_set="XP_Region" title="CCN-504" name="Bus 0: REQ: P-Cnt" description="Bus 0: REQ: Set P-Cnt, signaled when this XP sets the P-Cnt. This is not applicable for the SNP VC."/>
- <event event="0x0804" option_set="XP_Region" title="CCN-504" name="Bus 0: REQ: TknV" description="Bus 0: REQ: No TknV, signaled when this XP transmits a valid packet."/>
- <event event="0x0809" option_set="XP_Region" title="CCN-504" name="Bus 1: REQ: H-bit" description="Bus 1: REQ: Set H-bit, signaled when this XP sets the H-bit."/>
- <event event="0x080A" option_set="XP_Region" title="CCN-504" name="Bus 1: REQ: S-bit" description="Bus 1: REQ: Set S-bit, signaled when this XP sets the S-bit."/>
- <event event="0x080B" option_set="XP_Region" title="CCN-504" name="Bus 1: REQ: P-Cnt" description="Bus 1: REQ: Set P-Cnt, signaled when this XP sets the P-Cnt. This is not applicable for the SNP VC."/>
- <event event="0x080C" option_set="XP_Region" title="CCN-504" name="Bus 1: REQ: TknV" description="Bus 1: REQ: No TknV, signaled when this XP transmits a valid packet."/>
- <event event="0x0811" option_set="XP_Region" title="CCN-504" name="Bus 0: RSP: H-bit" description="Bus 0: RSP: Set H-bit, signaled when this XP sets the H-bit."/>
- <event event="0x0812" option_set="XP_Region" title="CCN-504" name="Bus 0: RSP: S-bit" description="Bus 0: RSP: Set S-bit, signaled when this XP sets the S-bit."/>
- <event event="0x0813" option_set="XP_Region" title="CCN-504" name="Bus 0: RSP: P-Cnt" description="Bus 0: RSP: Set P-Cnt, signaled when this XP sets the P-Cnt. This is not applicable for the SNP VC."/>
- <event event="0x0814" option_set="XP_Region" title="CCN-504" name="Bus 0: RSP: TknV" description="Bus 0: RSP: No TknV, signaled when this XP transmits a valid packet."/>
- <event event="0x0819" option_set="XP_Region" title="CCN-504" name="Bus 1: RSP: H-bit" description="Bus 1: RSP: Set H-bit, signaled when this XP sets the H-bit."/>
- <event event="0x081A" option_set="XP_Region" title="CCN-504" name="Bus 1: RSP: S-bit" description="Bus 1: RSP: Set S-bit, signaled when this XP sets the S-bit."/>
- <event event="0x081B" option_set="XP_Region" title="CCN-504" name="Bus 1: RSP: P-Cnt" description="Bus 1: RSP: Set P-Cnt, signaled when this XP sets the P-Cnt. This is not applicable for the SNP VC."/>
- <event event="0x081C" option_set="XP_Region" title="CCN-504" name="Bus 1: RSP: TknV" description="Bus 1: RSP: No TknV, signaled when this XP transmits a valid packet."/>
- <event event="0x0821" option_set="XP_Region" title="CCN-504" name="Bus 0: SNP: H-bit" description="Bus 0: SNP: Set H-bit, signaled when this XP sets the H-bit."/>
- <event event="0x0822" option_set="XP_Region" title="CCN-504" name="Bus 0: SNP: S-bit" description="Bus 0: SNP: Set S-bit, signaled when this XP sets the S-bit."/>
- <event event="0x0823" option_set="XP_Region" title="CCN-504" name="Bus 0: SNP: P-Cnt" description="Bus 0: SNP: Set P-Cnt, signaled when this XP sets the P-Cnt. This is not applicable for the SNP VC."/>
- <event event="0x0824" option_set="XP_Region" title="CCN-504" name="Bus 0: SNP: TknV" description="Bus 0: SNP: No TknV, signaled when this XP transmits a valid packet."/>
- <event event="0x0829" option_set="XP_Region" title="CCN-504" name="Bus 1: SNP: H-bit" description="Bus 1: SNP: Set H-bit, signaled when this XP sets the H-bit."/>
- <event event="0x082A" option_set="XP_Region" title="CCN-504" name="Bus 1: SNP: S-bit" description="Bus 1: SNP: Set S-bit, signaled when this XP sets the S-bit."/>
- <event event="0x082B" option_set="XP_Region" title="CCN-504" name="Bus 1: SNP: P-Cnt" description="Bus 1: SNP: Set P-Cnt, signaled when this XP sets the P-Cnt. This is not applicable for the SNP VC."/>
- <event event="0x082C" option_set="XP_Region" title="CCN-504" name="Bus 1: SNP: TknV" description="Bus 1: SNP: No TknV, signaled when this XP transmits a valid packet."/>
- <event event="0x0831" option_set="XP_Region" title="CCN-504" name="Bus 0: DAT: H-bit" description="Bus 0: DAT: Set H-bit, signaled when this XP sets the H-bit."/>
- <event event="0x0832" option_set="XP_Region" title="CCN-504" name="Bus 0: DAT: S-bit" description="Bus 0: DAT: Set S-bit, signaled when this XP sets the S-bit."/>
- <event event="0x0833" option_set="XP_Region" title="CCN-504" name="Bus 0: DAT: P-Cnt" description="Bus 0: DAT: Set P-Cnt, signaled when this XP sets the P-Cnt. This is not applicable for the SNP VC."/>
- <event event="0x0834" option_set="XP_Region" title="CCN-504" name="Bus 0: DAT: TknV" description="Bus 0: DAT: No TknV, signaled when this XP transmits a valid packet."/>
- <event event="0x0839" option_set="XP_Region" title="CCN-504" name="Bus 1: DAT: H-bit" description="Bus 1: DAT: Set H-bit, signaled when this XP sets the H-bit."/>
- <event event="0x083A" option_set="XP_Region" title="CCN-504" name="Bus 1: DAT: S-bit" description="Bus 1: DAT: Set S-bit, signaled when this XP sets the S-bit."/>
- <event event="0x083B" option_set="XP_Region" title="CCN-504" name="Bus 1: DAT: P-Cnt" description="Bus 1: DAT: Set P-Cnt, signaled when this XP sets the P-Cnt. This is not applicable for the SNP VC."/>
- <event event="0x083C" option_set="XP_Region" title="CCN-504" name="Bus 1: DAT: TknV" description="Bus 1: DAT: No TknV, signaled when this XP transmits a valid packet."/>
- <event event="0x0871" option_set="XP_Region" title="CCN-504" name="Bus 0: DATB: H-bit" description="Bus 0: DATB: Set H-bit, signaled when this XP sets the H-bit."/>
- <event event="0x0872" option_set="XP_Region" title="CCN-504" name="Bus 0: DATB: S-bit" description="Bus 0: DATB: Set S-bit, signaled when this XP sets the S-bit."/>
- <event event="0x0873" option_set="XP_Region" title="CCN-504" name="Bus 0: DATB: P-Cnt" description="Bus 0: DATB: Set P-Cnt, signaled when this XP sets the P-Cnt. This is not applicable for the SNP VC."/>
- <event event="0x0874" option_set="XP_Region" title="CCN-504" name="Bus 0: DATB: TknV" description="Bus 0: DATB: No TknV, signaled when this XP transmits a valid packet."/>
- <event event="0x0879" option_set="XP_Region" title="CCN-504" name="Bus 1: DATB: H-bit" description="Bus 1: DATB: Set H-bit, signaled when this XP sets the H-bit."/>
- <event event="0x087A" option_set="XP_Region" title="CCN-504" name="Bus 1: DATB: S-bit" description="Bus 1: DATB: Set S-bit, signaled when this XP sets the S-bit."/>
- <event event="0x087B" option_set="XP_Region" title="CCN-504" name="Bus 1: DATB: P-Cnt" description="Bus 1: DATB: Set P-Cnt, signaled when this XP sets the P-Cnt. This is not applicable for the SNP VC."/>
- <event event="0x087C" option_set="XP_Region" title="CCN-504" name="Bus 1: DATB: TknV" description="Bus 1: DATB: No TknV, signaled when this XP transmits a valid packet."/>
-
- <option_set name="HN-F_Region">
- <option event_delta="0x200000" name="HN-F 3" description="Fully-coherent Home Node 3"/>
- <option event_delta="0x210000" name="HN-F 5" description="Fully-coherent Home Node 5"/>
- <option event_delta="0x220000" name="HN-F 7" description="Fully-coherent Home Node 7"/>
- <option event_delta="0x230000" name="HN-F 8" description="Fully-coherent Home Node 8"/>
- <option event_delta="0x240000" name="HN-F 13" description="Fully-coherent Home Node 13"/>
- <option event_delta="0x250000" name="HN-F 15" description="Fully-coherent Home Node 15"/>
- <option event_delta="0x260000" name="HN-F 17" description="Fully-coherent Home Node 17"/>
- <option event_delta="0x270000" name="HN-F 18" description="Fully-coherent Home Node 18"/>
- </option_set>
-
- <event event="0x0401" option_set="HN-F_Region" title="CCN-504" name="Cache Miss" description="Counts the total cache misses. This is the first time lookup result, and is high priority."/>
- <event event="0x0402" option_set="HN-F_Region" title="CCN-504" name="L3 SF Cache Access" description="Counts the number of cache accesses. This is the first time access, and is high priority."/>
- <event event="0x0403" option_set="HN-F_Region" title="CCN-504" name="Cache Fill" description="Counts the total allocations in the HN L3 cache, and all cache line allocations to the L3 cache."/>
- <event event="0x0404" option_set="HN-F_Region" title="CCN-504" name="POCQ Retry" description="Counts the number of requests that have been retried."/>
- <event event="0x0405" option_set="HN-F_Region" title="CCN-504" name="POCQ Reqs Recvd" description="Counts the number of requests received by HN."/>
- <event event="0x0406" option_set="HN-F_Region" title="CCN-504" name="SF Hit" description="Counts the number of snoop filter hits."/>
- <event event="0x0407" option_set="HN-F_Region" title="CCN-504" name="SF Evictions" description="Counts the number of snoop filter evictions. Cache invalidations are initiated."/>
- <event event="0x0408" option_set="HN-F_Region" title="CCN-504" name="Snoops Sent" description="Counts the number of snoops sent. Does not differentiate between broadcast or directed snoops."/>
- <event event="0x0409" option_set="HN-F_Region" title="CCN-504" name="Snoops Broadcast" description="Counts the number of snoop broadcasts sent."/>
- <event event="0x040A" option_set="HN-F_Region" title="CCN-504" name="L3 Eviction" description="Counts the number of L3 evictions."/>
- <event event="0x040B" option_set="HN-F_Region" title="CCN-504" name="L3 Fill Invalid Way" description="Counts the number of L3 fills to an invalid way."/>
- <event event="0x040C" option_set="HN-F_Region" title="CCN-504" name="MC Retries" description="Counts the number of transactions retried by the memory controller."/>
- <event event="0x040D" option_set="HN-F_Region" title="CCN-504" name="MC Reqs" description="Counts the number of requests to the memory controller."/>
- <event event="0x040E" option_set="HN-F_Region" title="CCN-504" name="QOS HH Retry" description="Counts the number of times a highest-priority QoS class was retried at the HN-F."/>
-
- <option_set name="RN-I_Region">
- <option event_delta="0x800000" name="RN-I 0" description="I/O-coherent Requesting Node 0"/>
- <option event_delta="0x820000" name="RN-I 2" description="I/O-coherent Requesting Node 2"/>
- <option event_delta="0x860000" name="RN-I 6" description="I/O-coherent Requesting Node 6"/>
- <option event_delta="0x8C0000" name="RN-I 12" description="I/O-coherent Requesting Node 12"/>
- <option event_delta="0x900000" name="RN-I 16" description="I/O-coherent Requesting Node 16"/>
- <option event_delta="0x940000" name="RN-I 20" description="I/O-coherent Requesting Node 20"/>
- </option_set>
-
- <event event="0x1601" option_set="RN-I_Region" title="CCN-504" name="S0 RDataBeats" description="S0 RDataBeats."/>
- <event event="0x1602" option_set="RN-I_Region" title="CCN-504" name="S1 RDataBeats" description="S1 RDataBeats."/>
- <event event="0x1603" option_set="RN-I_Region" title="CCN-504" name="S2 RDataBeats" description="S2 RDataBeats."/>
- <event event="0x1604" option_set="RN-I_Region" title="CCN-504" name="RXDAT Flits received" description="RXDAT Flits received."/>
- <event event="0x1605" option_set="RN-I_Region" title="CCN-504" name="TXDAT Flits sent" description="TXDAT Flits sent."/>
- <event event="0x1606" option_set="RN-I_Region" title="CCN-504" name="Total TXREQ Flits sent" description="Total TXREQ Flits sent."/>
- <event event="0x1607" option_set="RN-I_Region" title="CCN-504" name="Retried TXREQ Flits sent" description="Retried TXREQ Flits sent."/>
- <event event="0x1608" option_set="RN-I_Region" title="CCN-504" name="RRT full" description="RRT full."/>
- <event event="0x1609" option_set="RN-I_Region" title="CCN-504" name="WRT full" description="WRT full."/>
- <event event="0x160A" option_set="RN-I_Region" title="CCN-504" name="Replayed TXREQ Flits" description="Replayed TXREQ Flits."/>
-
- <option_set name="SBAS_Region">
- <option event_delta="0x810000" name="SBAS 1" description="ACE master to CHI protocol bridge 1"/>
- <option event_delta="0x890000" name="SBAS 9" description="ACE master to CHI protocol bridge 9"/>
- <option event_delta="0x8B0000" name="SBAS 11" description="ACE master to CHI protocol bridge 11"/>
- <option event_delta="0x930000" name="SBAS 19" description="ACE master to CHI protocol bridge 19"/>
- </option_set>
-
- <event event="0x1001" option_set="SBAS_Region" title="CCN-504" name="S0 RDataBeats" description="S0 RDataBeats."/>
- <event event="0x1004" option_set="SBAS_Region" title="CCN-504" name="RXDAT Flits received" description="RXDAT Flits received."/>
- <event event="0x1005" option_set="SBAS_Region" title="CCN-504" name="TXDAT Flits sent" description="TXDAT Flits sent."/>
- <event event="0x1006" option_set="SBAS_Region" title="CCN-504" name="Total TXREQ Flits sent" description="Total TXREQ Flits sent."/>
- <event event="0x1007" option_set="SBAS_Region" title="CCN-504" name="Retried TXREQ Flits sent" description="Retried TXREQ Flits sent."/>
- <event event="0x1008" option_set="SBAS_Region" title="CCN-504" name="RRT full" description="RRT full."/>
- <event event="0x1009" option_set="SBAS_Region" title="CCN-504" name="WRT full" description="WRT full."/>
- <event event="0x100A" option_set="SBAS_Region" title="CCN-504" name="Replayed TXREQ Flits" description="Replayed TXREQ Flits."/>
-
- </category>
+++ /dev/null
- <counter_set name="ARMv7_Cortex_A12_cnt" count="6"/>
- <category name="Cortex-A12" counter_set="ARMv7_Cortex_A12_cnt" per_cpu="yes" supports_event_based_sampling="yes">
- <event counter="ARMv7_Cortex_A12_ccnt" event="0xff" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/>
- <event event="0x01" title="Cache" name="Instruction refill" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/>
- <event event="0x02" title="Cache" name="Inst TLB refill" description="Instruction fetch that causes a TLB refill of at least the level of TLB closest to the processor"/>
- <event event="0x03" title="Cache" name="Data refill" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/>
- <event event="0x04" title="Cache" name="Data access" description="Memory Read or Write operation that causes a cache access to at least the level of data or unified cache closest to the processor"/>
- <event event="0x05" title="Cache" name="Data TLB refill" description="Memory Read or Write operation that causes a TLB refill of at least the level of TLB closest to the processor"/>
- <event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/>
- <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/>
- <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/>
- <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/>
- <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/>
- <event event="0x12" title="Branch" name="Potential prediction" description="Branch or other change in program flow that could have been predicted by the branch prediction resources of the processor"/>
- <event event="0x13" title="Memory" name="Memory access" description="Data memory access"/>
- <event event="0x14" title="Cache" name="L1 inst access" description="Instruction cache access"/>
- <event event="0x15" title="Cache" name="L1 data write" description="Level 1 data cache Write-Back"/>
- <event event="0x16" title="Cache" name="L2 data access" description="Level 2 data cache access"/>
- <event event="0x17" title="Cache" name="L2 data refill" description="Level 2 data cache refill"/>
- <event event="0x18" title="Cache" name="L2 data write" description="Level 2 data cache Write-Back"/>
- <event event="0x19" title="Bus" name="Access" description="Bus - Access"/>
- <event event="0x1b" title="Instruction" name="Speculative" description="Instruction speculatively executed"/>
- <event event="0x1c" title="Memory" name="Translation table" description="Write to translation table base architecturally executed"/>
- <event event="0x1d" title="Bus" name="Cycle" description="Bus - Cycle"/>
- <event event="0x40" title="Cache" name="L1 data read" description="Level 1 data cache access - Read"/>
- <event event="0x41" title="Cache" name="L1 data access write" description="Level 1 data cache access - Write"/>
- <event event="0x50" title="Cache" name="L2 data read" description="Level 2 data cache access - Read"/>
- <event event="0x51" title="Cache" name="L2 data access write" description="Level 2 data cache access - Write"/>
- <event event="0x56" title="Cache" name="L2 data victim" description="Level 2 data cache Write-Back - Victim"/>
- <event event="0x57" title="Cache" name="L2 data clean" description="Level 2 data cache Write-Back - Cleaning and coherency"/>
- <event event="0x58" title="Cache" name="L2 data invalidate" description="Level 2 data cache invalidate"/>
- <event event="0x60" title="Bus" name="Read" description="Bus access - Read"/>
- <event event="0x62" title="Bus" name="Access shared" description="Bus access - Normal"/>
- <event event="0x63" title="Bus" name="Access not shared" description="Bus access - Not normal"/>
- <event event="0x64" title="Bus" name="Access normal" description="Bus access - Normal"/>
- <event event="0x65" title="Bus" name="Peripheral" description="Bus access - Peripheral"/>
- <event event="0x66" title="Memory" name="Read" description="Data memory access - Read"/>
- <event event="0x67" title="Memory" name="Write" description="Data memory access - Write"/>
- <event event="0x68" title="Memory" name="Unaligned Read" description="Unaligned access - Read"/>
- <event event="0x69" title="Memory" name="Unaligned Write" description="Unaligned access - Write"/>
- <event event="0x6a" title="Memory" name="Unaligned" description="Unaligned access"/>
- <event event="0x6c" title="Intrinsic" name="LDREX" description="Exclusive instruction speculatively executed - LDREX"/>
- <event event="0x6e" title="Intrinsic" name="STREX fail" description="Exclusive instruction speculatively executed - STREX fail"/>
- <event event="0x6f" title="Intrinsic" name="STREX" description="Exclusive instruction speculatively executed - STREX"/>
- <event event="0x70" title="Instruction" name="Load" description="Instruction speculatively executed - Load"/>
- <event event="0x71" title="Instruction" name="Store" description="Instruction speculatively executed - Store"/>
- <event event="0x72" title="Instruction" name="Load/Store" description="Instruction speculatively executed - Load or store"/>
- <event event="0x73" title="Instruction" name="Integer" description="Instruction speculatively executed - Integer data processing"/>
- <event event="0x74" title="Instruction" name="Advanced SIMD" description="Instruction speculatively executed - Advanced SIMD"/>
- <event event="0x75" title="Instruction" name="VFP" description="Instruction speculatively executed - VFP"/>
- <event event="0x76" title="Instruction" name="Software change" description="Instruction speculatively executed - Software change of the PC"/>
- <event event="0x78" title="Instruction" name="Immediate branch" description="Branch speculatively executed - Immediate branch"/>
- <event event="0x79" title="Instruction" name="Procedure return" description="Branch speculatively executed - Procedure return"/>
- <event event="0x7a" title="Instruction" name="Indirect branch" description="Branch speculatively executed - Indirect branch"/>
- <event event="0x7c" title="Instruction" name="ISB" description="Barrier speculatively executed - ISB"/>
- <event event="0x7d" title="Instruction" name="DSB" description="Barrier speculatively executed - DSB"/>
- <event event="0x7e" title="Instruction" name="DMB" description="Barrier speculatively executed - DMB"/>
- <event event="0x81" title="Exception" name="Undefined" description="Exception taken, other synchronous"/>
- <event event="0x8a" title="Exception" name="Hypervisor call" description="Exception taken, Hypervisor Call"/>
- <event event="0xc0" title="Instruction" name="Stalled Linefill" description="Instruction side stalled due to a Linefill"/>
- <event event="0xc1" title="Instruction" name="Stalled Page Table Walk" description="Instruction Side stalled due to a Page Table Walk"/>
- <event event="0xc2" title="Cache" name="4 Ways Read" description="Number of set of 4 ways read in the instruction cache - Tag RAM"/>
- <event event="0xc3" title="Cache" name="Ways Read" description="Number of ways read in the instruction cache - Data RAM"/>
- <event event="0xc4" title="Cache" name="BATC Read" description="Number of ways read in the instruction BTAC RAM"/>
- <event event="0xca" title="Memory" name="Snoop" description="Data snooped from other processor. This event counts memory-read operations that read data from another processor within the local Cortex-A12 cluster, rather than accessing the L2 cache or issuing an external read. It increments on each transaction, rather than on each beat of data"/>
- <event event="0xd3" title="Slots" name="Load-Store Unit" description="Duration during which all slots in the Load-Store Unit are busy"/>
- <event event="0xd8" title="Slots" name="Load-Store Issue Queue" description="Duration during which all slots in the Load-Store Issue queue are busy"/>
- <event event="0xd9" title="Slots" name="Data Processing Issue Queue" description="Duration during which all slots in the Data Processing issue queue are busy"/>
- <event event="0xda" title="Slots" name="Data Engine Issue Queue" description="Duration during which all slots in the Data Engine issue queue are busy"/>
- <event event="0xdb" title="NEON" name="Flush" description="Number of NEON instruction which fail their condition code and lead to a flush of the DE pipe"/>
- <event event="0xdc" title="Hypervisor" name="Traps" description="Number of Trap to hypervisor"/>
- <event event="0xde" title="PTM" name="EXTOUT 0" description="PTM EXTOUT 0"/>
- <event event="0xdf" title="PTM" name="EXTOUT 1" description="PTM EXTOUT 1"/>
- <event event="0xe0" title="MMU" name="Table Walk" description="Duration during which the MMU handle a Page table walk"/>
- <event event="0xe1" title="MMU" name="Stage1 Table Walk" description="Duration during which the MMU handle a Stage1 Page table walk"/>
- <event event="0xe2" title="MMU" name="Stage2 Table Walk" description="Duration during which the MMU handle a Stage2 Page table walk"/>
- <event event="0xe3" title="MMU" name="LSU Table Walk" description="Duration during which the MMU handle a Page table walk requested by the Load Store Unit"/>
- <event event="0xe4" title="MMU" name="Instruction Table Walk" description="Duration during which the MMU handle a Page table walk requested by the Instruction side"/>
- <event event="0xe5" title="MMU" name="Preload Table Walk" description="Duration during which the MMU handle a Page table walk requested by a Preload instruction or Prefetch request"/>
- <event event="0xe6" title="MMU" name="cp15 Table Walk" description="Duration during which the MMU handle a Page table walk requested by a cp15 operation (maintenance by MVA and VA-to-PA operation)"/>
- <event event="0xe7" title="Cache" name="L1 PLD TLB refill" description="Level 1 PLD TLB refill"/>
- <event event="0xe8" title="Cache" name="L1 CP15 TLB refill" description="Level 1 CP15 TLB refill"/>
- <event event="0xe9" title="Cache" name="L1 TLB flush" description="Level 1 TLB flush"/>
- <event event="0xea" title="Cache" name="L2 TLB access" description="Level 2 TLB access"/>
- <event event="0xeb" title="Cache" name="L2 TLB miss" description="Level 2 TLB miss"/>
- </category>
+++ /dev/null
- <counter_set name="ARMv7_Cortex_A15_cnt" count="6"/>
- <category name="Cortex-A15" counter_set="ARMv7_Cortex_A15_cnt" per_cpu="yes" supports_event_based_sampling="yes">
- <event counter="ARMv7_Cortex_A15_ccnt" event="0xff" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/>
- <event event="0x00" title="Software" name="Increment" description="Software increment architecturally executed"/>
- <event event="0x01" title="Cache" name="Instruction refill" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/>
- <event event="0x02" title="Cache" name="Inst TLB refill" description="Instruction fetch that causes a TLB refill of at least the level of TLB closest to the processor"/>
- <event event="0x03" title="Cache" name="Data refill" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/>
- <event event="0x04" title="Cache" name="Data access" description="Memory Read or Write operation that causes a cache access to at least the level of data or unified cache closest to the processor"/>
- <event event="0x05" title="Cache" name="Data TLB refill" description="Memory Read or Write operation that causes a TLB refill of at least the level of TLB closest to the processor"/>
- <event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/>
- <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/>
- <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/>
- <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/>
- <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/>
- <event event="0x12" title="Branch" name="Potential prediction" description="Branch or other change in program flow that could have been predicted by the branch prediction resources of the processor"/>
- <event event="0x13" title="Memory" name="Memory access" description="Data memory access"/>
- <event event="0x14" title="Cache" name="L1 inst access" description="Instruction cache access"/>
- <event event="0x15" title="Cache" name="L1 data write" description="Level 1 data cache Write-Back"/>
- <event event="0x16" title="Cache" name="L2 data access" description="Level 2 data cache access"/>
- <event event="0x17" title="Cache" name="L2 data refill" description="Level 2 data cache refill"/>
- <event event="0x18" title="Cache" name="L2 data write" description="Level 2 data cache Write-Back"/>
- <event event="0x19" title="Bus" name="Access" description="Bus - Access"/>
- <event event="0x1a" title="Memory" name="Error" description="Local memory error"/>
- <event event="0x1b" title="Instruction" name="Speculative" description="Instruction speculatively executed"/>
- <event event="0x1c" title="Memory" name="Translation table" description="Write to translation table base architecturally executed"/>
- <event event="0x1d" title="Bus" name="Cycle" description="Bus - Cycle"/>
- <event event="0x40" title="Cache" name="L1 data read" description="Level 1 data cache access - Read"/>
- <event event="0x41" title="Cache" name="L1 data access write" description="Level 1 data cache access - Write"/>
- <event event="0x42" title="Cache" name="L1 data refill read" description="Level 1 data cache refill - Read"/>
- <event event="0x43" title="Cache" name="L1 data refill write" description="Level 1 data cache refill - Write"/>
- <event event="0x46" title="Cache" name="L1 data victim" description="Level 1 data cache Write-Back - Victim"/>
- <event event="0x47" title="Cache" name="L1 data clean" description="Level 1 data cache Write-Back - Cleaning and coherency"/>
- <event event="0x48" title="Cache" name="L1 data invalidate" description="Level 1 data cache invalidate"/>
- <event event="0x4c" title="TLB" name="L1 data refill read" description="Level 1 data TLB refill - Read"/>
- <event event="0x4d" title="TLB" name="L1 data refill write" description="Level 1 data TLB refill - Write"/>
- <event event="0x50" title="Cache" name="L2 data read" description="Level 2 data cache access - Read"/>
- <event event="0x51" title="Cache" name="L2 data access write" description="Level 2 data cache access - Write"/>
- <event event="0x52" title="Cache" name="L2 data refill read" description="Level 2 data cache refill - Read"/>
- <event event="0x53" title="Cache" name="L2 data refill write" description="Level 2 data cache refill - Write"/>
- <event event="0x56" title="Cache" name="L2 data victim" description="Level 2 data cache Write-Back - Victim"/>
- <event event="0x57" title="Cache" name="L2 data clean" description="Level 2 data cache Write-Back - Cleaning and coherency"/>
- <event event="0x58" title="Cache" name="L2 data invalidate" description="Level 2 data cache invalidate"/>
- <event event="0x60" title="Bus" name="Read" description="Bus access - Read"/>
- <event event="0x61" title="Bus" name="Write" description="Bus access - Write"/>
- <event event="0x64" title="Bus" name="Access normal" description="Bus access - Normal"/>
- <event event="0x65" title="Bus" name="Peripheral" description="Bus access - Peripheral"/>
- <event event="0x66" title="Memory" name="Read" description="Data memory access - Read"/>
- <event event="0x67" title="Memory" name="Write" description="Data memory access - Write"/>
- <event event="0x68" title="Memory" name="Unaligned Read" description="Unaligned access - Read"/>
- <event event="0x69" title="Memory" name="Unaligned Write" description="Unaligned access - Write"/>
- <event event="0x6a" title="Memory" name="Unaligned" description="Unaligned access"/>
- <event event="0x6c" title="Intrinsic" name="LDREX" description="Exclusive instruction speculatively executed - LDREX"/>
- <event event="0x6d" title="Intrinsic" name="STREX pass" description="Exclusive instruction speculatively executed - STREX pass"/>
- <event event="0x6e" title="Intrinsic" name="STREX fail" description="Exclusive instruction speculatively executed - STREX fail"/>
- <event event="0x70" title="Instruction" name="Load" description="Instruction speculatively executed - Load"/>
- <event event="0x71" title="Instruction" name="Store" description="Instruction speculatively executed - Store"/>
- <event event="0x72" title="Instruction" name="Load/Store" description="Instruction speculatively executed - Load or store"/>
- <event event="0x73" title="Instruction" name="Integer" description="Instruction speculatively executed - Integer data processing"/>
- <event event="0x74" title="Instruction" name="Advanced SIMD" description="Instruction speculatively executed - Advanced SIMD"/>
- <event event="0x75" title="Instruction" name="VFP" description="Instruction speculatively executed - VFP"/>
- <event event="0x76" title="Instruction" name="Software change" description="Instruction speculatively executed - Software change of the PC"/>
- <event event="0x78" title="Instruction" name="Immediate branch" description="Branch speculatively executed - Immediate branch"/>
- <event event="0x79" title="Instruction" name="Procedure return" description="Branch speculatively executed - Procedure return"/>
- <event event="0x7a" title="Instruction" name="Indirect branch" description="Branch speculatively executed - Indirect branch"/>
- <event event="0x7c" title="Instruction" name="ISB" description="Barrier speculatively executed - ISB"/>
- <event event="0x7d" title="Instruction" name="DSB" description="Barrier speculatively executed - DSB"/>
- <event event="0x7e" title="Instruction" name="DMB" description="Barrier speculatively executed - DMB"/>
- </category>
+++ /dev/null
- <counter_set name="ARMv7_Cortex_A5_cnt" count="2"/>
- <category name="Cortex-A5" counter_set="ARMv7_Cortex_A5_cnt" per_cpu="yes" supports_event_based_sampling="yes">
- <event counter="ARMv7_Cortex_A5_ccnt" event="0xff" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/>
- <event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/>
- <event event="0x01" title="Cache" name="Instruction refill" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/>
- <event event="0x02" title="Cache" name="Inst TLB refill" description="Instruction fetch that causes a TLB refill of at least the level of TLB closest to the processor"/>
- <event event="0x03" title="Cache" name="Data refill" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/>
- <event event="0x04" title="Cache" name="Data access" description="Memory Read or Write operation that causes a cache access to at least the level of data or unified cache closest to the processor"/>
- <event event="0x05" title="Cache" name="Data TLB refill" description="Memory Read or Write operation that causes a TLB refill of at least the level of TLB closest to the processor"/>
- <event event="0x06" title="Instruction" name="Memory read" description="Memory-reading instruction architecturally executed"/>
- <event event="0x07" title="Instruction" name="Memory write" description="Memory-writing instruction architecturally executed"/>
- <event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/>
- <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/>
- <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/>
- <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/>
- <event event="0x0c" title="Branch" name="PC change" description="Software change of the Program Counter, except by an exception, architecturally executed"/>
- <event event="0x0d" title="Branch" name="Immediate" description="Immediate branch architecturally executed"/>
- <event event="0x0e" title="Procedure" name="Return" description="Procedure return, other than exception return, architecturally executed"/>
- <event event="0x0f" title="Memory" name="Unaligned access" description="Unaligned access architecturally executed"/>
- <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/>
- <event event="0x12" title="Branch" name="Potential prediction" description="Branch or other change in program flow that could have been predicted by the branch prediction resources of the processor"/>
- <event event="0x13" title="Memory" name="Memory access" description="Data memory access"/>
- <event event="0x14" title="Cache" name="Instruction access" description="Instruction cache access"/>
- <event event="0x15" title="Cache" name="Data eviction" description="Data cache eviction"/>
- <event event="0x86" title="Interrupts" name="IRQ" description="IRQ exception taken"/>
- <event event="0x87" title="Interrupts" name="FIQ" description="FIQ exception taken"/>
- <event event="0xC0" title="Memory" name="External request" description="External memory request"/>
- <event event="0xC1" title="Memory" name="Non-cacheable ext req" description="Non-cacheable external memory request"/>
- <event event="0xC2" title="Cache" name="Linefill" description="Linefill because of prefetch"/>
- <event event="0xC3" title="Cache" name="Linefill dropped" description="Prefetch linefill dropped"/>
- <event event="0xC4" title="Cache" name="Allocate mode enter" description="Entering read allocate mode"/>
- <event event="0xC5" title="Cache" name="Allocate mode" description="Read allocate mode"/>
- <event event="0xC7" title="ETM" name="ETM Ext Out[0]" description="ETM - ETM Ext Out[0]"/>
- <event event="0xC8" title="ETM" name="ETM Ext Out[1]" description="ETM - ETM Ext Out[1]"/>
- <event event="0xC9" title="Instruction" name="Pipeline stall" description="Data Write operation that stalls the pipeline because the store buffer is full"/>
- </category>
+++ /dev/null
- <counter_set name="ARM_Cortex-A53_cnt" count="6"/>
- <category name="Cortex-A53" counter_set="ARM_Cortex-A53_cnt" per_cpu="yes" supports_event_based_sampling="yes">
- <!-- 0x11 CPU_CYCLES - Cycle -->
- <event counter="ARM_Cortex-A53_ccnt" event="0x11" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/>
- <!-- 0x00 SW_INCR - Instruction architecturally executed (condition check pass) - Software increment -->
- <event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/>
- <!-- 0x01 L1I_CACHE_REFILL - Level 1 instruction cache refill -->
- <event event="0x01" title="Cache" name="Instruction refill" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/>
- <!-- 0x02 L1I_TLB_REFILL - Level 1 instruction TLB refill -->
- <event event="0x02" title="Cache" name="Inst TLB refill" description="Instruction fetch that causes a TLB refill of at least the level of TLB closest to the processor"/>
- <!-- 0x03 L1D_CACHE_REFILL - Level 1 data cache refill -->
- <event event="0x03" title="Cache" name="Data refill" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/>
- <!-- 0x04 L1D_CACHE - Level 1 data cache access -->
- <event event="0x04" title="Cache" name="Data access" description="Memory Read or Write operation that causes a cache access to at least the level of data or unified cache closest to the processor"/>
- <!-- 0x05 L1D_TLB_REFILL - Level 1 data TLB refill -->
- <event event="0x05" title="Cache" name="Data TLB refill" description="Memory Read or Write operation that causes a TLB refill of at least the level of TLB closest to the processor"/>
- <!-- 0x08 INST_RETIRED - Instruction architecturally executed -->
- <event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/>
- <!-- 0x09 EXC_TAKEN - Exception taken -->
- <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/>
- <!-- 0x0A EXC_RETURN - Instruction architecturally executed (condition check pass) - Exception return -->
- <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/>
- <!-- 0x0B CID_WRITE_RETIRED - Instruction architecturally executed (condition check pass) - Write to CONTEXTIDR -->
- <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/>
- <!-- 0x10 BR_MIS_PRED - Mispredicted or not predicted branch speculatively executed -->
- <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/>
- <!-- 0x12 BR_PRED - Predictable branch speculatively executed -->
- <event event="0x12" title="Branch" name="Potential prediction" description="Branch or other change in program flow that could have been predicted by the branch prediction resources of the processor"/>
- <!-- 0x13 MEM_ACCESS - Data memory access -->
- <event event="0x13" title="Memory" name="Memory access" description="Data memory access"/>
- <!-- 0x14 L1I_CACHE - Level 1 instruction cache access -->
- <event event="0x14" title="Cache" name="L1 inst access" description="Level 1 instruction cache access"/>
- <!-- 0x15 L1D_CACHE_WB - Level 1 data cache Write-Back -->
- <event event="0x15" title="Cache" name="L1 data write" description="Level 1 data cache Write-Back"/>
- <!-- 0x16 L2D_CACHE - Level 2 data cache access -->
- <event event="0x16" title="Cache" name="L2 data access" description="Level 2 data cache access"/>
- <!-- 0x17 L2D_CACHE_REFILL - Level 2 data cache refill -->
- <event event="0x17" title="Cache" name="L2 data refill" description="Level 2 data cache refill"/>
- <!-- 0x18 L2D_CACHE_WB - Level 2 data cache Write-Back -->
- <event event="0x18" title="Cache" name="L2 data write" description="Level 2 data cache Write-Back"/>
- <!-- 0x19 BUS_ACCESS - Bus access -->
- <event event="0x19" title="Bus" name="Access" description="Bus access"/>
- <!-- 0x1A MEMORY_ERROR - Local memory error -->
- <event event="0x1A" title="Memory" name="Error" description="Local memory error"/>
- <!-- 0x1B INST_SPEC - Operation speculatively executed -->
- <event event="0x1B" title="Instruction" name="Speculative" description="Operation speculatively executed"/>
- <!-- 0x1C TTBR_WRITE_RETIRED - Instruction architecturally executed (condition check pass) - Write to translation table base -->
- <event event="0x1C" title="Memory" name="Translation table" description="Instruction architecturally executed (condition check pass) - Write to translation table base"/>
- <!-- 0x1D BUS_CYCLES - Bus cycle -->
- <event event="0x1D" title="Bus" name="Cycle" description="Bus cycle"/>
- <!-- 0x1E CHAIN - Odd performance counter chain mode -->
- <event event="0x1E" title="Counter chain" name="Odd Performance" description="Odd performance counter chain mode"/>
- <!-- 0x40 L1D_CACHE_LD - Level 1 data cache access - Read -->
- <event event="0x40" title="Cache" name="L1 data read" description="Level 1 data cache access - Read"/>
- <!-- 0x41 L1D_CACHE_ST - Level 1 data cache access - Write -->
- <event event="0x41" title="Cache" name="L1 data access write" description="Level 1 data cache access - Write"/>
- <!-- 0x42 L1D_CACHE_REFILL_LD - Level 1 data cache refill - Read -->
- <event event="0x42" title="Cache" name="L1 data refill read" description="Level 1 data cache refill - Read"/>
- <!-- 0x43 L1D_CACHE_REFILL_ST - Level 1 data cache refill - Write -->
- <event event="0x43" title="Cache" name="L1 data refill write" description="Level 1 data cache refill - Write"/>
- <!-- 0x46 L1D_CACHE_WB_VICTIM - Level 1 data cache Write-back - Victim -->
- <event event="0x46" title="Cache" name="L1 data victim" description="Level 1 data cache Write-back - Victim"/>
- <!-- 0x47 L1D_CACHE_WB_CLEAN - Level 1 data cache Write-back - Cleaning and coherency -->
- <event event="0x47" title="Cache" name="L1 data clean" description="Level 1 data cache Write-back - Cleaning and coherency"/>
- <!-- 0x48 L1D_CACHE_INVAL - Level 1 data cache invalidate -->
- <event event="0x48" title="Cache" name="L1 data invalidate" description="Level 1 data cache invalidate"/>
- <!-- 0x4C L1D_TLB_REFILL_LD - Level 1 data TLB refill - Read -->
- <event event="0x4C" title="Cache" name="L1 data refill read" description="Level 1 data TLB refill - Read"/>
- <!-- 0x4D L1D_TLB_REFILL_ST - Level 1 data TLB refill - Write -->
- <event event="0x4D" title="Cache" name="L1 data refill write" description="Level 1 data TLB refill - Write"/>
- <!-- 0x50 L2D_CACHE_LD - Level 2 data cache access - Read -->
- <event event="0x50" title="Cache" name="L2 data read" description="Level 2 data cache access - Read"/>
- <!-- 0x51 L2D_CACHE_ST - Level 2 data cache access - Write -->
- <event event="0x51" title="Cache" name="L2 data access write" description="Level 2 data cache access - Write"/>
- <!-- 0x52 L2D_CACHE_REFILL_LD - Level 2 data cache refill - Read -->
- <event event="0x52" title="Cache" name="L2 data refill read" description="Level 2 data cache refill - Read"/>
- <!-- 0x53 L2D_CACHE_REFILL_ST - Level 2 data cache refill - Write -->
- <event event="0x53" title="Cache" name="L2 data refill write" description="Level 2 data cache refill - Write"/>
- <!-- 0x56 L2D_CACHE_WB_VICTIM - Level 2 data cache Write-back - Victim -->
- <event event="0x56" title="Cache" name="L2 data victim" description="Level 2 data cache Write-back - Victim"/>
- <!-- 0x57 L2D_CACHE_WB_CLEAN - Level 2 data cache Write-back - Cleaning and coherency -->
- <event event="0x57" title="Cache" name="L2 data clean" description="Level 2 data cache Write-back - Cleaning and coherency"/>
- <!-- 0x58 L2D_CACHE_INVAL - Level 2 data cache invalidate -->
- <event event="0x58" title="Cache" name="L2 data invalidate" description="Level 2 data cache invalidate"/>
- <!-- 0x60 BUS_ACCESS_LD - Bus access - Read -->
- <event event="0x60" title="Bus" name="Read" description="Bus access - Read"/>
- <!-- 0x61 BUS_ACCESS_ST - Bus access - Write -->
- <event event="0x61" title="Bus" name="Write" description="Bus access - Write"/>
- <!-- 0x62 BUS_ACCESS_SHARED - Bus access - Normal -->
- <event event="0x62" title="Bus" name="Access shared" description="Bus access - Normal"/>
- <!-- 0x63 BUS_ACCESS_NOT_SHARED - Bus access - Not normal -->
- <event event="0x63" title="Bus" name="Access not shared" description="Bus access - Not normal"/>
- <!-- 0x64 BUS_ACCESS_NORMAL - Bus access - Normal -->
- <event event="0x64" title="Bus" name="Access normal" description="Bus access - Normal"/>
- <!-- 0x65 BUS_ACCESS_PERIPH - Bus access - Peripheral -->
- <event event="0x65" title="Bus" name="Peripheral" description="Bus access - Peripheral"/>
- <!-- 0x66 MEM_ACCESS_LD - Data memory access - Read -->
- <event event="0x66" title="Memory" name="Read" description="Data memory access - Read"/>
- <!-- 0x67 MEM_ACCESS_ST - Data memory access - Write -->
- <event event="0x67" title="Memory" name="Write" description="Data memory access - Write"/>
- <!-- 0x68 UNALIGNED_LD_SPEC - Unaligned access - Read -->
- <event event="0x68" title="Memory" name="Unaligned Read" description="Unaligned access - Read"/>
- <!-- 0x69 UNALIGNED_ST_SPEC - Unaligned access - Write -->
- <event event="0x69" title="Memory" name="Unaligned Write" description="Unaligned access - Write"/>
- <!-- 0x6A UNALIGNED_LDST_SPEC - Unaligned access -->
- <event event="0x6A" title="Memory" name="Unaligned" description="Unaligned access"/>
- <!-- 0x6C LDREX_SPEC - Exclusive operation speculatively executed - LDREX -->
- <event event="0x6C" title="Intrinsic" name="LDREX" description="Exclusive operation speculatively executed - LDREX"/>
- <!-- 0x6D STREX_PASS_SPEC - Exclusive instruction speculatively executed - STREX pass -->
- <event event="0x6D" title="Intrinsic" name="STREX pass" description="Exclusive instruction speculatively executed - STREX pass"/>
- <!-- 0x6E STREX_FAIL_SPEC - Exclusive operation speculatively executed - STREX fail -->
- <event event="0x6E" title="Intrinsic" name="STREX fail" description="Exclusive operation speculatively executed - STREX fail"/>
- <!-- 0x70 LD_SPEC - Operation speculatively executed - Load -->
- <event event="0x70" title="Instruction" name="Load" description="Operation speculatively executed - Load"/>
- <!-- 0x71 ST_SPEC - Operation speculatively executed - Store -->
- <event event="0x71" title="Instruction" name="Store" description="Operation speculatively executed - Store"/>
- <!-- 0x72 LDST_SPEC - Operation speculatively executed - Load or store -->
- <event event="0x72" title="Instruction" name="Load/Store" description="Operation speculatively executed - Load or store"/>
- <!-- 0x73 DP_SPEC - Operation speculatively executed - Integer data processing -->
- <event event="0x73" title="Instruction" name="Integer" description="Operation speculatively executed - Integer data processing"/>
- <!-- 0x74 ASE_SPEC - Operation speculatively executed - Advanced SIMD -->
- <event event="0x74" title="Instruction" name="Advanced SIMD" description="Operation speculatively executed - Advanced SIMD"/>
- <!-- 0x75 VFP_SPEC - Operation speculatively executed - VFP -->
- <event event="0x75" title="Instruction" name="VFP" description="Operation speculatively executed - VFP"/>
- <!-- 0x76 PC_WRITE_SPEC - Operation speculatively executed - Software change of the PC -->
- <event event="0x76" title="Instruction" name="Software change" description="Operation speculatively executed - Software change of the PC"/>
- <!-- 0x77 CRYPTO_SPEC - Operation speculatively executed, crypto data processing -->
- <event event="0x77" title="Instruction" name="Crypto" description="Operation speculatively executed, crypto data processing"/>
- <!-- 0x78 BR_IMMED_SPEC - Branch speculatively executed - Immediate branch -->
- <event event="0x78" title="Instruction" name="Immediate branch" description="Branch speculatively executed - Immediate branch"/>
- <!-- 0x79 BR_RETURN_SPEC - Branch speculatively executed - Procedure return -->
- <event event="0x79" title="Instruction" name="Procedure return" description="Branch speculatively executed - Procedure return"/>
- <!-- 0x7A BR_INDIRECT_SPEC - Branch speculatively executed - Indirect branch -->
- <event event="0x7A" title="Instruction" name="Indirect branch" description="Branch speculatively executed - Indirect branch"/>
- <!-- 0x7C ISB_SPEC - Barrier speculatively executed - ISB -->
- <event event="0x7C" title="Instruction" name="ISB" description="Barrier speculatively executed - ISB"/>
- <!-- 0x7D DSB_SPEC - Barrier speculatively executed - DSB -->
- <event event="0x7D" title="Instruction" name="DSB" description="Barrier speculatively executed - DSB"/>
- <!-- 0x7E DMB_SPEC - Barrier speculatively executed - DMB -->
- <event event="0x7E" title="Instruction" name="DMB" description="Barrier speculatively executed - DMB"/>
- <!-- 0x81 EXC_UNDEF - Exception taken, other synchronous -->
- <event event="0x81" title="Exception" name="Undefined" description="Exception taken, other synchronous"/>
- <!-- 0x82 EXC_SVC - Exception taken, Supervisor Call -->
- <event event="0x82" title="Exception" name="Supervisor" description="Exception taken, Supervisor Call"/>
- <!-- 0x83 EXC_PABORT - Exception taken, Instruction Abort -->
- <event event="0x83" title="Exception" name="Instruction abort" description="Exception taken, Instruction Abort"/>
- <!-- 0x84 EXC_DABORT - Exception taken, Data Abort or SError -->
- <event event="0x84" title="Exception" name="Data abort" description="Exception taken, Data Abort or SError"/>
- <!-- 0x86 EXC_IRQ - Exception taken, IRQ -->
- <event event="0x86" title="Interrupts" name="IRQ" description="Exception taken, IRQ"/>
- <!-- 0x87 EXC_FIQ - Exception taken, FIQ -->
- <event event="0x87" title="Interrupts" name="FIQ" description="Exception taken, FIQ"/>
- <!-- 0x88 EXC_SMC - Exception taken, Secure Monitor Call -->
- <event event="0x88" title="Exception" name="Secure monitor call" description="Exception taken, Secure Monitor Call"/>
- <!-- 0x8A EXC_HVC - Exception taken, Hypervisor Call -->
- <event event="0x8A" title="Exception" name="Hypervisor call" description="Exception taken, Hypervisor Call"/>
- <!-- 0x8B EXC_TRAP_PABORT - Exception taken, Instruction Abort not taken locally -->
- <event event="0x8B" title="Exception" name="Instruction abort non-local" description="Exception taken, Instruction Abort not taken locally"/>
- <!-- 0x8C EXC_TRAP_DABORT - Exception taken, Data Abort or SError not taken locally -->
- <event event="0x8C" title="Exception" name="Data abort non-local" description="Exception taken, Data Abort or SError not taken locally"/>
- <!-- 0x8D EXC_TRAP_OTHER - Exception taken - Other traps not taken locally -->
- <event event="0x8D" title="Exception" name="Other non-local" description="Exception taken - Other traps not taken locally"/>
- <!-- 0x8E EXC_TRAP_IRQ - Exception taken, IRQ not taken locally -->
- <event event="0x8E" title="Exception" name="IRQ non-local" description="Exception taken, IRQ not taken locally"/>
- <!-- 0x8F EXC_TRAP_FIQ - Exception taken, FIQ not taken locally -->
- <event event="0x8F" title="Exception" name="FIQ non-local" description="Exception taken, FIQ not taken locally"/>
- <!-- 0x90 RC_LD_SPEC - Release consistency instruction speculatively executed - Load Acquire -->
- <event event="0x90" title="Release Consistency" name="Load" description="Release consistency instruction speculatively executed - Load Acquire"/>
- <!-- 0x91 RC_ST_SPEC - Release consistency instruction speculatively executed - Store Release -->
- <event event="0x91" title="Release Consistency" name="Store" description="Release consistency instruction speculatively executed - Store Release"/>
- </category>
+++ /dev/null
- <counter_set name="ARM_Cortex-A57_cnt" count="6"/>
- <category name="Cortex-A57" counter_set="ARM_Cortex-A57_cnt" per_cpu="yes" supports_event_based_sampling="yes">
- <!-- 0x11 CPU_CYCLES - Cycle -->
- <event counter="ARM_Cortex-A57_ccnt" event="0x11" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/>
- <!-- 0x00 SW_INCR - Instruction architecturally executed (condition check pass) - Software increment -->
- <event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/>
- <!-- 0x01 L1I_CACHE_REFILL - Level 1 instruction cache refill -->
- <event event="0x01" title="Cache" name="Instruction refill" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/>
- <!-- 0x02 L1I_TLB_REFILL - Level 1 instruction TLB refill -->
- <event event="0x02" title="Cache" name="Inst TLB refill" description="Instruction fetch that causes a TLB refill of at least the level of TLB closest to the processor"/>
- <!-- 0x03 L1D_CACHE_REFILL - Level 1 data cache refill -->
- <event event="0x03" title="Cache" name="Data refill" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/>
- <!-- 0x04 L1D_CACHE - Level 1 data cache access -->
- <event event="0x04" title="Cache" name="Data access" description="Memory Read or Write operation that causes a cache access to at least the level of data or unified cache closest to the processor"/>
- <!-- 0x05 L1D_TLB_REFILL - Level 1 data TLB refill -->
- <event event="0x05" title="Cache" name="Data TLB refill" description="Memory Read or Write operation that causes a TLB refill of at least the level of TLB closest to the processor"/>
- <!-- 0x08 INST_RETIRED - Instruction architecturally executed -->
- <event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/>
- <!-- 0x09 EXC_TAKEN - Exception taken -->
- <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/>
- <!-- 0x0A EXC_RETURN - Instruction architecturally executed (condition check pass) - Exception return -->
- <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/>
- <!-- 0x0B CID_WRITE_RETIRED - Instruction architecturally executed (condition check pass) - Write to CONTEXTIDR -->
- <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/>
- <!-- 0x10 BR_MIS_PRED - Mispredicted or not predicted branch speculatively executed -->
- <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/>
- <!-- 0x12 BR_PRED - Predictable branch speculatively executed -->
- <event event="0x12" title="Branch" name="Potential prediction" description="Branch or other change in program flow that could have been predicted by the branch prediction resources of the processor"/>
- <!-- 0x13 MEM_ACCESS - Data memory access -->
- <event event="0x13" title="Memory" name="Memory access" description="Data memory access"/>
- <!-- 0x14 L1I_CACHE - Level 1 instruction cache access -->
- <event event="0x14" title="Cache" name="L1 inst access" description="Level 1 instruction cache access"/>
- <!-- 0x15 L1D_CACHE_WB - Level 1 data cache Write-Back -->
- <event event="0x15" title="Cache" name="L1 data write" description="Level 1 data cache Write-Back"/>
- <!-- 0x16 L2D_CACHE - Level 2 data cache access -->
- <event event="0x16" title="Cache" name="L2 data access" description="Level 2 data cache access"/>
- <!-- 0x17 L2D_CACHE_REFILL - Level 2 data cache refill -->
- <event event="0x17" title="Cache" name="L2 data refill" description="Level 2 data cache refill"/>
- <!-- 0x18 L2D_CACHE_WB - Level 2 data cache Write-Back -->
- <event event="0x18" title="Cache" name="L2 data write" description="Level 2 data cache Write-Back"/>
- <!-- 0x19 BUS_ACCESS - Bus access -->
- <event event="0x19" title="Bus" name="Access" description="Bus access"/>
- <!-- 0x1A MEMORY_ERROR - Local memory error -->
- <event event="0x1A" title="Memory" name="Error" description="Local memory error"/>
- <!-- 0x1B INST_SPEC - Operation speculatively executed -->
- <event event="0x1B" title="Instruction" name="Speculative" description="Operation speculatively executed"/>
- <!-- 0x1C TTBR_WRITE_RETIRED - Instruction architecturally executed (condition check pass) - Write to translation table base -->
- <event event="0x1C" title="Memory" name="Translation table" description="Instruction architecturally executed (condition check pass) - Write to translation table base"/>
- <!-- 0x1D BUS_CYCLES - Bus cycle -->
- <event event="0x1D" title="Bus" name="Cycle" description="Bus cycle"/>
- <!-- 0x1E CHAIN - Odd performance counter chain mode -->
- <event event="0x1E" title="Counter chain" name="Odd Performance" description="Odd performance counter chain mode"/>
- <!-- 0x40 L1D_CACHE_LD - Level 1 data cache access - Read -->
- <event event="0x40" title="Cache" name="L1 data read" description="Level 1 data cache access - Read"/>
- <!-- 0x41 L1D_CACHE_ST - Level 1 data cache access - Write -->
- <event event="0x41" title="Cache" name="L1 data access write" description="Level 1 data cache access - Write"/>
- <!-- 0x42 L1D_CACHE_REFILL_LD - Level 1 data cache refill - Read -->
- <event event="0x42" title="Cache" name="L1 data refill read" description="Level 1 data cache refill - Read"/>
- <!-- 0x43 L1D_CACHE_REFILL_ST - Level 1 data cache refill - Write -->
- <event event="0x43" title="Cache" name="L1 data refill write" description="Level 1 data cache refill - Write"/>
- <!-- 0x46 L1D_CACHE_WB_VICTIM - Level 1 data cache Write-back - Victim -->
- <event event="0x46" title="Cache" name="L1 data victim" description="Level 1 data cache Write-back - Victim"/>
- <!-- 0x47 L1D_CACHE_WB_CLEAN - Level 1 data cache Write-back - Cleaning and coherency -->
- <event event="0x47" title="Cache" name="L1 data clean" description="Level 1 data cache Write-back - Cleaning and coherency"/>
- <!-- 0x48 L1D_CACHE_INVAL - Level 1 data cache invalidate -->
- <event event="0x48" title="Cache" name="L1 data invalidate" description="Level 1 data cache invalidate"/>
- <!-- 0x4C L1D_TLB_REFILL_LD - Level 1 data TLB refill - Read -->
- <event event="0x4C" title="Cache" name="L1 data refill read" description="Level 1 data TLB refill - Read"/>
- <!-- 0x4D L1D_TLB_REFILL_ST - Level 1 data TLB refill - Write -->
- <event event="0x4D" title="Cache" name="L1 data refill write" description="Level 1 data TLB refill - Write"/>
- <!-- 0x50 L2D_CACHE_LD - Level 2 data cache access - Read -->
- <event event="0x50" title="Cache" name="L2 data read" description="Level 2 data cache access - Read"/>
- <!-- 0x51 L2D_CACHE_ST - Level 2 data cache access - Write -->
- <event event="0x51" title="Cache" name="L2 data access write" description="Level 2 data cache access - Write"/>
- <!-- 0x52 L2D_CACHE_REFILL_LD - Level 2 data cache refill - Read -->
- <event event="0x52" title="Cache" name="L2 data refill read" description="Level 2 data cache refill - Read"/>
- <!-- 0x53 L2D_CACHE_REFILL_ST - Level 2 data cache refill - Write -->
- <event event="0x53" title="Cache" name="L2 data refill write" description="Level 2 data cache refill - Write"/>
- <!-- 0x56 L2D_CACHE_WB_VICTIM - Level 2 data cache Write-back - Victim -->
- <event event="0x56" title="Cache" name="L2 data victim" description="Level 2 data cache Write-back - Victim"/>
- <!-- 0x57 L2D_CACHE_WB_CLEAN - Level 2 data cache Write-back - Cleaning and coherency -->
- <event event="0x57" title="Cache" name="L2 data clean" description="Level 2 data cache Write-back - Cleaning and coherency"/>
- <!-- 0x58 L2D_CACHE_INVAL - Level 2 data cache invalidate -->
- <event event="0x58" title="Cache" name="L2 data invalidate" description="Level 2 data cache invalidate"/>
- <!-- 0x60 BUS_ACCESS_LD - Bus access - Read -->
- <event event="0x60" title="Bus" name="Read" description="Bus access - Read"/>
- <!-- 0x61 BUS_ACCESS_ST - Bus access - Write -->
- <event event="0x61" title="Bus" name="Write" description="Bus access - Write"/>
- <!-- 0x62 BUS_ACCESS_SHARED - Bus access - Normal -->
- <event event="0x62" title="Bus" name="Access shared" description="Bus access - Normal"/>
- <!-- 0x63 BUS_ACCESS_NOT_SHARED - Bus access - Not normal -->
- <event event="0x63" title="Bus" name="Access not shared" description="Bus access - Not normal"/>
- <!-- 0x64 BUS_ACCESS_NORMAL - Bus access - Normal -->
- <event event="0x64" title="Bus" name="Access normal" description="Bus access - Normal"/>
- <!-- 0x65 BUS_ACCESS_PERIPH - Bus access - Peripheral -->
- <event event="0x65" title="Bus" name="Peripheral" description="Bus access - Peripheral"/>
- <!-- 0x66 MEM_ACCESS_LD - Data memory access - Read -->
- <event event="0x66" title="Memory" name="Read" description="Data memory access - Read"/>
- <!-- 0x67 MEM_ACCESS_ST - Data memory access - Write -->
- <event event="0x67" title="Memory" name="Write" description="Data memory access - Write"/>
- <!-- 0x68 UNALIGNED_LD_SPEC - Unaligned access - Read -->
- <event event="0x68" title="Memory" name="Unaligned Read" description="Unaligned access - Read"/>
- <!-- 0x69 UNALIGNED_ST_SPEC - Unaligned access - Write -->
- <event event="0x69" title="Memory" name="Unaligned Write" description="Unaligned access - Write"/>
- <!-- 0x6A UNALIGNED_LDST_SPEC - Unaligned access -->
- <event event="0x6A" title="Memory" name="Unaligned" description="Unaligned access"/>
- <!-- 0x6C LDREX_SPEC - Exclusive operation speculatively executed - LDREX -->
- <event event="0x6C" title="Intrinsic" name="LDREX" description="Exclusive operation speculatively executed - LDREX"/>
- <!-- 0x6D STREX_PASS_SPEC - Exclusive instruction speculatively executed - STREX pass -->
- <event event="0x6D" title="Intrinsic" name="STREX pass" description="Exclusive instruction speculatively executed - STREX pass"/>
- <!-- 0x6E STREX_FAIL_SPEC - Exclusive operation speculatively executed - STREX fail -->
- <event event="0x6E" title="Intrinsic" name="STREX fail" description="Exclusive operation speculatively executed - STREX fail"/>
- <!-- 0x70 LD_SPEC - Operation speculatively executed - Load -->
- <event event="0x70" title="Instruction" name="Load" description="Operation speculatively executed - Load"/>
- <!-- 0x71 ST_SPEC - Operation speculatively executed - Store -->
- <event event="0x71" title="Instruction" name="Store" description="Operation speculatively executed - Store"/>
- <!-- 0x72 LDST_SPEC - Operation speculatively executed - Load or store -->
- <event event="0x72" title="Instruction" name="Load/Store" description="Operation speculatively executed - Load or store"/>
- <!-- 0x73 DP_SPEC - Operation speculatively executed - Integer data processing -->
- <event event="0x73" title="Instruction" name="Integer" description="Operation speculatively executed - Integer data processing"/>
- <!-- 0x74 ASE_SPEC - Operation speculatively executed - Advanced SIMD -->
- <event event="0x74" title="Instruction" name="Advanced SIMD" description="Operation speculatively executed - Advanced SIMD"/>
- <!-- 0x75 VFP_SPEC - Operation speculatively executed - VFP -->
- <event event="0x75" title="Instruction" name="VFP" description="Operation speculatively executed - VFP"/>
- <!-- 0x76 PC_WRITE_SPEC - Operation speculatively executed - Software change of the PC -->
- <event event="0x76" title="Instruction" name="Software change" description="Operation speculatively executed - Software change of the PC"/>
- <!-- 0x77 CRYPTO_SPEC - Operation speculatively executed, crypto data processing -->
- <event event="0x77" title="Instruction" name="Crypto" description="Operation speculatively executed, crypto data processing"/>
- <!-- 0x78 BR_IMMED_SPEC - Branch speculatively executed - Immediate branch -->
- <event event="0x78" title="Instruction" name="Immediate branch" description="Branch speculatively executed - Immediate branch"/>
- <!-- 0x79 BR_RETURN_SPEC - Branch speculatively executed - Procedure return -->
- <event event="0x79" title="Instruction" name="Procedure return" description="Branch speculatively executed - Procedure return"/>
- <!-- 0x7A BR_INDIRECT_SPEC - Branch speculatively executed - Indirect branch -->
- <event event="0x7A" title="Instruction" name="Indirect branch" description="Branch speculatively executed - Indirect branch"/>
- <!-- 0x7C ISB_SPEC - Barrier speculatively executed - ISB -->
- <event event="0x7C" title="Instruction" name="ISB" description="Barrier speculatively executed - ISB"/>
- <!-- 0x7D DSB_SPEC - Barrier speculatively executed - DSB -->
- <event event="0x7D" title="Instruction" name="DSB" description="Barrier speculatively executed - DSB"/>
- <!-- 0x7E DMB_SPEC - Barrier speculatively executed - DMB -->
- <event event="0x7E" title="Instruction" name="DMB" description="Barrier speculatively executed - DMB"/>
- <!-- 0x81 EXC_UNDEF - Exception taken, other synchronous -->
- <event event="0x81" title="Exception" name="Undefined" description="Exception taken, other synchronous"/>
- <!-- 0x82 EXC_SVC - Exception taken, Supervisor Call -->
- <event event="0x82" title="Exception" name="Supervisor" description="Exception taken, Supervisor Call"/>
- <!-- 0x83 EXC_PABORT - Exception taken, Instruction Abort -->
- <event event="0x83" title="Exception" name="Instruction abort" description="Exception taken, Instruction Abort"/>
- <!-- 0x84 EXC_DABORT - Exception taken, Data Abort or SError -->
- <event event="0x84" title="Exception" name="Data abort" description="Exception taken, Data Abort or SError"/>
- <!-- 0x86 EXC_IRQ - Exception taken, IRQ -->
- <event event="0x86" title="Interrupts" name="IRQ" description="Exception taken, IRQ"/>
- <!-- 0x87 EXC_FIQ - Exception taken, FIQ -->
- <event event="0x87" title="Interrupts" name="FIQ" description="Exception taken, FIQ"/>
- <!-- 0x88 EXC_SMC - Exception taken, Secure Monitor Call -->
- <event event="0x88" title="Exception" name="Secure monitor call" description="Exception taken, Secure Monitor Call"/>
- <!-- 0x8A EXC_HVC - Exception taken, Hypervisor Call -->
- <event event="0x8A" title="Exception" name="Hypervisor call" description="Exception taken, Hypervisor Call"/>
- <!-- 0x8B EXC_TRAP_PABORT - Exception taken, Instruction Abort not taken locally -->
- <event event="0x8B" title="Exception" name="Instruction abort non-local" description="Exception taken, Instruction Abort not taken locally"/>
- <!-- 0x8C EXC_TRAP_DABORT - Exception taken, Data Abort or SError not taken locally -->
- <event event="0x8C" title="Exception" name="Data abort non-local" description="Exception taken, Data Abort or SError not taken locally"/>
- <!-- 0x8D EXC_TRAP_OTHER - Exception taken - Other traps not taken locally -->
- <event event="0x8D" title="Exception" name="Other non-local" description="Exception taken - Other traps not taken locally"/>
- <!-- 0x8E EXC_TRAP_IRQ - Exception taken, IRQ not taken locally -->
- <event event="0x8E" title="Exception" name="IRQ non-local" description="Exception taken, IRQ not taken locally"/>
- <!-- 0x8F EXC_TRAP_FIQ - Exception taken, FIQ not taken locally -->
- <event event="0x8F" title="Exception" name="FIQ non-local" description="Exception taken, FIQ not taken locally"/>
- <!-- 0x90 RC_LD_SPEC - Release consistency instruction speculatively executed - Load Acquire -->
- <event event="0x90" title="Release Consistency" name="Load" description="Release consistency instruction speculatively executed - Load Acquire"/>
- <!-- 0x91 RC_ST_SPEC - Release consistency instruction speculatively executed - Store Release -->
- <event event="0x91" title="Release Consistency" name="Store" description="Release consistency instruction speculatively executed - Store Release"/>
- </category>
+++ /dev/null
- <counter_set name="ARMv7_Cortex_A7_cnt" count="4"/>
- <category name="Cortex-A7" counter_set="ARMv7_Cortex_A7_cnt" per_cpu="yes" supports_event_based_sampling="yes">
- <event counter="ARMv7_Cortex_A7_ccnt" event="0xff" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/>
- <event event="0x00" title="Software" name="Increment" description="Software increment architecturally executed"/>
- <event event="0x01" title="Cache" name="Instruction refill" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/>
- <event event="0x02" title="Cache" name="Inst TLB refill" description="Instruction fetch that causes a TLB refill of at least the level of TLB closest to the processor"/>
- <event event="0x03" title="Cache" name="Data refill" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/>
- <event event="0x04" title="Cache" name="Data access" description="Memory Read or Write operation that causes a cache access to at least the level of data or unified cache closest to the processor"/>
- <event event="0x05" title="Cache" name="Data TLB refill" description="Memory Read or Write operation that causes a TLB refill of at least the level of TLB closest to the processor"/>
- <event event="0x06" title="Memory" name="Data Read" description="Data read architecturally executed"/>
- <event event="0x07" title="Memory" name="Data Write" description="Data write architecturally executed"/>
- <event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/>
- <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/>
- <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/>
- <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/>
- <event event="0x0c" title="Branch" name="PC change" description="Software change of the Program Counter, except by an exception, architecturally executed"/>
- <event event="0x0d" title="Branch" name="Immediate" description="Immediate branch architecturally executed"/>
- <event event="0x0f" title="Memory" name="Unaligned access" description="Unaligned access architecturally executed"/>
- <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/>
- <event event="0x12" title="Branch" name="Potential prediction" description="Branch or other change in program flow that could have been predicted by the branch prediction resources of the processor"/>
- <event event="0x13" title="Memory" name="Memory access" description="Data memory access"/>
- <event event="0x14" title="Cache" name="L1 inst access" description="Instruction cache access"/>
- <event event="0x15" title="Cache" name="L1 data eviction" description="Level 1 data cache eviction"/>
- <event event="0x16" title="Cache" name="L2 data access" description="Level 2 data cache access"/>
- <event event="0x17" title="Cache" name="L2 data refill" description="Level 2 data cache refill"/>
- <event event="0x18" title="Cache" name="L2 data write" description="Level 2 data cache Write-Back"/>
- <event event="0x19" title="Bus" name="Access" description="Bus - Access"/>
- <event event="0x1d" title="Bus" name="Cycle" description="Bus - Cycle"/>
- <event event="0x60" title="Bus" name="Read" description="Bus access - Read"/>
- <event event="0x61" title="Bus" name="Write" description="Bus access - Write"/>
- <event event="0x86" title="Exception" name="IRQ" description="IRQ exception taken"/>
- <event event="0x87" title="Exception" name="FIQ" description="FIQ exception taken"/>
- <event event="0xC0" title="Memory" name="External request" description="External memory request"/>
- <event event="0xC1" title="Memory" name="Non-cacheable ext req" description="Non-cacheable external memory request"/>
- <event event="0xC2" title="Cache" name="Linefill" description="Linefill because of prefetch"/>
- <event event="0xC3" title="Cache" name="Linefill dropped" description="Prefetch linefill dropped"/>
- <event event="0xC4" title="Cache" name="Allocate mode enter" description="Entering read allocate mode"/>
- <event event="0xC5" title="Cache" name="Allocate mode" description="Read allocate mode"/>
- <event event="0xC7" title="ETM" name="ETM Ext Out[0]" description="ETM - ETM Ext Out[0]"/>
- <event event="0xC8" title="ETM" name="ETM Ext Out[1]" description="ETM - ETM Ext Out[1]"/>
- <event event="0xC9" title="Instruction" name="Pipeline stall" description="Data Write operation that stalls the pipeline because the store buffer is full"/>
- <event event="0xCA" title="Memory" name="Snoop" description="Data snooped from other processor. This event counts memory-read operations that read data from another processor within the local cluster, rather than accessing the L2 cache or issuing an external read."/>
- </category>
+++ /dev/null
- <counter_set name="ARMv7_Cortex_A8_cnt" count="4"/>
- <category name="Cortex-A8" counter_set="ARMv7_Cortex_A8_cnt" per_cpu="yes" supports_event_based_sampling="yes">
- <event counter="ARMv7_Cortex_A8_ccnt" event="0xff" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/>
- <event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/>
- <event event="0x01" title="Cache" name="Instruction refill" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/>
- <event event="0x02" title="Cache" name="Inst TLB refill" description="Instruction fetch that causes a TLB refill of at least the level of TLB closest to the processor"/>
- <event event="0x03" title="Cache" name="Data refill" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/>
- <event event="0x04" title="Cache" name="Data access" description="Memory Read or Write operation that causes a cache access to at least the level of data or unified cache closest to the processor"/>
- <event event="0x05" title="Cache" name="Data TLB refill" description="Memory Read or Write operation that causes a TLB refill of at least the level of TLB closest to the processor"/>
- <event event="0x06" title="Instruction" name="Memory read" description="Memory-reading instruction architecturally executed"/>
- <event event="0x07" title="Instruction" name="Memory write" description="Memory-writing instruction architecturally executed"/>
- <event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/>
- <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/>
- <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/>
- <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/>
- <event event="0x0c" title="Branch" name="PC change" description="Software change of the Program Counter, except by an exception, architecturally executed"/>
- <event event="0x0d" title="Branch" name="Immediate" description="Immediate branch architecturally executed"/>
- <event event="0x0e" title="Procedure" name="Return" description="Procedure return, other than exception return, architecturally executed"/>
- <event event="0x0f" title="Memory" name="Unaligned access" description="Unaligned access architecturally executed"/>
- <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/>
- <event event="0x12" title="Branch" name="Potential prediction" description="Branch or other change in program flow that could have been predicted by the branch prediction resources of the processor"/>
- <event event="0x40" title="Cache" name="Write buffer full" description="Any write buffer full cycle"/>
- <event event="0x41" title="Cache" name="L2 store" description="Any store that is merged in the L2 memory system"/>
- <event event="0x42" title="Cache" name="Bufferable transaction" description="Any bufferable store transaction from load/store to L2 cache, excluding eviction or cast out data"/>
- <event event="0x43" title="Cache" name="L2 access" description="Any accesses to the L2 cache"/>
- <event event="0x44" title="Cache" name="L2 miss" description="Any cacheable miss in the L2 cache"/>
- <event event="0x45" title="AXI" name="Read" description="The number of AXI read data transfers"/>
- <event event="0x46" title="AXI" name="Write" description="The number of AXI write data transfers"/>
- <event event="0x47" title="Memory" name="Replay event" description="Any replay event in the memory system"/>
- <event event="0x48" title="Memory" name="Unaligned access replay" description="Any unaligned memory access that results in a replay"/>
- <event event="0x49" title="Cache" name="L1 data hash miss" description="Any L1 data memory access that misses in the cache as a result of the hashing algorithm"/>
- <event event="0x4a" title="Cache" name="L1 inst hash miss" description="Any L1 instruction memory access that misses in the cache as a result of the hashing algorithm"/>
- <event event="0x4b" title="Cache" name="L1 page coloring" description="Any L1 data memory access in which a page coloring alias occurs"/>
- <event event="0x4c" title="NEON" name="L1 cache hit" description="Any NEON access that hits in the L1 data cache"/>
- <event event="0x4d" title="NEON" name="L1 cache access" description="Any NEON cacheable data accesses for L1 data cache"/>
- <event event="0x4e" title="NEON" name="L2 cache access" description="Any L2 cache accesses as a result of a NEON memory access"/>
- <event event="0x4f" title="NEON" name="L2 cache hit" description="Any NEON hit in the L2 cache"/>
- <event event="0x50" title="Cache" name="L1 inst access" description="Any L1 instruction cache access, excluding CP15 cache accesses"/>
- <event event="0x51" title="Branch" name="Return stack misprediction" description="Any return stack misprediction because of incorrect target address for a taken return stack pop"/>
- <event event="0x52" title="Branch" name="Direction misprediction" description="Branch direction misprediction"/>
- <event event="0x53" title="Branch" name="Taken prediction" description="Any predictable branch that is predicted to be taken"/>
- <event event="0x54" title="Branch" name="Executed and taken prediction" description="Any predictable branch that is executed and taken"/>
- <event event="0x55" title="Core" name="Operations issued" description="Number of operations issued, where an operation is either: an instruction or one operation in a sequence of operations that make up a multi-cycle instruction"/>
- <event event="0x56" title="Core" name="No issue cycles" description="Increment for every cycle that no instructions are available for issue"/>
- <event event="0x57" title="Core" name="Issue cycles" description="For every cycle, this event counts the number of instructions issued in that cycle. Multi-cycle instructions are only counted once"/>
- <event event="0x58" title="NEON" name="MRC data wait" description="Number of cycles the processor stalls waiting on MRC data from NEON"/>
- <event event="0x59" title="NEON" name="Full queue" description="Number of cycles that the processor stalls as a result of a full NEON instruction queue or NEON load queue"/>
- <event event="0x5a" title="NEON" name="Idle" description="Number of cycles that NEON and integer processors are both not idle"/>
- <event event="0x70" title="External" name="PMUEXTIN[0]" description="Counts any event from external input source PMUEXTIN[0]"/>
- <event event="0x71" title="External" name="PMUEXTIN[1]" description="Counts any event from external input source PMUEXTIN[1]"/>
- <event event="0x72" title="External" name="PMUEXTIN[0,1]" description="Counts any event from both external input sources PMUEXTIN[0] and PMUEXTIN[1]"/>
- </category>
+++ /dev/null
- <counter_set name="ARMv7_Cortex_A9_cnt" count="6"/>
- <category name="Cortex-A9" counter_set="ARMv7_Cortex_A9_cnt" per_cpu="yes" supports_event_based_sampling="yes">
- <event counter="ARMv7_Cortex_A9_ccnt" event="0xff" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/>
- <event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/>
- <event event="0x01" title="Cache" name="Instruction refill" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/>
- <event event="0x02" title="Cache" name="Inst TLB refill" description="Instruction fetch that causes a TLB refill of at least the level of TLB closest to the processor"/>
- <event event="0x03" title="Cache" name="Data refill" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/>
- <event event="0x04" title="Cache" name="Data access" description="Memory Read or Write operation that causes a cache access to at least the level of data or unified cache closest to the processor"/>
- <event event="0x05" title="Cache" name="Data TLB refill" description="Memory Read or Write operation that causes a TLB refill of at least the level of TLB closest to the processor"/>
- <event event="0x06" title="Instruction" name="Memory read" description="Memory-reading instruction architecturally executed"/>
- <event event="0x07" title="Instruction" name="Memory write" description="Memory-writing instruction architecturally executed"/>
- <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/>
- <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/>
- <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/>
- <event event="0x0c" title="Branch" name="PC change" description="Software change of the Program Counter, except by an exception, architecturally executed"/>
- <event event="0x0d" title="Branch" name="Immediate" description="Immediate branch architecturally executed"/>
- <event event="0x0f" title="Memory" name="Unaligned access" description="Unaligned access architecturally executed"/>
- <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/>
- <event event="0x12" title="Branch" name="Potential prediction" description="Branch or other change in program flow that could have been predicted by the branch prediction resources of the processor"/>
- <event event="0x40" title="Java" name="Bytecode execute" description="Counts the number of Java bytecodes being decoded, including speculative ones"/>
- <event event="0x41" title="Java" name="SW bytecode execute" description="Counts the number of software java bytecodes being decoded, including speculative ones"/>
- <event event="0x42" title="Jazelle" name="Backward branch execute" description="Counts the number of Jazelle taken branches being executed"/>
- <event event="0x50" title="Cache" name="Coherency miss" description="Counts the number of coherent linefill requests performed by the Cortex-A9 processor which also miss in all the other Cortex-A9 processors, meaning that the request is sent to the external memory"/>
- <event event="0x51" title="Cache" name="Coherency hit" description="Counts the number of coherent linefill requests performed by the Cortex-A9 processor which hit in another Cortex-A9 processor, meaning that the linefill data is fetched directly from the relevant Cortex-A9 cache"/>
- <event event="0x60" title="Cache" name="Inst dependent stall" description="Counts the number of cycles where the processor is ready to accept new instructions, but does not receive any because of the instruction side not being able to provide any and the instruction cache is currently performing at least one linefill"/>
- <event event="0x61" title="Cache" name="Data dependent stall" description="Counts the number of cycles where the core has some instructions that it cannot issue to any pipeline, and the Load Store unit has at least one pending linefill request, and no pending TLB requests"/>
- <event event="0x62" title="Cache" name="TLB stall" description="Counts the number of cycles where the processor is stalled waiting for the completion of translation table walks from the main TLB"/>
- <event event="0x63" title="Intrinsic" name="STREX pass" description="Counts the number of STREX instructions architecturally executed and passed"/>
- <event event="0x64" title="Intrinsic" name="STREX fail" description="Counts the number of STREX instructions architecturally executed and failed"/>
- <event event="0x65" title="Cache" name="Data eviction" description="Counts the number of eviction requests because of a linefill in the data cache"/>
- <event event="0x66" title="Pipeline" name="Issue stage no dispatch" description="Counts the number of cycles where the issue stage does not dispatch any instruction because it is empty or cannot dispatch any instructions"/>
- <event event="0x67" title="Pipeline" name="Issue stage empty" description="Counts the number of cycles where the issue stage is empty"/>
- <event event="0x68" title="Instruction" name="Executed" description="Counts the number of instructions going through the Register Renaming stage. This number is an approximate number of the total number of instructions speculatively executed, and even more approximate of the total number of instructions architecturally executed"/>
- <event event="0x69" title="Cache" name="Data linefills" description="Counts the number of linefills performed on the external AXI bus"/>
- <event event="0x6A" title="Cache" name="Prefetch linefills" description="Counts the number of data linefills caused by prefetcher requests"/>
- <event event="0x6B" title="Cache" name="Prefetch hits" description="Counts the number of cache hits in a line that belongs to a stream followed by the prefetcher"/>
- <event event="0x6E" title="Core" name="Functions" description="Counts the number of procedure returns whose condition codes do not fail, excluding all returns from exception"/>
- <event event="0x70" title="Instruction" name="Main execution unit" description="Counts the number of instructions being executed in the main execution pipeline of the processor, the multiply pipeline and arithmetic logic unit pipeline"/>
- <event event="0x71" title="Instruction" name="Second execution unit" description="Counts the number of instructions being executed in the processor second execution pipeline (ALU)"/>
- <event event="0x72" title="Instruction" name="Load/Store" description="Counts the number of instructions being executed in the Load/Store unit"/>
- <event event="0x73" title="Instruction" name="Floating point" description="Counts the number of Floating-point instructions going through the Register Rename stage"/>
- <event event="0x74" title="Instruction" name="NEON" description="Counts the number of NEON instructions going through the Register Rename stage"/>
- <event event="0x80" title="Stalls" name="PLD" description="Counts the number of cycles where the processor is stalled because PLD slots are all full"/>
- <event event="0x81" title="Stalls" name="Memory write" description="Counts the number of cycles when the processor is stalled and the data side is stalled too because it is full and executing writes to the external memory"/>
- <event event="0x82" title="Stalls" name="Inst main TLB miss" description="Counts the number of stall cycles because of main TLB misses on requests issued by the instruction side"/>
- <event event="0x83" title="Stalls" name="Data main TLB miss" description="Counts the number of stall cycles because of main TLB misses on requests issued by the data side"/>
- <event event="0x84" title="Stalls" name="Inst micro TLB miss" description="Counts the number of stall cycles because of micro TLB misses on the instruction side"/>
- <event event="0x85" title="Stalls" name="Data micro TLB miss" description="Counts the number of stall cycles because of micro TLB misses on the data side"/>
- <event event="0x86" title="Stalls" name="DMB" description="Counts the number of stall cycles because of the execution of a DMB memory barrier"/>
- <event event="0x8A" title="Clock" name="Integer core" description="Counts the number of cycles during which the integer core clock is enabled"/>
- <event event="0x8B" title="Clock" name="Data engine" description="Counts the number of cycles during which the Data Engine clock is enabled"/>
- <event event="0x8C" title="Clock" name="NEON" description="Counts the number of cycles when the NEON SIMD clock is enabled"/>
- <event event="0x8D" title="Memory" name="TLB inst allocations" description="Counts the number of TLB allocations because of Instruction requests"/>
- <event event="0x8E" title="Memory" name="TLB data allocations" description="Counts the number of TLB allocations because of Data requests"/>
- <event event="0x90" title="Instruction" name="ISB" description="Counts the number of ISB instructions architecturally executed"/>
- <event event="0x91" title="Instruction" name="DSB" description="Counts the number of DSB instructions architecturally executed"/>
- <event event="0x92" title="Instruction" name="DMB" description="Counts the number of DMB instructions speculatively executed"/>
- <event event="0x93" title="External" name="Interrupts" description="Counts the number of external interrupts executed by the processor"/>
- <event event="0xA0" title="PLE" name="Cache line rq completed" description="Counts the number of PLE cache line requests completed"/>
- <event event="0xA1" title="PLE" name="Cache line rq skipped" description="Counts the number of PLE cache line requests skipped"/>
- <event event="0xA2" title="PLE" name="FIFO flush" description="Counts the number of PLE FIFO flush requests"/>
- <event event="0xA3" title="PLE" name="Request completed" description="Counts the number of PLE FIFO flush completed"/>
- <event event="0xA4" title="PLE" name="FIFO overflow" description="Counts the number of PLE FIFO flush overflowed"/>
- <event event="0xA5" title="PLE" name="Request programmed" description="Counts the number of PLE FIFO flush program requests"/>
- </category>
+++ /dev/null
- <counter_set name="Krait_cnt" count="4"/>
- <category name="Krait" counter_set="Krait_cnt" per_cpu="yes" supports_event_based_sampling="yes">
- <event counter="Krait_ccnt" event="0xff" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/>
- <event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/>
- <event event="0x01" title="Cache" name="Instruction refill" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/>
- <event event="0x02" title="Cache" name="Inst TLB refill" description="Instruction fetch that causes a TLB refill of at least the level of TLB closest to the processor"/>
- <event event="0x03" title="Cache" name="Data refill" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/>
- <event event="0x04" title="Cache" name="Data access" description="Memory Read or Write operation that causes a cache access to at least the level of data or unified cache closest to the processor"/>
- <event event="0x05" title="Cache" name="Data TLB refill" description="Memory Read or Write operation that causes a TLB refill of at least the level of TLB closest to the processor"/>
- <event event="0x06" title="Instruction" name="Memory read" description="Memory-reading instruction architecturally executed"/>
- <event event="0x07" title="Instruction" name="Memory write" description="Memory-writing instruction architecturally executed"/>
- <event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/>
- <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/>
- <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/>
- <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/>
- <event event="0x0c" title="Program Counter" name="SW change" description="Software change of PC, except by an exception, architecturally executed"/>
- <event event="0x0d" title="Branch" name="Immediate" description="Immediate branch architecturally executed"/>
- <event event="0x0e" title="Branch" name="Procedure Return" description="Procedure return architecturally executed (not by exceptions)"/>
- <event event="0x0f" title="Memory" name="Unaligned access" description="Unaligned access architecturally executed"/>
- <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/>
- <event event="0x12" title="Branch" name="Potential prediction" description="Branch or other change in program flow that could have been predicted by the branch prediction resources of the processor"/>
- </category>
+++ /dev/null
- <counter_set name="L2C-310_cnt" count="2"/>
- <category name="L2C-310" counter_set="L2C-310_cnt" per_cpu="no">
- <event event="0x1" title="L2 Cache" name="CO" description="Eviction, CastOUT, of a line from the L2 cache"/>
- <event event="0x2" title="L2 Cache" name="DRH" description="Data read hit"/>
- <event event="0x3" title="L2 Cache" name="DRREQ" description="Data read request"/>
- <event event="0x4" title="L2 Cache" name="DWHIT" description="Data write hit"/>
- <event event="0x5" title="L2 Cache" name="DWREQ" description="Data write request"/>
- <event event="0x6" title="L2 Cache" name="DWTREQ" description="Data write request with write-through attribute"/>
- <event event="0x7" title="L2 Cache" name="IRHIT" description="Instruction read hit"/>
- <event event="0x8" title="L2 Cache" name="IRREQ" description="Instruction read request"/>
- <event event="0x9" title="L2 Cache" name="WA" description="Write allocate"/>
- <event event="0xa" title="L2 Cache" name="IPFALLOC" description="Allocation of a prefetch generated by L2C-310 into the L2 cache"/>
- <event event="0xb" title="L2 Cache" name="EPFHIT" description="Prefetch hint hits in the L2 cache"/>
- <event event="0xc" title="L2 Cache" name="EPFALLOC" description="Prefetch hint allocated into the L2 cache"/>
- <event event="0xd" title="L2 Cache" name="SRRCVD" description="Speculative read received"/>
- <event event="0xe" title="L2 Cache" name="SRCONF" description="Speculative read confirmed"/>
- <event event="0xf" title="L2 Cache" name="EPFRCVD" description="Prefetch hint received"/>
- </category>
+++ /dev/null
- <category name="Linux">
- <event counter="Linux_irq_softirq" title="Interrupts" name="SoftIRQ" per_cpu="yes" description="Linux SoftIRQ taken"/>
- <event counter="Linux_irq_irq" title="Interrupts" name="IRQ" per_cpu="yes" description="Linux IRQ taken"/>
- <event counter="Linux_block_rq_wr" title="Disk IO" name="Write" units="B" description="Disk IO Bytes Written"/>
- <event counter="Linux_block_rq_rd" title="Disk IO" name="Read" units="B" description="Disk IO Bytes Read"/>
- <event counter="Linux_net_rx" title="Network" name="Receive" units="B" description="Receive network traffic, including effect from Streamline"/>
- <event counter="Linux_net_tx" title="Network" name="Transmit" units="B" description="Transmit network traffic, including effect from Streamline"/>
- <event counter="Linux_sched_switch" title="Scheduler" name="Switch" per_cpu="yes" description="Context switch events"/>
- <event counter="Linux_meminfo_memused" title="Memory" name="Used" class="absolute" units="B" proc="yes" description="Total used memory size. Note: a process' used memory includes shared memory that may be counted more than once (equivalent to RES from top). Kernel threads are not filterable."/>
- <event counter="Linux_meminfo_memfree" title="Memory" name="Free" class="absolute" display="minimum" units="B" description="Available memory size"/>
- <event counter="Linux_meminfo_bufferram" title="Memory" name="Buffer" class="absolute" units="B" description="Memory used by OS disk buffers"/>
- <event counter="Linux_power_cpu_freq" title="Clock" name="Frequency" per_cpu="yes" class="absolute" units="Hz" series_composition="overlay" average_cores="yes" description="Frequency setting of the CPU"/>
- <event counter="Linux_power_cpu_idle" title="Idle" name="State" per_cpu="yes" class="absolute" description="CPU Idle State + 1, set the Sample Rate to None to prevent the hrtimer from interrupting the system"/>
- <event counter="Linux_cpu_wait_contention" title="CPU Contention" name="Wait" per_cpu="no" class="activity" derived="yes" rendering_type="bar" average_selection="yes" percentage="yes" modifier="10000" description="Thread waiting on contended resource"/>
- <event counter="Linux_cpu_wait_io" title="CPU I/O" name="Wait" per_cpu="no" class="activity" derived="yes" rendering_type="bar" average_selection="yes" percentage="yes" modifier="10000" description="Thread waiting on I/O resource"/>
- </category>
-
+++ /dev/null
- <counter_set name="ARM_Mali-4xx_VP_0_cnt" count="2"/>
- <counter_set name="ARM_Mali-4xx_SW_cnt" count="0"/>
- <counter_set name="ARM_Mali-4xx_Filmstrip_cnt" count="1"/>
- <category name="Mali-4xx-VP" counter_set="ARM_Mali-4xx_VP_0_cnt" per_cpu="no">
- <event event="0x01" title="Mali GPU Vertex Processor" name="Active cycles" description="Number of cycles per frame the MaliGP2 was active."/>
- <event event="0x02" title="Mali GPU Vertex Processor" name="Active cycles, vertex shader" description="Number of cycles per frame the vertex shader unit was active."/>
- <event event="0x03" title="Mali GPU Vertex Processor" name="Active cycles, vertex storer" description="Number of cycles per frame the vertex storer unit was active."/>
- <event event="0x04" title="Mali GPU Vertex Processor" name="Active cycles, vertex loader" description="Number of cycles per frame the vertex loader unit was active."/>
- <event event="0x05" title="Mali GPU Vertex Processor" name="Cycles vertex loader waiting for vertex shader" description="Number of cycles per frame the vertex loader was idle while waiting on the vertex shader."/>
- <event event="0x06" title="Mali GPU Vertex Processor" name="Words read, system bus" description="Total number of 64 bit words read by the GP2 from the system bus per frame."/>
- <event event="0x07" title="Mali GPU Vertex Processor" name="Words written, system bus" description="Total number of 64 bit words written by the GP2 to the system bus per frame."/>
- <event event="0x08" title="Mali GPU Vertex Processor" name="Read bursts, system bus" description="Number of read bursts by the GP2 from the system bus per frame."/>
- <event event="0x09" title="Mali GPU Vertex Processor" name="Write bursts, system bus" description="Number of write bursts from the MaliGP2 to the system bus per frame."/>
- <event event="0x0a" title="Mali GPU Vertex Processor" name="Vertices processed" description="Number of vertices processed by the MaliGP2 per frame."/>
- <event event="0x0b" title="Mali GPU Vertex Processor" name="Vertices fetched" description="Number of vertices fetched by the MaliGP2 per frame."/>
- <event event="0x0c" title="Mali GPU Vertex Processor" name="Primitives fetched" description="Number of graphics primitives fetched by the MaliGP2 per frame."/>
- <event event="0x0e" title="Mali GPU Vertex Processor" name="Primitives culled" description="Number of graphics primitives discarded per frame, because they were seen from the back or were offscreen."/>
- <event event="0x0f" title="Mali GPU Vertex Processor" name="Commands written to tiles" description="Number of commands (8 Bytes, mainly primitives) written by GP2 to the PP input data structure per frame."/>
- <event event="0x10" title="Mali GPU Vertex Processor" name="Memory blocks allocated" description="Number of overflow data blocks needed for outputting the PP input data structure per frame ."/>
- <event event="0x13" title="Mali GPU Vertex Processor" name="Vertex loader cache misses" description="Number of cache misses for the vertex shader's vertex input unit per frame."/>
- <event event="0x16" title="Mali GPU Vertex Processor" name="Active cycles, vertex shader command processor" description="Number of cycles per frame the GP2 vertex shader command processor was active. This includes time waiting for semaphores."/>
- <event event="0x17" title="Mali GPU Vertex Processor" name="Active cycles, PLBU command processor" description="Number of cycles per frame the MaliGP2 PLBU command processor was active. This includes time waiting for semaphores."/>
- <event event="0x18" title="Mali GPU Vertex Processor" name="MaliGP2 PLBU cycles per frame" description="Number of cycles per frame the MaliGP2 PLBU output unit was active. This includes time spent waiting on the bus."/>
- <event event="0x19" title="Mali GPU Vertex Processor" name="Active cycles, PLBU geometry processing" description="Number of cycles per frame the MaliGP2 PLBU was active, excepting final data output. In other words: active cycles through the prepare list commands. This includes time spent waiting on the bus."/>
- <event event="0x1b" title="Mali GPU Vertex Processor" name="Active cycles, PLBU primitive assembly" description="Number of active cycles per frame spent by the MaliGP2 PLBU doing primitive assembly. This does not include scissoring or final output. This includes time spent waiting on the bus."/>
- <event event="0x1c" title="Mali GPU Vertex Processor" name="Active cycles, PLBU vertex fetcher" description="Number of active cycles per frame spent by the MaliGP2 PLBU fetching vertex data. This includes time spent waiting on the bus."/>
- <event event="0x1e" title="Mali GPU Vertex Processor" name="Active cycles, Bounding-box and command generator" description="Number of active cycles per frame spent by the MaliGP2 PLBU setting up bounding boxes and commands (mainly graphics primitives). This includes time spent waiting on the bus."/>
- <event event="0x20" title="Mali GPU Vertex Processor" name="Active cycles, Scissor tile iterator" description="Number of active cycles per frame spent by the MaliGP2 PLBU iterating over tiles to perform scissoring. This includes time spent waiting on the bus."/>
- <event event="0x21" title="Mali GPU Vertex Processor" name="Active cycles, PLBU tile iterator" description="Number of active cycles per frame spent by the MaliGP2 PLBU iterating over the tiles in the bounding box generating commands (mainly graphics primitives). This includes time spent waiting on the bus."/>
- </category>
- <category name="Mali GPU Fragment Processor" per_cpu="no">
- <counter_set name="ARM_Mali-4xx_FP_0_cnt" title="Mali-4xx FP0" description="Mali GPU Fragment Processor 0" count="2"/>
- <counter_set name="ARM_Mali-4xx_FP_1_cnt" title="Mali-4xx FP1" description="Mali GPU Fragment Processor 1" count="2"/>
- <counter_set name="ARM_Mali-4xx_FP_2_cnt" title="Mali-4xx FP2" description="Mali GPU Fragment Processor 2" count="2"/>
- <counter_set name="ARM_Mali-4xx_FP_3_cnt" title="Mali-4xx FP3" description="Mali GPU Fragment Processor 3" count="2"/>
- <counter_set name="ARM_Mali-4xx_FP_4_cnt" title="Mali-4xx FP4" description="Mali GPU Fragment Processor 4" count="2"/>
- <counter_set name="ARM_Mali-4xx_FP_5_cnt" title="Mali-4xx FP5" description="Mali GPU Fragment Processor 5" count="2"/>
- <counter_set name="ARM_Mali-4xx_FP_6_cnt" title="Mali-4xx FP6" description="Mali GPU Fragment Processor 6" count="2"/>
- <counter_set name="ARM_Mali-4xx_FP_7_cnt" title="Mali-4xx FP7" description="Mali GPU Fragment Processor 7" count="2"/>
-
- <event event="0x00" title="Mali-4xx FP" name="Active clock cycles" description="Active clock cycles, between polygon start and IRQ."/>
- <event event="0x02" title="Mali-4xx FP" name="Total bus reads" description="Total number of 64-bit words read from the bus."/>
- <event event="0x03" title="Mali-4xx FP" name="Total bus writes" description="Total number of 64-bit words written to the bus."/>
- <event event="0x04" title="Mali-4xx FP" name="Bus read request cycles" description="Number of cycles during which the bus read request signal was HIGH."/>
- <event event="0x05" title="Mali-4xx FP" name="Bus write request cycles" description="Number of cycles during which the bus write request signal was HIGH."/>
- <event event="0x06" title="Mali-4xx FP" name="Bus read transactions count" description="Number of read requests accepted by the bus."/>
- <event event="0x07" title="Mali-4xx FP" name="Bus write transactions" description="Number of write requests accepted by the bus."/>
- <event event="0x09" title="Mali-4xx FP" name="Tile writeback writes" description="64-bit words written to the bus by the writeback unit."/>
- <event event="0x0a" title="Mali-4xx FP" name="Store unit writes" description="64-bit words written to the bus by the store unit."/>
- <event event="0x0d" title="Mali-4xx FP" name="Texture cache uncompressed reads" description="Number of 64-bit words read from the bus into the uncompressed textures cache."/>
- <event event="0x0e" title="Mali-4xx FP" name="Polygon list reads" description="Number of 64-bit words read from the bus by the polygon list reader."/>
- <event event="0x0f" title="Mali-4xx FP" name="RSW reads" description="Number of 64-bit words read from the bus into the Render State Word register."/>
- <event event="0x10" title="Mali-4xx FP" name="Vertex cache reads" description="Number of 64-bit words read from the bus into the vertex cache."/>
- <event event="0x11" title="Mali-4xx FP" name="Uniform remapping reads" description="Number of 64-bit words read from the bus when reading from the uniform remapping table."/>
- <event event="0x12" title="Mali-4xx FP" name="Program cache reads" description="Number of 64-bit words read from the bus into the fragment shader program cache."/>
- <event event="0x13" title="Mali-4xx FP" name="Varying reads" description="Number of 64-bit words containing varyings generated by the vertex processing read from the bus."/>
- <event event="0x14" title="Mali-4xx FP" name="Texture descriptors reads" description="Number of 64-bit words containing texture descriptors read from the bus."/>
- <event event="0x15" title="Mali-4xx FP" name="Texture descriptor remapping reads" description="Number of 64-bit words read from the bus when reading from the texture descriptor remapping table."/>
- <event event="0x17" title="Mali-4xx FP" name="Load unit reads" description="Number of 64-bit words read from the bus by the LOAD sub-instruction."/>
- <event event="0x18" title="Mali-4xx FP" name="Polygon count" description="Number of triangles read from the polygon list."/>
- <event event="0x19" title="Mali-4xx FP" name="Pixel rectangle count" description="Number of pixel rectangles read from the polygon list."/>
- <event event="0x1a" title="Mali-4xx FP" name="Lines count" description="Number of lines read from the polygon list."/>
- <event event="0x1b" title="Mali-4xx FP" name="Points count" description="Number of points read from the polygon list."/>
- <event event="0x1c" title="Mali-4xx FP" name="Stall cycles PolygonListReader" description="Number of clock cycles the Polygon List Reader waited for output being collected."/>
- <event event="0x1d" title="Mali-4xx FP" name="Stall cycles triangle setup" description="Number of clock cycles the TSC waited for input."/>
- <event event="0x1e" title="Mali-4xx FP" name="Quad rasterized count" description="Number of 2x?2 quads output from rasterizer."/>
- <event event="0x1f" title="Mali-4xx FP" name="Fragment rasterized count" description="Number of fragment rasterized. Fragments/(Quads*4) gives average actual fragments per quad."/>
- <event event="0x20" title="Mali-4xx FP" name="Fragment rejected fragment-kill count" description="Number of fragments exiting the fragment shader as killed."/>
- <event event="0x21" title="Mali-4xx FP" name="Fragment rejected fwd-fragment-kill count" description="Number of fragments killed by forward fragment kill."/>
- <event event="0x22" title="Mali-4xx FP" name="Fragment passed z/stencil count" description="Number of fragments passing Z and stencil test."/>
- <event event="0x23" title="Mali-4xx FP" name="Patches rejected early z/stencil count" description="Number of patches rejected by EarlyZ. A patch can be 8x8, 4x4 or 2x2 pixels."/>
- <event event="0x24" title="Mali-4xx FP" name="Patches evaluated" description="Number of patches evaluated for EarlyZ rejection."/>
- <event event="0x25" title="Mali-4xx FP" name="Instruction completed count" description="Number of fragment shader instruction words completed. It is a function of pixels processed and the length of the shader programs."/>
- <event event="0x26" title="Mali-4xx FP" name="Instruction failed rendezvous count" description="Number of fragment shader instructions not completed because of failed Rendezvous."/>
- <event event="0x27" title="Mali-4xx FP" name="Instruction failed varying-miss count" description="Number of fragment shader instructions not completed because of failed varying operation."/>
- <event event="0x28" title="Mali-4xx FP" name="Instruction failed texture-miss count" description="Number of fragment shader instructions not completed because of failed texture operation."/>
- <event event="0x29" title="Mali-4xx FP" name="Instruction failed load-miss count" description="Number of fragment shader instructions not completed because of failed load operation."/>
- <event event="0x2a" title="Mali-4xx FP" name="Instruction failed tile read-miss count" description="Number of fragment shader instructions not completed because of failed read from the tilebuffer."/>
- <event event="0x2b" title="Mali-4xx FP" name="Instruction failed store-miss count" description="Number of fragment shader instructions not completed because of failed store operation."/>
- <event event="0x2c" title="Mali-4xx FP" name="Rendezvous breakage count" description="Number of Rendezvous breakages reported."/>
- <event event="0x2d" title="Mali-4xx FP" name="Pipeline bubbles cycle count" description="Number of unused cycles in the fragment shader while rendering is active."/>
- <event event="0x2e" title="Mali-4xx FP" name="Texture mapper multipass count" description="Number of texture operations looped because of more texture passes needed."/>
- <event event="0x2f" title="Mali-4xx FP" name="Texture mapper cycle count" description="Number of texture operation cycles."/>
- <event event="0x30" title="Mali-4xx FP" name="Vertex cache hit count" description="Number of times a requested vertex was found in the cache (Number of vertex cache hits)."/>
- <event event="0x31" title="Mali-4xx FP" name="Vertex cache miss count" description="Number of times a requested vertex was not found in the cache (Number of vertex cache misses)."/>
- <event event="0x32" title="Mali-4xx FP" name="Varying cache hit count" description="Number of times a requested varying was found in the cache (Number of varying cache hits)."/>
- <event event="0x33" title="Mali-4xx FP" name="Varying cache miss count" description="Number of times a requested varying was not found in the cache (Number of varying cache misses)."/>
- <event event="0x34" title="Mali-4xx FP" name="Varying cache conflict miss count" description="Number of times a requested varying was not in the cache and its value, retrieved from memory, must overwrite an older cache entry. This happens when an access pattern cannot be serviced by the cache."/>
- <event event="0x35" title="Mali-4xx FP" name="Texture cache hit count" description="Number of times a requested texel was found in the texture cache (Number of texture cache hits)."/>
- <event event="0x36" title="Mali-4xx FP" name="Texture cache miss count" description="Number of times a requested texel was not found in the texture cache (Number of texture cache misses)."/>
- <event event="0x37" title="Mali-4xx FP" name="Texture cache conflict miss count" description="Number of times a requested texel was not in the cache and its value, retrieved from memory, must overwrite an older cache entry. This happens when an access pattern cannot be serviced by the cache."/>
- <event event="0x38" title="Mali-4xx FP" name="Compressed texture cache hit count" description="Number of times a requested item was found in the cache."/>
- <event event="0x39" title="Mali-4xx FP" name="Compressed texture cache miss count" description="Number of times a requested item was not found in the cache."/>
- <event event="0x3a" title="Mali-4xx FP" name="Load/Store cache hit count" description="Number of hits in the load/store cache."/>
- <event event="0x3b" title="Mali-4xx FP" name="Load/Store cache miss count" description="Number of misses in the load/store cache."/>
- <event event="0x3c" title="Mali-4xx FP" name="Program cache hit count" description="Number of hits in the program cache."/>
- <event event="0x3d" title="Mali-4xx FP" name="Program cache miss count" description="Number of misses in the program cache."/>
- </category>
- <counter_set name="ARM_Mali-4xx_L2_0_cnt" title="Mali-4xx L2 0" description="Mali GPU L2 Cache Core 0" count="2"/>
- <category name="Mali-4xx-L2_0" counter_set="ARM_Mali-4xx_L2_0_cnt" per_cpu="no">
- <event event="0x01" title="Mali L2 Cache" name="Total clock cycles" description="Total clock cycles"/>
- <event event="0x02" title="Mali L2 Cache" name="Active clock cycles" description="Active clock cycles"/>
-
- <option_set name="All">
- <option event_delta="0x08" name="Master" description="Master"/>
- <option event_delta="0x10" name="All slaves" description="All slaves"/>
- <option event_delta="0x20" name="Slave 0" description="Slave 0"/>
- <option event_delta="0x30" name="Slave 1" description="Slave 1"/>
- <option event_delta="0x40" name="Slave 2" description="Slave 2"/>
- <option event_delta="0x50" name="Slave 3" description="Slave 3"/>
- <option event_delta="0x60" name="Slave 4" description="Slave 4"/>
- </option_set>
-
- <option_set name="Slaves">
- <option event_delta="0x10" name="All slaves" description="All slaves"/>
- <option event_delta="0x20" name="Slave 0" description="Slave 0"/>
- <option event_delta="0x30" name="Slave 1" description="Slave 1"/>
- <option event_delta="0x40" name="Slave 2" description="Slave 2"/>
- <option event_delta="0x50" name="Slave 3" description="Slave 3"/>
- <option event_delta="0x60" name="Slave 4" description="Slave 4"/>
- </option_set>
-
- <event event="0x00" option_set="All" title="Mali L2 Cache" name="Read transactions" description="Read transactions"/>
- <event event="0x01" option_set="All" title="Mali L2 Cache" name="Write transactions" description="Write transactions"/>
- <event event="0x02" option_set="All" title="Mali L2 Cache" name="Words read" description="Words read"/>
- <event event="0x03" option_set="All" title="Mali L2 Cache" name="Words written" description="Words written"/>
- <event event="0x04" option_set="Slaves" title="Mali L2 Cache" name="Read hits" description="Read hits"/>
- <event event="0x05" option_set="Slaves" title="Mali L2 Cache" name="Read misses" description="Read misses"/>
- <event event="0x06" option_set="Slaves" title="Mali L2 Cache" name="Write invalidates" description="Write invalidates"/>
- <event event="0x07" option_set="Slaves" title="Mali L2 Cache" name="Read invalidates" description="Read invalidates"/>
- <event event="0x08" option_set="Slaves" title="Mali L2 Cache" name="Cacheable read transactions" description="Cacheable read transactions"/>
- </category>
- <counter_set name="ARM_Mali-4xx_L2_1_cnt" title="Mali-4xx L2 1" description="Mali GPU L2 Cache Core 1" count="2"/>
- <category name="Mali-4xx-L2_1" counter_set="ARM_Mali-4xx_L2_1_cnt" per_cpu="no">
- <event event="0x01" title="Mali L2 Cache" name="Total clock cycles" description="Total clock cycles"/>
- <event event="0x02" title="Mali L2 Cache" name="Active clock cycles" description="Active clock cycles"/>
-
- <option_set name="All">
- <option event_delta="0x08" name="Master" description="Master"/>
- <option event_delta="0x10" name="All slaves" description="All slaves"/>
- <option event_delta="0x20" name="Slave 0" description="Slave 0"/>
- <option event_delta="0x30" name="Slave 1" description="Slave 1"/>
- <option event_delta="0x40" name="Slave 2" description="Slave 2"/>
- <option event_delta="0x50" name="Slave 3" description="Slave 3"/>
- <option event_delta="0x60" name="Slave 4" description="Slave 4"/>
- </option_set>
-
- <option_set name="Slaves">
- <option event_delta="0x10" name="All slaves" description="All slaves"/>
- <option event_delta="0x20" name="Slave 0" description="Slave 0"/>
- <option event_delta="0x30" name="Slave 1" description="Slave 1"/>
- <option event_delta="0x40" name="Slave 2" description="Slave 2"/>
- <option event_delta="0x50" name="Slave 3" description="Slave 3"/>
- <option event_delta="0x60" name="Slave 4" description="Slave 4"/>
- </option_set>
-
- <event event="0x00" option_set="All" title="Mali L2 Cache" name="Read transactions" description="Read transactions"/>
- <event event="0x01" option_set="All" title="Mali L2 Cache" name="Write transactions" description="Write transactions"/>
- <event event="0x02" option_set="All" title="Mali L2 Cache" name="Words read" description="Words read"/>
- <event event="0x03" option_set="All" title="Mali L2 Cache" name="Words written" description="Words written"/>
- <event event="0x04" option_set="Slaves" title="Mali L2 Cache" name="Read hits" description="Read hits"/>
- <event event="0x05" option_set="Slaves" title="Mali L2 Cache" name="Read misses" description="Read misses"/>
- <event event="0x06" option_set="Slaves" title="Mali L2 Cache" name="Write invalidates" description="Write invalidates"/>
- <event event="0x07" option_set="Slaves" title="Mali L2 Cache" name="Read invalidates" description="Read invalidates"/>
- <event event="0x08" option_set="Slaves" title="Mali L2 Cache" name="Cacheable read transactions" description="Cacheable read transactions"/>
- </category>
- <counter_set name="ARM_Mali-4xx_L2_2_cnt" title="Mali-4xx L2 2" description="Mali GPU L2 Cache Core 2" count="2"/>
- <category name="Mali-4xx-L2_2" counter_set="ARM_Mali-4xx_L2_2_cnt" per_cpu="no">
- <event event="0x01" title="Mali L2 Cache" name="Total clock cycles" description="Total clock cycles"/>
- <event event="0x02" title="Mali L2 Cache" name="Active clock cycles" description="Active clock cycles"/>
-
- <option_set name="All">
- <option event_delta="0x08" name="Master" description="Master"/>
- <option event_delta="0x10" name="All slaves" description="All slaves"/>
- <option event_delta="0x20" name="Slave 0" description="Slave 0"/>
- <option event_delta="0x30" name="Slave 1" description="Slave 1"/>
- <option event_delta="0x40" name="Slave 2" description="Slave 2"/>
- <option event_delta="0x50" name="Slave 3" description="Slave 3"/>
- <option event_delta="0x60" name="Slave 4" description="Slave 4"/>
- </option_set>
-
- <option_set name="Slaves">
- <option event_delta="0x10" name="All slaves" description="All slaves"/>
- <option event_delta="0x20" name="Slave 0" description="Slave 0"/>
- <option event_delta="0x30" name="Slave 1" description="Slave 1"/>
- <option event_delta="0x40" name="Slave 2" description="Slave 2"/>
- <option event_delta="0x50" name="Slave 3" description="Slave 3"/>
- <option event_delta="0x60" name="Slave 4" description="Slave 4"/>
- </option_set>
-
- <event event="0x00" option_set="All" title="Mali L2 Cache" name="Read transactions" description="Read transactions"/>
- <event event="0x01" option_set="All" title="Mali L2 Cache" name="Write transactions" description="Write transactions"/>
- <event event="0x02" option_set="All" title="Mali L2 Cache" name="Words read" description="Words read"/>
- <event event="0x03" option_set="All" title="Mali L2 Cache" name="Words written" description="Words written"/>
- <event event="0x04" option_set="Slaves" title="Mali L2 Cache" name="Read hits" description="Read hits"/>
- <event event="0x05" option_set="Slaves" title="Mali L2 Cache" name="Read misses" description="Read misses"/>
- <event event="0x06" option_set="Slaves" title="Mali L2 Cache" name="Write invalidates" description="Write invalidates"/>
- <event event="0x07" option_set="Slaves" title="Mali L2 Cache" name="Read invalidates" description="Read invalidates"/>
- <event event="0x08" option_set="Slaves" title="Mali L2 Cache" name="Cacheable read transactions" description="Cacheable read transactions"/>
- </category>
- <category name="ARM Mali-4xx Filmstrip" counter_set="ARM_Mali-4xx_Filmstrip_cnt" per_cpu="no">
- <option_set name="fs">
- <option event_delta="0x3c" name="1:60" description="captures every 60th frame"/>
- <option event_delta="0x1e" name="1:30" description="captures every 30th frame"/>
- <option event_delta="0xa" name="1:10" description="captures every 10th frame"/>
- </option_set>
- <event event="0x0400" option_set="fs" title="ARM Mali-4xx" name="Filmstrip" description="Scaled framebuffer"/>
- </category>
- <category name="ARM_Mali-4xx_Voltage" per_cpu="no">
- <event counter="ARM_Mali-4xx_Voltage" title="Mali GPU Voltage" name="Voltage" class="absolute" display="average" average_selection="yes" units="mV" description="GPU core voltage."/>
- </category>
- <category name="ARM_Mali-4xx_Frequency" per_cpu="no">
- <event counter="ARM_Mali-4xx_Frequency" title="Mali GPU Frequency" name="Frequency" display="average" average_selection="yes" units="MHz" description="GPU core frequency."/>
- </category>
- <category name="Mali-4xx-SW" counter_set="ARM_Mali-4xx_SW_cnt" per_cpu="no">
- <!-- EGL Counters -->
- <event counter="ARM_Mali-4xx_SW_0" title="Mali EGL Software Counters" name="Blit Time" description="Time spent blitting the framebuffer from video memory to framebuffer."/>
- <!-- glDrawElements Counters -->
- <event counter="ARM_Mali-4xx_SW_1" title="glDrawElements Statistics" name="Calls to glDrawElements" description="Number of calls to glDrawElements."/>
- <event counter="ARM_Mali-4xx_SW_2" title="glDrawElements Statistics" name="Indices to glDrawElements" description="Number of indices to glDrawElements."/>
- <event counter="ARM_Mali-4xx_SW_3" title="glDrawElements Statistics" name="Transformed by glDrawElements" description="Number of vertices transformed by glDrawElements."/>
- <!-- glDrawArrays Counters -->
- <event counter="ARM_Mali-4xx_SW_4" title="glDrawArrays Statistics" name="Calls to glDrawArrays" description="Number of calls to glDrawArrays."/>
- <event counter="ARM_Mali-4xx_SW_5" title="glDrawArrays Statistics" name="Transformed by glDrawArrays" description="Number of vertices transformed by glDrawArrays."/>
- <!-- Draw Call Counters -->
- <event counter="ARM_Mali-4xx_SW_6" title="Drawcall Statistics" name="Points" description="Number of calls to glDraw* with parameter GL_POINTS."/>
- <event counter="ARM_Mali-4xx_SW_7" title="Drawcall Statistics" name="Lines" description="Number of calls to glDraw* with parameter GL_LINES."/>
- <event counter="ARM_Mali-4xx_SW_8" title="Drawcall Statistics" name="Lineloop" description="Number of calls to glDraw* with parameter GL_LINE_LOOP."/>
- <event counter="ARM_Mali-4xx_SW_9" title="Drawcall Statistics" name="Linestrip" description="Number of calls to glDraw* with parameter GL_LINE_STRIP."/>
- <event counter="ARM_Mali-4xx_SW_10" title="Drawcall Statistics" name="Triangles" description="Number of calls to glDraw* with parameter GL_TRIANGLES."/>
- <event counter="ARM_Mali-4xx_SW_11" title="Drawcall Statistics" name="Trianglestrip" description="Number of calls to glDraw* with parameter GL_TRIANGLE_STRIP."/>
- <event counter="ARM_Mali-4xx_SW_12" title="Drawcall Statistics" name="Trianglefan" description="Number of calls to glDraw* with parameter GL_TRIANGLE_FAN."/>
- <event counter="ARM_Mali-4xx_SW_13" title="Drawcall Statistics" name="Vertex Upload Time (us)" description="Time spent uploading vertex attributes and faceindex data not present in a VBO."/>
- <event counter="ARM_Mali-4xx_SW_14" title="Drawcall Statistics" name="Uniform Bytes Copied (bytes)" description="Number of bytes copied to Mali memory as a result of uniforms update."/>
- <!-- Buffer Profiling Counters -->
- <event counter="ARM_Mali-4xx_SW_15" title="Buffer Profiling" name="Texture Upload Time (ms)" description="Time spent uploading textures."/>
- <event counter="ARM_Mali-4xx_SW_16" title="Buffer Profiling" name="VBO Upload Time (ms)" description="Time spent uploading vertex buffer objects."/>
- <event counter="ARM_Mali-4xx_SW_17" title="Buffer Profiling" name="FBO Flushes" description="Number of flushed on framebuffer attachment."/>
- <!-- OpenGL ES 1.1 Emulation -->
- <event counter="ARM_Mali-4xx_SW_18" title="Fixed-function Emulation" name="# Vertex Shaders Generated" description="Number of vertex shaders generated."/>
- <event counter="ARM_Mali-4xx_SW_19" title="Fixed-function Emulation" name="# Fragment Shaders Generated" description="Number of fragment shaders generated."/>
- <!-- Geometry Statistics -->
- <event counter="ARM_Mali-4xx_SW_33" title="Geometry Statistics" name="Triangles" description="The total number of triangles passed to GLES per-frame."/>
- <event counter="ARM_Mali-4xx_SW_34" title="Geometry Statistics" name="Independent Triangles" description="Number of triangles passed to GLES using the mode GL_TRIANGLES."/>
- <event counter="ARM_Mali-4xx_SW_35" title="Geometry Statistics" name="Strip Triangles" description="Number of triangles passed to GLES using the mode GL_TRIANGLE_STRIP."/>
- <event counter="ARM_Mali-4xx_SW_36" title="Geometry Statistics" name="Fan Triangles" description="Number of triangles passed to GLES using the mode GL_TRIANGLE_FAN."/>
- <event counter="ARM_Mali-4xx_SW_37" title="Geometry Statistics" name="Lines" description="Number of lines passed to GLES per-frame."/>
- <event counter="ARM_Mali-4xx_SW_38" title="Geometry Statistics" name="Independent Lines" description="Number of lines passed to GLES using the mode GL_LINES."/>
- <event counter="ARM_Mali-4xx_SW_39" title="Geometry Statistics" name="Strip Lines" description="Number of lines passed to GLES using the mode GL_LINE_STRIP."/>
- <event counter="ARM_Mali-4xx_SW_40" title="Geometry Statistics" name="Loop Lines" description="Number of lines passed to GLES using the mode GL_LINE_LOOP."/>
- </category>
+++ /dev/null
-
- <category name="Mali-T6xx-SW-counters" per_cpu="no">
- <event counter="ARM_Mali-T6xx_TOTAL_ALLOC_PAGES" title="Mali Total Alloc Pages" name="Total number of allocated pages" description="Mali total number of allocated pages."/>
- </category>
-
- <category name="Mali-T6xx-PMShader" per_cpu="no">
- <event counter="ARM_Mali-T6xx_PM_SHADER_0" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 0" description="Mali PM Shader: PM Shader Core 0."/>
- <event counter="ARM_Mali-T6xx_PM_SHADER_1" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 1" description="Mali PM Shader: PM Shader Core 1."/>
- <event counter="ARM_Mali-T6xx_PM_SHADER_2" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 2" description="Mali PM Shader: PM Shader Core 2."/>
- <event counter="ARM_Mali-T6xx_PM_SHADER_3" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 3" description="Mali PM Shader: PM Shader Core 3."/>
- <event counter="ARM_Mali-T6xx_PM_SHADER_4" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 4" description="Mali PM Shader: PM Shader Core 4."/>
- <event counter="ARM_Mali-T6xx_PM_SHADER_5" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 5" description="Mali PM Shader: PM Shader Core 5."/>
- <event counter="ARM_Mali-T6xx_PM_SHADER_6" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 6" description="Mali PM Shader: PM Shader Core 6."/>
- <event counter="ARM_Mali-T6xx_PM_SHADER_7" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 7" description="Mali PM Shader: PM Shader Core 7."/>
- </category>
-
- <category name="Mali-T6xx-PMTiler" per_cpu="no">
- <event counter="ARM_Mali-T6xx_PM_TILER_0" display="average" average_selection="yes" percentage="yes" title="Mali PM Tiler" name="PM Tiler Core 0" description="Mali PM Tiler: PM Tiler Core 0."/>
- </category>
-
- <category name="Mali-T6xx-PML2" per_cpu="no">
- <event counter="ARM_Mali-T6xx_PM_L2_0" display="average" average_selection="yes" percentage="yes" title="Mali PM L2" name="PM L2 Core 0" description="Mali PM L2: PM L2 Core 0."/>
- <event counter="ARM_Mali-T6xx_PM_L2_1" display="average" average_selection="yes" percentage="yes" title="Mali PM L2" name="PM L2 Core 1" description="Mali PM L2: PM L2 Core 1."/>
- </category>
-
- <category name="Mali-T6xx-MMU_AS" per_cpu="no">
- <event counter="ARM_Mali-T6xx_MMU_AS_0" display="average" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 0" description="Mali MMU Address Space 0 usage."/>
- <event counter="ARM_Mali-T6xx_MMU_AS_1" display="average" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 1" description="Mali MMU Address Space 1 usage."/>
- <event counter="ARM_Mali-T6xx_MMU_AS_2" display="average" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 2" description="Mali MMU Address Space 2 usage."/>
- <event counter="ARM_Mali-T6xx_MMU_AS_3" display="average" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 3" description="Mali MMU Address Space 3 usage."/>
- </category>
-
- <category name="Mali-T6xx-MMU_page_fault" per_cpu="no">
- <event counter="ARM_Mali-T6xx_MMU_PAGE_FAULT_0" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 0" description="Reports the number of newly allocated pages after a MMU page fault in address space 0."/>
- <event counter="ARM_Mali-T6xx_MMU_PAGE_FAULT_1" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 1" description="Reports the number of newly allocated pages after a MMU page fault in address space 1."/>
- <event counter="ARM_Mali-T6xx_MMU_PAGE_FAULT_2" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 2" description="Reports the number of newly allocated pages after a MMU page fault in address space 2."/>
- <event counter="ARM_Mali-T6xx_MMU_PAGE_FAULT_3" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 3" description="Reports the number of newly allocated pages after a MMU page fault in address space 3."/>
- </category>
-
- <counter_set name="ARM_Mali-T6xx_Filmstrip_cnt" count="1"/>
- <category name="ARM Mali-T6xx Filmstrip" counter_set="ARM_Mali-T6xx_Filmstrip_cnt" per_cpu="no">
- <option_set name="fs">
- <option event_delta="0x3c" name="1:60" description="captures every 60th frame"/>
- <option event_delta="0x1e" name="1:30" description="captures every 30th frame"/>
- <option event_delta="0xa" name="1:10" description="captures every 10th frame"/>
- </option_set>
- <event event="0x0400" option_set="fs" title="ARM Mali-T6xx" name="Filmstrip" description="Scaled framebuffer"/>
- </category>
+++ /dev/null
-
- <category name="Mali-T6xx-JobManager" per_cpu="no">
-
- <event counter="ARM_Mali-T6xx_GPU_ACTIVE" title="Mali Job Manager Cycles" name="GPU cycles" description="Number of cycles the GPU was active"/>
- <event counter="ARM_Mali-T6xx_IRQ_ACTIVE" title="Mali Job Manager Cycles" name="IRQ cycles" description="Number of cycles the GPU had a pending interrupt"/>
- <event counter="ARM_Mali-T6xx_JS0_ACTIVE" title="Mali Job Manager Cycles" name="JS0 cycles" description="Number of cycles JS0 (fragment) was active"/>
- <event counter="ARM_Mali-T6xx_JS1_ACTIVE" title="Mali Job Manager Cycles" name="JS1 cycles" description="Number of cycles JS1 (vertex/tiler/compute) was active"/>
- <event counter="ARM_Mali-T6xx_JS2_ACTIVE" title="Mali Job Manager Cycles" name="JS2 cycles" description="Number of cycles JS2 (vertex/compute) was active"/>
-
- <event counter="ARM_Mali-T6xx_JS0_JOBS" title="Mali Job Manager Work" name="JS0 jobs" description="Number of Jobs (fragment) completed in JS0"/>
- <event counter="ARM_Mali-T6xx_JS0_TASKS" title="Mali Job Manager Work" name="JS0 tasks" description="Number of Tasks completed in JS0"/>
- <event counter="ARM_Mali-T6xx_JS1_JOBS" title="Mali Job Manager Work" name="JS1 jobs" description="Number of Jobs (vertex/tiler/compute) completed in JS1"/>
- <event counter="ARM_Mali-T6xx_JS1_TASKS" title="Mali Job Manager Work" name="JS1 tasks" description="Number of Tasks completed in JS1"/>
- <event counter="ARM_Mali-T6xx_JS2_TASKS" title="Mali Job Manager Work" name="JS2 tasks" description="Number of Tasks completed in JS2"/>
- <event counter="ARM_Mali-T6xx_JS2_JOBS" title="Mali Job Manager Work" name="JS2 jobs" description="Number of Jobs (vertex/compute) completed in JS2"/>
-
- </category>
-
- <category name="Mali-T6xx-Tiler" per_cpu="no">
-
- <event counter="ARM_Mali-T6xx_POLYGONS" title="Mali Tiler Primitives" name="Polygons" description="Number of polygons processed"/>
- <event counter="ARM_Mali-T6xx_QUADS" title="Mali Tiler Primitives" name="Quads" description="Number of quads processed"/>
- <event counter="ARM_Mali-T6xx_TRIANGLES" title="Mali Tiler Primitives" name="Triangles" description="Number of triangles processed"/>
- <event counter="ARM_Mali-T6xx_LINES" title="Mali Tiler Primitives" name="Lines" description="Number of lines processed"/>
- <event counter="ARM_Mali-T6xx_POINTS" title="Mali Tiler Primitives" name="Points" description="Number of points processed"/>
-
- <event counter="ARM_Mali-T6xx_FRONT_FACING" title="Mali Tiler Culling" name="Front facing prims" description="Number of front facing primitives"/>
- <event counter="ARM_Mali-T6xx_BACK_FACING" title="Mali Tiler Culling" name="Back facing prims" description="Number of back facing primitives"/>
- <event counter="ARM_Mali-T6xx_PRIM_VISIBLE" title="Mali Tiler Culling" name="Visible prims" description="Number of visible primitives"/>
- <event counter="ARM_Mali-T6xx_PRIM_CULLED" title="Mali Tiler Culling" name="Culled prims" description="Number of culled primitives"/>
- <event counter="ARM_Mali-T6xx_PRIM_CLIPPED" title="Mali Tiler Culling" name="Clipped prims" description="Number of clipped primitives"/>
-
- <event counter="ARM_Mali-T6xx_LEVEL0" title="Mali Tiler Hierarchy" name="L0 prims" description="Number of primitives in hierarchy level 0"/>
- <event counter="ARM_Mali-T6xx_LEVEL1" title="Mali Tiler Hierarchy" name="L1 prims" description="Number of primitives in hierarchy level 1"/>
- <event counter="ARM_Mali-T6xx_LEVEL2" title="Mali Tiler Hierarchy" name="L2 prims" description="Number of primitives in hierarchy level 2"/>
- <event counter="ARM_Mali-T6xx_LEVEL3" title="Mali Tiler Hierarchy" name="L3 prims" description="Number of primitives in hierarchy level 3"/>
- <event counter="ARM_Mali-T6xx_LEVEL4" title="Mali Tiler Hierarchy" name="L4 prims" description="Number of primitives in hierarchy level 4"/>
- <event counter="ARM_Mali-T6xx_LEVEL5" title="Mali Tiler Hierarchy" name="L5 prims" description="Number of primitives in hierarchy level 5"/>
- <event counter="ARM_Mali-T6xx_LEVEL6" title="Mali Tiler Hierarchy" name="L6 prims" description="Number of primitives in hierarchy level 6"/>
- <event counter="ARM_Mali-T6xx_LEVEL7" title="Mali Tiler Hierarchy" name="L7 prims" description="Number of primitives in hierarchy level 7"/>
-
- <event counter="ARM_Mali-T6xx_COMMAND_1" title="Mali Tiler Commands" name="Prims in 1 command" description="Number of primitives producing 1 command"/>
- <event counter="ARM_Mali-T6xx_COMMAND_2" title="Mali Tiler Commands" name="Prims in 2 command" description="Number of primitives producing 2 commands"/>
- <event counter="ARM_Mali-T6xx_COMMAND_3" title="Mali Tiler Commands" name="Prims in 3 command" description="Number of primitives producing 3 commands"/>
- <event counter="ARM_Mali-T6xx_COMMAND_4" title="Mali Tiler Commands" name="Prims in 4 command" description="Number of primitives producing 4 commands"/>
- <event counter="ARM_Mali-T6xx_COMMAND_4_7" title="Mali Tiler Commands" name="Prims in 4-7 commands" description="Number of primitives producing 4-7 commands"/>
- <event counter="ARM_Mali-T6xx_COMMAND_5_7" title="Mali Tiler Commands" name="Prims in 5-7 commands" description="Number of primitives producing 5-7 commands"/>
- <event counter="ARM_Mali-T6xx_COMMAND_8_15" title="Mali Tiler Commands" name="Prims in 8-15 commands" description="Number of primitives producing 8-15 commands"/>
- <event counter="ARM_Mali-T6xx_COMMAND_16_63" title="Mali Tiler Commands" name="Prims in 16-63 commands" description="Number of primitives producing 16-63 commands"/>
- <event counter="ARM_Mali-T6xx_COMMAND_64" title="Mali Tiler Commands" name="Prims in >= 64 commands" description="Number of primitives producing >= 64 commands"/>
-
- </category>
-
- <category name="Mali-T6xx-ShaderCore" per_cpu="no">
-
- <event counter="ARM_Mali-T6xx_TRIPIPE_ACTIVE" title="Mali Core Cycles" name="Tripipe cycles" description="Number of cycles the Tripipe was active"/>
- <event counter="ARM_Mali-T6xx_FRAG_ACTIVE" title="Mali Core Cycles" name="Fragment cycles" description="Number of cycles fragment processing was active"/>
- <event counter="ARM_Mali-T6xx_COMPUTE_ACTIVE" title="Mali Core Cycles" name="Compute cycles" description="Number of cycles vertex\compute processing was active"/>
- <event counter="ARM_Mali-T6xx_FRAG_CYCLE_NO_TILE" title="Mali Core Cycles" name="Fragment cycles waiting for tile" description="Number of cycles spent waiting for a physical tile buffer"/>
-
- <event counter="ARM_Mali-T6xx_FRAG_THREADS" title="Mali Core Threads" name="Fragment threads" description="Number of fragment threads started"/>
- <event counter="ARM_Mali-T6xx_FRAG_DUMMY_THREADS" title="Mali Core Threads" name="Dummy fragment threads" description="Number of dummy fragment threads started"/>
- <event counter="ARM_Mali-T6xx_FRAG_QUADS_LZS_TEST" title="Mali Core Threads" name="Frag threads doing late ZS" description="Number of threads doing late ZS test"/>
- <event counter="ARM_Mali-T6xx_FRAG_QUADS_LZS_KILLED" title="Mali Core Threads" name="Frag threads killed late ZS" description="Number of threads killed by late ZS test"/>
- <event counter="ARM_Mali-T6xx_FRAG_THREADS_LZS_TEST" title="Mali Core Threads" name="Frag threads doing late ZS" description="Number of threads doing late ZS test"/>
- <event counter="ARM_Mali-T6xx_FRAG_THREADS_LZS_KILLED" title="Mali Core Threads" name="Frag threads killed late ZS" description="Number of threads killed by late ZS test"/>
-
- <event counter="ARM_Mali-T6xx_COMPUTE_TASKS" title="Mali Compute Threads" name="Compute tasks" description="Number of compute tasks"/>
- <event counter="ARM_Mali-T6xx_COMPUTE_THREADS" title="Mali Compute Threads" name="Compute threads started" description="Number of compute threads started"/>
- <event counter="ARM_Mali-T6xx_COMPUTE_CYCLES_DESC" title="Mali Compute Threads" name="Compute cycles awaiting descriptors" description="Number of compute cycles spent waiting for descriptors"/>
-
- <event counter="ARM_Mali-T6xx_FRAG_PRIMATIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/>
- <event counter="ARM_Mali-T6xx_FRAG_PRIMATIVES_DROPPED" title="Mali Fragment Primitives" name="Primitives dropped" description="Number of primitives dropped because out of tile"/>
- <event counter="ARM_Mali-T6xx_FRAG_PRIMITIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/>
- <event counter="ARM_Mali-T6xx_FRAG_PRIMITIVES_DROPPED" title="Mali Fragment Primitives" name="Primitives dropped" description="Number of primitives dropped because out of tile"/>
-
- <event counter="ARM_Mali-T6xx_FRAG_QUADS_RAST" title="Mali Fragment Quads" name="Quads rasterized" description="Number of quads rasterized"/>
- <event counter="ARM_Mali-T6xx_FRAG_QUADS_EZS_TEST" title="Mali Fragment Quads" name="Quads doing early ZS" description="Number of quads doing early ZS test"/>
- <event counter="ARM_Mali-T6xx_FRAG_QUADS_EZS_KILLED" title="Mali Fragment Quads" name="Quads killed early Z" description="Number of quads killed by early ZS test"/>
-
- <event counter="ARM_Mali-T6xx_FRAG_NUM_TILES" title="Mali Fragment Tasks" name="Tiles rendered" description="Number of tiles rendered"/>
- <event counter="ARM_Mali-T6xx_FRAG_TRANS_ELIM" title="Mali Fragment Tasks" name="Tile writes killed by TE" description="Number of tile writes skipped by transaction elimination"/>
-
- <event counter="ARM_Mali-T6xx_ARITH_WORDS" title="Mali Arithmetic Pipe" name="A instructions" description="Number of instructions completed by the the A-pipe (normalized per pipeline)"/>
-
- <event counter="ARM_Mali-T6xx_LS_WORDS" title="Mali Load/Store Pipe" name="LS instructions" description="Number of instructions completed by the LS-pipe"/>
- <event counter="ARM_Mali-T6xx_LS_ISSUES" title="Mali Load/Store Pipe" name="LS instruction issues" description="Number of instructions issued to the LS-pipe, including restarts"/>
-
- <event counter="ARM_Mali-T6xx_TEX_WORDS" title="Mali Texture Pipe" name="T instructions" description="Number of instructions completed by the T-pipe"/>
- <event counter="ARM_Mali-T6xx_TEX_THREADS" title="Mali Texture Pipe" name="T instruction issues" description="Number of instructions issused to the T-pipe, including restarts"/>
- <event counter="ARM_Mali-T6xx_TEX_RECIRC_FMISS" title="Mali Texture Pipe" name="Cache misses" description="Number of instructions in the T-pipe, recirculated due to cache miss"/>
-
- <event counter="ARM_Mali-T6xx_LSC_READ_HITS" title="Mali Load/Store Cache" name="Read hits" description="Number of read hits in the Load/Store cache"/>
- <event counter="ARM_Mali-T6xx_LSC_READ_MISSES" title="Mali Load/Store Cache" name="Read misses" description="Number of read misses in the Load/Store cache"/>
- <event counter="ARM_Mali-T6xx_LSC_WRITE_HITS" title="Mali Load/Store Cache" name="Write hits" description="Number of write hits in the Load/Store cache"/>
- <event counter="ARM_Mali-T6xx_LSC_WRITE_MISSES" title="Mali Load/Store Cache" name="Write misses" description="Number of write misses in the Load/Store cache"/>
- <event counter="ARM_Mali-T6xx_LSC_ATOMIC_HITS" title="Mali Load/Store Cache" name="Atomic hits" description="Number of atomic hits in the Load/Store cache"/>
- <event counter="ARM_Mali-T6xx_LSC_ATOMIC_MISSES" title="Mali Load/Store Cache" name="Atomic misses" description="Number of atomic misses in the Load/Store cache"/>
- <event counter="ARM_Mali-T6xx_LSC_LINE_FETCHES" title="Mali Load/Store Cache" name="Line fetches" description="Number of line fetches in the Load/Store cache"/>
- <event counter="ARM_Mali-T6xx_LSC_DIRTY_LINE" title="Mali Load/Store Cache" name="Dirty line evictions" description="Number of dirty line evictions in the Load/Store cache"/>
- <event counter="ARM_Mali-T6xx_LSC_SNOOPS" title="Mali Load/Store Cache" name="Snoops in to LSC" description="Number of coherent memory snoops in to the Load/Store cache"/>
-
- </category>
-
- <category name="Mali-T6xx-L2AndMMU" per_cpu="no">
-
- <event counter="ARM_Mali-T6xx_L2_WRITE_BEATS" title="Mali L2 Cache" name="External write beats" description="Number of external bus write beats"/>
- <event counter="ARM_Mali-T6xx_L2_READ_BEATS" title="Mali L2 Cache" name="External read beats" description="Number of external bus read beats"/>
- <event counter="ARM_Mali-T6xx_L2_READ_SNOOP" title="Mali L2 Cache" name="Read snoops" description="Number of read transaction snoops"/>
- <event counter="ARM_Mali-T6xx_L2_READ_HIT" title="Mali L2 Cache" name="L2 read hits" description="Number of reads hitting in the L2 cache"/>
- <event counter="ARM_Mali-T6xx_L2_WRITE_SNOOP" title="Mali L2 Cache" name="Write snoops" description="Number of write transaction snoops"/>
- <event counter="ARM_Mali-T6xx_L2_WRITE_HIT" title="Mali L2 Cache" name="L2 write hits" description="Number of writes hitting in the L2 cache"/>
- <event counter="ARM_Mali-T6xx_L2_EXT_AR_STALL" title="Mali L2 Cache" name="External bus stalls (AR)" description="Number of cycles a valid read address (AR) is stalled by the external interconnect"/>
- <event counter="ARM_Mali-T6xx_L2_EXT_W_STALL" title="Mali L2 Cache" name="External bus stalls (W)" description="Number of cycles a valid write data (W channel) is stalled by the external interconnect"/>
-
- </category>
+++ /dev/null
- <counter_set name="Perf_Hardware_cnt" count="6"/>
- <category name="Perf Hardware" counter_set="Perf_Hardware_cnt" per_cpu="yes" supports_event_based_sampling="yes">
- <event counter="Perf_Hardware_ccnt" event="0" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/>
- <event event="1" title="Instruction" name="Executed" description="Instruction executed"/>
- <event event="2" title="Cache" name="References" description="Cache References"/>
- <event event="3" title="Cache" name="Misses" description="Cache Misses"/>
- <event event="4" title="Branch" name="Instructions" description="Branch or other change in program flow that could have been predicted by the branch prediction resources of the processor"/>
- <event event="5" title="Branch" name="Misses" description="Branch mispredicted or not predicted"/>
- <event event="6" title="Bus" name="Cycles" description="Bus Cycles"/>
- <event event="7" title="Instruction" name="Stalled Frontend" description="Stalled Frontend Cycles"/>
- <event event="8" title="Instruction" name="Stalled Backend" description="Stalled Backend Cycles"/>
- </category>
+++ /dev/null
- <counter_set name="Scorpion_cnt" count="4"/>
- <category name="Scorpion" counter_set="Scorpion_cnt" per_cpu="yes" supports_event_based_sampling="yes">
- <event counter="Scorpion_ccnt" event="0xff" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/>
- <event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/>
- <event event="0x01" title="Cache" name="Instruction refill" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/>
- <event event="0x02" title="Cache" name="Inst TLB refill" description="Instruction fetch that causes a TLB refill of at least the level of TLB closest to the processor"/>
- <event event="0x03" title="Cache" name="Data refill" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/>
- <event event="0x04" title="Cache" name="Data access" description="Memory Read or Write operation that causes a cache access to at least the level of data or unified cache closest to the processor"/>
- <event event="0x05" title="Cache" name="Data TLB refill" description="Memory Read or Write operation that causes a TLB refill of at least the level of TLB closest to the processor"/>
- <event event="0x06" title="Instruction" name="Memory read" description="Memory-reading instruction architecturally executed"/>
- <event event="0x07" title="Instruction" name="Memory write" description="Memory-writing instruction architecturally executed"/>
- <event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/>
- <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/>
- <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/>
- <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/>
- <event event="0x0c" title="Program Counter" name="SW change" description="Software change of PC, except by an exception, architecturally executed"/>
- <event event="0x0d" title="Branch" name="Immediate" description="Immediate branch architecturally executed"/>
- <event event="0x0e" title="Branch" name="Procedure Return" description="Procedure return architecturally executed (not by exceptions)"/>
- <event event="0x0f" title="Memory" name="Unaligned access" description="Unaligned access architecturally executed"/>
- <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/>
- <event event="0x12" title="Branch" name="Potential prediction" description="Branch or other change in program flow that could have been predicted by the branch prediction resources of the processor"/>
- <event event="0x4c" title="Scorpion" name="ICACHE_EXPL_INV" description="I-cache explicit invalidates"/>
- <event event="0x4d" title="Scorpion" name="ICACHE_MISS" description="I-cache misses"/>
- <event event="0x4e" title="Scorpion" name="ICACHE_ACCESS" description="I-cache accesses"/>
- <event event="0x4f" title="Scorpion" name="ICACHE_CACHEREQ_L2" description="I-cache cacheable requests to L2"/>
- <event event="0x50" title="Scorpion" name="ICACHE_NOCACHE_L2" description="I-cache non-cacheable requests to L2"/>
- <event event="0x51" title="Scorpion" name="HIQUP_NOPED" description="Conditional instructions HIQUPs NOPed"/>
- <event event="0x52" title="Scorpion" name="DATA_ABORT" description="Interrupts and Exceptions Data Abort"/>
- <event event="0x53" title="Scorpion" name="IRQ" description="Interrupts and Exceptions IRQ"/>
- <event event="0x54" title="Scorpion" name="FIQ" description="Interrupts and Exceptions FIQ"/>
- <event event="0x55" title="Scorpion" name="ALL_EXCPT" description="Interrupts and Exceptions All interrupts"/>
- <event event="0x56" title="Scorpion" name="UNDEF" description="Interrupts and Exceptions Undefined"/>
- <event event="0x57" title="Scorpion" name="SVC" description="Interrupts and Exceptions SVC"/>
- <event event="0x58" title="Scorpion" name="SMC" description="Interrupts and Exceptions SMC"/>
- <event event="0x59" title="Scorpion" name="PREFETCH_ABORT" description="Interrupts and Exceptions Prefetch Abort"/>
- <event event="0x5a" title="Scorpion" name="INDEX_CHECK" description="Interrupts and Exceptions Index Check"/>
- <event event="0x5b" title="Scorpion" name="NULL_CHECK" description="Interrupts and Exceptions Null Check"/>
- <event event="0x5c" title="Scorpion" name="EXPL_ICIALLU" description="I-cache and BTAC Invalidates Explicit ICIALLU"/>
- <event event="0x5d" title="Scorpion" name="IMPL_ICIALLU" description="I-cache and BTAC Invalidates Implicit ICIALLU"/>
- <event event="0x5e" title="Scorpion" name="NONICIALLU_BTAC_INV" description="I-cache and BTAC Invalidates Non-ICIALLU BTAC Invalidate"/>
- <event event="0x5f" title="Scorpion" name="ICIMVAU_IMPL_ICIALLU" description="I-cache and BTAC Invalidates ICIMVAU-implied ICIALLU"/>
- <event event="0x60" title="Scorpion" name="SPIPE_ONLY_CYCLES" description="Issue S-pipe only issue cycles"/>
- <event event="0x61" title="Scorpion" name="XPIPE_ONLY_CYCLES" description="Issue X-pipe only issue cycles"/>
- <event event="0x62" title="Scorpion" name="DUAL_CYCLES" description="Issue dual issue cycles"/>
- <event event="0x63" title="Scorpion" name="DISPATCH_ANY_CYCLES" description="Dispatch any dispatch cycles"/>
- <event event="0x64" title="Scorpion" name="FIFO_FULLBLK_CMT" description="Commits Trace FIFO full Blk CMT"/>
- <event event="0x65" title="Scorpion" name="FAIL_COND_INST" description="Conditional instructions failing conditional instrs (excluding branches)"/>
- <event event="0x66" title="Scorpion" name="PASS_COND_INST" description="Conditional instructions passing conditional instrs (excluding branches)"/>
- <event event="0x67" title="Scorpion" name="ALLOW_VU_CLK" description="Unit Clock Gating Allow VU Clks"/>
- <event event="0x68" title="Scorpion" name="VU_IDLE" description="Unit Clock Gating VU Idle"/>
- <event event="0x69" title="Scorpion" name="ALLOW_L2_CLK" description="Unit Clock Gating Allow L2 Clks"/>
- <event event="0x6a" title="Scorpion" name="L2_IDLE" description="Unit Clock Gating L2 Idle"/>
- <event event="0x6b" title="Scorpion" name="DTLB_IMPL_INV_SCTLR_DACR" description="DTLB implicit invalidates writes to SCTLR and DACR"/>
- <event event="0x6c" title="Scorpion" name="DTLB_EXPL_INV" description="DTLB explicit invalidates"/>
- <event event="0x6d" title="Scorpion" name="DTLB_MISS" description="DTLB misses"/>
- <event event="0x6e" title="Scorpion" name="DTLB_ACCESS" description="DTLB accesses"/>
- <event event="0x6f" title="Scorpion" name="ITLB_MISS" description="ITLB misses"/>
- <event event="0x70" title="Scorpion" name="ITLB_IMPL_INV" description="ITLB implicit ITLB invalidates"/>
- <event event="0x71" title="Scorpion" name="ITLB_EXPL_INV" description="ITLB explicit ITLB invalidates"/>
- <event event="0x72" title="Scorpion" name="UTLB_D_MISS" description="UTLB d-side misses"/>
- <event event="0x73" title="Scorpion" name="UTLB_D_ACCESS" description="UTLB d-side accesses"/>
- <event event="0x74" title="Scorpion" name="UTLB_I_MISS" description="UTLB i-side misses"/>
- <event event="0x75" title="Scorpion" name="UTLB_I_ACCESS" description="UTLB i-side accesses"/>
- <event event="0x76" title="Scorpion" name="UTLB_INV_ASID" description="UTLB invalidate by ASID"/>
- <event event="0x77" title="Scorpion" name="UTLB_INV_MVA" description="UTLB invalidate by MVA"/>
- <event event="0x78" title="Scorpion" name="UTLB_INV_ALL" description="UTLB invalidate all"/>
- <event event="0x79" title="Scorpion" name="S2_HOLD_RDQ_UNAVAIL" description="S2 hold RDQ unavail"/>
- <event event="0x7a" title="Scorpion" name="S2_HOLD" description="S2 hold"/>
- <event event="0x7b" title="Scorpion" name="S2_HOLD_DEV_OP" description="S2 hold device op"/>
- <event event="0x7c" title="Scorpion" name="S2_HOLD_ORDER" description="S2 hold strongly ordered op"/>
- <event event="0x7d" title="Scorpion" name="S2_HOLD_BARRIER" description="S2 hold barrier"/>
- <event event="0x7e" title="Scorpion" name="VIU_DUAL_CYCLE" description="Scorpion VIU dual cycle"/>
- <event event="0x7f" title="Scorpion" name="VIU_SINGLE_CYCLE" description="Scorpion VIU single cycle"/>
- <event event="0x80" title="Scorpion" name="VX_PIPE_WAR_STALL_CYCLES" description="Scorpion VX pipe WAR cycles"/>
- <event event="0x81" title="Scorpion" name="VX_PIPE_WAW_STALL_CYCLES" description="Scorpion VX pipe WAW cycles"/>
- <event event="0x82" title="Scorpion" name="VX_PIPE_RAW_STALL_CYCLES" description="Scorpion VX pipe RAW cycles"/>
- <event event="0x83" title="Scorpion" name="VX_PIPE_LOAD_USE_STALL" description="Scorpion VX pipe load use stall"/>
- <event event="0x84" title="Scorpion" name="VS_PIPE_WAR_STALL_CYCLES" description="Scorpion VS pipe WAR stall cycles"/>
- <event event="0x85" title="Scorpion" name="VS_PIPE_WAW_STALL_CYCLES" description="Scorpion VS pipe WAW stall cycles"/>
- <event event="0x86" title="Scorpion" name="VS_PIPE_RAW_STALL_CYCLES" description="Scorpion VS pipe RAW stall cycles"/>
- <event event="0x87" title="Scorpion" name="EXCEPTIONS_INV_OPERATION" description="Scorpion invalid operation exceptions"/>
- <event event="0x88" title="Scorpion" name="EXCEPTIONS_DIV_BY_ZERO" description="Scorpion divide by zero exceptions"/>
- <event event="0x89" title="Scorpion" name="COND_INST_FAIL_VX_PIPE" description="Scorpion conditional instruction fail VX pipe"/>
- <event event="0x8a" title="Scorpion" name="COND_INST_FAIL_VS_PIPE" description="Scorpion conditional instruction fail VS pipe"/>
- <event event="0x8b" title="Scorpion" name="EXCEPTIONS_OVERFLOW" description="Scorpion overflow exceptions"/>
- <event event="0x8c" title="Scorpion" name="EXCEPTIONS_UNDERFLOW" description="Scorpion underflow exceptions"/>
- <event event="0x8d" title="Scorpion" name="EXCEPTIONS_DENORM" description="Scorpion denorm exceptions"/>
- <event event="0x8e" title="Scorpion" name="BANK_AB_HIT" description="L2 hit rates bank A/B hits"/>
- <event event="0x8f" title="Scorpion" name="BANK_AB_ACCESS" description="L2 hit rates bank A/B accesses"/>
- <event event="0x90" title="Scorpion" name="BANK_CD_HIT" description="L2 hit rates bank C/D hits"/>
- <event event="0x91" title="Scorpion" name="BANK_CD_ACCESS" description="L2 hit rates bank C/D accesses"/>
- <event event="0x92" title="Scorpion" name="BANK_AB_DSIDE_HIT" description="L2 hit rates bank A/B d-side hits"/>
- <event event="0x93" title="Scorpion" name="BANK_AB_DSIDE_ACCESS" description="L2 hit rates bank A/B d-side accesses"/>
- <event event="0x94" title="Scorpion" name="BANK_CD_DSIDE_HIT" description="L2 hit rates bank C/D d-side hits"/>
- <event event="0x95" title="Scorpion" name="BANK_CD_DSIDE_ACCESS" description="L2 hit rates bank C/D d-side accesses"/>
- <event event="0x96" title="Scorpion" name="BANK_AB_ISIDE_HIT" description="L2 hit rates bank A/B i-side hits"/>
- <event event="0x97" title="Scorpion" name="BANK_AB_ISIDE_ACCESS" description="L2 hit rates bank A/B i-side accesses"/>
- <event event="0x98" title="Scorpion" name="BANK_CD_ISIDE_HIT" description="L2 hit rates bank C/D i-side hits"/>
- <event event="0x99" title="Scorpion" name="BANK_CD_ISIDE_ACCESS" description="L2 hit rates bank C/D i-side accesses"/>
- <event event="0x9a" title="Scorpion" name="ISIDE_RD_WAIT" description="fills and castouts cycles that i-side RD requests wait on data from bus"/>
- <event event="0x9b" title="Scorpion" name="DSIDE_RD_WAIT" description="fills and castouts cycles that d-side RD requests wait on data from bus"/>
- <event event="0x9c" title="Scorpion" name="BANK_BYPASS_WRITE" description="fills and castouts bank bypass writes"/>
- <event event="0x9d" title="Scorpion" name="BANK_AB_NON_CASTOUT" description="fills and castouts bank A/B non-castout writes to bus"/>
- <event event="0x9e" title="Scorpion" name="BANK_AB_L2_CASTOUT" description="fills and castouts bank A/B L2 castouts (granules)"/>
- <event event="0x9f" title="Scorpion" name="BANK_CD_NON_CASTOUT" description="fills and castouts bank C/D non-castout writes to bus"/>
- <event event="0xa0" title="Scorpion" name="BANK_CD_L2_CASTOUT" description="fills and castouts bank C/D L2 castouts (granules)"/>
- </category>
+++ /dev/null
- <counter_set name="ScorpionMP_cnt" count="4"/>
- <category name="ScorpionMP" counter_set="ScorpionMP_cnt" per_cpu="yes" supports_event_based_sampling="yes">
- <event counter="ScorpionMP_ccnt" event="0xff" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/>
- <event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/>
- <event event="0x01" title="Cache" name="Instruction refill" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/>
- <event event="0x02" title="Cache" name="Inst TLB refill" description="Instruction fetch that causes a TLB refill of at least the level of TLB closest to the processor"/>
- <event event="0x03" title="Cache" name="Data refill" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/>
- <event event="0x04" title="Cache" name="Data access" description="Memory Read or Write operation that causes a cache access to at least the level of data or unified cache closest to the processor"/>
- <event event="0x05" title="Cache" name="Data TLB refill" description="Memory Read or Write operation that causes a TLB refill of at least the level of TLB closest to the processor"/>
- <event event="0x06" title="Instruction" name="Memory read" description="Memory-reading instruction architecturally executed"/>
- <event event="0x07" title="Instruction" name="Memory write" description="Memory-writing instruction architecturally executed"/>
- <event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/>
- <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/>
- <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/>
- <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/>
- <event event="0x0c" title="Program Counter" name="SW change" description="Software change of PC, except by an exception, architecturally executed"/>
- <event event="0x0d" title="Branch" name="Immediate" description="Immediate branch architecturally executed"/>
- <event event="0x0e" title="Branch" name="Procedure Return" description="Procedure return architecturally executed (not by exceptions)"/>
- <event event="0x0f" title="Memory" name="Unaligned access" description="Unaligned access architecturally executed"/>
- <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/>
- <event event="0x12" title="Branch" name="Potential prediction" description="Branch or other change in program flow that could have been predicted by the branch prediction resources of the processor"/>
- <event event="0x4c" title="Scorpion" name="ICACHE_EXPL_INV" description="I-cache explicit invalidates"/>
- <event event="0x4d" title="Scorpion" name="ICACHE_MISS" description="I-cache misses"/>
- <event event="0x4e" title="Scorpion" name="ICACHE_ACCESS" description="I-cache accesses"/>
- <event event="0x4f" title="Scorpion" name="ICACHE_CACHEREQ_L2" description="I-cache cacheable requests to L2"/>
- <event event="0x50" title="Scorpion" name="ICACHE_NOCACHE_L2" description="I-cache non-cacheable requests to L2"/>
- <event event="0x51" title="Scorpion" name="HIQUP_NOPED" description="Conditional instructions HIQUPs NOPed"/>
- <event event="0x52" title="Scorpion" name="DATA_ABORT" description="Interrupts and Exceptions Data Abort"/>
- <event event="0x53" title="Scorpion" name="IRQ" description="Interrupts and Exceptions IRQ"/>
- <event event="0x54" title="Scorpion" name="FIQ" description="Interrupts and Exceptions FIQ"/>
- <event event="0x55" title="Scorpion" name="ALL_EXCPT" description="Interrupts and Exceptions All interrupts"/>
- <event event="0x56" title="Scorpion" name="UNDEF" description="Interrupts and Exceptions Undefined"/>
- <event event="0x57" title="Scorpion" name="SVC" description="Interrupts and Exceptions SVC"/>
- <event event="0x58" title="Scorpion" name="SMC" description="Interrupts and Exceptions SMC"/>
- <event event="0x59" title="Scorpion" name="PREFETCH_ABORT" description="Interrupts and Exceptions Prefetch Abort"/>
- <event event="0x5a" title="Scorpion" name="INDEX_CHECK" description="Interrupts and Exceptions Index Check"/>
- <event event="0x5b" title="Scorpion" name="NULL_CHECK" description="Interrupts and Exceptions Null Check"/>
- <event event="0x5c" title="Scorpion" name="EXPL_ICIALLU" description="I-cache and BTAC Invalidates Explicit ICIALLU"/>
- <event event="0x5d" title="Scorpion" name="IMPL_ICIALLU" description="I-cache and BTAC Invalidates Implicit ICIALLU"/>
- <event event="0x5e" title="Scorpion" name="NONICIALLU_BTAC_INV" description="I-cache and BTAC Invalidates Non-ICIALLU BTAC Invalidate"/>
- <event event="0x5f" title="Scorpion" name="ICIMVAU_IMPL_ICIALLU" description="I-cache and BTAC Invalidates ICIMVAU-implied ICIALLU"/>
- <event event="0x60" title="Scorpion" name="SPIPE_ONLY_CYCLES" description="Issue S-pipe only issue cycles"/>
- <event event="0x61" title="Scorpion" name="XPIPE_ONLY_CYCLES" description="Issue X-pipe only issue cycles"/>
- <event event="0x62" title="Scorpion" name="DUAL_CYCLES" description="Issue dual issue cycles"/>
- <event event="0x63" title="Scorpion" name="DISPATCH_ANY_CYCLES" description="Dispatch any dispatch cycles"/>
- <event event="0x64" title="Scorpion" name="FIFO_FULLBLK_CMT" description="Commits Trace FIFO full Blk CMT"/>
- <event event="0x65" title="Scorpion" name="FAIL_COND_INST" description="Conditional instructions failing conditional instrs (excluding branches)"/>
- <event event="0x66" title="Scorpion" name="PASS_COND_INST" description="Conditional instructions passing conditional instrs (excluding branches)"/>
- <event event="0x67" title="Scorpion" name="ALLOW_VU_CLK" description="Unit Clock Gating Allow VU Clks"/>
- <event event="0x68" title="Scorpion" name="VU_IDLE" description="Unit Clock Gating VU Idle"/>
- <event event="0x69" title="Scorpion" name="ALLOW_L2_CLK" description="Unit Clock Gating Allow L2 Clks"/>
- <event event="0x6a" title="Scorpion" name="L2_IDLE" description="Unit Clock Gating L2 Idle"/>
- <event event="0x6b" title="Scorpion" name="DTLB_IMPL_INV_SCTLR_DACR" description="DTLB implicit invalidates writes to SCTLR and DACR"/>
- <event event="0x6c" title="Scorpion" name="DTLB_EXPL_INV" description="DTLB explicit invalidates"/>
- <event event="0x6d" title="Scorpion" name="DTLB_MISS" description="DTLB misses"/>
- <event event="0x6e" title="Scorpion" name="DTLB_ACCESS" description="DTLB accesses"/>
- <event event="0x6f" title="Scorpion" name="ITLB_MISS" description="ITLB misses"/>
- <event event="0x70" title="Scorpion" name="ITLB_IMPL_INV" description="ITLB implicit ITLB invalidates"/>
- <event event="0x71" title="Scorpion" name="ITLB_EXPL_INV" description="ITLB explicit ITLB invalidates"/>
- <event event="0x72" title="Scorpion" name="UTLB_D_MISS" description="UTLB d-side misses"/>
- <event event="0x73" title="Scorpion" name="UTLB_D_ACCESS" description="UTLB d-side accesses"/>
- <event event="0x74" title="Scorpion" name="UTLB_I_MISS" description="UTLB i-side misses"/>
- <event event="0x75" title="Scorpion" name="UTLB_I_ACCESS" description="UTLB i-side accesses"/>
- <event event="0x76" title="Scorpion" name="UTLB_INV_ASID" description="UTLB invalidate by ASID"/>
- <event event="0x77" title="Scorpion" name="UTLB_INV_MVA" description="UTLB invalidate by MVA"/>
- <event event="0x78" title="Scorpion" name="UTLB_INV_ALL" description="UTLB invalidate all"/>
- <event event="0x79" title="Scorpion" name="S2_HOLD_RDQ_UNAVAIL" description="S2 hold RDQ unavail"/>
- <event event="0x7a" title="Scorpion" name="S2_HOLD" description="S2 hold"/>
- <event event="0x7b" title="Scorpion" name="S2_HOLD_DEV_OP" description="S2 hold device op"/>
- <event event="0x7c" title="Scorpion" name="S2_HOLD_ORDER" description="S2 hold strongly ordered op"/>
- <event event="0x7d" title="Scorpion" name="S2_HOLD_BARRIER" description="S2 hold barrier"/>
- <event event="0x7e" title="Scorpion" name="VIU_DUAL_CYCLE" description="Scorpion VIU dual cycle"/>
- <event event="0x7f" title="Scorpion" name="VIU_SINGLE_CYCLE" description="Scorpion VIU single cycle"/>
- <event event="0x80" title="Scorpion" name="VX_PIPE_WAR_STALL_CYCLES" description="Scorpion VX pipe WAR cycles"/>
- <event event="0x81" title="Scorpion" name="VX_PIPE_WAW_STALL_CYCLES" description="Scorpion VX pipe WAW cycles"/>
- <event event="0x82" title="Scorpion" name="VX_PIPE_RAW_STALL_CYCLES" description="Scorpion VX pipe RAW cycles"/>
- <event event="0x83" title="Scorpion" name="VX_PIPE_LOAD_USE_STALL" description="Scorpion VX pipe load use stall"/>
- <event event="0x84" title="Scorpion" name="VS_PIPE_WAR_STALL_CYCLES" description="Scorpion VS pipe WAR stall cycles"/>
- <event event="0x85" title="Scorpion" name="VS_PIPE_WAW_STALL_CYCLES" description="Scorpion VS pipe WAW stall cycles"/>
- <event event="0x86" title="Scorpion" name="VS_PIPE_RAW_STALL_CYCLES" description="Scorpion VS pipe RAW stall cycles"/>
- <event event="0x87" title="Scorpion" name="EXCEPTIONS_INV_OPERATION" description="Scorpion invalid operation exceptions"/>
- <event event="0x88" title="Scorpion" name="EXCEPTIONS_DIV_BY_ZERO" description="Scorpion divide by zero exceptions"/>
- <event event="0x89" title="Scorpion" name="COND_INST_FAIL_VX_PIPE" description="Scorpion conditional instruction fail VX pipe"/>
- <event event="0x8a" title="Scorpion" name="COND_INST_FAIL_VS_PIPE" description="Scorpion conditional instruction fail VS pipe"/>
- <event event="0x8b" title="Scorpion" name="EXCEPTIONS_OVERFLOW" description="Scorpion overflow exceptions"/>
- <event event="0x8c" title="Scorpion" name="EXCEPTIONS_UNDERFLOW" description="Scorpion underflow exceptions"/>
- <event event="0x8d" title="Scorpion" name="EXCEPTIONS_DENORM" description="Scorpion denorm exceptions"/>
- <event event="0x8e" title="ScorpionMP" name="NUM_BARRIERS" description="Barriers"/>
- <event event="0x8f" title="ScorpionMP" name="BARRIER_CYCLES" description="Barrier cycles"/>
- </category>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<events>
+++ /dev/null
-/*
- * Performance events:
- *
- * Copyright (C) 2008-2009, Thomas Gleixner <tglx@linutronix.de>
- * Copyright (C) 2008-2011, Red Hat, Inc., Ingo Molnar
- * Copyright (C) 2008-2011, Red Hat, Inc., Peter Zijlstra
- *
- * Data type definitions, declarations, prototypes.
- *
- * Started by: Thomas Gleixner and Ingo Molnar
- *
- * For licencing details see kernel-base/COPYING
- */
-#ifndef _LINUX_PERF_EVENT_H
-#define _LINUX_PERF_EVENT_H
-
-#include <linux/types.h>
-#include <linux/ioctl.h>
-#include <asm/byteorder.h>
-
-/*
- * User-space ABI bits:
- */
-
-/*
- * attr.type
- */
-enum perf_type_id {
- PERF_TYPE_HARDWARE = 0,
- PERF_TYPE_SOFTWARE = 1,
- PERF_TYPE_TRACEPOINT = 2,
- PERF_TYPE_HW_CACHE = 3,
- PERF_TYPE_RAW = 4,
- PERF_TYPE_BREAKPOINT = 5,
-
- PERF_TYPE_MAX, /* non-ABI */
-};
-
-/*
- * Generalized performance event event_id types, used by the
- * attr.event_id parameter of the sys_perf_event_open()
- * syscall:
- */
-enum perf_hw_id {
- /*
- * Common hardware events, generalized by the kernel:
- */
- PERF_COUNT_HW_CPU_CYCLES = 0,
- PERF_COUNT_HW_INSTRUCTIONS = 1,
- PERF_COUNT_HW_CACHE_REFERENCES = 2,
- PERF_COUNT_HW_CACHE_MISSES = 3,
- PERF_COUNT_HW_BRANCH_INSTRUCTIONS = 4,
- PERF_COUNT_HW_BRANCH_MISSES = 5,
- PERF_COUNT_HW_BUS_CYCLES = 6,
- PERF_COUNT_HW_STALLED_CYCLES_FRONTEND = 7,
- PERF_COUNT_HW_STALLED_CYCLES_BACKEND = 8,
- PERF_COUNT_HW_REF_CPU_CYCLES = 9,
-
- PERF_COUNT_HW_MAX, /* non-ABI */
-};
-
-/*
- * Generalized hardware cache events:
- *
- * { L1-D, L1-I, LLC, ITLB, DTLB, BPU, NODE } x
- * { read, write, prefetch } x
- * { accesses, misses }
- */
-enum perf_hw_cache_id {
- PERF_COUNT_HW_CACHE_L1D = 0,
- PERF_COUNT_HW_CACHE_L1I = 1,
- PERF_COUNT_HW_CACHE_LL = 2,
- PERF_COUNT_HW_CACHE_DTLB = 3,
- PERF_COUNT_HW_CACHE_ITLB = 4,
- PERF_COUNT_HW_CACHE_BPU = 5,
- PERF_COUNT_HW_CACHE_NODE = 6,
-
- PERF_COUNT_HW_CACHE_MAX, /* non-ABI */
-};
-
-enum perf_hw_cache_op_id {
- PERF_COUNT_HW_CACHE_OP_READ = 0,
- PERF_COUNT_HW_CACHE_OP_WRITE = 1,
- PERF_COUNT_HW_CACHE_OP_PREFETCH = 2,
-
- PERF_COUNT_HW_CACHE_OP_MAX, /* non-ABI */
-};
-
-enum perf_hw_cache_op_result_id {
- PERF_COUNT_HW_CACHE_RESULT_ACCESS = 0,
- PERF_COUNT_HW_CACHE_RESULT_MISS = 1,
-
- PERF_COUNT_HW_CACHE_RESULT_MAX, /* non-ABI */
-};
-
-/*
- * Special "software" events provided by the kernel, even if the hardware
- * does not support performance events. These events measure various
- * physical and sw events of the kernel (and allow the profiling of them as
- * well):
- */
-enum perf_sw_ids {
- PERF_COUNT_SW_CPU_CLOCK = 0,
- PERF_COUNT_SW_TASK_CLOCK = 1,
- PERF_COUNT_SW_PAGE_FAULTS = 2,
- PERF_COUNT_SW_CONTEXT_SWITCHES = 3,
- PERF_COUNT_SW_CPU_MIGRATIONS = 4,
- PERF_COUNT_SW_PAGE_FAULTS_MIN = 5,
- PERF_COUNT_SW_PAGE_FAULTS_MAJ = 6,
- PERF_COUNT_SW_ALIGNMENT_FAULTS = 7,
- PERF_COUNT_SW_EMULATION_FAULTS = 8,
- PERF_COUNT_SW_DUMMY = 9,
-
- PERF_COUNT_SW_MAX, /* non-ABI */
-};
-
-/*
- * Bits that can be set in attr.sample_type to request information
- * in the overflow packets.
- */
-enum perf_event_sample_format {
- PERF_SAMPLE_IP = 1U << 0,
- PERF_SAMPLE_TID = 1U << 1,
- PERF_SAMPLE_TIME = 1U << 2,
- PERF_SAMPLE_ADDR = 1U << 3,
- PERF_SAMPLE_READ = 1U << 4,
- PERF_SAMPLE_CALLCHAIN = 1U << 5,
- PERF_SAMPLE_ID = 1U << 6,
- PERF_SAMPLE_CPU = 1U << 7,
- PERF_SAMPLE_PERIOD = 1U << 8,
- PERF_SAMPLE_STREAM_ID = 1U << 9,
- PERF_SAMPLE_RAW = 1U << 10,
- PERF_SAMPLE_BRANCH_STACK = 1U << 11,
- PERF_SAMPLE_REGS_USER = 1U << 12,
- PERF_SAMPLE_STACK_USER = 1U << 13,
- PERF_SAMPLE_WEIGHT = 1U << 14,
- PERF_SAMPLE_DATA_SRC = 1U << 15,
- PERF_SAMPLE_IDENTIFIER = 1U << 16,
-
- PERF_SAMPLE_MAX = 1U << 17, /* non-ABI */
-};
-
-/*
- * values to program into branch_sample_type when PERF_SAMPLE_BRANCH is set
- *
- * If the user does not pass priv level information via branch_sample_type,
- * the kernel uses the event's priv level. Branch and event priv levels do
- * not have to match. Branch priv level is checked for permissions.
- *
- * The branch types can be combined, however BRANCH_ANY covers all types
- * of branches and therefore it supersedes all the other types.
- */
-enum perf_branch_sample_type {
- PERF_SAMPLE_BRANCH_USER = 1U << 0, /* user branches */
- PERF_SAMPLE_BRANCH_KERNEL = 1U << 1, /* kernel branches */
- PERF_SAMPLE_BRANCH_HV = 1U << 2, /* hypervisor branches */
-
- PERF_SAMPLE_BRANCH_ANY = 1U << 3, /* any branch types */
- PERF_SAMPLE_BRANCH_ANY_CALL = 1U << 4, /* any call branch */
- PERF_SAMPLE_BRANCH_ANY_RETURN = 1U << 5, /* any return branch */
- PERF_SAMPLE_BRANCH_IND_CALL = 1U << 6, /* indirect calls */
- PERF_SAMPLE_BRANCH_ABORT_TX = 1U << 7, /* transaction aborts */
- PERF_SAMPLE_BRANCH_IN_TX = 1U << 8, /* in transaction */
- PERF_SAMPLE_BRANCH_NO_TX = 1U << 9, /* not in transaction */
-
- PERF_SAMPLE_BRANCH_MAX = 1U << 10, /* non-ABI */
-};
-
-#define PERF_SAMPLE_BRANCH_PLM_ALL \
- (PERF_SAMPLE_BRANCH_USER|\
- PERF_SAMPLE_BRANCH_KERNEL|\
- PERF_SAMPLE_BRANCH_HV)
-
-/*
- * Values to determine ABI of the registers dump.
- */
-enum perf_sample_regs_abi {
- PERF_SAMPLE_REGS_ABI_NONE = 0,
- PERF_SAMPLE_REGS_ABI_32 = 1,
- PERF_SAMPLE_REGS_ABI_64 = 2,
-};
-
-/*
- * The format of the data returned by read() on a perf event fd,
- * as specified by attr.read_format:
- *
- * struct read_format {
- * { u64 value;
- * { u64 time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED
- * { u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
- * { u64 id; } && PERF_FORMAT_ID
- * } && !PERF_FORMAT_GROUP
- *
- * { u64 nr;
- * { u64 time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED
- * { u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
- * { u64 value;
- * { u64 id; } && PERF_FORMAT_ID
- * } cntr[nr];
- * } && PERF_FORMAT_GROUP
- * };
- */
-enum perf_event_read_format {
- PERF_FORMAT_TOTAL_TIME_ENABLED = 1U << 0,
- PERF_FORMAT_TOTAL_TIME_RUNNING = 1U << 1,
- PERF_FORMAT_ID = 1U << 2,
- PERF_FORMAT_GROUP = 1U << 3,
-
- PERF_FORMAT_MAX = 1U << 4, /* non-ABI */
-};
-
-#define PERF_ATTR_SIZE_VER0 64 /* sizeof first published struct */
-#define PERF_ATTR_SIZE_VER1 72 /* add: config2 */
-#define PERF_ATTR_SIZE_VER2 80 /* add: branch_sample_type */
-#define PERF_ATTR_SIZE_VER3 96 /* add: sample_regs_user */
- /* add: sample_stack_user */
-
-/*
- * Hardware event_id to monitor via a performance monitoring event:
- */
-struct perf_event_attr {
-
- /*
- * Major type: hardware/software/tracepoint/etc.
- */
- __u32 type;
-
- /*
- * Size of the attr structure, for fwd/bwd compat.
- */
- __u32 size;
-
- /*
- * Type specific configuration information.
- */
- __u64 config;
-
- union {
- __u64 sample_period;
- __u64 sample_freq;
- };
-
- __u64 sample_type;
- __u64 read_format;
-
- __u64 disabled : 1, /* off by default */
- inherit : 1, /* children inherit it */
- pinned : 1, /* must always be on PMU */
- exclusive : 1, /* only group on PMU */
- exclude_user : 1, /* don't count user */
- exclude_kernel : 1, /* ditto kernel */
- exclude_hv : 1, /* ditto hypervisor */
- exclude_idle : 1, /* don't count when idle */
- mmap : 1, /* include mmap data */
- comm : 1, /* include comm data */
- freq : 1, /* use freq, not period */
- inherit_stat : 1, /* per task counts */
- enable_on_exec : 1, /* next exec enables */
- task : 1, /* trace fork/exit */
- watermark : 1, /* wakeup_watermark */
- /*
- * precise_ip:
- *
- * 0 - SAMPLE_IP can have arbitrary skid
- * 1 - SAMPLE_IP must have constant skid
- * 2 - SAMPLE_IP requested to have 0 skid
- * 3 - SAMPLE_IP must have 0 skid
- *
- * See also PERF_RECORD_MISC_EXACT_IP
- */
- precise_ip : 2, /* skid constraint */
- mmap_data : 1, /* non-exec mmap data */
- sample_id_all : 1, /* sample_type all events */
-
- exclude_host : 1, /* don't count in host */
- exclude_guest : 1, /* don't count in guest */
-
- exclude_callchain_kernel : 1, /* exclude kernel callchains */
- exclude_callchain_user : 1, /* exclude user callchains */
- mmap2 : 1, /* include mmap with inode data */
-
- __reserved_1 : 40;
-
- union {
- __u32 wakeup_events; /* wakeup every n events */
- __u32 wakeup_watermark; /* bytes before wakeup */
- };
-
- __u32 bp_type;
- union {
- __u64 bp_addr;
- __u64 config1; /* extension of config */
- };
- union {
- __u64 bp_len;
- __u64 config2; /* extension of config1 */
- };
- __u64 branch_sample_type; /* enum perf_branch_sample_type */
-
- /*
- * Defines set of user regs to dump on samples.
- * See asm/perf_regs.h for details.
- */
- __u64 sample_regs_user;
-
- /*
- * Defines size of the user stack to dump on samples.
- */
- __u32 sample_stack_user;
-
- /* Align to u64. */
- __u32 __reserved_2;
-};
-
-#define perf_flags(attr) (*(&(attr)->read_format + 1))
-
-/*
- * Ioctls that can be done on a perf event fd:
- */
-#define PERF_EVENT_IOC_ENABLE _IO ('$', 0)
-#define PERF_EVENT_IOC_DISABLE _IO ('$', 1)
-#define PERF_EVENT_IOC_REFRESH _IO ('$', 2)
-#define PERF_EVENT_IOC_RESET _IO ('$', 3)
-#define PERF_EVENT_IOC_PERIOD _IOW('$', 4, __u64)
-#define PERF_EVENT_IOC_SET_OUTPUT _IO ('$', 5)
-#define PERF_EVENT_IOC_SET_FILTER _IOW('$', 6, char *)
-#define PERF_EVENT_IOC_ID _IOR('$', 7, __u64 *)
-
-enum perf_event_ioc_flags {
- PERF_IOC_FLAG_GROUP = 1U << 0,
-};
-
-/*
- * Structure of the page that can be mapped via mmap
- */
-struct perf_event_mmap_page {
- __u32 version; /* version number of this structure */
- __u32 compat_version; /* lowest version this is compat with */
-
- /*
- * Bits needed to read the hw events in user-space.
- *
- * u32 seq, time_mult, time_shift, idx, width;
- * u64 count, enabled, running;
- * u64 cyc, time_offset;
- * s64 pmc = 0;
- *
- * do {
- * seq = pc->lock;
- * barrier()
- *
- * enabled = pc->time_enabled;
- * running = pc->time_running;
- *
- * if (pc->cap_usr_time && enabled != running) {
- * cyc = rdtsc();
- * time_offset = pc->time_offset;
- * time_mult = pc->time_mult;
- * time_shift = pc->time_shift;
- * }
- *
- * idx = pc->index;
- * count = pc->offset;
- * if (pc->cap_usr_rdpmc && idx) {
- * width = pc->pmc_width;
- * pmc = rdpmc(idx - 1);
- * }
- *
- * barrier();
- * } while (pc->lock != seq);
- *
- * NOTE: for obvious reason this only works on self-monitoring
- * processes.
- */
- __u32 lock; /* seqlock for synchronization */
- __u32 index; /* hardware event identifier */
- __s64 offset; /* add to hardware event value */
- __u64 time_enabled; /* time event active */
- __u64 time_running; /* time event on cpu */
- union {
- __u64 capabilities;
- struct {
- __u64 cap_bit0 : 1, /* Always 0, deprecated, see commit 860f085b74e9 */
- cap_bit0_is_deprecated : 1, /* Always 1, signals that bit 0 is zero */
-
- cap_user_rdpmc : 1, /* The RDPMC instruction can be used to read counts */
- cap_user_time : 1, /* The time_* fields are used */
- cap_user_time_zero : 1, /* The time_zero field is used */
- cap_____res : 59;
- };
- };
-
- /*
- * If cap_usr_rdpmc this field provides the bit-width of the value
- * read using the rdpmc() or equivalent instruction. This can be used
- * to sign extend the result like:
- *
- * pmc <<= 64 - width;
- * pmc >>= 64 - width; // signed shift right
- * count += pmc;
- */
- __u16 pmc_width;
-
- /*
- * If cap_usr_time the below fields can be used to compute the time
- * delta since time_enabled (in ns) using rdtsc or similar.
- *
- * u64 quot, rem;
- * u64 delta;
- *
- * quot = (cyc >> time_shift);
- * rem = cyc & ((1 << time_shift) - 1);
- * delta = time_offset + quot * time_mult +
- * ((rem * time_mult) >> time_shift);
- *
- * Where time_offset,time_mult,time_shift and cyc are read in the
- * seqcount loop described above. This delta can then be added to
- * enabled and possible running (if idx), improving the scaling:
- *
- * enabled += delta;
- * if (idx)
- * running += delta;
- *
- * quot = count / running;
- * rem = count % running;
- * count = quot * enabled + (rem * enabled) / running;
- */
- __u16 time_shift;
- __u32 time_mult;
- __u64 time_offset;
- /*
- * If cap_usr_time_zero, the hardware clock (e.g. TSC) can be calculated
- * from sample timestamps.
- *
- * time = timestamp - time_zero;
- * quot = time / time_mult;
- * rem = time % time_mult;
- * cyc = (quot << time_shift) + (rem << time_shift) / time_mult;
- *
- * And vice versa:
- *
- * quot = cyc >> time_shift;
- * rem = cyc & ((1 << time_shift) - 1);
- * timestamp = time_zero + quot * time_mult +
- * ((rem * time_mult) >> time_shift);
- */
- __u64 time_zero;
- __u32 size; /* Header size up to __reserved[] fields. */
-
- /*
- * Hole for extension of the self monitor capabilities
- */
-
- __u8 __reserved[118*8+4]; /* align to 1k. */
-
- /*
- * Control data for the mmap() data buffer.
- *
- * User-space reading the @data_head value should issue an smp_rmb(),
- * after reading this value.
- *
- * When the mapping is PROT_WRITE the @data_tail value should be
- * written by userspace to reflect the last read data, after issueing
- * an smp_mb() to separate the data read from the ->data_tail store.
- * In this case the kernel will not over-write unread data.
- *
- * See perf_output_put_handle() for the data ordering.
- */
- __u64 data_head; /* head in the data section */
- __u64 data_tail; /* user-space written tail */
-};
-
-#define PERF_RECORD_MISC_CPUMODE_MASK (7 << 0)
-#define PERF_RECORD_MISC_CPUMODE_UNKNOWN (0 << 0)
-#define PERF_RECORD_MISC_KERNEL (1 << 0)
-#define PERF_RECORD_MISC_USER (2 << 0)
-#define PERF_RECORD_MISC_HYPERVISOR (3 << 0)
-#define PERF_RECORD_MISC_GUEST_KERNEL (4 << 0)
-#define PERF_RECORD_MISC_GUEST_USER (5 << 0)
-
-#define PERF_RECORD_MISC_MMAP_DATA (1 << 13)
-/*
- * Indicates that the content of PERF_SAMPLE_IP points to
- * the actual instruction that triggered the event. See also
- * perf_event_attr::precise_ip.
- */
-#define PERF_RECORD_MISC_EXACT_IP (1 << 14)
-/*
- * Reserve the last bit to indicate some extended misc field
- */
-#define PERF_RECORD_MISC_EXT_RESERVED (1 << 15)
-
-struct perf_event_header {
- __u32 type;
- __u16 misc;
- __u16 size;
-};
-
-enum perf_event_type {
-
- /*
- * If perf_event_attr.sample_id_all is set then all event types will
- * have the sample_type selected fields related to where/when
- * (identity) an event took place (TID, TIME, ID, STREAM_ID, CPU,
- * IDENTIFIER) described in PERF_RECORD_SAMPLE below, it will be stashed
- * just after the perf_event_header and the fields already present for
- * the existing fields, i.e. at the end of the payload. That way a newer
- * perf.data file will be supported by older perf tools, with these new
- * optional fields being ignored.
- *
- * struct sample_id {
- * { u32 pid, tid; } && PERF_SAMPLE_TID
- * { u64 time; } && PERF_SAMPLE_TIME
- * { u64 id; } && PERF_SAMPLE_ID
- * { u64 stream_id;} && PERF_SAMPLE_STREAM_ID
- * { u32 cpu, res; } && PERF_SAMPLE_CPU
- * { u64 id; } && PERF_SAMPLE_IDENTIFIER
- * } && perf_event_attr::sample_id_all
- *
- * Note that PERF_SAMPLE_IDENTIFIER duplicates PERF_SAMPLE_ID. The
- * advantage of PERF_SAMPLE_IDENTIFIER is that its position is fixed
- * relative to header.size.
- */
-
- /*
- * The MMAP events record the PROT_EXEC mappings so that we can
- * correlate userspace IPs to code. They have the following structure:
- *
- * struct {
- * struct perf_event_header header;
- *
- * u32 pid, tid;
- * u64 addr;
- * u64 len;
- * u64 pgoff;
- * char filename[];
- * struct sample_id sample_id;
- * };
- */
- PERF_RECORD_MMAP = 1,
-
- /*
- * struct {
- * struct perf_event_header header;
- * u64 id;
- * u64 lost;
- * struct sample_id sample_id;
- * };
- */
- PERF_RECORD_LOST = 2,
-
- /*
- * struct {
- * struct perf_event_header header;
- *
- * u32 pid, tid;
- * char comm[];
- * struct sample_id sample_id;
- * };
- */
- PERF_RECORD_COMM = 3,
-
- /*
- * struct {
- * struct perf_event_header header;
- * u32 pid, ppid;
- * u32 tid, ptid;
- * u64 time;
- * struct sample_id sample_id;
- * };
- */
- PERF_RECORD_EXIT = 4,
-
- /*
- * struct {
- * struct perf_event_header header;
- * u64 time;
- * u64 id;
- * u64 stream_id;
- * struct sample_id sample_id;
- * };
- */
- PERF_RECORD_THROTTLE = 5,
- PERF_RECORD_UNTHROTTLE = 6,
-
- /*
- * struct {
- * struct perf_event_header header;
- * u32 pid, ppid;
- * u32 tid, ptid;
- * u64 time;
- * struct sample_id sample_id;
- * };
- */
- PERF_RECORD_FORK = 7,
-
- /*
- * struct {
- * struct perf_event_header header;
- * u32 pid, tid;
- *
- * struct read_format values;
- * struct sample_id sample_id;
- * };
- */
- PERF_RECORD_READ = 8,
-
- /*
- * struct {
- * struct perf_event_header header;
- *
- * #
- * # Note that PERF_SAMPLE_IDENTIFIER duplicates PERF_SAMPLE_ID.
- * # The advantage of PERF_SAMPLE_IDENTIFIER is that its position
- * # is fixed relative to header.
- * #
- *
- * { u64 id; } && PERF_SAMPLE_IDENTIFIER
- * { u64 ip; } && PERF_SAMPLE_IP
- * { u32 pid, tid; } && PERF_SAMPLE_TID
- * { u64 time; } && PERF_SAMPLE_TIME
- * { u64 addr; } && PERF_SAMPLE_ADDR
- * { u64 id; } && PERF_SAMPLE_ID
- * { u64 stream_id;} && PERF_SAMPLE_STREAM_ID
- * { u32 cpu, res; } && PERF_SAMPLE_CPU
- * { u64 period; } && PERF_SAMPLE_PERIOD
- *
- * { struct read_format values; } && PERF_SAMPLE_READ
- *
- * { u64 nr,
- * u64 ips[nr]; } && PERF_SAMPLE_CALLCHAIN
- *
- * #
- * # The RAW record below is opaque data wrt the ABI
- * #
- * # That is, the ABI doesn't make any promises wrt to
- * # the stability of its content, it may vary depending
- * # on event, hardware, kernel version and phase of
- * # the moon.
- * #
- * # In other words, PERF_SAMPLE_RAW contents are not an ABI.
- * #
- *
- * { u32 size;
- * char data[size];}&& PERF_SAMPLE_RAW
- *
- * { u64 nr;
- * { u64 from, to, flags } lbr[nr];} && PERF_SAMPLE_BRANCH_STACK
- *
- * { u64 abi; # enum perf_sample_regs_abi
- * u64 regs[weight(mask)]; } && PERF_SAMPLE_REGS_USER
- *
- * { u64 size;
- * char data[size];
- * u64 dyn_size; } && PERF_SAMPLE_STACK_USER
- *
- * { u64 weight; } && PERF_SAMPLE_WEIGHT
- * { u64 data_src; } && PERF_SAMPLE_DATA_SRC
- * };
- */
- PERF_RECORD_SAMPLE = 9,
-
- /*
- * The MMAP2 records are an augmented version of MMAP, they add
- * maj, min, ino numbers to be used to uniquely identify each mapping
- *
- * struct {
- * struct perf_event_header header;
- *
- * u32 pid, tid;
- * u64 addr;
- * u64 len;
- * u64 pgoff;
- * u32 maj;
- * u32 min;
- * u64 ino;
- * u64 ino_generation;
- * char filename[];
- * struct sample_id sample_id;
- * };
- */
- PERF_RECORD_MMAP2 = 10,
-
- PERF_RECORD_MAX, /* non-ABI */
-};
-
-#define PERF_MAX_STACK_DEPTH 127
-
-enum perf_callchain_context {
- PERF_CONTEXT_HV = (__u64)-32,
- PERF_CONTEXT_KERNEL = (__u64)-128,
- PERF_CONTEXT_USER = (__u64)-512,
-
- PERF_CONTEXT_GUEST = (__u64)-2048,
- PERF_CONTEXT_GUEST_KERNEL = (__u64)-2176,
- PERF_CONTEXT_GUEST_USER = (__u64)-2560,
-
- PERF_CONTEXT_MAX = (__u64)-4095,
-};
-
-#define PERF_FLAG_FD_NO_GROUP (1U << 0)
-#define PERF_FLAG_FD_OUTPUT (1U << 1)
-#define PERF_FLAG_PID_CGROUP (1U << 2) /* pid=cgroup id, per-cpu mode only */
-
-union perf_mem_data_src {
- __u64 val;
- struct {
- __u64 mem_op:5, /* type of opcode */
- mem_lvl:14, /* memory hierarchy level */
- mem_snoop:5, /* snoop mode */
- mem_lock:2, /* lock instr */
- mem_dtlb:7, /* tlb access */
- mem_rsvd:31;
- };
-};
-
-/* type of opcode (load/store/prefetch,code) */
-#define PERF_MEM_OP_NA 0x01 /* not available */
-#define PERF_MEM_OP_LOAD 0x02 /* load instruction */
-#define PERF_MEM_OP_STORE 0x04 /* store instruction */
-#define PERF_MEM_OP_PFETCH 0x08 /* prefetch */
-#define PERF_MEM_OP_EXEC 0x10 /* code (execution) */
-#define PERF_MEM_OP_SHIFT 0
-
-/* memory hierarchy (memory level, hit or miss) */
-#define PERF_MEM_LVL_NA 0x01 /* not available */
-#define PERF_MEM_LVL_HIT 0x02 /* hit level */
-#define PERF_MEM_LVL_MISS 0x04 /* miss level */
-#define PERF_MEM_LVL_L1 0x08 /* L1 */
-#define PERF_MEM_LVL_LFB 0x10 /* Line Fill Buffer */
-#define PERF_MEM_LVL_L2 0x20 /* L2 */
-#define PERF_MEM_LVL_L3 0x40 /* L3 */
-#define PERF_MEM_LVL_LOC_RAM 0x80 /* Local DRAM */
-#define PERF_MEM_LVL_REM_RAM1 0x100 /* Remote DRAM (1 hop) */
-#define PERF_MEM_LVL_REM_RAM2 0x200 /* Remote DRAM (2 hops) */
-#define PERF_MEM_LVL_REM_CCE1 0x400 /* Remote Cache (1 hop) */
-#define PERF_MEM_LVL_REM_CCE2 0x800 /* Remote Cache (2 hops) */
-#define PERF_MEM_LVL_IO 0x1000 /* I/O memory */
-#define PERF_MEM_LVL_UNC 0x2000 /* Uncached memory */
-#define PERF_MEM_LVL_SHIFT 5
-
-/* snoop mode */
-#define PERF_MEM_SNOOP_NA 0x01 /* not available */
-#define PERF_MEM_SNOOP_NONE 0x02 /* no snoop */
-#define PERF_MEM_SNOOP_HIT 0x04 /* snoop hit */
-#define PERF_MEM_SNOOP_MISS 0x08 /* snoop miss */
-#define PERF_MEM_SNOOP_HITM 0x10 /* snoop hit modified */
-#define PERF_MEM_SNOOP_SHIFT 19
-
-/* locked instruction */
-#define PERF_MEM_LOCK_NA 0x01 /* not available */
-#define PERF_MEM_LOCK_LOCKED 0x02 /* locked transaction */
-#define PERF_MEM_LOCK_SHIFT 24
-
-/* TLB access */
-#define PERF_MEM_TLB_NA 0x01 /* not available */
-#define PERF_MEM_TLB_HIT 0x02 /* hit level */
-#define PERF_MEM_TLB_MISS 0x04 /* miss level */
-#define PERF_MEM_TLB_L1 0x08 /* L1 */
-#define PERF_MEM_TLB_L2 0x10 /* L2 */
-#define PERF_MEM_TLB_WK 0x20 /* Hardware Walker*/
-#define PERF_MEM_TLB_OS 0x40 /* OS fault handler */
-#define PERF_MEM_TLB_SHIFT 26
-
-#define PERF_MEM_S(a, s) \
- (((u64)PERF_MEM_##a##_##s) << PERF_MEM_##a##_SHIFT)
-
-/*
- * single taken branch record layout:
- *
- * from: source instruction (may not always be a branch insn)
- * to: branch target
- * mispred: branch target was mispredicted
- * predicted: branch target was predicted
- *
- * support for mispred, predicted is optional. In case it
- * is not supported mispred = predicted = 0.
- *
- * in_tx: running in a hardware transaction
- * abort: aborting a hardware transaction
- */
-struct perf_branch_entry {
- __u64 from;
- __u64 to;
- __u64 mispred:1, /* target mispredicted */
- predicted:1,/* target predicted */
- in_tx:1, /* in transaction */
- abort:1, /* transaction abort */
- reserved:60;
-};
-
-#endif /* _LINUX_PERF_EVENT_H */
+++ /dev/null
-perf_event.3.12.h
\ No newline at end of file
+++ /dev/null
-/**
- * Copyright (C) ARM Limited 2010-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <arpa/inet.h>
-#include <fcntl.h>
-#include <pthread.h>
-#include <sys/mman.h>
-#include <sys/mount.h>
-#include <sys/prctl.h>
-#include <sys/resource.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/syscall.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include "Child.h"
-#include "KMod.h"
-#include "Logging.h"
-#include "OlySocket.h"
-#include "OlyUtility.h"
-#include "SessionData.h"
-
-#define DEBUG false
-
-extern Child* child;
-static int shutdownFilesystem();
-static pthread_mutex_t numSessions_mutex;
-static int numSessions = 0;
-static OlyServerSocket* sock = NULL;
-static bool driverRunningAtStart = false;
-static bool driverMountedAtStart = false;
-
-struct cmdline_t {
- int port;
- char* module;
-};
-
-#define DEFAULT_PORT 8080
-
-void cleanUp() {
- if (shutdownFilesystem() == -1) {
- logg->logMessage("Error shutting down gator filesystem");
- }
- delete sock;
- delete util;
- delete logg;
-}
-
-// CTRL C Signal Handler
-static void handler(int signum) {
- logg->logMessage("Received signal %d, gator daemon exiting", signum);
-
- // Case 1: both child and parent receive the signal
- if (numSessions > 0) {
- // Arbitrary sleep of 1 second to give time for the child to exit;
- // if something bad happens, continue the shutdown process regardless
- sleep(1);
- }
-
- // Case 2: only the parent received the signal
- if (numSessions > 0) {
- // Kill child threads - the first signal exits gracefully
- logg->logMessage("Killing process group as %d child was running when signal was received", numSessions);
- kill(0, SIGINT);
-
- // Give time for the child to exit
- sleep(1);
-
- if (numSessions > 0) {
- // The second signal force kills the child
- logg->logMessage("Force kill the child");
- kill(0, SIGINT);
- // Again, sleep for 1 second
- sleep(1);
-
- if (numSessions > 0) {
- // Something bad has really happened; the child is not exiting and therefore may hold the /dev/gator resource open
- printf("Unable to kill the gatord child process, thus gator.ko may still be loaded.\n");
- }
- }
- }
-
- cleanUp();
- exit(0);
-}
-
-// Child exit Signal Handler
-static void child_exit(int) {
- int status;
- int pid = wait(&status);
- if (pid != -1) {
- pthread_mutex_lock(&numSessions_mutex);
- numSessions--;
- pthread_mutex_unlock(&numSessions_mutex);
- logg->logMessage("Child process %d exited with status %d", pid, status);
- }
-}
-
-static int udpPort(int port) {
- int s;
- struct sockaddr_in6 sockaddr;
- int on;
- int family = AF_INET6;
-
- s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
- if (s == -1) {
- family = AF_INET;
- s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if (s == -1) {
- logg->logError(__FILE__, __LINE__, "socket failed");
- handleException();
- }
- }
-
- on = 1;
- if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) != 0) {
- logg->logError(__FILE__, __LINE__, "setsockopt failed");
- handleException();
- }
-
- memset((void*)&sockaddr, 0, sizeof(sockaddr));
- sockaddr.sin6_family = family;
- sockaddr.sin6_port = htons(port);
- sockaddr.sin6_addr = in6addr_any;
- if (bind(s, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) < 0) {
- logg->logError(__FILE__, __LINE__, "socket failed");
- handleException();
- }
-
- return s;
-}
-
-#define UDP_ANS_PORT 30000
-#define UDP_REQ_PORT 30001
-
-typedef struct {
- char rviHeader[8];
- uint32_t messageID;
- uint8_t ethernetAddress[8];
- uint32_t ethernetType;
- uint32_t dhcp;
- char dhcpName[40];
- uint32_t ipAddress;
- uint32_t defaultGateway;
- uint32_t subnetMask;
- uint32_t activeConnections;
-} RVIConfigureInfo;
-
-static const char DST_REQ[] = { 'D', 'S', 'T', '_', 'R', 'E', 'Q', ' ', 0, 0, 0, 0x64 };
-
-static void* answerThread(void* pVoid) {
- prctl(PR_SET_NAME, (unsigned long)&"gatord-discover", 0, 0, 0);
- const struct cmdline_t * const cmdline = (struct cmdline_t *)pVoid;
- RVIConfigureInfo dstAns;
- int req = udpPort(UDP_REQ_PORT);
- int ans = udpPort(UDP_ANS_PORT);
-
- // Format the answer buffer
- memset(&dstAns, 0, sizeof(dstAns));
- memcpy(dstAns.rviHeader, "STR_ANS ", sizeof(dstAns.rviHeader));
- if (gethostname(dstAns.dhcpName, sizeof(dstAns.dhcpName) - 1) != 0) {
- logg->logError(__FILE__, __LINE__, "gethostname failed");
- handleException();
- }
- // Subvert the defaultGateway field for the port number
- if (cmdline->port != DEFAULT_PORT) {
- dstAns.defaultGateway = cmdline->port;
- }
- // Subvert the subnetMask field for the protocol version
- dstAns.subnetMask = PROTOCOL_VERSION;
-
- for (;;) {
- char buf[128];
- struct sockaddr_in6 sockaddr;
- socklen_t addrlen;
- int read;
- addrlen = sizeof(sockaddr);
- read = recvfrom(req, &buf, sizeof(buf), 0, (struct sockaddr *)&sockaddr, &addrlen);
- if (read < 0) {
- logg->logError(__FILE__, __LINE__, "recvfrom failed");
- handleException();
- } else if ((read == 12) && (memcmp(buf, DST_REQ, sizeof(DST_REQ)) == 0)) {
- if (sendto(ans, &dstAns, sizeof(dstAns), 0, (struct sockaddr *)&sockaddr, addrlen) != sizeof(dstAns)) {
- logg->logError(__FILE__, __LINE__, "sendto failed");
- handleException();
- }
- }
- }
-}
-
-// retval: -1 = failure; 0 = was already mounted; 1 = successfully mounted
-static int mountGatorFS() {
- // If already mounted,
- if (access("/dev/gator/buffer", F_OK) == 0) {
- return 0;
- }
-
- // else, mount the filesystem
- mkdir("/dev/gator", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
- if (mount("nodev", "/dev/gator", "gatorfs", 0, NULL) != 0) {
- return -1;
- } else {
- return 1;
- }
-}
-
-static bool init_module (const char * const location) {
- bool ret(false);
- const int fd = open(location, O_RDONLY);
- if (fd >= 0) {
- struct stat st;
- if (fstat(fd, &st) == 0) {
- void * const p = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
- if (p != MAP_FAILED) {
- if (syscall(__NR_init_module, p, st.st_size, "") == 0) {
- ret = true;
- }
- munmap(p, st.st_size);
- }
- }
- close(fd);
- }
-
- return ret;
-}
-
-static bool setupFilesystem(char* module) {
- if (module) {
- // unmount and rmmod if the module was specified on the commandline, i.e. ensure that the specified module is indeed running
- shutdownFilesystem();
-
- // if still mounted
- if (access("/dev/gator/buffer", F_OK) == 0) {
- logg->logError(__FILE__, __LINE__, "Unable to remove the running gator.ko. Manually remove the module or use the running module by not specifying one on the commandline");
- handleException();
- }
- }
-
- const int retval = mountGatorFS();
- if (retval == 1) {
- logg->logMessage("Driver already running at startup");
- driverRunningAtStart = true;
- } else if (retval == 0) {
- logg->logMessage("Driver already mounted at startup");
- driverRunningAtStart = driverMountedAtStart = true;
- } else {
- char command[256]; // arbitrarily large amount
- char location[256]; // arbitrarily large amount
-
- if (module) {
- strncpy(location, module, sizeof(location));
- } else {
- // Is the driver co-located in the same directory?
- if (util->getApplicationFullPath(location, sizeof(location)) != 0) { // allow some buffer space
- logg->logMessage("Unable to determine the full path of gatord, the cwd will be used");
- }
- strncat(location, "gator.ko", sizeof(location) - strlen(location) - 1);
- }
-
- if (access(location, F_OK) == -1) {
- // The gator kernel is not already loaded and unable to locate gator.ko
- return false;
- }
-
- // Load driver
- bool success = init_module(location);
- if (!success) {
- logg->logMessage("init_module failed, trying insmod");
- snprintf(command, sizeof(command), "insmod %s >/dev/null 2>&1", location);
- if (system(command) != 0) {
- logg->logMessage("Unable to load gator.ko driver with command: %s", command);
- logg->logError(__FILE__, __LINE__, "Unable to load (insmod) gator.ko driver:\n >>> gator.ko must be built against the current kernel version & configuration\n >>> See dmesg for more details");
- handleException();
- }
- }
-
- if (mountGatorFS() == -1) {
- logg->logError(__FILE__, __LINE__, "Unable to mount the gator filesystem needed for profiling.");
- handleException();
- }
- }
-
- return true;
-}
-
-static int shutdownFilesystem() {
- if (driverMountedAtStart == false) {
- umount("/dev/gator");
- }
- if (driverRunningAtStart == false) {
- if (syscall(__NR_delete_module, "gator", O_NONBLOCK) != 0) {
- logg->logMessage("delete_module failed, trying rmmod");
- if (system("rmmod gator >/dev/null 2>&1") != 0) {
- return -1;
- }
- }
- }
-
- return 0; // success
-}
-
-static struct cmdline_t parseCommandLine(int argc, char** argv) {
- struct cmdline_t cmdline;
- cmdline.port = DEFAULT_PORT;
- cmdline.module = NULL;
- char version_string[256]; // arbitrary length to hold the version information
- int c;
-
- // build the version string
- if (PROTOCOL_VERSION < PROTOCOL_DEV) {
- snprintf(version_string, sizeof(version_string), "Streamline gatord version %d (DS-5 v5.%d)", PROTOCOL_VERSION, PROTOCOL_VERSION);
- } else {
- snprintf(version_string, sizeof(version_string), "Streamline gatord development version %d", PROTOCOL_VERSION);
- }
-
- while ((c = getopt(argc, argv, "hvp:s:c:e:m:o:")) != -1) {
- switch(c) {
- case 'c':
- gSessionData->mConfigurationXMLPath = optarg;
- break;
- case 'e':
- gSessionData->mEventsXMLPath = optarg;
- break;
- case 'm':
- cmdline.module = optarg;
- break;
- case 'p':
- cmdline.port = strtol(optarg, NULL, 10);
- break;
- case 's':
- gSessionData->mSessionXMLPath = optarg;
- break;
- case 'o':
- gSessionData->mTargetPath = optarg;
- break;
- case 'h':
- case '?':
- logg->logError(__FILE__, __LINE__,
- "%s. All parameters are optional:\n"
- "-c config_xml path and filename of the configuration.xml to use\n"
- "-e events_xml path and filename of the events.xml to use\n"
- "-h this help page\n"
- "-m module path and filename of gator.ko\n"
- "-p port_number port upon which the server listens; default is 8080\n"
- "-s session_xml path and filename of a session xml used for local capture\n"
- "-o apc_dir path and name of the output for a local capture\n"
- "-v version information\n"
- , version_string);
- handleException();
- break;
- case 'v':
- logg->logError(__FILE__, __LINE__, version_string);
- handleException();
- break;
- }
- }
-
- // Error checking
- if (cmdline.port != DEFAULT_PORT && gSessionData->mSessionXMLPath != NULL) {
- logg->logError(__FILE__, __LINE__, "Only a port or a session xml can be specified, not both");
- handleException();
- }
-
- if (gSessionData->mTargetPath != NULL && gSessionData->mSessionXMLPath == NULL) {
- logg->logError(__FILE__, __LINE__, "Missing -s command line option required for a local capture.");
- handleException();
- }
-
- if (optind < argc) {
- logg->logError(__FILE__, __LINE__, "Unknown argument: %s. Use '-h' for help.", argv[optind]);
- handleException();
- }
-
- return cmdline;
-}
-
-// Gator data flow: collector -> collector fifo -> sender
-int main(int argc, char** argv) {
- // Ensure proper signal handling by making gatord the process group leader
- // e.g. it may not be the group leader when launched as 'sudo gatord'
- setsid();
-
- logg = new Logging(DEBUG); // Set up global thread-safe logging
- gSessionData = new SessionData(); // Global data class
- util = new OlyUtility(); // Set up global utility class
-
- // Initialize drivers
- new KMod();
-
- prctl(PR_SET_NAME, (unsigned long)&"gatord-main", 0, 0, 0);
- pthread_mutex_init(&numSessions_mutex, NULL);
-
- signal(SIGINT, handler);
- signal(SIGTERM, handler);
- signal(SIGABRT, handler);
-
- // Set to high priority
- if (setpriority(PRIO_PROCESS, syscall(__NR_gettid), -19) == -1) {
- logg->logMessage("setpriority() failed");
- }
-
- // Parse the command line parameters
- struct cmdline_t cmdline = parseCommandLine(argc, argv);
-
- // Verify root permissions
- uid_t euid = geteuid();
- if (euid) {
- logg->logError(__FILE__, __LINE__, "gatord must be launched with root privileges");
- handleException();
- }
-
- // Call before setting up the SIGCHLD handler, as system() spawns child processes
- if (!setupFilesystem(cmdline.module)) {
- logg->logMessage("Unable to setup gatorfs, trying perf");
- if (!gSessionData->perf.setup()) {
- logg->logError(__FILE__, __LINE__,
- "Unable to locate gator.ko driver:\n"
- " >>> gator.ko should be co-located with gatord in the same directory\n"
- " >>> OR insmod gator.ko prior to launching gatord\n"
- " >>> OR specify the location of gator.ko on the command line\n"
- " >>> OR run Linux 3.12 or later with perf support to collect data via userspace only");
- handleException();
- }
- }
-
- gSessionData->hwmon.setup();
-
- // Handle child exit codes
- signal(SIGCHLD, child_exit);
-
- // Ignore the SIGPIPE signal so that any send to a broken socket will return an error code instead of asserting a signal
- // Handling the error at the send function call is much easier than trying to do anything intelligent in the sig handler
- signal(SIGPIPE, SIG_IGN);
-
- // If the command line argument is a session xml file, no need to open a socket
- if (gSessionData->mSessionXMLPath) {
- child = new Child();
- child->run();
- delete child;
- } else {
- pthread_t answerThreadID;
- if (pthread_create(&answerThreadID, NULL, answerThread, &cmdline)) {
- logg->logError(__FILE__, __LINE__, "Failed to create answer thread");
- handleException();
- }
- sock = new OlyServerSocket(cmdline.port);
- // Forever loop, can be exited via a signal or exception
- while (1) {
- logg->logMessage("Waiting on connection...");
- OlySocket client(sock->acceptConnection());
-
- int pid = fork();
- if (pid < 0) {
- // Error
- logg->logError(__FILE__, __LINE__, "Fork process failed. Please power cycle the target device if this error persists.");
- } else if (pid == 0) {
- // Child
- sock->closeServerSocket();
- child = new Child(&client, numSessions + 1);
- child->run();
- delete child;
- exit(0);
- } else {
- // Parent
- client.closeSocket();
-
- pthread_mutex_lock(&numSessions_mutex);
- numSessions++;
- pthread_mutex_unlock(&numSessions_mutex);
-
- // Maximum number of connections is 2
- int wait = 0;
- while (numSessions > 1) {
- // Throttle until one of the children exits before continuing to accept another socket connection
- logg->logMessage("%d sessions active!", numSessions);
- if (wait++ >= 10) { // Wait no more than 10 seconds
- // Kill last created child
- kill(pid, SIGALRM);
- break;
- }
- sleep(1);
- }
- }
- }
- }
-
- cleanUp();
- return 0;
-}
+++ /dev/null
- Mini-XML License
- September 18, 2010
-
-
-The Mini-XML library and included programs are provided under the
-terms of the GNU Library General Public License version 2 (LGPL2)
-with the following exceptions:
-
- 1. Static linking of applications to the Mini-XML library
-does not constitute a derivative work and does not require
-the author to provide source code for the application, use
-the shared Mini-XML libraries, or link their applications
-against a user-supplied version of Mini-XML.
-
-If you link the application to a modified version of
-Mini-XML, then the changes to Mini-XML must be provided
-under the terms of the LGPL2 in sections 1, 2, and 4.
-
- 2. You do not have to provide a copy of the Mini-XML license
-with programs that are linked to the Mini-XML library, nor
-do you have to identify the Mini-XML license in your
-program or documentation as required by section 6 of the
-LGPL2.
-
-
-\f GNU LIBRARY GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1991 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- [This is the first released version of the library GPL. It is
- numbered 2 because it goes with version 2 of the ordinary GPL.]
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
- This license, the Library General Public License, applies to some
-specially designated Free Software Foundation software, and to any
-other libraries whose authors decide to use it. You can use it for
-your libraries, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if
-you distribute copies of the library, or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link a program with the library, you must provide
-complete object files to the recipients so that they can relink them
-with the library, after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
-
- Our method of protecting your rights has two steps: (1) copyright
-the library, and (2) offer you this license which gives you legal
-permission to copy, distribute and/or modify the library.
-
- Also, for each distributor's protection, we want to make certain
-that everyone understands that there is no warranty for this free
-library. If the library is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original
-version, so that any problems introduced by others will not reflect on
-the original authors' reputations.
-\f
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that companies distributing free
-software will individually obtain patent licenses, thus in effect
-transforming the program into proprietary software. To prevent this,
-we have made it clear that any patent must be licensed for everyone's
-free use or not licensed at all.
-
- Most GNU software, including some libraries, is covered by the ordinary
-GNU General Public License, which was designed for utility programs. This
-license, the GNU Library General Public License, applies to certain
-designated libraries. This license is quite different from the ordinary
-one; be sure to read it in full, and don't assume that anything in it is
-the same as in the ordinary license.
-
- The reason we have a separate public license for some libraries is that
-they blur the distinction we usually make between modifying or adding to a
-program and simply using it. Linking a program with a library, without
-changing the library, is in some sense simply using the library, and is
-analogous to running a utility program or application program. However, in
-a textual and legal sense, the linked executable is a combined work, a
-derivative of the original library, and the ordinary General Public License
-treats it as such.
-
- Because of this blurred distinction, using the ordinary General
-Public License for libraries did not effectively promote software
-sharing, because most developers did not use the libraries. We
-concluded that weaker conditions might promote sharing better.
-
- However, unrestricted linking of non-free programs would deprive the
-users of those programs of all benefit from the free status of the
-libraries themselves. This Library General Public License is intended to
-permit developers of non-free programs to use free libraries, while
-preserving your freedom as a user of such programs to change the free
-libraries that are incorporated in them. (We have not seen how to achieve
-this as regards changes in header files, but we have achieved it as regards
-changes in the actual functions of the Library.) The hope is that this
-will lead to faster development of free libraries.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, while the latter only
-works together with the library.
-
- Note that it is possible for a library to be covered by the ordinary
-General Public License rather than by this special one.
-\f
- GNU LIBRARY GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library which
-contains a notice placed by the copyright holder or other authorized
-party saying it may be distributed under the terms of this Library
-General Public License (also called "this License"). Each licensee is
-addressed as "you".
-
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
-
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-\f
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) The modified work must itself be a software library.
-
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
-these notices.
-\f
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
-
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-\f
- 6. As an exception to the Sections above, you may also compile or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
-of these things:
-
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
-
- b) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
-
- c) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
-
- d) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the source code distributed need not include anything that is normally
-distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-\f
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-\f
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded. In such case, this License incorporates the limitation as if
-written in the body of this License.
-
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Library General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-\f
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
- END OF TERMS AND CONDITIONS
-\f
- Appendix: How to Apply These Terms to Your New Libraries
-
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
- To apply these terms, attach the following notices to the library. It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
- <one line to give the library's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
- <signature of Ty Coon>, 1 April 1990
- Ty Coon, President of Vice
-
-That's all there is to it!
+++ /dev/null
-/* config.h. Generated from config.h.in by configure. */
-/*
- * "$Id: config.h.in 408 2010-09-19 05:26:46Z mike $"
- *
- * Configuration file for Mini-XML, a small XML-like file parsing library.
- *
- * Copyright 2003-2010 by Michael R Sweet.
- *
- * These coded instructions, statements, and computer programs are the
- * property of Michael R Sweet and are protected by Federal copyright
- * law. Distribution and use rights are outlined in the file "COPYING"
- * which should have been included with this file. If this file is
- * missing or damaged, see the license at:
- *
- * http://www.minixml.org/
- */
-
-/*
- * Include necessary headers...
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <ctype.h>
-
-
-/*
- * Version number...
- */
-
-#define MXML_VERSION "Mini-XML v2.7"
-
-
-/*
- * Inline function support...
- */
-
-#define inline
-
-
-/*
- * Long long support...
- */
-
-#define HAVE_LONG_LONG 1
-
-
-/*
- * Do we have the snprintf() and vsnprintf() functions?
- */
-
-#define HAVE_SNPRINTF 1
-#define HAVE_VSNPRINTF 1
-
-
-/*
- * Do we have the strXXX() functions?
- */
-
-#define HAVE_STRDUP 1
-
-
-/*
- * Do we have threading support?
- */
-
-#define HAVE_PTHREAD_H 1
-
-
-/*
- * Define prototypes for string functions as needed...
- */
-
-# ifndef HAVE_STRDUP
-extern char *_mxml_strdup(const char *);
-# define strdup _mxml_strdup
-# endif /* !HAVE_STRDUP */
-
-extern char *_mxml_strdupf(const char *, ...);
-extern char *_mxml_vstrdupf(const char *, va_list);
-
-# ifndef HAVE_SNPRINTF
-extern int _mxml_snprintf(char *, size_t, const char *, ...);
-# define snprintf _mxml_snprintf
-# endif /* !HAVE_SNPRINTF */
-
-# ifndef HAVE_VSNPRINTF
-extern int _mxml_vsnprintf(char *, size_t, const char *, va_list);
-# define vsnprintf _mxml_vsnprintf
-# endif /* !HAVE_VSNPRINTF */
-
-/*
- * End of "$Id: config.h.in 408 2010-09-19 05:26:46Z mike $".
- */
+++ /dev/null
-/*
- * "$Id: mxml-attr.c 408 2010-09-19 05:26:46Z mike $"
- *
- * Attribute support code for Mini-XML, a small XML-like file parsing library.
- *
- * Copyright 2003-2010 by Michael R Sweet.
- *
- * These coded instructions, statements, and computer programs are the
- * property of Michael R Sweet and are protected by Federal copyright
- * law. Distribution and use rights are outlined in the file "COPYING"
- * which should have been included with this file. If this file is
- * missing or damaged, see the license at:
- *
- * http://www.minixml.org/
- *
- * Contents:
- *
- * mxmlElementDeleteAttr() - Delete an attribute.
- * mxmlElementGetAttr() - Get an attribute.
- * mxmlElementSetAttr() - Set an attribute.
- * mxmlElementSetAttrf() - Set an attribute with a formatted value.
- * mxml_set_attr() - Set or add an attribute name/value pair.
- */
-
-/*
- * Include necessary headers...
- */
-
-#include "config.h"
-#include "mxml.h"
-
-
-/*
- * Local functions...
- */
-
-static int mxml_set_attr(mxml_node_t *node, const char *name,
- char *value);
-
-
-/*
- * 'mxmlElementDeleteAttr()' - Delete an attribute.
- *
- * @since Mini-XML 2.4@
- */
-
-void
-mxmlElementDeleteAttr(mxml_node_t *node,/* I - Element */
- const char *name)/* I - Attribute name */
-{
- int i; /* Looping var */
- mxml_attr_t *attr; /* Cirrent attribute */
-
-
-#ifdef DEBUG
- fprintf(stderr, "mxmlElementDeleteAttr(node=%p, name=\"%s\")\n",
- node, name ? name : "(null)");
-#endif /* DEBUG */
-
- /*
- * Range check input...
- */
-
- if (!node || node->type != MXML_ELEMENT || !name)
- return;
-
- /*
- * Look for the attribute...
- */
-
- for (i = node->value.element.num_attrs, attr = node->value.element.attrs;
- i > 0;
- i --, attr ++)
- {
-#ifdef DEBUG
- printf(" %s=\"%s\"\n", attr->name, attr->value);
-#endif /* DEBUG */
-
- if (!strcmp(attr->name, name))
- {
- /*
- * Delete this attribute...
- */
-
- free(attr->name);
- free(attr->value);
-
- i --;
- if (i > 0)
- memmove(attr, attr + 1, i * sizeof(mxml_attr_t));
-
- node->value.element.num_attrs --;
- return;
- }
- }
-}
-
-
-/*
- * 'mxmlElementGetAttr()' - Get an attribute.
- *
- * This function returns NULL if the node is not an element or the
- * named attribute does not exist.
- */
-
-const char * /* O - Attribute value or NULL */
-mxmlElementGetAttr(mxml_node_t *node, /* I - Element node */
- const char *name) /* I - Name of attribute */
-{
- int i; /* Looping var */
- mxml_attr_t *attr; /* Cirrent attribute */
-
-
-#ifdef DEBUG
- fprintf(stderr, "mxmlElementGetAttr(node=%p, name=\"%s\")\n",
- node, name ? name : "(null)");
-#endif /* DEBUG */
-
- /*
- * Range check input...
- */
-
- if (!node || node->type != MXML_ELEMENT || !name)
- return (NULL);
-
- /*
- * Look for the attribute...
- */
-
- for (i = node->value.element.num_attrs, attr = node->value.element.attrs;
- i > 0;
- i --, attr ++)
- {
-#ifdef DEBUG
- printf(" %s=\"%s\"\n", attr->name, attr->value);
-#endif /* DEBUG */
-
- if (!strcmp(attr->name, name))
- {
-#ifdef DEBUG
- printf(" Returning \"%s\"!\n", attr->value);
-#endif /* DEBUG */
- return (attr->value);
- }
- }
-
- /*
- * Didn't find attribute, so return NULL...
- */
-
-#ifdef DEBUG
- puts(" Returning NULL!\n");
-#endif /* DEBUG */
-
- return (NULL);
-}
-
-
-/*
- * 'mxmlElementSetAttr()' - Set an attribute.
- *
- * If the named attribute already exists, the value of the attribute
- * is replaced by the new string value. The string value is copied
- * into the element node. This function does nothing if the node is
- * not an element.
- */
-
-void
-mxmlElementSetAttr(mxml_node_t *node, /* I - Element node */
- const char *name, /* I - Name of attribute */
- const char *value) /* I - Attribute value */
-{
- char *valuec; /* Copy of value */
-
-
-#ifdef DEBUG
- fprintf(stderr, "mxmlElementSetAttr(node=%p, name=\"%s\", value=\"%s\")\n",
- node, name ? name : "(null)", value ? value : "(null)");
-#endif /* DEBUG */
-
- /*
- * Range check input...
- */
-
- if (!node || node->type != MXML_ELEMENT || !name)
- return;
-
- if (value)
- valuec = strdup(value);
- else
- valuec = NULL;
-
- if (mxml_set_attr(node, name, valuec))
- free(valuec);
-}
-
-
-/*
- * 'mxmlElementSetAttrf()' - Set an attribute with a formatted value.
- *
- * If the named attribute already exists, the value of the attribute
- * is replaced by the new formatted string. The formatted string value is
- * copied into the element node. This function does nothing if the node
- * is not an element.
- *
- * @since Mini-XML 2.3@
- */
-
-void
-mxmlElementSetAttrf(mxml_node_t *node, /* I - Element node */
- const char *name, /* I - Name of attribute */
- const char *format,/* I - Printf-style attribute value */
- ...) /* I - Additional arguments as needed */
-{
- va_list ap; /* Argument pointer */
- char *value; /* Value */
-
-
-#ifdef DEBUG
- fprintf(stderr,
- "mxmlElementSetAttrf(node=%p, name=\"%s\", format=\"%s\", ...)\n",
- node, name ? name : "(null)", format ? format : "(null)");
-#endif /* DEBUG */
-
- /*
- * Range check input...
- */
-
- if (!node || node->type != MXML_ELEMENT || !name || !format)
- return;
-
- /*
- * Format the value...
- */
-
- va_start(ap, format);
- value = _mxml_vstrdupf(format, ap);
- va_end(ap);
-
- if (!value)
- mxml_error("Unable to allocate memory for attribute '%s' in element %s!",
- name, node->value.element.name);
- else if (mxml_set_attr(node, name, value))
- free(value);
-}
-
-
-/*
- * 'mxml_set_attr()' - Set or add an attribute name/value pair.
- */
-
-static int /* O - 0 on success, -1 on failure */
-mxml_set_attr(mxml_node_t *node, /* I - Element node */
- const char *name, /* I - Attribute name */
- char *value) /* I - Attribute value */
-{
- int i; /* Looping var */
- mxml_attr_t *attr; /* New attribute */
-
-
- /*
- * Look for the attribute...
- */
-
- for (i = node->value.element.num_attrs, attr = node->value.element.attrs;
- i > 0;
- i --, attr ++)
- if (!strcmp(attr->name, name))
- {
- /*
- * Free the old value as needed...
- */
-
- if (attr->value)
- free(attr->value);
-
- attr->value = value;
-
- return (0);
- }
-
- /*
- * Add a new attribute...
- */
-
- if (node->value.element.num_attrs == 0)
- attr = malloc(sizeof(mxml_attr_t));
- else
- attr = realloc(node->value.element.attrs,
- (node->value.element.num_attrs + 1) * sizeof(mxml_attr_t));
-
- if (!attr)
- {
- mxml_error("Unable to allocate memory for attribute '%s' in element %s!",
- name, node->value.element.name);
- return (-1);
- }
-
- node->value.element.attrs = attr;
- attr += node->value.element.num_attrs;
-
- if ((attr->name = strdup(name)) == NULL)
- {
- mxml_error("Unable to allocate memory for attribute '%s' in element %s!",
- name, node->value.element.name);
- return (-1);
- }
-
- attr->value = value;
-
- node->value.element.num_attrs ++;
-
- return (0);
-}
-
-
-/*
- * End of "$Id: mxml-attr.c 408 2010-09-19 05:26:46Z mike $".
- */
+++ /dev/null
-/*
- * "$Id: mxml-entity.c 408 2010-09-19 05:26:46Z mike $"
- *
- * Character entity support code for Mini-XML, a small XML-like
- * file parsing library.
- *
- * Copyright 2003-2010 by Michael R Sweet.
- *
- * These coded instructions, statements, and computer programs are the
- * property of Michael R Sweet and are protected by Federal copyright
- * law. Distribution and use rights are outlined in the file "COPYING"
- * which should have been included with this file. If this file is
- * missing or damaged, see the license at:
- *
- * http://www.minixml.org/
- *
- * Contents:
- *
- * mxmlEntityAddCallback() - Add a callback to convert entities to
- * Unicode.
- * mxmlEntityGetName() - Get the name that corresponds to the
- * character value.
- * mxmlEntityGetValue() - Get the character corresponding to a named
- * entity.
- * mxmlEntityRemoveCallback() - Remove a callback.
- * _mxml_entity_cb() - Lookup standard (X)HTML entities.
- */
-
-/*
- * Include necessary headers...
- */
-
-#include "mxml-private.h"
-
-
-/*
- * 'mxmlEntityAddCallback()' - Add a callback to convert entities to Unicode.
- */
-
-int /* O - 0 on success, -1 on failure */
-mxmlEntityAddCallback(
- mxml_entity_cb_t cb) /* I - Callback function to add */
-{
- _mxml_global_t *global = _mxml_global();
- /* Global data */
-
-
- if (global->num_entity_cbs < (int)(sizeof(global->entity_cbs) / sizeof(global->entity_cbs[0])))
- {
- global->entity_cbs[global->num_entity_cbs] = cb;
- global->num_entity_cbs ++;
-
- return (0);
- }
- else
- {
- mxml_error("Unable to add entity callback!");
-
- return (-1);
- }
-}
-
-
-/*
- * 'mxmlEntityGetName()' - Get the name that corresponds to the character value.
- *
- * If val does not need to be represented by a named entity, NULL is returned.
- */
-
-const char * /* O - Entity name or NULL */
-mxmlEntityGetName(int val) /* I - Character value */
-{
- switch (val)
- {
- case '&' :
- return ("amp");
-
- case '<' :
- return ("lt");
-
- case '>' :
- return ("gt");
-
- case '\"' :
- return ("quot");
-
- default :
- return (NULL);
- }
-}
-
-
-/*
- * 'mxmlEntityGetValue()' - Get the character corresponding to a named entity.
- *
- * The entity name can also be a numeric constant. -1 is returned if the
- * name is not known.
- */
-
-int /* O - Character value or -1 on error */
-mxmlEntityGetValue(const char *name) /* I - Entity name */
-{
- int i; /* Looping var */
- int ch; /* Character value */
- _mxml_global_t *global = _mxml_global();
- /* Global data */
-
-
- for (i = 0; i < global->num_entity_cbs; i ++)
- if ((ch = (global->entity_cbs[i])(name)) >= 0)
- return (ch);
-
- return (-1);
-}
-
-
-/*
- * 'mxmlEntityRemoveCallback()' - Remove a callback.
- */
-
-void
-mxmlEntityRemoveCallback(
- mxml_entity_cb_t cb) /* I - Callback function to remove */
-{
- int i; /* Looping var */
- _mxml_global_t *global = _mxml_global();
- /* Global data */
-
-
- for (i = 0; i < global->num_entity_cbs; i ++)
- if (cb == global->entity_cbs[i])
- {
- /*
- * Remove the callback...
- */
-
- global->num_entity_cbs --;
-
- if (i < global->num_entity_cbs)
- memmove(global->entity_cbs + i, global->entity_cbs + i + 1,
- (global->num_entity_cbs - i) * sizeof(global->entity_cbs[0]));
-
- return;
- }
-}
-
-
-/*
- * '_mxml_entity_cb()' - Lookup standard (X)HTML entities.
- */
-
-int /* O - Unicode value or -1 */
-_mxml_entity_cb(const char *name) /* I - Entity name */
-{
- int diff, /* Difference between names */
- current, /* Current entity in search */
- first, /* First entity in search */
- last; /* Last entity in search */
- static const struct
- {
- const char *name; /* Entity name */
- int val; /* Character value */
- } entities[] =
- {
- { "AElig", 198 },
- { "Aacute", 193 },
- { "Acirc", 194 },
- { "Agrave", 192 },
- { "Alpha", 913 },
- { "Aring", 197 },
- { "Atilde", 195 },
- { "Auml", 196 },
- { "Beta", 914 },
- { "Ccedil", 199 },
- { "Chi", 935 },
- { "Dagger", 8225 },
- { "Delta", 916 },
- { "Dstrok", 208 },
- { "ETH", 208 },
- { "Eacute", 201 },
- { "Ecirc", 202 },
- { "Egrave", 200 },
- { "Epsilon", 917 },
- { "Eta", 919 },
- { "Euml", 203 },
- { "Gamma", 915 },
- { "Iacute", 205 },
- { "Icirc", 206 },
- { "Igrave", 204 },
- { "Iota", 921 },
- { "Iuml", 207 },
- { "Kappa", 922 },
- { "Lambda", 923 },
- { "Mu", 924 },
- { "Ntilde", 209 },
- { "Nu", 925 },
- { "OElig", 338 },
- { "Oacute", 211 },
- { "Ocirc", 212 },
- { "Ograve", 210 },
- { "Omega", 937 },
- { "Omicron", 927 },
- { "Oslash", 216 },
- { "Otilde", 213 },
- { "Ouml", 214 },
- { "Phi", 934 },
- { "Pi", 928 },
- { "Prime", 8243 },
- { "Psi", 936 },
- { "Rho", 929 },
- { "Scaron", 352 },
- { "Sigma", 931 },
- { "THORN", 222 },
- { "Tau", 932 },
- { "Theta", 920 },
- { "Uacute", 218 },
- { "Ucirc", 219 },
- { "Ugrave", 217 },
- { "Upsilon", 933 },
- { "Uuml", 220 },
- { "Xi", 926 },
- { "Yacute", 221 },
- { "Yuml", 376 },
- { "Zeta", 918 },
- { "aacute", 225 },
- { "acirc", 226 },
- { "acute", 180 },
- { "aelig", 230 },
- { "agrave", 224 },
- { "alefsym", 8501 },
- { "alpha", 945 },
- { "amp", '&' },
- { "and", 8743 },
- { "ang", 8736 },
- { "apos", '\'' },
- { "aring", 229 },
- { "asymp", 8776 },
- { "atilde", 227 },
- { "auml", 228 },
- { "bdquo", 8222 },
- { "beta", 946 },
- { "brkbar", 166 },
- { "brvbar", 166 },
- { "bull", 8226 },
- { "cap", 8745 },
- { "ccedil", 231 },
- { "cedil", 184 },
- { "cent", 162 },
- { "chi", 967 },
- { "circ", 710 },
- { "clubs", 9827 },
- { "cong", 8773 },
- { "copy", 169 },
- { "crarr", 8629 },
- { "cup", 8746 },
- { "curren", 164 },
- { "dArr", 8659 },
- { "dagger", 8224 },
- { "darr", 8595 },
- { "deg", 176 },
- { "delta", 948 },
- { "diams", 9830 },
- { "die", 168 },
- { "divide", 247 },
- { "eacute", 233 },
- { "ecirc", 234 },
- { "egrave", 232 },
- { "empty", 8709 },
- { "emsp", 8195 },
- { "ensp", 8194 },
- { "epsilon", 949 },
- { "equiv", 8801 },
- { "eta", 951 },
- { "eth", 240 },
- { "euml", 235 },
- { "euro", 8364 },
- { "exist", 8707 },
- { "fnof", 402 },
- { "forall", 8704 },
- { "frac12", 189 },
- { "frac14", 188 },
- { "frac34", 190 },
- { "frasl", 8260 },
- { "gamma", 947 },
- { "ge", 8805 },
- { "gt", '>' },
- { "hArr", 8660 },
- { "harr", 8596 },
- { "hearts", 9829 },
- { "hellip", 8230 },
- { "hibar", 175 },
- { "iacute", 237 },
- { "icirc", 238 },
- { "iexcl", 161 },
- { "igrave", 236 },
- { "image", 8465 },
- { "infin", 8734 },
- { "int", 8747 },
- { "iota", 953 },
- { "iquest", 191 },
- { "isin", 8712 },
- { "iuml", 239 },
- { "kappa", 954 },
- { "lArr", 8656 },
- { "lambda", 955 },
- { "lang", 9001 },
- { "laquo", 171 },
- { "larr", 8592 },
- { "lceil", 8968 },
- { "ldquo", 8220 },
- { "le", 8804 },
- { "lfloor", 8970 },
- { "lowast", 8727 },
- { "loz", 9674 },
- { "lrm", 8206 },
- { "lsaquo", 8249 },
- { "lsquo", 8216 },
- { "lt", '<' },
- { "macr", 175 },
- { "mdash", 8212 },
- { "micro", 181 },
- { "middot", 183 },
- { "minus", 8722 },
- { "mu", 956 },
- { "nabla", 8711 },
- { "nbsp", 160 },
- { "ndash", 8211 },
- { "ne", 8800 },
- { "ni", 8715 },
- { "not", 172 },
- { "notin", 8713 },
- { "nsub", 8836 },
- { "ntilde", 241 },
- { "nu", 957 },
- { "oacute", 243 },
- { "ocirc", 244 },
- { "oelig", 339 },
- { "ograve", 242 },
- { "oline", 8254 },
- { "omega", 969 },
- { "omicron", 959 },
- { "oplus", 8853 },
- { "or", 8744 },
- { "ordf", 170 },
- { "ordm", 186 },
- { "oslash", 248 },
- { "otilde", 245 },
- { "otimes", 8855 },
- { "ouml", 246 },
- { "para", 182 },
- { "part", 8706 },
- { "permil", 8240 },
- { "perp", 8869 },
- { "phi", 966 },
- { "pi", 960 },
- { "piv", 982 },
- { "plusmn", 177 },
- { "pound", 163 },
- { "prime", 8242 },
- { "prod", 8719 },
- { "prop", 8733 },
- { "psi", 968 },
- { "quot", '\"' },
- { "rArr", 8658 },
- { "radic", 8730 },
- { "rang", 9002 },
- { "raquo", 187 },
- { "rarr", 8594 },
- { "rceil", 8969 },
- { "rdquo", 8221 },
- { "real", 8476 },
- { "reg", 174 },
- { "rfloor", 8971 },
- { "rho", 961 },
- { "rlm", 8207 },
- { "rsaquo", 8250 },
- { "rsquo", 8217 },
- { "sbquo", 8218 },
- { "scaron", 353 },
- { "sdot", 8901 },
- { "sect", 167 },
- { "shy", 173 },
- { "sigma", 963 },
- { "sigmaf", 962 },
- { "sim", 8764 },
- { "spades", 9824 },
- { "sub", 8834 },
- { "sube", 8838 },
- { "sum", 8721 },
- { "sup", 8835 },
- { "sup1", 185 },
- { "sup2", 178 },
- { "sup3", 179 },
- { "supe", 8839 },
- { "szlig", 223 },
- { "tau", 964 },
- { "there4", 8756 },
- { "theta", 952 },
- { "thetasym", 977 },
- { "thinsp", 8201 },
- { "thorn", 254 },
- { "tilde", 732 },
- { "times", 215 },
- { "trade", 8482 },
- { "uArr", 8657 },
- { "uacute", 250 },
- { "uarr", 8593 },
- { "ucirc", 251 },
- { "ugrave", 249 },
- { "uml", 168 },
- { "upsih", 978 },
- { "upsilon", 965 },
- { "uuml", 252 },
- { "weierp", 8472 },
- { "xi", 958 },
- { "yacute", 253 },
- { "yen", 165 },
- { "yuml", 255 },
- { "zeta", 950 },
- { "zwj", 8205 },
- { "zwnj", 8204 }
- };
-
-
- /*
- * Do a binary search for the named entity...
- */
-
- first = 0;
- last = (int)(sizeof(entities) / sizeof(entities[0]) - 1);
-
- while ((last - first) > 1)
- {
- current = (first + last) / 2;
-
- if ((diff = strcmp(name, entities[current].name)) == 0)
- return (entities[current].val);
- else if (diff < 0)
- last = current;
- else
- first = current;
- }
-
- /*
- * If we get here, there is a small chance that there is still
- * a match; check first and last...
- */
-
- if (!strcmp(name, entities[first].name))
- return (entities[first].val);
- else if (!strcmp(name, entities[last].name))
- return (entities[last].val);
- else
- return (-1);
-}
-
-
-/*
- * End of "$Id: mxml-entity.c 408 2010-09-19 05:26:46Z mike $".
- */
+++ /dev/null
-/*
- * "$Id: mxml-file.c 438 2011-03-24 05:47:51Z mike $"
- *
- * File loading code for Mini-XML, a small XML-like file parsing library.
- *
- * Copyright 2003-2011 by Michael R Sweet.
- *
- * These coded instructions, statements, and computer programs are the
- * property of Michael R Sweet and are protected by Federal copyright
- * law. Distribution and use rights are outlined in the file "COPYING"
- * which should have been included with this file. If this file is
- * missing or damaged, see the license at:
- *
- * http://www.minixml.org/
- *
- * Contents:
- *
- * mxmlLoadFd() - Load a file descriptor into an XML node tree.
- * mxmlLoadFile() - Load a file into an XML node tree.
- * mxmlLoadString() - Load a string into an XML node tree.
- * mxmlSaveAllocString() - Save an XML tree to an allocated string.
- * mxmlSaveFd() - Save an XML tree to a file descriptor.
- * mxmlSaveFile() - Save an XML tree to a file.
- * mxmlSaveString() - Save an XML node tree to a string.
- * mxmlSAXLoadFd() - Load a file descriptor into an XML node tree
- * using a SAX callback.
- * mxmlSAXLoadFile() - Load a file into an XML node tree
- * using a SAX callback.
- * mxmlSAXLoadString() - Load a string into an XML node tree
- * using a SAX callback.
- * mxmlSetCustomHandlers() - Set the handling functions for custom data.
- * mxmlSetErrorCallback() - Set the error message callback.
- * mxmlSetWrapMargin() - Set the wrap margin when saving XML data.
- * mxml_add_char() - Add a character to a buffer, expanding as needed.
- * mxml_fd_getc() - Read a character from a file descriptor.
- * mxml_fd_putc() - Write a character to a file descriptor.
- * mxml_fd_read() - Read a buffer of data from a file descriptor.
- * mxml_fd_write() - Write a buffer of data to a file descriptor.
- * mxml_file_getc() - Get a character from a file.
- * mxml_file_putc() - Write a character to a file.
- * mxml_get_entity() - Get the character corresponding to an entity...
- * mxml_load_data() - Load data into an XML node tree.
- * mxml_parse_element() - Parse an element for any attributes...
- * mxml_string_getc() - Get a character from a string.
- * mxml_string_putc() - Write a character to a string.
- * mxml_write_name() - Write a name string.
- * mxml_write_node() - Save an XML node to a file.
- * mxml_write_string() - Write a string, escaping & and < as needed.
- * mxml_write_ws() - Do whitespace callback...
- */
-
-/*
- * Include necessary headers...
- */
-
-#ifndef WIN32
-# include <unistd.h>
-#endif /* !WIN32 */
-#include "mxml-private.h"
-
-
-/*
- * Character encoding...
- */
-
-#define ENCODE_UTF8 0 /* UTF-8 */
-#define ENCODE_UTF16BE 1 /* UTF-16 Big-Endian */
-#define ENCODE_UTF16LE 2 /* UTF-16 Little-Endian */
-
-
-/*
- * Macro to test for a bad XML character...
- */
-
-#define mxml_bad_char(ch) ((ch) < ' ' && (ch) != '\n' && (ch) != '\r' && (ch) != '\t')
-
-
-/*
- * Types and structures...
- */
-
-typedef int (*_mxml_getc_cb_t)(void *, int *);
-typedef int (*_mxml_putc_cb_t)(int, void *);
-
-typedef struct _mxml_fdbuf_s /**** File descriptor buffer ****/
-{
- int fd; /* File descriptor */
- unsigned char *current, /* Current position in buffer */
- *end, /* End of buffer */
- buffer[8192]; /* Character buffer */
-} _mxml_fdbuf_t;
-
-
-/*
- * Local functions...
- */
-
-static int mxml_add_char(int ch, char **ptr, char **buffer,
- int *bufsize);
-static int mxml_fd_getc(void *p, int *encoding);
-static int mxml_fd_putc(int ch, void *p);
-static int mxml_fd_read(_mxml_fdbuf_t *buf);
-static int mxml_fd_write(_mxml_fdbuf_t *buf);
-static int mxml_file_getc(void *p, int *encoding);
-static int mxml_file_putc(int ch, void *p);
-static int mxml_get_entity(mxml_node_t *parent, void *p,
- int *encoding,
- _mxml_getc_cb_t getc_cb);
-static inline int mxml_isspace(int ch)
- {
- return (ch == ' ' || ch == '\t' || ch == '\r' ||
- ch == '\n');
- }
-static mxml_node_t *mxml_load_data(mxml_node_t *top, void *p,
- mxml_load_cb_t cb,
- _mxml_getc_cb_t getc_cb,
- mxml_sax_cb_t sax_cb, void *sax_data);
-static int mxml_parse_element(mxml_node_t *node, void *p,
- int *encoding,
- _mxml_getc_cb_t getc_cb);
-static int mxml_string_getc(void *p, int *encoding);
-static int mxml_string_putc(int ch, void *p);
-static int mxml_write_name(const char *s, void *p,
- _mxml_putc_cb_t putc_cb);
-static int mxml_write_node(mxml_node_t *node, void *p,
- mxml_save_cb_t cb, int col,
- _mxml_putc_cb_t putc_cb,
- _mxml_global_t *global);
-static int mxml_write_string(const char *s, void *p,
- _mxml_putc_cb_t putc_cb);
-static int mxml_write_ws(mxml_node_t *node, void *p,
- mxml_save_cb_t cb, int ws,
- int col, _mxml_putc_cb_t putc_cb);
-
-
-/*
- * 'mxmlLoadFd()' - Load a file descriptor into an XML node tree.
- *
- * The nodes in the specified file are added to the specified top node.
- * If no top node is provided, the XML file MUST be well-formed with a
- * single parent node like <?xml> for the entire file. The callback
- * function returns the value type that should be used for child nodes.
- * If MXML_NO_CALLBACK is specified then all child nodes will be either
- * MXML_ELEMENT or MXML_TEXT nodes.
- *
- * The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK,
- * MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading
- * child nodes of the specified type.
- */
-
-mxml_node_t * /* O - First node or NULL if the file could not be read. */
-mxmlLoadFd(mxml_node_t *top, /* I - Top node */
- int fd, /* I - File descriptor to read from */
- mxml_load_cb_t cb) /* I - Callback function or MXML_NO_CALLBACK */
-{
- _mxml_fdbuf_t buf; /* File descriptor buffer */
-
-
- /*
- * Initialize the file descriptor buffer...
- */
-
- buf.fd = fd;
- buf.current = buf.buffer;
- buf.end = buf.buffer;
-
- /*
- * Read the XML data...
- */
-
- return (mxml_load_data(top, &buf, cb, mxml_fd_getc, MXML_NO_CALLBACK, NULL));
-}
-
-
-/*
- * 'mxmlLoadFile()' - Load a file into an XML node tree.
- *
- * The nodes in the specified file are added to the specified top node.
- * If no top node is provided, the XML file MUST be well-formed with a
- * single parent node like <?xml> for the entire file. The callback
- * function returns the value type that should be used for child nodes.
- * If MXML_NO_CALLBACK is specified then all child nodes will be either
- * MXML_ELEMENT or MXML_TEXT nodes.
- *
- * The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK,
- * MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading
- * child nodes of the specified type.
- */
-
-mxml_node_t * /* O - First node or NULL if the file could not be read. */
-mxmlLoadFile(mxml_node_t *top, /* I - Top node */
- FILE *fp, /* I - File to read from */
- mxml_load_cb_t cb) /* I - Callback function or MXML_NO_CALLBACK */
-{
- /*
- * Read the XML data...
- */
-
- return (mxml_load_data(top, fp, cb, mxml_file_getc, MXML_NO_CALLBACK, NULL));
-}
-
-
-/*
- * 'mxmlLoadString()' - Load a string into an XML node tree.
- *
- * The nodes in the specified string are added to the specified top node.
- * If no top node is provided, the XML string MUST be well-formed with a
- * single parent node like <?xml> for the entire string. The callback
- * function returns the value type that should be used for child nodes.
- * If MXML_NO_CALLBACK is specified then all child nodes will be either
- * MXML_ELEMENT or MXML_TEXT nodes.
- *
- * The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK,
- * MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading
- * child nodes of the specified type.
- */
-
-mxml_node_t * /* O - First node or NULL if the string has errors. */
-mxmlLoadString(mxml_node_t *top, /* I - Top node */
- const char *s, /* I - String to load */
- mxml_load_cb_t cb) /* I - Callback function or MXML_NO_CALLBACK */
-{
- /*
- * Read the XML data...
- */
-
- return (mxml_load_data(top, (void *)&s, cb, mxml_string_getc, MXML_NO_CALLBACK,
- NULL));
-}
-
-
-/*
- * 'mxmlSaveAllocString()' - Save an XML tree to an allocated string.
- *
- * This function returns a pointer to a string containing the textual
- * representation of the XML node tree. The string should be freed
- * using the free() function when you are done with it. NULL is returned
- * if the node would produce an empty string or if the string cannot be
- * allocated.
- *
- * The callback argument specifies a function that returns a whitespace
- * string or NULL before and after each element. If MXML_NO_CALLBACK
- * is specified, whitespace will only be added before MXML_TEXT nodes
- * with leading whitespace and before attribute names inside opening
- * element tags.
- */
-
-char * /* O - Allocated string or NULL */
-mxmlSaveAllocString(
- mxml_node_t *node, /* I - Node to write */
- mxml_save_cb_t cb) /* I - Whitespace callback or MXML_NO_CALLBACK */
-{
- int bytes; /* Required bytes */
- char buffer[8192]; /* Temporary buffer */
- char *s; /* Allocated string */
-
-
- /*
- * Write the node to the temporary buffer...
- */
-
- bytes = mxmlSaveString(node, buffer, sizeof(buffer), cb);
-
- if (bytes <= 0)
- return (NULL);
-
- if (bytes < (int)(sizeof(buffer) - 1))
- {
- /*
- * Node fit inside the buffer, so just duplicate that string and
- * return...
- */
-
- return (strdup(buffer));
- }
-
- /*
- * Allocate a buffer of the required size and save the node to the
- * new buffer...
- */
-
- if ((s = malloc(bytes + 1)) == NULL)
- return (NULL);
-
- mxmlSaveString(node, s, bytes + 1, cb);
-
- /*
- * Return the allocated string...
- */
-
- return (s);
-}
-
-
-/*
- * 'mxmlSaveFd()' - Save an XML tree to a file descriptor.
- *
- * The callback argument specifies a function that returns a whitespace
- * string or NULL before and after each element. If MXML_NO_CALLBACK
- * is specified, whitespace will only be added before MXML_TEXT nodes
- * with leading whitespace and before attribute names inside opening
- * element tags.
- */
-
-int /* O - 0 on success, -1 on error. */
-mxmlSaveFd(mxml_node_t *node, /* I - Node to write */
- int fd, /* I - File descriptor to write to */
- mxml_save_cb_t cb) /* I - Whitespace callback or MXML_NO_CALLBACK */
-{
- int col; /* Final column */
- _mxml_fdbuf_t buf; /* File descriptor buffer */
- _mxml_global_t *global = _mxml_global();
- /* Global data */
-
-
- /*
- * Initialize the file descriptor buffer...
- */
-
- buf.fd = fd;
- buf.current = buf.buffer;
- buf.end = buf.buffer + sizeof(buf.buffer);
-
- /*
- * Write the node...
- */
-
- if ((col = mxml_write_node(node, &buf, cb, 0, mxml_fd_putc, global)) < 0)
- return (-1);
-
- if (col > 0)
- if (mxml_fd_putc('\n', &buf) < 0)
- return (-1);
-
- /*
- * Flush and return...
- */
-
- return (mxml_fd_write(&buf));
-}
-
-
-/*
- * 'mxmlSaveFile()' - Save an XML tree to a file.
- *
- * The callback argument specifies a function that returns a whitespace
- * string or NULL before and after each element. If MXML_NO_CALLBACK
- * is specified, whitespace will only be added before MXML_TEXT nodes
- * with leading whitespace and before attribute names inside opening
- * element tags.
- */
-
-int /* O - 0 on success, -1 on error. */
-mxmlSaveFile(mxml_node_t *node, /* I - Node to write */
- FILE *fp, /* I - File to write to */
- mxml_save_cb_t cb) /* I - Whitespace callback or MXML_NO_CALLBACK */
-{
- int col; /* Final column */
- _mxml_global_t *global = _mxml_global();
- /* Global data */
-
-
- /*
- * Write the node...
- */
-
- if ((col = mxml_write_node(node, fp, cb, 0, mxml_file_putc, global)) < 0)
- return (-1);
-
- if (col > 0)
- if (putc('\n', fp) < 0)
- return (-1);
-
- /*
- * Return 0 (success)...
- */
-
- return (0);
-}
-
-
-/*
- * 'mxmlSaveString()' - Save an XML node tree to a string.
- *
- * This function returns the total number of bytes that would be
- * required for the string but only copies (bufsize - 1) characters
- * into the specified buffer.
- *
- * The callback argument specifies a function that returns a whitespace
- * string or NULL before and after each element. If MXML_NO_CALLBACK
- * is specified, whitespace will only be added before MXML_TEXT nodes
- * with leading whitespace and before attribute names inside opening
- * element tags.
- */
-
-int /* O - Size of string */
-mxmlSaveString(mxml_node_t *node, /* I - Node to write */
- char *buffer, /* I - String buffer */
- int bufsize, /* I - Size of string buffer */
- mxml_save_cb_t cb) /* I - Whitespace callback or MXML_NO_CALLBACK */
-{
- int col; /* Final column */
- char *ptr[2]; /* Pointers for putc_cb */
- _mxml_global_t *global = _mxml_global();
- /* Global data */
-
-
- /*
- * Write the node...
- */
-
- ptr[0] = buffer;
- ptr[1] = buffer + bufsize;
-
- if ((col = mxml_write_node(node, ptr, cb, 0, mxml_string_putc, global)) < 0)
- return (-1);
-
- if (col > 0)
- mxml_string_putc('\n', ptr);
-
- /*
- * Nul-terminate the buffer...
- */
-
- if (ptr[0] >= ptr[1])
- buffer[bufsize - 1] = '\0';
- else
- ptr[0][0] = '\0';
-
- /*
- * Return the number of characters...
- */
-
- return (ptr[0] - buffer);
-}
-
-
-/*
- * 'mxmlSAXLoadFd()' - Load a file descriptor into an XML node tree
- * using a SAX callback.
- *
- * The nodes in the specified file are added to the specified top node.
- * If no top node is provided, the XML file MUST be well-formed with a
- * single parent node like <?xml> for the entire file. The callback
- * function returns the value type that should be used for child nodes.
- * If MXML_NO_CALLBACK is specified then all child nodes will be either
- * MXML_ELEMENT or MXML_TEXT nodes.
- *
- * The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK,
- * MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading
- * child nodes of the specified type.
- *
- * The SAX callback must call mxmlRetain() for any nodes that need to
- * be kept for later use. Otherwise, nodes are deleted when the parent
- * node is closed or after each data, comment, CDATA, or directive node.
- *
- * @since Mini-XML 2.3@
- */
-
-mxml_node_t * /* O - First node or NULL if the file could not be read. */
-mxmlSAXLoadFd(mxml_node_t *top, /* I - Top node */
- int fd, /* I - File descriptor to read from */
- mxml_load_cb_t cb, /* I - Callback function or MXML_NO_CALLBACK */
- mxml_sax_cb_t sax_cb, /* I - SAX callback or MXML_NO_CALLBACK */
- void *sax_data) /* I - SAX user data */
-{
- _mxml_fdbuf_t buf; /* File descriptor buffer */
-
-
- /*
- * Initialize the file descriptor buffer...
- */
-
- buf.fd = fd;
- buf.current = buf.buffer;
- buf.end = buf.buffer;
-
- /*
- * Read the XML data...
- */
-
- return (mxml_load_data(top, &buf, cb, mxml_fd_getc, sax_cb, sax_data));
-}
-
-
-/*
- * 'mxmlSAXLoadFile()' - Load a file into an XML node tree
- * using a SAX callback.
- *
- * The nodes in the specified file are added to the specified top node.
- * If no top node is provided, the XML file MUST be well-formed with a
- * single parent node like <?xml> for the entire file. The callback
- * function returns the value type that should be used for child nodes.
- * If MXML_NO_CALLBACK is specified then all child nodes will be either
- * MXML_ELEMENT or MXML_TEXT nodes.
- *
- * The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK,
- * MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading
- * child nodes of the specified type.
- *
- * The SAX callback must call mxmlRetain() for any nodes that need to
- * be kept for later use. Otherwise, nodes are deleted when the parent
- * node is closed or after each data, comment, CDATA, or directive node.
- *
- * @since Mini-XML 2.3@
- */
-
-mxml_node_t * /* O - First node or NULL if the file could not be read. */
-mxmlSAXLoadFile(
- mxml_node_t *top, /* I - Top node */
- FILE *fp, /* I - File to read from */
- mxml_load_cb_t cb, /* I - Callback function or MXML_NO_CALLBACK */
- mxml_sax_cb_t sax_cb, /* I - SAX callback or MXML_NO_CALLBACK */
- void *sax_data) /* I - SAX user data */
-{
- /*
- * Read the XML data...
- */
-
- return (mxml_load_data(top, fp, cb, mxml_file_getc, sax_cb, sax_data));
-}
-
-
-/*
- * 'mxmlSAXLoadString()' - Load a string into an XML node tree
- * using a SAX callback.
- *
- * The nodes in the specified string are added to the specified top node.
- * If no top node is provided, the XML string MUST be well-formed with a
- * single parent node like <?xml> for the entire string. The callback
- * function returns the value type that should be used for child nodes.
- * If MXML_NO_CALLBACK is specified then all child nodes will be either
- * MXML_ELEMENT or MXML_TEXT nodes.
- *
- * The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK,
- * MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading
- * child nodes of the specified type.
- *
- * The SAX callback must call mxmlRetain() for any nodes that need to
- * be kept for later use. Otherwise, nodes are deleted when the parent
- * node is closed or after each data, comment, CDATA, or directive node.
- *
- * @since Mini-XML 2.3@
- */
-
-mxml_node_t * /* O - First node or NULL if the string has errors. */
-mxmlSAXLoadString(
- mxml_node_t *top, /* I - Top node */
- const char *s, /* I - String to load */
- mxml_load_cb_t cb, /* I - Callback function or MXML_NO_CALLBACK */
- mxml_sax_cb_t sax_cb, /* I - SAX callback or MXML_NO_CALLBACK */
- void *sax_data) /* I - SAX user data */
-{
- /*
- * Read the XML data...
- */
-
- return (mxml_load_data(top, (void *)&s, cb, mxml_string_getc, sax_cb, sax_data));
-}
-
-
-/*
- * 'mxmlSetCustomHandlers()' - Set the handling functions for custom data.
- *
- * The load function accepts a node pointer and a data string and must
- * return 0 on success and non-zero on error.
- *
- * The save function accepts a node pointer and must return a malloc'd
- * string on success and NULL on error.
- *
- */
-
-void
-mxmlSetCustomHandlers(
- mxml_custom_load_cb_t load, /* I - Load function */
- mxml_custom_save_cb_t save) /* I - Save function */
-{
- _mxml_global_t *global = _mxml_global();
- /* Global data */
-
-
- global->custom_load_cb = load;
- global->custom_save_cb = save;
-}
-
-
-/*
- * 'mxmlSetErrorCallback()' - Set the error message callback.
- */
-
-void
-mxmlSetErrorCallback(mxml_error_cb_t cb)/* I - Error callback function */
-{
- _mxml_global_t *global = _mxml_global();
- /* Global data */
-
-
- global->error_cb = cb;
-}
-
-
-/*
- * 'mxmlSetWrapMargin()' - Set the wrap margin when saving XML data.
- *
- * Wrapping is disabled when "column" is 0.
- *
- * @since Mini-XML 2.3@
- */
-
-void
-mxmlSetWrapMargin(int column) /* I - Column for wrapping, 0 to disable wrapping */
-{
- _mxml_global_t *global = _mxml_global();
- /* Global data */
-
-
- global->wrap = column;
-}
-
-
-/*
- * 'mxml_add_char()' - Add a character to a buffer, expanding as needed.
- */
-
-static int /* O - 0 on success, -1 on error */
-mxml_add_char(int ch, /* I - Character to add */
- char **bufptr, /* IO - Current position in buffer */
- char **buffer, /* IO - Current buffer */
- int *bufsize) /* IO - Current buffer size */
-{
- char *newbuffer; /* New buffer value */
-
-
- if (*bufptr >= (*buffer + *bufsize - 4))
- {
- /*
- * Increase the size of the buffer...
- */
-
- if (*bufsize < 1024)
- (*bufsize) *= 2;
- else
- (*bufsize) += 1024;
-
- if ((newbuffer = realloc(*buffer, *bufsize)) == NULL)
- {
- free(*buffer);
-
- mxml_error("Unable to expand string buffer to %d bytes!", *bufsize);
-
- return (-1);
- }
-
- *bufptr = newbuffer + (*bufptr - *buffer);
- *buffer = newbuffer;
- }
-
- if (ch < 0x80)
- {
- /*
- * Single byte ASCII...
- */
-
- *(*bufptr)++ = ch;
- }
- else if (ch < 0x800)
- {
- /*
- * Two-byte UTF-8...
- */
-
- *(*bufptr)++ = 0xc0 | (ch >> 6);
- *(*bufptr)++ = 0x80 | (ch & 0x3f);
- }
- else if (ch < 0x10000)
- {
- /*
- * Three-byte UTF-8...
- */
-
- *(*bufptr)++ = 0xe0 | (ch >> 12);
- *(*bufptr)++ = 0x80 | ((ch >> 6) & 0x3f);
- *(*bufptr)++ = 0x80 | (ch & 0x3f);
- }
- else
- {
- /*
- * Four-byte UTF-8...
- */
-
- *(*bufptr)++ = 0xf0 | (ch >> 18);
- *(*bufptr)++ = 0x80 | ((ch >> 12) & 0x3f);
- *(*bufptr)++ = 0x80 | ((ch >> 6) & 0x3f);
- *(*bufptr)++ = 0x80 | (ch & 0x3f);
- }
-
- return (0);
-}
-
-
-/*
- * 'mxml_fd_getc()' - Read a character from a file descriptor.
- */
-
-static int /* O - Character or EOF */
-mxml_fd_getc(void *p, /* I - File descriptor buffer */
- int *encoding) /* IO - Encoding */
-{
- _mxml_fdbuf_t *buf; /* File descriptor buffer */
- int ch, /* Current character */
- temp; /* Temporary character */
-
-
- /*
- * Grab the next character in the buffer...
- */
-
- buf = (_mxml_fdbuf_t *)p;
-
- if (buf->current >= buf->end)
- if (mxml_fd_read(buf) < 0)
- return (EOF);
-
- ch = *(buf->current)++;
-
- switch (*encoding)
- {
- case ENCODE_UTF8 :
- /*
- * Got a UTF-8 character; convert UTF-8 to Unicode and return...
- */
-
- if (!(ch & 0x80))
- {
-#if DEBUG > 1
- printf("mxml_fd_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
-#endif /* DEBUG > 1 */
-
- if (mxml_bad_char(ch))
- {
- mxml_error("Bad control character 0x%02x not allowed by XML standard!",
- ch);
- return (EOF);
- }
-
- return (ch);
- }
- else if (ch == 0xfe)
- {
- /*
- * UTF-16 big-endian BOM?
- */
-
- if (buf->current >= buf->end)
- if (mxml_fd_read(buf) < 0)
- return (EOF);
-
- ch = *(buf->current)++;
-
- if (ch != 0xff)
- return (EOF);
-
- *encoding = ENCODE_UTF16BE;
-
- return (mxml_fd_getc(p, encoding));
- }
- else if (ch == 0xff)
- {
- /*
- * UTF-16 little-endian BOM?
- */
-
- if (buf->current >= buf->end)
- if (mxml_fd_read(buf) < 0)
- return (EOF);
-
- ch = *(buf->current)++;
-
- if (ch != 0xfe)
- return (EOF);
-
- *encoding = ENCODE_UTF16LE;
-
- return (mxml_fd_getc(p, encoding));
- }
- else if ((ch & 0xe0) == 0xc0)
- {
- /*
- * Two-byte value...
- */
-
- if (buf->current >= buf->end)
- if (mxml_fd_read(buf) < 0)
- return (EOF);
-
- temp = *(buf->current)++;
-
- if ((temp & 0xc0) != 0x80)
- return (EOF);
-
- ch = ((ch & 0x1f) << 6) | (temp & 0x3f);
-
- if (ch < 0x80)
- {
- mxml_error("Invalid UTF-8 sequence for character 0x%04x!", ch);
- return (EOF);
- }
- }
- else if ((ch & 0xf0) == 0xe0)
- {
- /*
- * Three-byte value...
- */
-
- if (buf->current >= buf->end)
- if (mxml_fd_read(buf) < 0)
- return (EOF);
-
- temp = *(buf->current)++;
-
- if ((temp & 0xc0) != 0x80)
- return (EOF);
-
- ch = ((ch & 0x0f) << 6) | (temp & 0x3f);
-
- if (buf->current >= buf->end)
- if (mxml_fd_read(buf) < 0)
- return (EOF);
-
- temp = *(buf->current)++;
-
- if ((temp & 0xc0) != 0x80)
- return (EOF);
-
- ch = (ch << 6) | (temp & 0x3f);
-
- if (ch < 0x800)
- {
- mxml_error("Invalid UTF-8 sequence for character 0x%04x!", ch);
- return (EOF);
- }
-
- /*
- * Ignore (strip) Byte Order Mark (BOM)...
- */
-
- if (ch == 0xfeff)
- return (mxml_fd_getc(p, encoding));
- }
- else if ((ch & 0xf8) == 0xf0)
- {
- /*
- * Four-byte value...
- */
-
- if (buf->current >= buf->end)
- if (mxml_fd_read(buf) < 0)
- return (EOF);
-
- temp = *(buf->current)++;
-
- if ((temp & 0xc0) != 0x80)
- return (EOF);
-
- ch = ((ch & 0x07) << 6) | (temp & 0x3f);
-
- if (buf->current >= buf->end)
- if (mxml_fd_read(buf) < 0)
- return (EOF);
-
- temp = *(buf->current)++;
-
- if ((temp & 0xc0) != 0x80)
- return (EOF);
-
- ch = (ch << 6) | (temp & 0x3f);
-
- if (buf->current >= buf->end)
- if (mxml_fd_read(buf) < 0)
- return (EOF);
-
- temp = *(buf->current)++;
-
- if ((temp & 0xc0) != 0x80)
- return (EOF);
-
- ch = (ch << 6) | (temp & 0x3f);
-
- if (ch < 0x10000)
- {
- mxml_error("Invalid UTF-8 sequence for character 0x%04x!", ch);
- return (EOF);
- }
- }
- else
- return (EOF);
- break;
-
- case ENCODE_UTF16BE :
- /*
- * Read UTF-16 big-endian char...
- */
-
- if (buf->current >= buf->end)
- if (mxml_fd_read(buf) < 0)
- return (EOF);
-
- temp = *(buf->current)++;
-
- ch = (ch << 8) | temp;
-
- if (mxml_bad_char(ch))
- {
- mxml_error("Bad control character 0x%02x not allowed by XML standard!",
- ch);
- return (EOF);
- }
- else if (ch >= 0xd800 && ch <= 0xdbff)
- {
- /*
- * Multi-word UTF-16 char...
- */
-
- int lch;
-
- if (buf->current >= buf->end)
- if (mxml_fd_read(buf) < 0)
- return (EOF);
-
- lch = *(buf->current)++;
-
- if (buf->current >= buf->end)
- if (mxml_fd_read(buf) < 0)
- return (EOF);
-
- temp = *(buf->current)++;
-
- lch = (lch << 8) | temp;
-
- if (lch < 0xdc00 || lch >= 0xdfff)
- return (EOF);
-
- ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
- }
- break;
-
- case ENCODE_UTF16LE :
- /*
- * Read UTF-16 little-endian char...
- */
-
- if (buf->current >= buf->end)
- if (mxml_fd_read(buf) < 0)
- return (EOF);
-
- temp = *(buf->current)++;
-
- ch |= (temp << 8);
-
- if (mxml_bad_char(ch))
- {
- mxml_error("Bad control character 0x%02x not allowed by XML standard!",
- ch);
- return (EOF);
- }
- else if (ch >= 0xd800 && ch <= 0xdbff)
- {
- /*
- * Multi-word UTF-16 char...
- */
-
- int lch;
-
- if (buf->current >= buf->end)
- if (mxml_fd_read(buf) < 0)
- return (EOF);
-
- lch = *(buf->current)++;
-
- if (buf->current >= buf->end)
- if (mxml_fd_read(buf) < 0)
- return (EOF);
-
- temp = *(buf->current)++;
-
- lch |= (temp << 8);
-
- if (lch < 0xdc00 || lch >= 0xdfff)
- return (EOF);
-
- ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
- }
- break;
- }
-
-#if DEBUG > 1
- printf("mxml_fd_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
-#endif /* DEBUG > 1 */
-
- return (ch);
-}
-
-
-/*
- * 'mxml_fd_putc()' - Write a character to a file descriptor.
- */
-
-static int /* O - 0 on success, -1 on error */
-mxml_fd_putc(int ch, /* I - Character */
- void *p) /* I - File descriptor buffer */
-{
- _mxml_fdbuf_t *buf; /* File descriptor buffer */
-
-
- /*
- * Flush the write buffer as needed...
- */
-
- buf = (_mxml_fdbuf_t *)p;
-
- if (buf->current >= buf->end)
- if (mxml_fd_write(buf) < 0)
- return (-1);
-
- *(buf->current)++ = ch;
-
- /*
- * Return successfully...
- */
-
- return (0);
-}
-
-
-/*
- * 'mxml_fd_read()' - Read a buffer of data from a file descriptor.
- */
-
-static int /* O - 0 on success, -1 on error */
-mxml_fd_read(_mxml_fdbuf_t *buf) /* I - File descriptor buffer */
-{
- int bytes; /* Bytes read... */
-
-
- /*
- * Range check input...
- */
-
- if (!buf)
- return (-1);
-
- /*
- * Read from the file descriptor...
- */
-
- while ((bytes = read(buf->fd, buf->buffer, sizeof(buf->buffer))) < 0)
-#ifdef EINTR
- if (errno != EAGAIN && errno != EINTR)
-#else
- if (errno != EAGAIN)
-#endif /* EINTR */
- return (-1);
-
- if (bytes == 0)
- return (-1);
-
- /*
- * Update the pointers and return success...
- */
-
- buf->current = buf->buffer;
- buf->end = buf->buffer + bytes;
-
- return (0);
-}
-
-
-/*
- * 'mxml_fd_write()' - Write a buffer of data to a file descriptor.
- */
-
-static int /* O - 0 on success, -1 on error */
-mxml_fd_write(_mxml_fdbuf_t *buf) /* I - File descriptor buffer */
-{
- int bytes; /* Bytes written */
- unsigned char *ptr; /* Pointer into buffer */
-
-
- /*
- * Range check...
- */
-
- if (!buf)
- return (-1);
-
- /*
- * Return 0 if there is nothing to write...
- */
-
- if (buf->current == buf->buffer)
- return (0);
-
- /*
- * Loop until we have written everything...
- */
-
- for (ptr = buf->buffer; ptr < buf->current; ptr += bytes)
- if ((bytes = write(buf->fd, ptr, buf->current - ptr)) < 0)
- return (-1);
-
- /*
- * All done, reset pointers and return success...
- */
-
- buf->current = buf->buffer;
-
- return (0);
-}
-
-
-/*
- * 'mxml_file_getc()' - Get a character from a file.
- */
-
-static int /* O - Character or EOF */
-mxml_file_getc(void *p, /* I - Pointer to file */
- int *encoding) /* IO - Encoding */
-{
- int ch, /* Character from file */
- temp; /* Temporary character */
- FILE *fp; /* Pointer to file */
-
-
- /*
- * Read a character from the file and see if it is EOF or ASCII...
- */
-
- fp = (FILE *)p;
- ch = getc(fp);
-
- if (ch == EOF)
- return (EOF);
-
- switch (*encoding)
- {
- case ENCODE_UTF8 :
- /*
- * Got a UTF-8 character; convert UTF-8 to Unicode and return...
- */
-
- if (!(ch & 0x80))
- {
- if (mxml_bad_char(ch))
- {
- mxml_error("Bad control character 0x%02x not allowed by XML standard!",
- ch);
- return (EOF);
- }
-
-#if DEBUG > 1
- printf("mxml_file_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
-#endif /* DEBUG > 1 */
-
- return (ch);
- }
- else if (ch == 0xfe)
- {
- /*
- * UTF-16 big-endian BOM?
- */
-
- ch = getc(fp);
- if (ch != 0xff)
- return (EOF);
-
- *encoding = ENCODE_UTF16BE;
-
- return (mxml_file_getc(p, encoding));
- }
- else if (ch == 0xff)
- {
- /*
- * UTF-16 little-endian BOM?
- */
-
- ch = getc(fp);
- if (ch != 0xfe)
- return (EOF);
-
- *encoding = ENCODE_UTF16LE;
-
- return (mxml_file_getc(p, encoding));
- }
- else if ((ch & 0xe0) == 0xc0)
- {
- /*
- * Two-byte value...
- */
-
- if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)
- return (EOF);
-
- ch = ((ch & 0x1f) << 6) | (temp & 0x3f);
-
- if (ch < 0x80)
- {
- mxml_error("Invalid UTF-8 sequence for character 0x%04x!", ch);
- return (EOF);
- }
- }
- else if ((ch & 0xf0) == 0xe0)
- {
- /*
- * Three-byte value...
- */
-
- if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)
- return (EOF);
-
- ch = ((ch & 0x0f) << 6) | (temp & 0x3f);
-
- if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)
- return (EOF);
-
- ch = (ch << 6) | (temp & 0x3f);
-
- if (ch < 0x800)
- {
- mxml_error("Invalid UTF-8 sequence for character 0x%04x!", ch);
- return (EOF);
- }
-
- /*
- * Ignore (strip) Byte Order Mark (BOM)...
- */
-
- if (ch == 0xfeff)
- return (mxml_file_getc(p, encoding));
- }
- else if ((ch & 0xf8) == 0xf0)
- {
- /*
- * Four-byte value...
- */
-
- if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)
- return (EOF);
-
- ch = ((ch & 0x07) << 6) | (temp & 0x3f);
-
- if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)
- return (EOF);
-
- ch = (ch << 6) | (temp & 0x3f);
-
- if ((temp = getc(fp)) == EOF || (temp & 0xc0) != 0x80)
- return (EOF);
-
- ch = (ch << 6) | (temp & 0x3f);
-
- if (ch < 0x10000)
- {
- mxml_error("Invalid UTF-8 sequence for character 0x%04x!", ch);
- return (EOF);
- }
- }
- else
- return (EOF);
- break;
-
- case ENCODE_UTF16BE :
- /*
- * Read UTF-16 big-endian char...
- */
-
- ch = (ch << 8) | getc(fp);
-
- if (mxml_bad_char(ch))
- {
- mxml_error("Bad control character 0x%02x not allowed by XML standard!",
- ch);
- return (EOF);
- }
- else if (ch >= 0xd800 && ch <= 0xdbff)
- {
- /*
- * Multi-word UTF-16 char...
- */
-
- int lch = (getc(fp) << 8);
- lch |= getc(fp);
-
- if (lch < 0xdc00 || lch >= 0xdfff)
- return (EOF);
-
- ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
- }
- break;
-
- case ENCODE_UTF16LE :
- /*
- * Read UTF-16 little-endian char...
- */
-
- ch |= (getc(fp) << 8);
-
- if (mxml_bad_char(ch))
- {
- mxml_error("Bad control character 0x%02x not allowed by XML standard!",
- ch);
- return (EOF);
- }
- else if (ch >= 0xd800 && ch <= 0xdbff)
- {
- /*
- * Multi-word UTF-16 char...
- */
-
- int lch = getc(fp);
- lch |= (getc(fp) << 8);
-
- if (lch < 0xdc00 || lch >= 0xdfff)
- return (EOF);
-
- ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
- }
- break;
- }
-
-#if DEBUG > 1
- printf("mxml_file_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
-#endif /* DEBUG > 1 */
-
- return (ch);
-}
-
-
-/*
- * 'mxml_file_putc()' - Write a character to a file.
- */
-
-static int /* O - 0 on success, -1 on failure */
-mxml_file_putc(int ch, /* I - Character to write */
- void *p) /* I - Pointer to file */
-{
- return (putc(ch, (FILE *)p) == EOF ? -1 : 0);
-}
-
-
-/*
- * 'mxml_get_entity()' - Get the character corresponding to an entity...
- */
-
-static int /* O - Character value or EOF on error */
-mxml_get_entity(mxml_node_t *parent, /* I - Parent node */
- void *p, /* I - Pointer to source */
- int *encoding, /* IO - Character encoding */
- int (*getc_cb)(void *, int *))
- /* I - Get character function */
-{
- int ch; /* Current character */
- char entity[64], /* Entity string */
- *entptr; /* Pointer into entity */
-
-
- entptr = entity;
-
- while ((ch = (*getc_cb)(p, encoding)) != EOF)
- if (ch > 126 || (!isalnum(ch) && ch != '#'))
- break;
- else if (entptr < (entity + sizeof(entity) - 1))
- *entptr++ = ch;
- else
- {
- mxml_error("Entity name too long under parent <%s>!",
- parent ? parent->value.element.name : "null");
- break;
- }
-
- *entptr = '\0';
-
- if (ch != ';')
- {
- mxml_error("Character entity \"%s\" not terminated under parent <%s>!",
- entity, parent ? parent->value.element.name : "null");
- return (EOF);
- }
-
- if (entity[0] == '#')
- {
- if (entity[1] == 'x')
- ch = strtol(entity + 2, NULL, 16);
- else
- ch = strtol(entity + 1, NULL, 10);
- }
- else if ((ch = mxmlEntityGetValue(entity)) < 0)
- mxml_error("Entity name \"%s;\" not supported under parent <%s>!",
- entity, parent ? parent->value.element.name : "null");
-
- if (mxml_bad_char(ch))
- {
- mxml_error("Bad control character 0x%02x under parent <%s> not allowed by XML standard!",
- ch, parent ? parent->value.element.name : "null");
- return (EOF);
- }
-
- return (ch);
-}
-
-
-/*
- * 'mxml_load_data()' - Load data into an XML node tree.
- */
-
-static mxml_node_t * /* O - First node or NULL if the file could not be read. */
-mxml_load_data(
- mxml_node_t *top, /* I - Top node */
- void *p, /* I - Pointer to data */
- mxml_load_cb_t cb, /* I - Callback function or MXML_NO_CALLBACK */
- _mxml_getc_cb_t getc_cb, /* I - Read function */
- mxml_sax_cb_t sax_cb, /* I - SAX callback or MXML_NO_CALLBACK */
- void *sax_data) /* I - SAX user data */
-{
- mxml_node_t *node, /* Current node */
- *first, /* First node added */
- *parent; /* Current parent node */
- int ch, /* Character from file */
- whitespace; /* Non-zero if whitespace seen */
- char *buffer, /* String buffer */
- *bufptr; /* Pointer into buffer */
- int bufsize; /* Size of buffer */
- mxml_type_t type; /* Current node type */
- int encoding; /* Character encoding */
- _mxml_global_t *global = _mxml_global();
- /* Global data */
- static const char * const types[] = /* Type strings... */
- {
- "MXML_ELEMENT", /* XML element with attributes */
- "MXML_INTEGER", /* Integer value */
- "MXML_OPAQUE", /* Opaque string */
- "MXML_REAL", /* Real value */
- "MXML_TEXT", /* Text fragment */
- "MXML_CUSTOM" /* Custom data */
- };
-
-
- /*
- * Read elements and other nodes from the file...
- */
-
- if ((buffer = malloc(64)) == NULL)
- {
- mxml_error("Unable to allocate string buffer!");
- return (NULL);
- }
-
- bufsize = 64;
- bufptr = buffer;
- parent = top;
- first = NULL;
- whitespace = 0;
- encoding = ENCODE_UTF8;
-
- if (cb && parent)
- type = (*cb)(parent);
- else
- type = MXML_TEXT;
-
- while ((ch = (*getc_cb)(p, &encoding)) != EOF)
- {
- if ((ch == '<' ||
- (mxml_isspace(ch) && type != MXML_OPAQUE && type != MXML_CUSTOM)) &&
- bufptr > buffer)
- {
- /*
- * Add a new value node...
- */
-
- *bufptr = '\0';
-
- switch (type)
- {
- case MXML_INTEGER :
- node = mxmlNewInteger(parent, strtol(buffer, &bufptr, 0));
- break;
-
- case MXML_OPAQUE :
- node = mxmlNewOpaque(parent, buffer);
- break;
-
- case MXML_REAL :
- node = mxmlNewReal(parent, strtod(buffer, &bufptr));
- break;
-
- case MXML_TEXT :
- node = mxmlNewText(parent, whitespace, buffer);
- break;
-
- case MXML_CUSTOM :
- if (global->custom_load_cb)
- {
- /*
- * Use the callback to fill in the custom data...
- */
-
- node = mxmlNewCustom(parent, NULL, NULL);
-
- if ((*global->custom_load_cb)(node, buffer))
- {
- mxml_error("Bad custom value '%s' in parent <%s>!",
- buffer, parent ? parent->value.element.name : "null");
- mxmlDelete(node);
- node = NULL;
- }
- break;
- }
-
- default : /* Ignore... */
- node = NULL;
- break;
- }
-
- if (*bufptr)
- {
- /*
- * Bad integer/real number value...
- */
-
- mxml_error("Bad %s value '%s' in parent <%s>!",
- type == MXML_INTEGER ? "integer" : "real", buffer,
- parent ? parent->value.element.name : "null");
- break;
- }
-
- bufptr = buffer;
- whitespace = mxml_isspace(ch) && type == MXML_TEXT;
-
- if (!node && type != MXML_IGNORE)
- {
- /*
- * Print error and return...
- */
-
- mxml_error("Unable to add value node of type %s to parent <%s>!",
- types[type], parent ? parent->value.element.name : "null");
- goto error;
- }
-
- if (sax_cb)
- {
- (*sax_cb)(node, MXML_SAX_DATA, sax_data);
-
- if (!mxmlRelease(node))
- node = NULL;
- }
-
- if (!first && node)
- first = node;
- }
- else if (mxml_isspace(ch) && type == MXML_TEXT)
- whitespace = 1;
-
- /*
- * Add lone whitespace node if we have an element and existing
- * whitespace...
- */
-
- if (ch == '<' && whitespace && type == MXML_TEXT)
- {
- if (parent)
- {
- node = mxmlNewText(parent, whitespace, "");
-
- if (sax_cb)
- {
- (*sax_cb)(node, MXML_SAX_DATA, sax_data);
-
- if (!mxmlRelease(node))
- node = NULL;
- }
-
- if (!first && node)
- first = node;
- }
-
- whitespace = 0;
- }
-
- if (ch == '<')
- {
- /*
- * Start of open/close tag...
- */
-
- bufptr = buffer;
-
- while ((ch = (*getc_cb)(p, &encoding)) != EOF)
- if (mxml_isspace(ch) || ch == '>' || (ch == '/' && bufptr > buffer))
- break;
- else if (ch == '<')
- {
- mxml_error("Bare < in element!");
- goto error;
- }
- else if (ch == '&')
- {
- if ((ch = mxml_get_entity(parent, p, &encoding, getc_cb)) == EOF)
- goto error;
-
- if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
- goto error;
- }
- else if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
- goto error;
- else if (((bufptr - buffer) == 1 && buffer[0] == '?') ||
- ((bufptr - buffer) == 3 && !strncmp(buffer, "!--", 3)) ||
- ((bufptr - buffer) == 8 && !strncmp(buffer, "![CDATA[", 8)))
- break;
-
- *bufptr = '\0';
-
- if (!strcmp(buffer, "!--"))
- {
- /*
- * Gather rest of comment...
- */
-
- while ((ch = (*getc_cb)(p, &encoding)) != EOF)
- {
- if (ch == '>' && bufptr > (buffer + 4) &&
- bufptr[-3] != '-' && bufptr[-2] == '-' && bufptr[-1] == '-')
- break;
- else if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
- goto error;
- }
-
- /*
- * Error out if we didn't get the whole comment...
- */
-
- if (ch != '>')
- {
- /*
- * Print error and return...
- */
-
- mxml_error("Early EOF in comment node!");
- goto error;
- }
-
-
- /*
- * Otherwise add this as an element under the current parent...
- */
-
- *bufptr = '\0';
-
- if (!parent && first)
- {
- /*
- * There can only be one root element!
- */
-
- mxml_error("<%s> cannot be a second root node after <%s>",
- buffer, first->value.element.name);
- goto error;
- }
-
- if ((node = mxmlNewElement(parent, buffer)) == NULL)
- {
- /*
- * Just print error for now...
- */
-
- mxml_error("Unable to add comment node to parent <%s>!",
- parent ? parent->value.element.name : "null");
- break;
- }
-
- if (sax_cb)
- {
- (*sax_cb)(node, MXML_SAX_COMMENT, sax_data);
-
- if (!mxmlRelease(node))
- node = NULL;
- }
-
- if (node && !first)
- first = node;
- }
- else if (!strcmp(buffer, "![CDATA["))
- {
- /*
- * Gather CDATA section...
- */
-
- while ((ch = (*getc_cb)(p, &encoding)) != EOF)
- {
- if (ch == '>' && !strncmp(bufptr - 2, "]]", 2))
- break;
- else if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
- goto error;
- }
-
- /*
- * Error out if we didn't get the whole comment...
- */
-
- if (ch != '>')
- {
- /*
- * Print error and return...
- */
-
- mxml_error("Early EOF in CDATA node!");
- goto error;
- }
-
-
- /*
- * Otherwise add this as an element under the current parent...
- */
-
- *bufptr = '\0';
-
- if (!parent && first)
- {
- /*
- * There can only be one root element!
- */
-
- mxml_error("<%s> cannot be a second root node after <%s>",
- buffer, first->value.element.name);
- goto error;
- }
-
- if ((node = mxmlNewElement(parent, buffer)) == NULL)
- {
- /*
- * Print error and return...
- */
-
- mxml_error("Unable to add CDATA node to parent <%s>!",
- parent ? parent->value.element.name : "null");
- goto error;
- }
-
- if (sax_cb)
- {
- (*sax_cb)(node, MXML_SAX_CDATA, sax_data);
-
- if (!mxmlRelease(node))
- node = NULL;
- }
-
- if (node && !first)
- first = node;
- }
- else if (buffer[0] == '?')
- {
- /*
- * Gather rest of processing instruction...
- */
-
- while ((ch = (*getc_cb)(p, &encoding)) != EOF)
- {
- if (ch == '>' && bufptr > buffer && bufptr[-1] == '?')
- break;
- else if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
- goto error;
- }
-
- /*
- * Error out if we didn't get the whole processing instruction...
- */
-
- if (ch != '>')
- {
- /*
- * Print error and return...
- */
-
- mxml_error("Early EOF in processing instruction node!");
- goto error;
- }
-
- /*
- * Otherwise add this as an element under the current parent...
- */
-
- *bufptr = '\0';
-
- if (!parent && first)
- {
- /*
- * There can only be one root element!
- */
-
- mxml_error("<%s> cannot be a second root node after <%s>",
- buffer, first->value.element.name);
- goto error;
- }
-
- if ((node = mxmlNewElement(parent, buffer)) == NULL)
- {
- /*
- * Print error and return...
- */
-
- mxml_error("Unable to add processing instruction node to parent <%s>!",
- parent ? parent->value.element.name : "null");
- goto error;
- }
-
- if (sax_cb)
- {
- (*sax_cb)(node, MXML_SAX_DIRECTIVE, sax_data);
-
- if (!mxmlRelease(node))
- node = NULL;
- }
-
- if (node)
- {
- if (!first)
- first = node;
-
- if (!parent)
- {
- parent = node;
-
- if (cb)
- type = (*cb)(parent);
- }
- }
- }
- else if (buffer[0] == '!')
- {
- /*
- * Gather rest of declaration...
- */
-
- do
- {
- if (ch == '>')
- break;
- else
- {
- if (ch == '&')
- if ((ch = mxml_get_entity(parent, p, &encoding, getc_cb)) == EOF)
- goto error;
-
- if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
- goto error;
- }
- }
- while ((ch = (*getc_cb)(p, &encoding)) != EOF);
-
- /*
- * Error out if we didn't get the whole declaration...
- */
-
- if (ch != '>')
- {
- /*
- * Print error and return...
- */
-
- mxml_error("Early EOF in declaration node!");
- goto error;
- }
-
- /*
- * Otherwise add this as an element under the current parent...
- */
-
- *bufptr = '\0';
-
- if (!parent && first)
- {
- /*
- * There can only be one root element!
- */
-
- mxml_error("<%s> cannot be a second root node after <%s>",
- buffer, first->value.element.name);
- goto error;
- }
-
- if ((node = mxmlNewElement(parent, buffer)) == NULL)
- {
- /*
- * Print error and return...
- */
-
- mxml_error("Unable to add declaration node to parent <%s>!",
- parent ? parent->value.element.name : "null");
- goto error;
- }
-
- if (sax_cb)
- {
- (*sax_cb)(node, MXML_SAX_DIRECTIVE, sax_data);
-
- if (!mxmlRelease(node))
- node = NULL;
- }
-
- if (node)
- {
- if (!first)
- first = node;
-
- if (!parent)
- {
- parent = node;
-
- if (cb)
- type = (*cb)(parent);
- }
- }
- }
- else if (buffer[0] == '/')
- {
- /*
- * Handle close tag...
- */
-
- if (!parent || strcmp(buffer + 1, parent->value.element.name))
- {
- /*
- * Close tag doesn't match tree; print an error for now...
- */
-
- mxml_error("Mismatched close tag <%s> under parent <%s>!",
- buffer, parent ? parent->value.element.name : "(null)");
- goto error;
- }
-
- /*
- * Keep reading until we see >...
- */
-
- while (ch != '>' && ch != EOF)
- ch = (*getc_cb)(p, &encoding);
-
- node = parent;
- parent = parent->parent;
-
- if (sax_cb)
- {
- (*sax_cb)(node, MXML_SAX_ELEMENT_CLOSE, sax_data);
-
- if (!mxmlRelease(node) && first == node)
- first = NULL;
- }
-
- /*
- * Ascend into the parent and set the value type as needed...
- */
-
- if (cb && parent)
- type = (*cb)(parent);
- }
- else
- {
- /*
- * Handle open tag...
- */
-
- if (!parent && first)
- {
- /*
- * There can only be one root element!
- */
-
- mxml_error("<%s> cannot be a second root node after <%s>",
- buffer, first->value.element.name);
- goto error;
- }
-
- if ((node = mxmlNewElement(parent, buffer)) == NULL)
- {
- /*
- * Just print error for now...
- */
-
- mxml_error("Unable to add element node to parent <%s>!",
- parent ? parent->value.element.name : "null");
- goto error;
- }
-
- if (mxml_isspace(ch))
- {
- if ((ch = mxml_parse_element(node, p, &encoding, getc_cb)) == EOF)
- goto error;
- }
- else if (ch == '/')
- {
- if ((ch = (*getc_cb)(p, &encoding)) != '>')
- {
- mxml_error("Expected > but got '%c' instead for element <%s/>!",
- ch, buffer);
- mxmlDelete(node);
- goto error;
- }
-
- ch = '/';
- }
-
- if (sax_cb)
- (*sax_cb)(node, MXML_SAX_ELEMENT_OPEN, sax_data);
-
- if (!first)
- first = node;
-
- if (ch == EOF)
- break;
-
- if (ch != '/')
- {
- /*
- * Descend into this node, setting the value type as needed...
- */
-
- parent = node;
-
- if (cb && parent)
- type = (*cb)(parent);
- }
- else if (sax_cb)
- {
- (*sax_cb)(node, MXML_SAX_ELEMENT_CLOSE, sax_data);
-
- if (!mxmlRelease(node) && first == node)
- first = NULL;
- }
- }
-
- bufptr = buffer;
- }
- else if (ch == '&')
- {
- /*
- * Add character entity to current buffer...
- */
-
- if ((ch = mxml_get_entity(parent, p, &encoding, getc_cb)) == EOF)
- goto error;
-
- if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
- goto error;
- }
- else if (type == MXML_OPAQUE || type == MXML_CUSTOM || !mxml_isspace(ch))
- {
- /*
- * Add character to current buffer...
- */
-
- if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
- goto error;
- }
- }
-
- /*
- * Free the string buffer - we don't need it anymore...
- */
-
- free(buffer);
-
- /*
- * Find the top element and return it...
- */
-
- if (parent)
- {
- node = parent;
-
- while (parent->parent != top && parent->parent)
- parent = parent->parent;
-
- if (node != parent)
- {
- mxml_error("Missing close tag </%s> under parent <%s>!",
- node->value.element.name,
- node->parent ? node->parent->value.element.name : "(null)");
-
- mxmlDelete(first);
-
- return (NULL);
- }
- }
-
- if (parent)
- return (parent);
- else
- return (first);
-
- /*
- * Common error return...
- */
-
-error:
-
- mxmlDelete(first);
-
- free(buffer);
-
- return (NULL);
-}
-
-
-/*
- * 'mxml_parse_element()' - Parse an element for any attributes...
- */
-
-static int /* O - Terminating character */
-mxml_parse_element(
- mxml_node_t *node, /* I - Element node */
- void *p, /* I - Data to read from */
- int *encoding, /* IO - Encoding */
- _mxml_getc_cb_t getc_cb) /* I - Data callback */
-{
- int ch, /* Current character in file */
- quote; /* Quoting character */
- char *name, /* Attribute name */
- *value, /* Attribute value */
- *ptr; /* Pointer into name/value */
- int namesize, /* Size of name string */
- valsize; /* Size of value string */
-
-
- /*
- * Initialize the name and value buffers...
- */
-
- if ((name = malloc(64)) == NULL)
- {
- mxml_error("Unable to allocate memory for name!");
- return (EOF);
- }
-
- namesize = 64;
-
- if ((value = malloc(64)) == NULL)
- {
- free(name);
- mxml_error("Unable to allocate memory for value!");
- return (EOF);
- }
-
- valsize = 64;
-
- /*
- * Loop until we hit a >, /, ?, or EOF...
- */
-
- while ((ch = (*getc_cb)(p, encoding)) != EOF)
- {
-#if DEBUG > 1
- fprintf(stderr, "parse_element: ch='%c'\n", ch);
-#endif /* DEBUG > 1 */
-
- /*
- * Skip leading whitespace...
- */
-
- if (mxml_isspace(ch))
- continue;
-
- /*
- * Stop at /, ?, or >...
- */
-
- if (ch == '/' || ch == '?')
- {
- /*
- * Grab the > character and print an error if it isn't there...
- */
-
- quote = (*getc_cb)(p, encoding);
-
- if (quote != '>')
- {
- mxml_error("Expected '>' after '%c' for element %s, but got '%c'!",
- ch, node->value.element.name, quote);
- goto error;
- }
-
- break;
- }
- else if (ch == '<')
- {
- mxml_error("Bare < in element %s!", node->value.element.name);
- goto error;
- }
- else if (ch == '>')
- break;
-
- /*
- * Read the attribute name...
- */
-
- name[0] = ch;
- ptr = name + 1;
-
- if (ch == '\"' || ch == '\'')
- {
- /*
- * Name is in quotes, so get a quoted string...
- */
-
- quote = ch;
-
- while ((ch = (*getc_cb)(p, encoding)) != EOF)
- {
- if (ch == '&')
- if ((ch = mxml_get_entity(node, p, encoding, getc_cb)) == EOF)
- goto error;
-
- if (mxml_add_char(ch, &ptr, &name, &namesize))
- goto error;
-
- if (ch == quote)
- break;
- }
- }
- else
- {
- /*
- * Grab an normal, non-quoted name...
- */
-
- while ((ch = (*getc_cb)(p, encoding)) != EOF)
- if (mxml_isspace(ch) || ch == '=' || ch == '/' || ch == '>' ||
- ch == '?')
- break;
- else
- {
- if (ch == '&')
- if ((ch = mxml_get_entity(node, p, encoding, getc_cb)) == EOF)
- goto error;
-
- if (mxml_add_char(ch, &ptr, &name, &namesize))
- goto error;
- }
- }
-
- *ptr = '\0';
-
- if (mxmlElementGetAttr(node, name))
- goto error;
-
- while (ch != EOF && mxml_isspace(ch))
- ch = (*getc_cb)(p, encoding);
-
- if (ch == '=')
- {
- /*
- * Read the attribute value...
- */
-
- while ((ch = (*getc_cb)(p, encoding)) != EOF && mxml_isspace(ch));
-
- if (ch == EOF)
- {
- mxml_error("Missing value for attribute '%s' in element %s!",
- name, node->value.element.name);
- goto error;
- }
-
- if (ch == '\'' || ch == '\"')
- {
- /*
- * Read quoted value...
- */
-
- quote = ch;
- ptr = value;
-
- while ((ch = (*getc_cb)(p, encoding)) != EOF)
- if (ch == quote)
- break;
- else
- {
- if (ch == '&')
- if ((ch = mxml_get_entity(node, p, encoding, getc_cb)) == EOF)
- goto error;
-
- if (mxml_add_char(ch, &ptr, &value, &valsize))
- goto error;
- }
-
- *ptr = '\0';
- }
- else
- {
- /*
- * Read unquoted value...
- */
-
- value[0] = ch;
- ptr = value + 1;
-
- while ((ch = (*getc_cb)(p, encoding)) != EOF)
- if (mxml_isspace(ch) || ch == '=' || ch == '/' || ch == '>')
- break;
- else
- {
- if (ch == '&')
- if ((ch = mxml_get_entity(node, p, encoding, getc_cb)) == EOF)
- goto error;
-
- if (mxml_add_char(ch, &ptr, &value, &valsize))
- goto error;
- }
-
- *ptr = '\0';
- }
-
- /*
- * Set the attribute with the given string value...
- */
-
- mxmlElementSetAttr(node, name, value);
- }
- else
- {
- mxml_error("Missing value for attribute '%s' in element %s!",
- name, node->value.element.name);
- goto error;
- }
-
- /*
- * Check the end character...
- */
-
- if (ch == '/' || ch == '?')
- {
- /*
- * Grab the > character and print an error if it isn't there...
- */
-
- quote = (*getc_cb)(p, encoding);
-
- if (quote != '>')
- {
- mxml_error("Expected '>' after '%c' for element %s, but got '%c'!",
- ch, node->value.element.name, quote);
- ch = EOF;
- }
-
- break;
- }
- else if (ch == '>')
- break;
- }
-
- /*
- * Free the name and value buffers and return...
- */
-
- free(name);
- free(value);
-
- return (ch);
-
- /*
- * Common error return point...
- */
-
-error:
-
- free(name);
- free(value);
-
- return (EOF);
-}
-
-
-/*
- * 'mxml_string_getc()' - Get a character from a string.
- */
-
-static int /* O - Character or EOF */
-mxml_string_getc(void *p, /* I - Pointer to file */
- int *encoding) /* IO - Encoding */
-{
- int ch; /* Character */
- const char **s; /* Pointer to string pointer */
-
-
- s = (const char **)p;
-
- if ((ch = (*s)[0] & 255) != 0 || *encoding == ENCODE_UTF16LE)
- {
- /*
- * Got character; convert UTF-8 to integer and return...
- */
-
- (*s)++;
-
- switch (*encoding)
- {
- case ENCODE_UTF8 :
- if (!(ch & 0x80))
- {
-#if DEBUG > 1
- printf("mxml_string_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
-#endif /* DEBUG > 1 */
-
- if (mxml_bad_char(ch))
- {
- mxml_error("Bad control character 0x%02x not allowed by XML standard!",
- ch);
- return (EOF);
- }
-
- return (ch);
- }
- else if (ch == 0xfe)
- {
- /*
- * UTF-16 big-endian BOM?
- */
-
- if (((*s)[0] & 255) != 0xff)
- return (EOF);
-
- *encoding = ENCODE_UTF16BE;
- (*s)++;
-
- return (mxml_string_getc(p, encoding));
- }
- else if (ch == 0xff)
- {
- /*
- * UTF-16 little-endian BOM?
- */
-
- if (((*s)[0] & 255) != 0xfe)
- return (EOF);
-
- *encoding = ENCODE_UTF16LE;
- (*s)++;
-
- return (mxml_string_getc(p, encoding));
- }
- else if ((ch & 0xe0) == 0xc0)
- {
- /*
- * Two-byte value...
- */
-
- if (((*s)[0] & 0xc0) != 0x80)
- return (EOF);
-
- ch = ((ch & 0x1f) << 6) | ((*s)[0] & 0x3f);
-
- (*s)++;
-
- if (ch < 0x80)
- {
- mxml_error("Invalid UTF-8 sequence for character 0x%04x!", ch);
- return (EOF);
- }
-
-#if DEBUG > 1
- printf("mxml_string_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
-#endif /* DEBUG > 1 */
-
- return (ch);
- }
- else if ((ch & 0xf0) == 0xe0)
- {
- /*
- * Three-byte value...
- */
-
- if (((*s)[0] & 0xc0) != 0x80 ||
- ((*s)[1] & 0xc0) != 0x80)
- return (EOF);
-
- ch = ((((ch & 0x0f) << 6) | ((*s)[0] & 0x3f)) << 6) | ((*s)[1] & 0x3f);
-
- (*s) += 2;
-
- if (ch < 0x800)
- {
- mxml_error("Invalid UTF-8 sequence for character 0x%04x!", ch);
- return (EOF);
- }
-
- /*
- * Ignore (strip) Byte Order Mark (BOM)...
- */
-
- if (ch == 0xfeff)
- return (mxml_string_getc(p, encoding));
-
-#if DEBUG > 1
- printf("mxml_string_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
-#endif /* DEBUG > 1 */
-
- return (ch);
- }
- else if ((ch & 0xf8) == 0xf0)
- {
- /*
- * Four-byte value...
- */
-
- if (((*s)[0] & 0xc0) != 0x80 ||
- ((*s)[1] & 0xc0) != 0x80 ||
- ((*s)[2] & 0xc0) != 0x80)
- return (EOF);
-
- ch = ((((((ch & 0x07) << 6) | ((*s)[0] & 0x3f)) << 6) |
- ((*s)[1] & 0x3f)) << 6) | ((*s)[2] & 0x3f);
-
- (*s) += 3;
-
- if (ch < 0x10000)
- {
- mxml_error("Invalid UTF-8 sequence for character 0x%04x!", ch);
- return (EOF);
- }
-
-#if DEBUG > 1
- printf("mxml_string_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
-#endif /* DEBUG > 1 */
-
- return (ch);
- }
- else
- return (EOF);
-
- case ENCODE_UTF16BE :
- /*
- * Read UTF-16 big-endian char...
- */
-
- ch = (ch << 8) | ((*s)[0] & 255);
- (*s) ++;
-
- if (mxml_bad_char(ch))
- {
- mxml_error("Bad control character 0x%02x not allowed by XML standard!",
- ch);
- return (EOF);
- }
- else if (ch >= 0xd800 && ch <= 0xdbff)
- {
- /*
- * Multi-word UTF-16 char...
- */
-
- int lch; /* Lower word */
-
-
- if (!(*s)[0])
- return (EOF);
-
- lch = (((*s)[0] & 255) << 8) | ((*s)[1] & 255);
- (*s) += 2;
-
- if (lch < 0xdc00 || lch >= 0xdfff)
- return (EOF);
-
- ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
- }
-
-#if DEBUG > 1
- printf("mxml_string_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
-#endif /* DEBUG > 1 */
-
- return (ch);
-
- case ENCODE_UTF16LE :
- /*
- * Read UTF-16 little-endian char...
- */
-
- ch = ch | (((*s)[0] & 255) << 8);
-
- if (!ch)
- {
- (*s) --;
- return (EOF);
- }
-
- (*s) ++;
-
- if (mxml_bad_char(ch))
- {
- mxml_error("Bad control character 0x%02x not allowed by XML standard!",
- ch);
- return (EOF);
- }
- else if (ch >= 0xd800 && ch <= 0xdbff)
- {
- /*
- * Multi-word UTF-16 char...
- */
-
- int lch; /* Lower word */
-
-
- if (!(*s)[1])
- return (EOF);
-
- lch = (((*s)[1] & 255) << 8) | ((*s)[0] & 255);
- (*s) += 2;
-
- if (lch < 0xdc00 || lch >= 0xdfff)
- return (EOF);
-
- ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
- }
-
-#if DEBUG > 1
- printf("mxml_string_getc: %c (0x%04x)\n", ch < ' ' ? '.' : ch, ch);
-#endif /* DEBUG > 1 */
-
- return (ch);
- }
- }
-
- return (EOF);
-}
-
-
-/*
- * 'mxml_string_putc()' - Write a character to a string.
- */
-
-static int /* O - 0 on success, -1 on failure */
-mxml_string_putc(int ch, /* I - Character to write */
- void *p) /* I - Pointer to string pointers */
-{
- char **pp; /* Pointer to string pointers */
-
-
- pp = (char **)p;
-
- if (pp[0] < pp[1])
- pp[0][0] = ch;
-
- pp[0] ++;
-
- return (0);
-}
-
-
-/*
- * 'mxml_write_name()' - Write a name string.
- */
-
-static int /* O - 0 on success, -1 on failure */
-mxml_write_name(const char *s, /* I - Name to write */
- void *p, /* I - Write pointer */
- int (*putc_cb)(int, void *))
- /* I - Write callback */
-{
- char quote; /* Quote character */
- const char *name; /* Entity name */
-
-
- if (*s == '\"' || *s == '\'')
- {
- /*
- * Write a quoted name string...
- */
-
- if ((*putc_cb)(*s, p) < 0)
- return (-1);
-
- quote = *s++;
-
- while (*s && *s != quote)
- {
- if ((name = mxmlEntityGetName(*s)) != NULL)
- {
- if ((*putc_cb)('&', p) < 0)
- return (-1);
-
- while (*name)
- {
- if ((*putc_cb)(*name, p) < 0)
- return (-1);
-
- name ++;
- }
-
- if ((*putc_cb)(';', p) < 0)
- return (-1);
- }
- else if ((*putc_cb)(*s, p) < 0)
- return (-1);
-
- s ++;
- }
-
- /*
- * Write the end quote...
- */
-
- if ((*putc_cb)(quote, p) < 0)
- return (-1);
- }
- else
- {
- /*
- * Write a non-quoted name string...
- */
-
- while (*s)
- {
- if ((*putc_cb)(*s, p) < 0)
- return (-1);
-
- s ++;
- }
- }
-
- return (0);
-}
-
-
-/*
- * 'mxml_write_node()' - Save an XML node to a file.
- */
-
-static int /* O - Column or -1 on error */
-mxml_write_node(mxml_node_t *node, /* I - Node to write */
- void *p, /* I - File to write to */
- mxml_save_cb_t cb, /* I - Whitespace callback */
- int col, /* I - Current column */
- _mxml_putc_cb_t putc_cb,/* I - Output callback */
- _mxml_global_t *global)/* I - Global data */
-{
- int i, /* Looping var */
- width; /* Width of attr + value */
- mxml_attr_t *attr; /* Current attribute */
- char s[255]; /* Temporary string */
-
-
- /*
- * Print the node value...
- */
-
- switch (node->type)
- {
- case MXML_ELEMENT :
- col = mxml_write_ws(node, p, cb, MXML_WS_BEFORE_OPEN, col, putc_cb);
-
- if ((*putc_cb)('<', p) < 0)
- return (-1);
- if (node->value.element.name[0] == '?' ||
- !strncmp(node->value.element.name, "!--", 3) ||
- !strncmp(node->value.element.name, "![CDATA[", 8))
- {
- /*
- * Comments, CDATA, and processing instructions do not
- * use character entities.
- */
-
- const char *ptr; /* Pointer into name */
-
-
- for (ptr = node->value.element.name; *ptr; ptr ++)
- if ((*putc_cb)(*ptr, p) < 0)
- return (-1);
- }
- else if (mxml_write_name(node->value.element.name, p, putc_cb) < 0)
- return (-1);
-
- col += strlen(node->value.element.name) + 1;
-
- for (i = node->value.element.num_attrs, attr = node->value.element.attrs;
- i > 0;
- i --, attr ++)
- {
- width = strlen(attr->name);
-
- if (attr->value)
- width += strlen(attr->value) + 3;
-
- if (global->wrap > 0 && (col + width) > global->wrap)
- {
- if ((*putc_cb)('\n', p) < 0)
- return (-1);
-
- col = 0;
- }
- else
- {
- if ((*putc_cb)(' ', p) < 0)
- return (-1);
-
- col ++;
- }
-
- if (mxml_write_name(attr->name, p, putc_cb) < 0)
- return (-1);
-
- if (attr->value)
- {
- if ((*putc_cb)('=', p) < 0)
- return (-1);
- if ((*putc_cb)('\"', p) < 0)
- return (-1);
- if (mxml_write_string(attr->value, p, putc_cb) < 0)
- return (-1);
- if ((*putc_cb)('\"', p) < 0)
- return (-1);
- }
-
- col += width;
- }
-
- if (node->child)
- {
- /*
- * Write children...
- */
-
- mxml_node_t *child; /* Current child */
-
-
- if ((*putc_cb)('>', p) < 0)
- return (-1);
- else
- col ++;
-
- col = mxml_write_ws(node, p, cb, MXML_WS_AFTER_OPEN, col, putc_cb);
-
- for (child = node->child; child; child = child->next)
- {
- if ((col = mxml_write_node(child, p, cb, col, putc_cb, global)) < 0)
- return (-1);
- }
-
- /*
- * The ? and ! elements are special-cases and have no end tags...
- */
-
- if (node->value.element.name[0] != '!' &&
- node->value.element.name[0] != '?')
- {
- col = mxml_write_ws(node, p, cb, MXML_WS_BEFORE_CLOSE, col, putc_cb);
-
- if ((*putc_cb)('<', p) < 0)
- return (-1);
- if ((*putc_cb)('/', p) < 0)
- return (-1);
- if (mxml_write_string(node->value.element.name, p, putc_cb) < 0)
- return (-1);
- if ((*putc_cb)('>', p) < 0)
- return (-1);
-
- col += strlen(node->value.element.name) + 3;
-
- col = mxml_write_ws(node, p, cb, MXML_WS_AFTER_CLOSE, col, putc_cb);
- }
- }
- else if (node->value.element.name[0] == '!' ||
- node->value.element.name[0] == '?')
- {
- /*
- * The ? and ! elements are special-cases...
- */
-
- if ((*putc_cb)('>', p) < 0)
- return (-1);
- else
- col ++;
-
- col = mxml_write_ws(node, p, cb, MXML_WS_AFTER_OPEN, col, putc_cb);
- }
- else
- {
- if ((*putc_cb)(' ', p) < 0)
- return (-1);
- if ((*putc_cb)('/', p) < 0)
- return (-1);
- if ((*putc_cb)('>', p) < 0)
- return (-1);
-
- col += 3;
-
- col = mxml_write_ws(node, p, cb, MXML_WS_AFTER_OPEN, col, putc_cb);
- }
- break;
-
- case MXML_INTEGER :
- if (node->prev)
- {
- if (global->wrap > 0 && col > global->wrap)
- {
- if ((*putc_cb)('\n', p) < 0)
- return (-1);
-
- col = 0;
- }
- else if ((*putc_cb)(' ', p) < 0)
- return (-1);
- else
- col ++;
- }
-
- sprintf(s, "%d", node->value.integer);
- if (mxml_write_string(s, p, putc_cb) < 0)
- return (-1);
-
- col += strlen(s);
- break;
-
- case MXML_OPAQUE :
- if (mxml_write_string(node->value.opaque, p, putc_cb) < 0)
- return (-1);
-
- col += strlen(node->value.opaque);
- break;
-
- case MXML_REAL :
- if (node->prev)
- {
- if (global->wrap > 0 && col > global->wrap)
- {
- if ((*putc_cb)('\n', p) < 0)
- return (-1);
-
- col = 0;
- }
- else if ((*putc_cb)(' ', p) < 0)
- return (-1);
- else
- col ++;
- }
-
- sprintf(s, "%f", node->value.real);
- if (mxml_write_string(s, p, putc_cb) < 0)
- return (-1);
-
- col += strlen(s);
- break;
-
- case MXML_TEXT :
- if (node->value.text.whitespace && col > 0)
- {
- if (global->wrap > 0 && col > global->wrap)
- {
- if ((*putc_cb)('\n', p) < 0)
- return (-1);
-
- col = 0;
- }
- else if ((*putc_cb)(' ', p) < 0)
- return (-1);
- else
- col ++;
- }
-
- if (mxml_write_string(node->value.text.string, p, putc_cb) < 0)
- return (-1);
-
- col += strlen(node->value.text.string);
- break;
-
- case MXML_CUSTOM :
- if (global->custom_save_cb)
- {
- char *data; /* Custom data string */
- const char *newline; /* Last newline in string */
-
-
- if ((data = (*global->custom_save_cb)(node)) == NULL)
- return (-1);
-
- if (mxml_write_string(data, p, putc_cb) < 0)
- return (-1);
-
- if ((newline = strrchr(data, '\n')) == NULL)
- col += strlen(data);
- else
- col = strlen(newline);
-
- free(data);
- break;
- }
-
- default : /* Should never happen */
- return (-1);
- }
-
- return (col);
-}
-
-
-/*
- * 'mxml_write_string()' - Write a string, escaping & and < as needed.
- */
-
-static int /* O - 0 on success, -1 on failure */
-mxml_write_string(
- const char *s, /* I - String to write */
- void *p, /* I - Write pointer */
- _mxml_putc_cb_t putc_cb) /* I - Write callback */
-{
- const char *name; /* Entity name, if any */
-
-
- while (*s)
- {
- if ((name = mxmlEntityGetName(*s)) != NULL)
- {
- if ((*putc_cb)('&', p) < 0)
- return (-1);
-
- while (*name)
- {
- if ((*putc_cb)(*name, p) < 0)
- return (-1);
- name ++;
- }
-
- if ((*putc_cb)(';', p) < 0)
- return (-1);
- }
- else if ((*putc_cb)(*s, p) < 0)
- return (-1);
-
- s ++;
- }
-
- return (0);
-}
-
-
-/*
- * 'mxml_write_ws()' - Do whitespace callback...
- */
-
-static int /* O - New column */
-mxml_write_ws(mxml_node_t *node, /* I - Current node */
- void *p, /* I - Write pointer */
- mxml_save_cb_t cb, /* I - Callback function */
- int ws, /* I - Where value */
- int col, /* I - Current column */
- _mxml_putc_cb_t putc_cb) /* I - Write callback */
-{
- const char *s; /* Whitespace string */
-
-
- if (cb && (s = (*cb)(node, ws)) != NULL)
- {
- while (*s)
- {
- if ((*putc_cb)(*s, p) < 0)
- return (-1);
- else if (*s == '\n')
- col = 0;
- else if (*s == '\t')
- {
- col += MXML_TAB;
- col = col - (col % MXML_TAB);
- }
- else
- col ++;
-
- s ++;
- }
- }
-
- return (col);
-}
-
-
-/*
- * End of "$Id: mxml-file.c 438 2011-03-24 05:47:51Z mike $".
- */
+++ /dev/null
-/*
- * "$Id: mxml-get.c 427 2011-01-03 02:03:29Z mike $"
- *
- * Node get functions for Mini-XML, a small XML-like file parsing library.
- *
- * Copyright 2011 by Michael R Sweet.
- *
- * These coded instructions, statements, and computer programs are the
- * property of Michael R Sweet and are protected by Federal copyright
- * law. Distribution and use rights are outlined in the file "COPYING"
- * which should have been included with this file. If this file is
- * missing or damaged, see the license at:
- *
- * http://www.minixml.org/
- *
- * Contents:
- *
- * mxmlGetCDATA() - Get the value for a CDATA node.
- * mxmlGetCustom() - Get the value for a custom node.
- * mxmlGetElement() - Get the name for an element node.
- * mxmlGetFirstChild() - Get the first child of an element node.
- * mxmlGetInteger() - Get the integer value from the specified node or its
- * first child.
- * mxmlGetLastChild() - Get the last child of an element node.
- * mxmlGetNextSibling() - Get the next node for the current parent.
- * mxmlGetOpaque() - Get an opaque string value for a node or its first
- * child.
- * mxmlGetParent() - Get the parent node.
- * mxmlGetPrevSibling() - Get the previous node for the current parent.
- * mxmlGetReal() - Get the real value for a node or its first child.
- * mxmlGetText() - Get the text value for a node or its first child.
- * mxmlGetType() - Get the node type.
- * mxmlGetUserData() - Get the user data pointer for a node.
- */
-
-/*
- * Include necessary headers...
- */
-
-#include "config.h"
-#include "mxml.h"
-
-
-/*
- * 'mxmlGetCDATA()' - Get the value for a CDATA node.
- *
- * @code NULL@ is returned if the node is not a CDATA element.
- *
- * @since Mini-XML 2.7@
- */
-
-const char * /* O - CDATA value or NULL */
-mxmlGetCDATA(mxml_node_t *node) /* I - Node to get */
-{
- /*
- * Range check input...
- */
-
- if (!node || node->type != MXML_ELEMENT ||
- strncmp(node->value.element.name, "![CDATA[", 8))
- return (NULL);
-
- /*
- * Return the text following the CDATA declaration...
- */
-
- return (node->value.element.name + 8);
-}
-
-
-/*
- * 'mxmlGetCustom()' - Get the value for a custom node.
- *
- * @code NULL@ is returned if the node (or its first child) is not a custom
- * value node.
- *
- * @since Mini-XML 2.7@
- */
-
-const void * /* O - Custom value or NULL */
-mxmlGetCustom(mxml_node_t *node) /* I - Node to get */
-{
- /*
- * Range check input...
- */
-
- if (!node)
- return (NULL);
-
- /*
- * Return the integer value...
- */
-
- if (node->type == MXML_CUSTOM)
- return (node->value.custom.data);
- else if (node->type == MXML_ELEMENT &&
- node->child &&
- node->child->type == MXML_CUSTOM)
- return (node->child->value.custom.data);
- else
- return (NULL);
-}
-
-
-/*
- * 'mxmlGetElement()' - Get the name for an element node.
- *
- * @code NULL@ is returned if the node is not an element node.
- *
- * @since Mini-XML 2.7@
- */
-
-const char * /* O - Element name or NULL */
-mxmlGetElement(mxml_node_t *node) /* I - Node to get */
-{
- /*
- * Range check input...
- */
-
- if (!node || node->type != MXML_ELEMENT)
- return (NULL);
-
- /*
- * Return the element name...
- */
-
- return (node->value.element.name);
-}
-
-
-/*
- * 'mxmlGetFirstChild()' - Get the first child of an element node.
- *
- * @code NULL@ is returned if the node is not an element node or if the node
- * has no children.
- *
- * @since Mini-XML 2.7@
- */
-
-mxml_node_t * /* O - First child or NULL */
-mxmlGetFirstChild(mxml_node_t *node) /* I - Node to get */
-{
- /*
- * Range check input...
- */
-
- if (!node || node->type != MXML_ELEMENT)
- return (NULL);
-
- /*
- * Return the first child node...
- */
-
- return (node->child);
-}
-
-
-/*
- * 'mxmlGetInteger()' - Get the integer value from the specified node or its
- * first child.
- *
- * 0 is returned if the node (or its first child) is not an integer value node.
- *
- * @since Mini-XML 2.7@
- */
-
-int /* O - Integer value or 0 */
-mxmlGetInteger(mxml_node_t *node) /* I - Node to get */
-{
- /*
- * Range check input...
- */
-
- if (!node)
- return (0);
-
- /*
- * Return the integer value...
- */
-
- if (node->type == MXML_INTEGER)
- return (node->value.integer);
- else if (node->type == MXML_ELEMENT &&
- node->child &&
- node->child->type == MXML_INTEGER)
- return (node->child->value.integer);
- else
- return (0);
-}
-
-
-/*
- * 'mxmlGetLastChild()' - Get the last child of an element node.
- *
- * @code NULL@ is returned if the node is not an element node or if the node
- * has no children.
- *
- * @since Mini-XML 2.7@
- */
-
-mxml_node_t * /* O - Last child or NULL */
-mxmlGetLastChild(mxml_node_t *node) /* I - Node to get */
-{
- /*
- * Range check input...
- */
-
- if (!node || node->type != MXML_ELEMENT)
- return (NULL);
-
- /*
- * Return the node type...
- */
-
- return (node->last_child);
-}
-
-
-/*
- * 'mxmlGetNextSibling()' - Get the next node for the current parent.
- *
- * @code NULL@ is returned if this is the last child for the current parent.
- *
- * @since Mini-XML 2.7@
- */
-
-mxml_node_t *
-mxmlGetNextSibling(mxml_node_t *node) /* I - Node to get */
-{
- /*
- * Range check input...
- */
-
- if (!node)
- return (NULL);
-
- /*
- * Return the node type...
- */
-
- return (node->next);
-}
-
-
-/*
- * 'mxmlGetOpaque()' - Get an opaque string value for a node or its first child.
- *
- * @code NULL@ is returned if the node (or its first child) is not an opaque
- * value node.
- *
- * @since Mini-XML 2.7@
- */
-
-const char * /* O - Opaque string or NULL */
-mxmlGetOpaque(mxml_node_t *node) /* I - Node to get */
-{
- /*
- * Range check input...
- */
-
- if (!node)
- return (NULL);
-
- /*
- * Return the integer value...
- */
-
- if (node->type == MXML_OPAQUE)
- return (node->value.opaque);
- else if (node->type == MXML_ELEMENT &&
- node->child &&
- node->child->type == MXML_OPAQUE)
- return (node->child->value.opaque);
- else
- return (NULL);
-}
-
-
-/*
- * 'mxmlGetParent()' - Get the parent node.
- *
- * @code NULL@ is returned for a root node.
- *
- * @since Mini-XML 2.7@
- */
-
-mxml_node_t * /* O - Parent node or NULL */
-mxmlGetParent(mxml_node_t *node) /* I - Node to get */
-{
- /*
- * Range check input...
- */
-
- if (!node)
- return (NULL);
-
- /*
- * Return the node type...
- */
-
- return (node->parent);
-}
-
-
-/*
- * 'mxmlGetPrevSibling()' - Get the previous node for the current parent.
- *
- * @code NULL@ is returned if this is the first child for the current parent.
- *
- * @since Mini-XML 2.7@
- */
-
-mxml_node_t * /* O - Previous node or NULL */
-mxmlGetPrevSibling(mxml_node_t *node) /* I - Node to get */
-{
- /*
- * Range check input...
- */
-
- if (!node)
- return (NULL);
-
- /*
- * Return the node type...
- */
-
- return (node->prev);
-}
-
-
-/*
- * 'mxmlGetReal()' - Get the real value for a node or its first child.
- *
- * 0.0 is returned if the node (or its first child) is not a real value node.
- *
- * @since Mini-XML 2.7@
- */
-
-double /* O - Real value or 0.0 */
-mxmlGetReal(mxml_node_t *node) /* I - Node to get */
-{
- /*
- * Range check input...
- */
-
- if (!node)
- return (0.0);
-
- /*
- * Return the integer value...
- */
-
- if (node->type == MXML_REAL)
- return (node->value.real);
- else if (node->type == MXML_ELEMENT &&
- node->child &&
- node->child->type == MXML_REAL)
- return (node->child->value.real);
- else
- return (0.0);
-}
-
-
-/*
- * 'mxmlGetText()' - Get the text value for a node or its first child.
- *
- * @code NULL@ is returned if the node (or its first child) is not a text node.
- * The "whitespace" argument can be NULL.
- *
- * @since Mini-XML 2.7@
- */
-
-const char * /* O - Text string or NULL */
-mxmlGetText(mxml_node_t *node, /* I - Node to get */
- int *whitespace) /* O - 1 if string is preceded by whitespace, 0 otherwise */
-{
- /*
- * Range check input...
- */
-
- if (!node)
- {
- if (whitespace)
- *whitespace = 0;
-
- return (NULL);
- }
-
- /*
- * Return the integer value...
- */
-
- if (node->type == MXML_TEXT)
- {
- if (whitespace)
- *whitespace = node->value.text.whitespace;
-
- return (node->value.text.string);
- }
- else if (node->type == MXML_ELEMENT &&
- node->child &&
- node->child->type == MXML_TEXT)
- {
- if (whitespace)
- *whitespace = node->child->value.text.whitespace;
-
- return (node->child->value.text.string);
- }
- else
- {
- if (whitespace)
- *whitespace = 0;
-
- return (NULL);
- }
-}
-
-
-/*
- * 'mxmlGetType()' - Get the node type.
- *
- * @code MXML_IGNORE@ is returned if "node" is @code NULL@.
- *
- * @since Mini-XML 2.7@
- */
-
-mxml_type_t /* O - Type of node */
-mxmlGetType(mxml_node_t *node) /* I - Node to get */
-{
- /*
- * Range check input...
- */
-
- if (!node)
- return (MXML_IGNORE);
-
- /*
- * Return the node type...
- */
-
- return (node->type);
-}
-
-
-/*
- * 'mxmlGetUserData()' - Get the user data pointer for a node.
- *
- * @since Mini-XML 2.7@
- */
-
-void * /* O - User data pointer */
-mxmlGetUserData(mxml_node_t *node) /* I - Node to get */
-{
- /*
- * Range check input...
- */
-
- if (!node)
- return (NULL);
-
- /*
- * Return the user data pointer...
- */
-
- return (node->user_data);
-}
-
-
-/*
- * End of "$Id: mxml-get.c 427 2011-01-03 02:03:29Z mike $".
- */
+++ /dev/null
-/*
- * "$Id: mxml-index.c 426 2011-01-01 23:42:17Z mike $"
- *
- * Index support code for Mini-XML, a small XML-like file parsing library.
- *
- * Copyright 2003-2011 by Michael R Sweet.
- *
- * These coded instructions, statements, and computer programs are the
- * property of Michael R Sweet and are protected by Federal copyright
- * law. Distribution and use rights are outlined in the file "COPYING"
- * which should have been included with this file. If this file is
- * missing or damaged, see the license at:
- *
- * http://www.minixml.org/
- *
- * Contents:
- *
- */
-
-/*
- * Include necessary headers...
- */
-
-#include "config.h"
-#include "mxml.h"
-
-
-/*
- * Sort functions...
- */
-
-static int index_compare(mxml_index_t *ind, mxml_node_t *first,
- mxml_node_t *second);
-static int index_find(mxml_index_t *ind, const char *element,
- const char *value, mxml_node_t *node);
-static void index_sort(mxml_index_t *ind, int left, int right);
-
-
-/*
- * 'mxmlIndexDelete()' - Delete an index.
- */
-
-void
-mxmlIndexDelete(mxml_index_t *ind) /* I - Index to delete */
-{
- /*
- * Range check input..
- */
-
- if (!ind)
- return;
-
- /*
- * Free memory...
- */
-
- if (ind->attr)
- free(ind->attr);
-
- if (ind->alloc_nodes)
- free(ind->nodes);
-
- free(ind);
-}
-
-
-/*
- * 'mxmlIndexEnum()' - Return the next node in the index.
- *
- * Nodes are returned in the sorted order of the index.
- */
-
-mxml_node_t * /* O - Next node or NULL if there is none */
-mxmlIndexEnum(mxml_index_t *ind) /* I - Index to enumerate */
-{
- /*
- * Range check input...
- */
-
- if (!ind)
- return (NULL);
-
- /*
- * Return the next node...
- */
-
- if (ind->cur_node < ind->num_nodes)
- return (ind->nodes[ind->cur_node ++]);
- else
- return (NULL);
-}
-
-
-/*
- * 'mxmlIndexFind()' - Find the next matching node.
- *
- * You should call mxmlIndexReset() prior to using this function for
- * the first time with a particular set of "element" and "value"
- * strings. Passing NULL for both "element" and "value" is equivalent
- * to calling mxmlIndexEnum().
- */
-
-mxml_node_t * /* O - Node or NULL if none found */
-mxmlIndexFind(mxml_index_t *ind, /* I - Index to search */
- const char *element, /* I - Element name to find, if any */
- const char *value) /* I - Attribute value, if any */
-{
- int diff, /* Difference between names */
- current, /* Current entity in search */
- first, /* First entity in search */
- last; /* Last entity in search */
-
-
-#ifdef DEBUG
- printf("mxmlIndexFind(ind=%p, element=\"%s\", value=\"%s\")\n",
- ind, element ? element : "(null)", value ? value : "(null)");
-#endif /* DEBUG */
-
- /*
- * Range check input...
- */
-
- if (!ind || (!ind->attr && value))
- {
-#ifdef DEBUG
- puts(" returning NULL...");
- printf(" ind->attr=\"%s\"\n", ind->attr ? ind->attr : "(null)");
-#endif /* DEBUG */
-
- return (NULL);
- }
-
- /*
- * If both element and value are NULL, just enumerate the nodes in the
- * index...
- */
-
- if (!element && !value)
- return (mxmlIndexEnum(ind));
-
- /*
- * If there are no nodes in the index, return NULL...
- */
-
- if (!ind->num_nodes)
- {
-#ifdef DEBUG
- puts(" returning NULL...");
- puts(" no nodes!");
-#endif /* DEBUG */
-
- return (NULL);
- }
-
- /*
- * If cur_node == 0, then find the first matching node...
- */
-
- if (ind->cur_node == 0)
- {
- /*
- * Find the first node using a modified binary search algorithm...
- */
-
- first = 0;
- last = ind->num_nodes - 1;
-
-#ifdef DEBUG
- printf(" find first time, num_nodes=%d...\n", ind->num_nodes);
-#endif /* DEBUG */
-
- while ((last - first) > 1)
- {
- current = (first + last) / 2;
-
-#ifdef DEBUG
- printf(" first=%d, last=%d, current=%d\n", first, last, current);
-#endif /* DEBUG */
-
- if ((diff = index_find(ind, element, value, ind->nodes[current])) == 0)
- {
- /*
- * Found a match, move back to find the first...
- */
-
-#ifdef DEBUG
- puts(" match!");
-#endif /* DEBUG */
-
- while (current > 0 &&
- !index_find(ind, element, value, ind->nodes[current - 1]))
- current --;
-
-#ifdef DEBUG
- printf(" returning first match=%d\n", current);
-#endif /* DEBUG */
-
- /*
- * Return the first match and save the index to the next...
- */
-
- ind->cur_node = current + 1;
-
- return (ind->nodes[current]);
- }
- else if (diff < 0)
- last = current;
- else
- first = current;
-
-#ifdef DEBUG
- printf(" diff=%d\n", diff);
-#endif /* DEBUG */
- }
-
- /*
- * If we get this far, then we found exactly 0 or 1 matches...
- */
-
- for (current = first; current <= last; current ++)
- if (!index_find(ind, element, value, ind->nodes[current]))
- {
- /*
- * Found exactly one (or possibly two) match...
- */
-
-#ifdef DEBUG
- printf(" returning only match %d...\n", current);
-#endif /* DEBUG */
-
- ind->cur_node = current + 1;
-
- return (ind->nodes[current]);
- }
-
- /*
- * No matches...
- */
-
- ind->cur_node = ind->num_nodes;
-
-#ifdef DEBUG
- puts(" returning NULL...");
-#endif /* DEBUG */
-
- return (NULL);
- }
- else if (ind->cur_node < ind->num_nodes &&
- !index_find(ind, element, value, ind->nodes[ind->cur_node]))
- {
- /*
- * Return the next matching node...
- */
-
-#ifdef DEBUG
- printf(" returning next match %d...\n", ind->cur_node);
-#endif /* DEBUG */
-
- return (ind->nodes[ind->cur_node ++]);
- }
-
- /*
- * If we get this far, then we have no matches...
- */
-
- ind->cur_node = ind->num_nodes;
-
-#ifdef DEBUG
- puts(" returning NULL...");
-#endif /* DEBUG */
-
- return (NULL);
-}
-
-
-/*
- * 'mxmlIndexGetCount()' - Get the number of nodes in an index.
- *
- * @since Mini-XML 2.7@
- */
-
-int /* I - Number of nodes in index */
-mxmlIndexGetCount(mxml_index_t *ind) /* I - Index of nodes */
-{
- /*
- * Range check input...
- */
-
- if (!ind)
- return (0);
-
- /*
- * Return the number of nodes in the index...
- */
-
- return (ind->num_nodes);
-}
-
-
-/*
- * 'mxmlIndexNew()' - Create a new index.
- *
- * The index will contain all nodes that contain the named element and/or
- * attribute. If both "element" and "attr" are NULL, then the index will
- * contain a sorted list of the elements in the node tree. Nodes are
- * sorted by element name and optionally by attribute value if the "attr"
- * argument is not NULL.
- */
-
-mxml_index_t * /* O - New index */
-mxmlIndexNew(mxml_node_t *node, /* I - XML node tree */
- const char *element, /* I - Element to index or NULL for all */
- const char *attr) /* I - Attribute to index or NULL for none */
-{
- mxml_index_t *ind; /* New index */
- mxml_node_t *current, /* Current node in index */
- **temp; /* Temporary node pointer array */
-
-
- /*
- * Range check input...
- */
-
-#ifdef DEBUG
- printf("mxmlIndexNew(node=%p, element=\"%s\", attr=\"%s\")\n",
- node, element ? element : "(null)", attr ? attr : "(null)");
-#endif /* DEBUG */
-
- if (!node)
- return (NULL);
-
- /*
- * Create a new index...
- */
-
- if ((ind = calloc(1, sizeof(mxml_index_t))) == NULL)
- {
- mxml_error("Unable to allocate %d bytes for index - %s",
- sizeof(mxml_index_t), strerror(errno));
- return (NULL);
- }
-
- if (attr)
- ind->attr = strdup(attr);
-
- if (!element && !attr)
- current = node;
- else
- current = mxmlFindElement(node, node, element, attr, NULL, MXML_DESCEND);
-
- while (current)
- {
- if (ind->num_nodes >= ind->alloc_nodes)
- {
- if (!ind->alloc_nodes)
- temp = malloc(64 * sizeof(mxml_node_t *));
- else
- temp = realloc(ind->nodes, (ind->alloc_nodes + 64) * sizeof(mxml_node_t *));
-
- if (!temp)
- {
- /*
- * Unable to allocate memory for the index, so abort...
- */
-
- mxml_error("Unable to allocate %d bytes for index: %s",
- (ind->alloc_nodes + 64) * sizeof(mxml_node_t *),
- strerror(errno));
-
- mxmlIndexDelete(ind);
- return (NULL);
- }
-
- ind->nodes = temp;
- ind->alloc_nodes += 64;
- }
-
- ind->nodes[ind->num_nodes ++] = current;
-
- current = mxmlFindElement(current, node, element, attr, NULL, MXML_DESCEND);
- }
-
- /*
- * Sort nodes based upon the search criteria...
- */
-
-#ifdef DEBUG
- {
- int i; /* Looping var */
-
-
- printf("%d node(s) in index.\n\n", ind->num_nodes);
-
- if (attr)
- {
- printf("Node Address Element %s\n", attr);
- puts("-------- -------- -------------- ------------------------------");
-
- for (i = 0; i < ind->num_nodes; i ++)
- printf("%8d %-8p %-14.14s %s\n", i, ind->nodes[i],
- ind->nodes[i]->value.element.name,
- mxmlElementGetAttr(ind->nodes[i], attr));
- }
- else
- {
- puts("Node Address Element");
- puts("-------- -------- --------------");
-
- for (i = 0; i < ind->num_nodes; i ++)
- printf("%8d %-8p %s\n", i, ind->nodes[i],
- ind->nodes[i]->value.element.name);
- }
-
- putchar('\n');
- }
-#endif /* DEBUG */
-
- if (ind->num_nodes > 1)
- index_sort(ind, 0, ind->num_nodes - 1);
-
-#ifdef DEBUG
- {
- int i; /* Looping var */
-
-
- puts("After sorting:\n");
-
- if (attr)
- {
- printf("Node Address Element %s\n", attr);
- puts("-------- -------- -------------- ------------------------------");
-
- for (i = 0; i < ind->num_nodes; i ++)
- printf("%8d %-8p %-14.14s %s\n", i, ind->nodes[i],
- ind->nodes[i]->value.element.name,
- mxmlElementGetAttr(ind->nodes[i], attr));
- }
- else
- {
- puts("Node Address Element");
- puts("-------- -------- --------------");
-
- for (i = 0; i < ind->num_nodes; i ++)
- printf("%8d %-8p %s\n", i, ind->nodes[i],
- ind->nodes[i]->value.element.name);
- }
-
- putchar('\n');
- }
-#endif /* DEBUG */
-
- /*
- * Return the new index...
- */
-
- return (ind);
-}
-
-
-/*
- * 'mxmlIndexReset()' - Reset the enumeration/find pointer in the index and
- * return the first node in the index.
- *
- * This function should be called prior to using mxmlIndexEnum() or
- * mxmlIndexFind() for the first time.
- */
-
-mxml_node_t * /* O - First node or NULL if there is none */
-mxmlIndexReset(mxml_index_t *ind) /* I - Index to reset */
-{
-#ifdef DEBUG
- printf("mxmlIndexReset(ind=%p)\n", ind);
-#endif /* DEBUG */
-
- /*
- * Range check input...
- */
-
- if (!ind)
- return (NULL);
-
- /*
- * Set the index to the first element...
- */
-
- ind->cur_node = 0;
-
- /*
- * Return the first node...
- */
-
- if (ind->num_nodes)
- return (ind->nodes[0]);
- else
- return (NULL);
-}
-
-
-/*
- * 'index_compare()' - Compare two nodes.
- */
-
-static int /* O - Result of comparison */
-index_compare(mxml_index_t *ind, /* I - Index */
- mxml_node_t *first, /* I - First node */
- mxml_node_t *second) /* I - Second node */
-{
- int diff; /* Difference */
-
-
- /*
- * Check the element name...
- */
-
- if ((diff = strcmp(first->value.element.name,
- second->value.element.name)) != 0)
- return (diff);
-
- /*
- * Check the attribute value...
- */
-
- if (ind->attr)
- {
- if ((diff = strcmp(mxmlElementGetAttr(first, ind->attr),
- mxmlElementGetAttr(second, ind->attr))) != 0)
- return (diff);
- }
-
- /*
- * No difference, return 0...
- */
-
- return (0);
-}
-
-
-/*
- * 'index_find()' - Compare a node with index values.
- */
-
-static int /* O - Result of comparison */
-index_find(mxml_index_t *ind, /* I - Index */
- const char *element, /* I - Element name or NULL */
- const char *value, /* I - Attribute value or NULL */
- mxml_node_t *node) /* I - Node */
-{
- int diff; /* Difference */
-
-
- /*
- * Check the element name...
- */
-
- if (element)
- {
- if ((diff = strcmp(element, node->value.element.name)) != 0)
- return (diff);
- }
-
- /*
- * Check the attribute value...
- */
-
- if (value)
- {
- if ((diff = strcmp(value, mxmlElementGetAttr(node, ind->attr))) != 0)
- return (diff);
- }
-
- /*
- * No difference, return 0...
- */
-
- return (0);
-}
-
-
-/*
- * 'index_sort()' - Sort the nodes in the index...
- *
- * This function implements the classic quicksort algorithm...
- */
-
-static void
-index_sort(mxml_index_t *ind, /* I - Index to sort */
- int left, /* I - Left node in partition */
- int right) /* I - Right node in partition */
-{
- mxml_node_t *pivot, /* Pivot node */
- *temp; /* Swap node */
- int templ, /* Temporary left node */
- tempr; /* Temporary right node */
-
-
- /*
- * Loop until we have sorted all the way to the right...
- */
-
- do
- {
- /*
- * Sort the pivot in the current partition...
- */
-
- pivot = ind->nodes[left];
-
- for (templ = left, tempr = right; templ < tempr;)
- {
- /*
- * Move left while left node <= pivot node...
- */
-
- while ((templ < right) &&
- index_compare(ind, ind->nodes[templ], pivot) <= 0)
- templ ++;
-
- /*
- * Move right while right node > pivot node...
- */
-
- while ((tempr > left) &&
- index_compare(ind, ind->nodes[tempr], pivot) > 0)
- tempr --;
-
- /*
- * Swap nodes if needed...
- */
-
- if (templ < tempr)
- {
- temp = ind->nodes[templ];
- ind->nodes[templ] = ind->nodes[tempr];
- ind->nodes[tempr] = temp;
- }
- }
-
- /*
- * When we get here, the right (tempr) node is the new position for the
- * pivot node...
- */
-
- if (index_compare(ind, pivot, ind->nodes[tempr]) > 0)
- {
- ind->nodes[left] = ind->nodes[tempr];
- ind->nodes[tempr] = pivot;
- }
-
- /*
- * Recursively sort the left partition as needed...
- */
-
- if (left < (tempr - 1))
- index_sort(ind, left, tempr - 1);
- }
- while (right > (left = tempr + 1));
-}
-
-
-/*
- * End of "$Id: mxml-index.c 426 2011-01-01 23:42:17Z mike $".
- */
+++ /dev/null
-/*
- * "$Id: mxml-node.c 436 2011-01-22 01:02:05Z mike $"
- *
- * Node support code for Mini-XML, a small XML-like file parsing library.
- *
- * Copyright 2003-2011 by Michael R Sweet.
- *
- * These coded instructions, statements, and computer programs are the
- * property of Michael R Sweet and are protected by Federal copyright
- * law. Distribution and use rights are outlined in the file "COPYING"
- * which should have been included with this file. If this file is
- * missing or damaged, see the license at:
- *
- * http://www.minixml.org/
- *
- * Contents:
- *
- * mxmlAdd() - Add a node to a tree.
- * mxmlDelete() - Delete a node and all of its children.
- * mxmlGetRefCount() - Get the current reference (use) count for a node.
- * mxmlNewCDATA() - Create a new CDATA node.
- * mxmlNewCustom() - Create a new custom data node.
- * mxmlNewElement() - Create a new element node.
- * mxmlNewInteger() - Create a new integer node.
- * mxmlNewOpaque() - Create a new opaque string.
- * mxmlNewReal() - Create a new real number node.
- * mxmlNewText() - Create a new text fragment node.
- * mxmlNewTextf() - Create a new formatted text fragment node.
- * mxmlRemove() - Remove a node from its parent.
- * mxmlNewXML() - Create a new XML document tree.
- * mxmlRelease() - Release a node.
- * mxmlRetain() - Retain a node.
- * mxml_new() - Create a new node.
- */
-
-/*
- * Include necessary headers...
- */
-
-#include "config.h"
-#include "mxml.h"
-
-
-/*
- * Local functions...
- */
-
-static mxml_node_t *mxml_new(mxml_node_t *parent, mxml_type_t type);
-
-
-/*
- * 'mxmlAdd()' - Add a node to a tree.
- *
- * Adds the specified node to the parent. If the child argument is not
- * NULL, puts the new node before or after the specified child depending
- * on the value of the where argument. If the child argument is NULL,
- * puts the new node at the beginning of the child list (MXML_ADD_BEFORE)
- * or at the end of the child list (MXML_ADD_AFTER). The constant
- * MXML_ADD_TO_PARENT can be used to specify a NULL child pointer.
- */
-
-void
-mxmlAdd(mxml_node_t *parent, /* I - Parent node */
- int where, /* I - Where to add, MXML_ADD_BEFORE or MXML_ADD_AFTER */
- mxml_node_t *child, /* I - Child node for where or MXML_ADD_TO_PARENT */
- mxml_node_t *node) /* I - Node to add */
-{
-#ifdef DEBUG
- fprintf(stderr, "mxmlAdd(parent=%p, where=%d, child=%p, node=%p)\n", parent,
- where, child, node);
-#endif /* DEBUG */
-
- /*
- * Range check input...
- */
-
- if (!parent || !node)
- return;
-
-#if DEBUG > 1
- fprintf(stderr, " BEFORE: node->parent=%p\n", node->parent);
- if (parent)
- {
- fprintf(stderr, " BEFORE: parent->child=%p\n", parent->child);
- fprintf(stderr, " BEFORE: parent->last_child=%p\n", parent->last_child);
- fprintf(stderr, " BEFORE: parent->prev=%p\n", parent->prev);
- fprintf(stderr, " BEFORE: parent->next=%p\n", parent->next);
- }
-#endif /* DEBUG > 1 */
-
- /*
- * Remove the node from any existing parent...
- */
-
- if (node->parent)
- mxmlRemove(node);
-
- /*
- * Reset pointers...
- */
-
- node->parent = parent;
-
- switch (where)
- {
- case MXML_ADD_BEFORE :
- if (!child || child == parent->child || child->parent != parent)
- {
- /*
- * Insert as first node under parent...
- */
-
- node->next = parent->child;
-
- if (parent->child)
- parent->child->prev = node;
- else
- parent->last_child = node;
-
- parent->child = node;
- }
- else
- {
- /*
- * Insert node before this child...
- */
-
- node->next = child;
- node->prev = child->prev;
-
- if (child->prev)
- child->prev->next = node;
- else
- parent->child = node;
-
- child->prev = node;
- }
- break;
-
- case MXML_ADD_AFTER :
- if (!child || child == parent->last_child || child->parent != parent)
- {
- /*
- * Insert as last node under parent...
- */
-
- node->parent = parent;
- node->prev = parent->last_child;
-
- if (parent->last_child)
- parent->last_child->next = node;
- else
- parent->child = node;
-
- parent->last_child = node;
- }
- else
- {
- /*
- * Insert node after this child...
- */
-
- node->prev = child;
- node->next = child->next;
-
- if (child->next)
- child->next->prev = node;
- else
- parent->last_child = node;
-
- child->next = node;
- }
- break;
- }
-
-#if DEBUG > 1
- fprintf(stderr, " AFTER: node->parent=%p\n", node->parent);
- if (parent)
- {
- fprintf(stderr, " AFTER: parent->child=%p\n", parent->child);
- fprintf(stderr, " AFTER: parent->last_child=%p\n", parent->last_child);
- fprintf(stderr, " AFTER: parent->prev=%p\n", parent->prev);
- fprintf(stderr, " AFTER: parent->next=%p\n", parent->next);
- }
-#endif /* DEBUG > 1 */
-}
-
-
-/*
- * 'mxmlDelete()' - Delete a node and all of its children.
- *
- * If the specified node has a parent, this function first removes the
- * node from its parent using the mxmlRemove() function.
- */
-
-void
-mxmlDelete(mxml_node_t *node) /* I - Node to delete */
-{
- int i; /* Looping var */
-
-
-#ifdef DEBUG
- fprintf(stderr, "mxmlDelete(node=%p)\n", node);
-#endif /* DEBUG */
-
- /*
- * Range check input...
- */
-
- if (!node)
- return;
-
- /*
- * Remove the node from its parent, if any...
- */
-
- mxmlRemove(node);
-
- /*
- * Delete children...
- */
-
- while (node->child)
- mxmlDelete(node->child);
-
- /*
- * Now delete any node data...
- */
-
- switch (node->type)
- {
- case MXML_ELEMENT :
- if (node->value.element.name)
- free(node->value.element.name);
-
- if (node->value.element.num_attrs)
- {
- for (i = 0; i < node->value.element.num_attrs; i ++)
- {
- if (node->value.element.attrs[i].name)
- free(node->value.element.attrs[i].name);
- if (node->value.element.attrs[i].value)
- free(node->value.element.attrs[i].value);
- }
-
- free(node->value.element.attrs);
- }
- break;
- case MXML_INTEGER :
- /* Nothing to do */
- break;
- case MXML_OPAQUE :
- if (node->value.opaque)
- free(node->value.opaque);
- break;
- case MXML_REAL :
- /* Nothing to do */
- break;
- case MXML_TEXT :
- if (node->value.text.string)
- free(node->value.text.string);
- break;
- case MXML_CUSTOM :
- if (node->value.custom.data &&
- node->value.custom.destroy)
- (*(node->value.custom.destroy))(node->value.custom.data);
- break;
- default :
- break;
- }
-
- /*
- * Free this node...
- */
-
- free(node);
-}
-
-
-/*
- * 'mxmlGetRefCount()' - Get the current reference (use) count for a node.
- *
- * The initial reference count of new nodes is 1. Use the @link mxmlRetain@
- * and @link mxmlRelease@ functions to increment and decrement a node's
- * reference count.
- *
- * @since Mini-XML 2.7@.
- */
-
-int /* O - Reference count */
-mxmlGetRefCount(mxml_node_t *node) /* I - Node */
-{
- /*
- * Range check input...
- */
-
- if (!node)
- return (0);
-
- /*
- * Return the reference count...
- */
-
- return (node->ref_count);
-}
-
-
-/*
- * 'mxmlNewCDATA()' - Create a new CDATA node.
- *
- * The new CDATA node is added to the end of the specified parent's child
- * list. The constant MXML_NO_PARENT can be used to specify that the new
- * CDATA node has no parent. The data string must be nul-terminated and
- * is copied into the new node. CDATA nodes use the MXML_ELEMENT type.
- *
- * @since Mini-XML 2.3@
- */
-
-mxml_node_t * /* O - New node */
-mxmlNewCDATA(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
- const char *data) /* I - Data string */
-{
- mxml_node_t *node; /* New node */
-
-
-#ifdef DEBUG
- fprintf(stderr, "mxmlNewCDATA(parent=%p, data=\"%s\")\n",
- parent, data ? data : "(null)");
-#endif /* DEBUG */
-
- /*
- * Range check input...
- */
-
- if (!data)
- return (NULL);
-
- /*
- * Create the node and set the name value...
- */
-
- if ((node = mxml_new(parent, MXML_ELEMENT)) != NULL)
- node->value.element.name = _mxml_strdupf("![CDATA[%s]]", data);
-
- return (node);
-}
-
-
-/*
- * 'mxmlNewCustom()' - Create a new custom data node.
- *
- * The new custom node is added to the end of the specified parent's child
- * list. The constant MXML_NO_PARENT can be used to specify that the new
- * element node has no parent. NULL can be passed when the data in the
- * node is not dynamically allocated or is separately managed.
- *
- * @since Mini-XML 2.1@
- */
-
-mxml_node_t * /* O - New node */
-mxmlNewCustom(
- mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
- void *data, /* I - Pointer to data */
- mxml_custom_destroy_cb_t destroy) /* I - Function to destroy data */
-{
- mxml_node_t *node; /* New node */
-
-
-#ifdef DEBUG
- fprintf(stderr, "mxmlNewCustom(parent=%p, data=%p, destroy=%p)\n", parent,
- data, destroy);
-#endif /* DEBUG */
-
- /*
- * Create the node and set the value...
- */
-
- if ((node = mxml_new(parent, MXML_CUSTOM)) != NULL)
- {
- node->value.custom.data = data;
- node->value.custom.destroy = destroy;
- }
-
- return (node);
-}
-
-
-/*
- * 'mxmlNewElement()' - Create a new element node.
- *
- * The new element node is added to the end of the specified parent's child
- * list. The constant MXML_NO_PARENT can be used to specify that the new
- * element node has no parent.
- */
-
-mxml_node_t * /* O - New node */
-mxmlNewElement(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
- const char *name) /* I - Name of element */
-{
- mxml_node_t *node; /* New node */
-
-
-#ifdef DEBUG
- fprintf(stderr, "mxmlNewElement(parent=%p, name=\"%s\")\n", parent,
- name ? name : "(null)");
-#endif /* DEBUG */
-
- /*
- * Range check input...
- */
-
- if (!name)
- return (NULL);
-
- /*
- * Create the node and set the element name...
- */
-
- if ((node = mxml_new(parent, MXML_ELEMENT)) != NULL)
- node->value.element.name = strdup(name);
-
- return (node);
-}
-
-
-/*
- * 'mxmlNewInteger()' - Create a new integer node.
- *
- * The new integer node is added to the end of the specified parent's child
- * list. The constant MXML_NO_PARENT can be used to specify that the new
- * integer node has no parent.
- */
-
-mxml_node_t * /* O - New node */
-mxmlNewInteger(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
- int integer) /* I - Integer value */
-{
- mxml_node_t *node; /* New node */
-
-
-#ifdef DEBUG
- fprintf(stderr, "mxmlNewInteger(parent=%p, integer=%d)\n", parent, integer);
-#endif /* DEBUG */
-
- /*
- * Create the node and set the element name...
- */
-
- if ((node = mxml_new(parent, MXML_INTEGER)) != NULL)
- node->value.integer = integer;
-
- return (node);
-}
-
-
-/*
- * 'mxmlNewOpaque()' - Create a new opaque string.
- *
- * The new opaque node is added to the end of the specified parent's child
- * list. The constant MXML_NO_PARENT can be used to specify that the new
- * opaque node has no parent. The opaque string must be nul-terminated and
- * is copied into the new node.
- */
-
-mxml_node_t * /* O - New node */
-mxmlNewOpaque(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
- const char *opaque) /* I - Opaque string */
-{
- mxml_node_t *node; /* New node */
-
-
-#ifdef DEBUG
- fprintf(stderr, "mxmlNewOpaque(parent=%p, opaque=\"%s\")\n", parent,
- opaque ? opaque : "(null)");
-#endif /* DEBUG */
-
- /*
- * Range check input...
- */
-
- if (!opaque)
- return (NULL);
-
- /*
- * Create the node and set the element name...
- */
-
- if ((node = mxml_new(parent, MXML_OPAQUE)) != NULL)
- node->value.opaque = strdup(opaque);
-
- return (node);
-}
-
-
-/*
- * 'mxmlNewReal()' - Create a new real number node.
- *
- * The new real number node is added to the end of the specified parent's
- * child list. The constant MXML_NO_PARENT can be used to specify that
- * the new real number node has no parent.
- */
-
-mxml_node_t * /* O - New node */
-mxmlNewReal(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
- double real) /* I - Real number value */
-{
- mxml_node_t *node; /* New node */
-
-
-#ifdef DEBUG
- fprintf(stderr, "mxmlNewReal(parent=%p, real=%g)\n", parent, real);
-#endif /* DEBUG */
-
- /*
- * Create the node and set the element name...
- */
-
- if ((node = mxml_new(parent, MXML_REAL)) != NULL)
- node->value.real = real;
-
- return (node);
-}
-
-
-/*
- * 'mxmlNewText()' - Create a new text fragment node.
- *
- * The new text node is added to the end of the specified parent's child
- * list. The constant MXML_NO_PARENT can be used to specify that the new
- * text node has no parent. The whitespace parameter is used to specify
- * whether leading whitespace is present before the node. The text
- * string must be nul-terminated and is copied into the new node.
- */
-
-mxml_node_t * /* O - New node */
-mxmlNewText(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
- int whitespace, /* I - 1 = leading whitespace, 0 = no whitespace */
- const char *string) /* I - String */
-{
- mxml_node_t *node; /* New node */
-
-
-#ifdef DEBUG
- fprintf(stderr, "mxmlNewText(parent=%p, whitespace=%d, string=\"%s\")\n",
- parent, whitespace, string ? string : "(null)");
-#endif /* DEBUG */
-
- /*
- * Range check input...
- */
-
- if (!string)
- return (NULL);
-
- /*
- * Create the node and set the text value...
- */
-
- if ((node = mxml_new(parent, MXML_TEXT)) != NULL)
- {
- node->value.text.whitespace = whitespace;
- node->value.text.string = strdup(string);
- }
-
- return (node);
-}
-
-
-/*
- * 'mxmlNewTextf()' - Create a new formatted text fragment node.
- *
- * The new text node is added to the end of the specified parent's child
- * list. The constant MXML_NO_PARENT can be used to specify that the new
- * text node has no parent. The whitespace parameter is used to specify
- * whether leading whitespace is present before the node. The format
- * string must be nul-terminated and is formatted into the new node.
- */
-
-mxml_node_t * /* O - New node */
-mxmlNewTextf(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
- int whitespace, /* I - 1 = leading whitespace, 0 = no whitespace */
- const char *format, /* I - Printf-style frmat string */
- ...) /* I - Additional args as needed */
-{
- mxml_node_t *node; /* New node */
- va_list ap; /* Pointer to arguments */
-
-
-#ifdef DEBUG
- fprintf(stderr, "mxmlNewTextf(parent=%p, whitespace=%d, format=\"%s\", ...)\n",
- parent, whitespace, format ? format : "(null)");
-#endif /* DEBUG */
-
- /*
- * Range check input...
- */
-
- if (!format)
- return (NULL);
-
- /*
- * Create the node and set the text value...
- */
-
- if ((node = mxml_new(parent, MXML_TEXT)) != NULL)
- {
- va_start(ap, format);
-
- node->value.text.whitespace = whitespace;
- node->value.text.string = _mxml_vstrdupf(format, ap);
-
- va_end(ap);
- }
-
- return (node);
-}
-
-
-/*
- * 'mxmlRemove()' - Remove a node from its parent.
- *
- * Does not free memory used by the node - use mxmlDelete() for that.
- * This function does nothing if the node has no parent.
- */
-
-void
-mxmlRemove(mxml_node_t *node) /* I - Node to remove */
-{
-#ifdef DEBUG
- fprintf(stderr, "mxmlRemove(node=%p)\n", node);
-#endif /* DEBUG */
-
- /*
- * Range check input...
- */
-
- if (!node || !node->parent)
- return;
-
- /*
- * Remove from parent...
- */
-
-#if DEBUG > 1
- fprintf(stderr, " BEFORE: node->parent=%p\n", node->parent);
- if (node->parent)
- {
- fprintf(stderr, " BEFORE: node->parent->child=%p\n", node->parent->child);
- fprintf(stderr, " BEFORE: node->parent->last_child=%p\n", node->parent->last_child);
- }
- fprintf(stderr, " BEFORE: node->child=%p\n", node->child);
- fprintf(stderr, " BEFORE: node->last_child=%p\n", node->last_child);
- fprintf(stderr, " BEFORE: node->prev=%p\n", node->prev);
- fprintf(stderr, " BEFORE: node->next=%p\n", node->next);
-#endif /* DEBUG > 1 */
-
- if (node->prev)
- node->prev->next = node->next;
- else
- node->parent->child = node->next;
-
- if (node->next)
- node->next->prev = node->prev;
- else
- node->parent->last_child = node->prev;
-
- node->parent = NULL;
- node->prev = NULL;
- node->next = NULL;
-
-#if DEBUG > 1
- fprintf(stderr, " AFTER: node->parent=%p\n", node->parent);
- if (node->parent)
- {
- fprintf(stderr, " AFTER: node->parent->child=%p\n", node->parent->child);
- fprintf(stderr, " AFTER: node->parent->last_child=%p\n", node->parent->last_child);
- }
- fprintf(stderr, " AFTER: node->child=%p\n", node->child);
- fprintf(stderr, " AFTER: node->last_child=%p\n", node->last_child);
- fprintf(stderr, " AFTER: node->prev=%p\n", node->prev);
- fprintf(stderr, " AFTER: node->next=%p\n", node->next);
-#endif /* DEBUG > 1 */
-}
-
-
-/*
- * 'mxmlNewXML()' - Create a new XML document tree.
- *
- * The "version" argument specifies the version number to put in the
- * ?xml element node. If NULL, version 1.0 is assumed.
- *
- * @since Mini-XML 2.3@
- */
-
-mxml_node_t * /* O - New ?xml node */
-mxmlNewXML(const char *version) /* I - Version number to use */
-{
- char element[1024]; /* Element text */
-
-
- snprintf(element, sizeof(element), "?xml version=\"%s\" encoding=\"utf-8\"?",
- version ? version : "1.0");
-
- return (mxmlNewElement(NULL, element));
-}
-
-
-/*
- * 'mxmlRelease()' - Release a node.
- *
- * When the reference count reaches zero, the node (and any children)
- * is deleted via mxmlDelete().
- *
- * @since Mini-XML 2.3@
- */
-
-int /* O - New reference count */
-mxmlRelease(mxml_node_t *node) /* I - Node */
-{
- if (node)
- {
- if ((-- node->ref_count) <= 0)
- {
- mxmlDelete(node);
- return (0);
- }
- else
- return (node->ref_count);
- }
- else
- return (-1);
-}
-
-
-/*
- * 'mxmlRetain()' - Retain a node.
- *
- * @since Mini-XML 2.3@
- */
-
-int /* O - New reference count */
-mxmlRetain(mxml_node_t *node) /* I - Node */
-{
- if (node)
- return (++ node->ref_count);
- else
- return (-1);
-}
-
-
-/*
- * 'mxml_new()' - Create a new node.
- */
-
-static mxml_node_t * /* O - New node */
-mxml_new(mxml_node_t *parent, /* I - Parent node */
- mxml_type_t type) /* I - Node type */
-{
- mxml_node_t *node; /* New node */
-
-
-#if DEBUG > 1
- fprintf(stderr, "mxml_new(parent=%p, type=%d)\n", parent, type);
-#endif /* DEBUG > 1 */
-
- /*
- * Allocate memory for the node...
- */
-
- if ((node = calloc(1, sizeof(mxml_node_t))) == NULL)
- {
-#if DEBUG > 1
- fputs(" returning NULL\n", stderr);
-#endif /* DEBUG > 1 */
-
- return (NULL);
- }
-
-#if DEBUG > 1
- fprintf(stderr, " returning %p\n", node);
-#endif /* DEBUG > 1 */
-
- /*
- * Set the node type...
- */
-
- node->type = type;
- node->ref_count = 1;
-
- /*
- * Add to the parent if present...
- */
-
- if (parent)
- mxmlAdd(parent, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, node);
-
- /*
- * Return the new node...
- */
-
- return (node);
-}
-
-
-/*
- * End of "$Id: mxml-node.c 436 2011-01-22 01:02:05Z mike $".
- */
+++ /dev/null
-/*
- * "$Id: mxml-private.c 422 2010-11-07 22:55:11Z mike $"
- *
- * Private functions for Mini-XML, a small XML-like file parsing library.
- *
- * Copyright 2003-2010 by Michael R Sweet.
- *
- * These coded instructions, statements, and computer programs are the
- * property of Michael R Sweet and are protected by Federal copyright
- * law. Distribution and use rights are outlined in the file "COPYING"
- * which should have been included with this file. If this file is
- * missing or damaged, see the license at:
- *
- * http://www.minixml.org/
- *
- * Contents:
- *
- * mxml_error() - Display an error message.
- * mxml_integer_cb() - Default callback for integer values.
- * mxml_opaque_cb() - Default callback for opaque values.
- * mxml_real_cb() - Default callback for real number values.
- * _mxml_global() - Get global data.
- */
-
-/*
- * Include necessary headers...
- */
-
-#include "mxml-private.h"
-
-
-/*
- * Some crazy people think that unloading a shared object is a good or safe
- * thing to do. Unfortunately, most objects are simply *not* safe to unload
- * and bad things *will* happen.
- *
- * The following mess of conditional code allows us to provide a destructor
- * function in Mini-XML for our thread-global storage so that it can possibly
- * be unloaded safely, although since there is no standard way to do so I
- * can't even provide any guarantees that you can do it safely on all platforms.
- *
- * This code currently supports AIX, HP-UX, Linux, Mac OS X, Solaris, and
- * Windows. It might work on the BSDs and IRIX, but I haven't tested that.
- */
-
-#if defined(__sun) || defined(_AIX)
-# pragma fini(_mxml_fini)
-# define _MXML_FINI _mxml_fini
-#elif defined(__hpux)
-# pragma FINI _mxml_fini
-# define _MXML_FINI _mxml_fini
-#elif defined(__GNUC__) /* Linux and Mac OS X */
-# define _MXML_FINI __attribute((destructor)) _mxml_fini
-#else
-# define _MXML_FINI _fini
-#endif /* __sun */
-
-
-/*
- * 'mxml_error()' - Display an error message.
- */
-
-void
-mxml_error(const char *format, /* I - Printf-style format string */
- ...) /* I - Additional arguments as needed */
-{
- va_list ap; /* Pointer to arguments */
- char s[1024]; /* Message string */
- _mxml_global_t *global = _mxml_global();
- /* Global data */
-
-
- /*
- * Range check input...
- */
-
- if (!format)
- return;
-
- /*
- * Format the error message string...
- */
-
- va_start(ap, format);
-
- vsnprintf(s, sizeof(s), format, ap);
-
- va_end(ap);
-
- /*
- * And then display the error message...
- */
-
- if (global->error_cb)
- (*global->error_cb)(s);
- else
- fprintf(stderr, "mxml: %s\n", s);
-}
-
-
-/*
- * 'mxml_ignore_cb()' - Default callback for ignored values.
- */
-
-mxml_type_t /* O - Node type */
-mxml_ignore_cb(mxml_node_t *node) /* I - Current node */
-{
- (void)node;
-
- return (MXML_IGNORE);
-}
-
-
-/*
- * 'mxml_integer_cb()' - Default callback for integer values.
- */
-
-mxml_type_t /* O - Node type */
-mxml_integer_cb(mxml_node_t *node) /* I - Current node */
-{
- (void)node;
-
- return (MXML_INTEGER);
-}
-
-
-/*
- * 'mxml_opaque_cb()' - Default callback for opaque values.
- */
-
-mxml_type_t /* O - Node type */
-mxml_opaque_cb(mxml_node_t *node) /* I - Current node */
-{
- (void)node;
-
- return (MXML_OPAQUE);
-}
-
-
-/*
- * 'mxml_real_cb()' - Default callback for real number values.
- */
-
-mxml_type_t /* O - Node type */
-mxml_real_cb(mxml_node_t *node) /* I - Current node */
-{
- (void)node;
-
- return (MXML_REAL);
-}
-
-
-#ifdef HAVE_PTHREAD_H /**** POSIX threading ****/
-# include <pthread.h>
-
-static pthread_key_t _mxml_key = -1; /* Thread local storage key */
-static pthread_once_t _mxml_key_once = PTHREAD_ONCE_INIT;
- /* One-time initialization object */
-static void _mxml_init(void);
-static void _mxml_destructor(void *g);
-
-
-/*
- * '_mxml_destructor()' - Free memory used for globals...
- */
-
-static void
-_mxml_destructor(void *g) /* I - Global data */
-{
- free(g);
-}
-
-
-/*
- * '_mxml_fini()' - Clean up when unloaded.
- */
-
-static void
-_MXML_FINI(void)
-{
- _mxml_global_t *global; /* Global data */
-
-
- if (_mxml_key != -1)
- {
- if ((global = (_mxml_global_t *)pthread_getspecific(_mxml_key)) != NULL)
- _mxml_destructor(global);
-
- pthread_key_delete(_mxml_key);
- _mxml_key = -1;
- }
-}
-
-
-/*
- * '_mxml_global()' - Get global data.
- */
-
-_mxml_global_t * /* O - Global data */
-_mxml_global(void)
-{
- _mxml_global_t *global; /* Global data */
-
-
- pthread_once(&_mxml_key_once, _mxml_init);
-
- if ((global = (_mxml_global_t *)pthread_getspecific(_mxml_key)) == NULL)
- {
- global = (_mxml_global_t *)calloc(1, sizeof(_mxml_global_t));
- pthread_setspecific(_mxml_key, global);
-
- global->num_entity_cbs = 1;
- global->entity_cbs[0] = _mxml_entity_cb;
- global->wrap = 72;
- }
-
- return (global);
-}
-
-
-/*
- * '_mxml_init()' - Initialize global data...
- */
-
-static void
-_mxml_init(void)
-{
- pthread_key_create(&_mxml_key, _mxml_destructor);
-}
-
-
-#elif defined(WIN32) && defined(MXML1_EXPORTS) /**** WIN32 threading ****/
-# include <windows.h>
-
-static DWORD _mxml_tls_index; /* Index for global storage */
-
-
-/*
- * 'DllMain()' - Main entry for library.
- */
-
-BOOL WINAPI /* O - Success/failure */
-DllMain(HINSTANCE hinst, /* I - DLL module handle */
- DWORD reason, /* I - Reason */
- LPVOID reserved) /* I - Unused */
-{
- _mxml_global_t *global; /* Global data */
-
-
- (void)hinst;
- (void)reserved;
-
- switch (reason)
- {
- case DLL_PROCESS_ATTACH : /* Called on library initialization */
- if ((_mxml_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES)
- return (FALSE);
- break;
-
- case DLL_THREAD_DETACH : /* Called when a thread terminates */
- if ((global = (_mxml_global_t *)TlsGetValue(_mxml_tls_index)) != NULL)
- free(global);
- break;
-
- case DLL_PROCESS_DETACH : /* Called when library is unloaded */
- if ((global = (_mxml_global_t *)TlsGetValue(_mxml_tls_index)) != NULL)
- free(global);
-
- TlsFree(_mxml_tls_index);
- break;
-
- default:
- break;
- }
-
- return (TRUE);
-}
-
-
-/*
- * '_mxml_global()' - Get global data.
- */
-
-_mxml_global_t * /* O - Global data */
-_mxml_global(void)
-{
- _mxml_global_t *global; /* Global data */
-
-
- if ((global = (_mxml_global_t *)TlsGetValue(_mxml_tls_index)) == NULL)
- {
- global = (_mxml_global_t *)calloc(1, sizeof(_mxml_global_t));
-
- global->num_entity_cbs = 1;
- global->entity_cbs[0] = _mxml_entity_cb;
- global->wrap = 72;
-
- TlsSetValue(_mxml_tls_index, (LPVOID)global);
- }
-
- return (global);
-}
-
-
-#else /**** No threading ****/
-/*
- * '_mxml_global()' - Get global data.
- */
-
-_mxml_global_t * /* O - Global data */
-_mxml_global(void)
-{
- static _mxml_global_t global = /* Global data */
- {
- NULL, /* error_cb */
- 1, /* num_entity_cbs */
- { _mxml_entity_cb }, /* entity_cbs */
- 72, /* wrap */
- NULL, /* custom_load_cb */
- NULL /* custom_save_cb */
- };
-
-
- return (&global);
-}
-#endif /* HAVE_PTHREAD_H */
-
-
-/*
- * End of "$Id: mxml-private.c 422 2010-11-07 22:55:11Z mike $".
- */
+++ /dev/null
-/*
- * "$Id: mxml-private.h 408 2010-09-19 05:26:46Z mike $"
- *
- * Private definitions for Mini-XML, a small XML-like file parsing library.
- *
- * Copyright 2003-2010 by Michael R Sweet.
- *
- * These coded instructions, statements, and computer programs are the
- * property of Michael R Sweet and are protected by Federal copyright
- * law. Distribution and use rights are outlined in the file "COPYING"
- * which should have been included with this file. If this file is
- * missing or damaged, see the license at:
- *
- * http://www.minixml.org/
- */
-
-/*
- * Include necessary headers...
- */
-
-#include "config.h"
-#include "mxml.h"
-
-
-/*
- * Global, per-thread data...
- */
-
-typedef struct _mxml_global_s
-{
- void (*error_cb)(const char *);
- int num_entity_cbs;
- int (*entity_cbs[100])(const char *name);
- int wrap;
- mxml_custom_load_cb_t custom_load_cb;
- mxml_custom_save_cb_t custom_save_cb;
-} _mxml_global_t;
-
-
-/*
- * Functions...
- */
-
-extern _mxml_global_t *_mxml_global(void);
-extern int _mxml_entity_cb(const char *name);
-
-
-/*
- * End of "$Id: mxml-private.h 408 2010-09-19 05:26:46Z mike $".
- */
+++ /dev/null
-/*
- * "$Id: mxml-search.c 427 2011-01-03 02:03:29Z mike $"
- *
- * Search/navigation functions for Mini-XML, a small XML-like file
- * parsing library.
- *
- * Copyright 2003-2010 by Michael R Sweet.
- *
- * These coded instructions, statements, and computer programs are the
- * property of Michael R Sweet and are protected by Federal copyright
- * law. Distribution and use rights are outlined in the file "COPYING"
- * which should have been included with this file. If this file is
- * missing or damaged, see the license at:
- *
- * http://www.minixml.org/
- *
- * Contents:
- *
- * mxmlFindElement() - Find the named element.
- * mxmlFindValue() - Find a value with the given path.
- * mxmlWalkNext() - Walk to the next logical node in the tree.
- * mxmlWalkPrev() - Walk to the previous logical node in the tree.
- */
-
-/*
- * Include necessary headers...
- */
-
-#include "config.h"
-#include "mxml.h"
-
-
-/*
- * 'mxmlFindElement()' - Find the named element.
- *
- * The search is constrained by the name, attribute name, and value; any
- * NULL names or values are treated as wildcards, so different kinds of
- * searches can be implemented by looking for all elements of a given name
- * or all elements with a specific attribute. The descend argument determines
- * whether the search descends into child nodes; normally you will use
- * MXML_DESCEND_FIRST for the initial search and MXML_NO_DESCEND to find
- * additional direct descendents of the node. The top node argument
- * constrains the search to a particular node's children.
- */
-
-mxml_node_t * /* O - Element node or NULL */
-mxmlFindElement(mxml_node_t *node, /* I - Current node */
- mxml_node_t *top, /* I - Top node */
- const char *name, /* I - Element name or NULL for any */
- const char *attr, /* I - Attribute name, or NULL for none */
- const char *value, /* I - Attribute value, or NULL for any */
- int descend) /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */
-{
- const char *temp; /* Current attribute value */
-
-
- /*
- * Range check input...
- */
-
- if (!node || !top || (!attr && value))
- return (NULL);
-
- /*
- * Start with the next node...
- */
-
- node = mxmlWalkNext(node, top, descend);
-
- /*
- * Loop until we find a matching element...
- */
-
- while (node != NULL)
- {
- /*
- * See if this node matches...
- */
-
- if (node->type == MXML_ELEMENT &&
- node->value.element.name &&
- (!name || !strcmp(node->value.element.name, name)))
- {
- /*
- * See if we need to check for an attribute...
- */
-
- if (!attr)
- return (node); /* No attribute search, return it... */
-
- /*
- * Check for the attribute...
- */
-
- if ((temp = mxmlElementGetAttr(node, attr)) != NULL)
- {
- /*
- * OK, we have the attribute, does it match?
- */
-
- if (!value || !strcmp(value, temp))
- return (node); /* Yes, return it... */
- }
- }
-
- /*
- * No match, move on to the next node...
- */
-
- if (descend == MXML_DESCEND)
- node = mxmlWalkNext(node, top, MXML_DESCEND);
- else
- node = node->next;
- }
-
- return (NULL);
-}
-
-
-/*
- * 'mxmlFindPath()' - Find a node with the given path.
- *
- * The "path" is a slash-separated list of element names. The name "*" is
- * considered a wildcard for one or more levels of elements. For example,
- * "foo/one/two", "bar/two/one", "*\/one", and so forth.
- *
- * The first child node of the found node is returned if the given node has
- * children and the first child is a value node.
- *
- * @since Mini-XML 2.7@
- */
-
-mxml_node_t * /* O - Found node or NULL */
-mxmlFindPath(mxml_node_t *top, /* I - Top node */
- const char *path) /* I - Path to element */
-{
- mxml_node_t *node; /* Current node */
- char element[256]; /* Current element name */
- const char *pathsep; /* Separator in path */
- int descend; /* mxmlFindElement option */
-
-
- /*
- * Range check input...
- */
-
- if (!top || !path || !*path)
- return (NULL);
-
- /*
- * Search each element in the path...
- */
-
- node = top;
- while (*path)
- {
- /*
- * Handle wildcards...
- */
-
- if (!strncmp(path, "*/", 2))
- {
- path += 2;
- descend = MXML_DESCEND;
- }
- else
- descend = MXML_DESCEND_FIRST;
-
- /*
- * Get the next element in the path...
- */
-
- if ((pathsep = strchr(path, '/')) == NULL)
- pathsep = path + strlen(path);
-
- if (pathsep == path || (pathsep - path) >= sizeof(element))
- return (NULL);
-
- memcpy(element, path, pathsep - path);
- element[pathsep - path] = '\0';
-
- if (*pathsep)
- path = pathsep + 1;
- else
- path = pathsep;
-
- /*
- * Search for the element...
- */
-
- if ((node = mxmlFindElement(node, node, element, NULL, NULL,
- descend)) == NULL)
- return (NULL);
- }
-
- /*
- * If we get this far, return the node or its first child...
- */
-
- if (node->child && node->child->type != MXML_ELEMENT)
- return (node->child);
- else
- return (node);
-}
-
-
-/*
- * 'mxmlWalkNext()' - Walk to the next logical node in the tree.
- *
- * The descend argument controls whether the first child is considered
- * to be the next node. The top node argument constrains the walk to
- * the node's children.
- */
-
-mxml_node_t * /* O - Next node or NULL */
-mxmlWalkNext(mxml_node_t *node, /* I - Current node */
- mxml_node_t *top, /* I - Top node */
- int descend) /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */
-{
- if (!node)
- return (NULL);
- else if (node->child && descend)
- return (node->child);
- else if (node == top)
- return (NULL);
- else if (node->next)
- return (node->next);
- else if (node->parent && node->parent != top)
- {
- node = node->parent;
-
- while (!node->next)
- if (node->parent == top || !node->parent)
- return (NULL);
- else
- node = node->parent;
-
- return (node->next);
- }
- else
- return (NULL);
-}
-
-
-/*
- * 'mxmlWalkPrev()' - Walk to the previous logical node in the tree.
- *
- * The descend argument controls whether the previous node's last child
- * is considered to be the previous node. The top node argument constrains
- * the walk to the node's children.
- */
-
-mxml_node_t * /* O - Previous node or NULL */
-mxmlWalkPrev(mxml_node_t *node, /* I - Current node */
- mxml_node_t *top, /* I - Top node */
- int descend) /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */
-{
- if (!node || node == top)
- return (NULL);
- else if (node->prev)
- {
- if (node->prev->last_child && descend)
- {
- /*
- * Find the last child under the previous node...
- */
-
- node = node->prev->last_child;
-
- while (node->last_child)
- node = node->last_child;
-
- return (node);
- }
- else
- return (node->prev);
- }
- else if (node->parent != top)
- return (node->parent);
- else
- return (NULL);
-}
-
-
-/*
- * End of "$Id: mxml-search.c 427 2011-01-03 02:03:29Z mike $".
- */
+++ /dev/null
-/*
- * "$Id: mxml-set.c 441 2011-12-09 23:49:00Z mike $"
- *
- * Node set functions for Mini-XML, a small XML-like file parsing library.
- *
- * Copyright 2003-2011 by Michael R Sweet.
- *
- * These coded instructions, statements, and computer programs are the
- * property of Michael R Sweet and are protected by Federal copyright
- * law. Distribution and use rights are outlined in the file "COPYING"
- * which should have been included with this file. If this file is
- * missing or damaged, see the license at:
- *
- * http://www.minixml.org/
- *
- * Contents:
- *
- * mxmlSetCDATA() - Set the element name of a CDATA node.
- * mxmlSetCustom() - Set the data and destructor of a custom data node.
- * mxmlSetElement() - Set the name of an element node.
- * mxmlSetInteger() - Set the value of an integer node.
- * mxmlSetOpaque() - Set the value of an opaque node.
- * mxmlSetReal() - Set the value of a real number node.
- * mxmlSetText() - Set the value of a text node.
- * mxmlSetTextf() - Set the value of a text node to a formatted string.
- * mxmlSetUserData() - Set the user data pointer for a node.
- */
-
-/*
- * Include necessary headers...
- */
-
-#include "config.h"
-#include "mxml.h"
-
-
-/*
- * 'mxmlSetCDATA()' - Set the element name of a CDATA node.
- *
- * The node is not changed if it (or its first child) is not a CDATA element node.
- *
- * @since Mini-XML 2.3@
- */
-
-int /* O - 0 on success, -1 on failure */
-mxmlSetCDATA(mxml_node_t *node, /* I - Node to set */
- const char *data) /* I - New data string */
-{
- /*
- * Range check input...
- */
-
- if (node && node->type == MXML_ELEMENT &&
- strncmp(node->value.element.name, "![CDATA[", 8) &&
- node->child && node->child->type == MXML_ELEMENT &&
- !strncmp(node->child->value.element.name, "![CDATA[", 8))
- node = node->child;
-
- if (!node || node->type != MXML_ELEMENT || !data ||
- strncmp(node->value.element.name, "![CDATA[", 8))
- return (-1);
-
- /*
- * Free any old element value and set the new value...
- */
-
- if (node->value.element.name)
- free(node->value.element.name);
-
- node->value.element.name = _mxml_strdupf("![CDATA[%s]]", data);
-
- return (0);
-}
-
-
-/*
- * 'mxmlSetCustom()' - Set the data and destructor of a custom data node.
- *
- * The node is not changed if it (or its first child) is not a custom node.
- *
- * @since Mini-XML 2.1@
- */
-
-int /* O - 0 on success, -1 on failure */
-mxmlSetCustom(
- mxml_node_t *node, /* I - Node to set */
- void *data, /* I - New data pointer */
- mxml_custom_destroy_cb_t destroy) /* I - New destructor function */
-{
- /*
- * Range check input...
- */
-
- if (node && node->type == MXML_ELEMENT &&
- node->child && node->child->type == MXML_CUSTOM)
- node = node->child;
-
- if (!node || node->type != MXML_CUSTOM)
- return (-1);
-
- /*
- * Free any old element value and set the new value...
- */
-
- if (node->value.custom.data && node->value.custom.destroy)
- (*(node->value.custom.destroy))(node->value.custom.data);
-
- node->value.custom.data = data;
- node->value.custom.destroy = destroy;
-
- return (0);
-}
-
-
-/*
- * 'mxmlSetElement()' - Set the name of an element node.
- *
- * The node is not changed if it is not an element node.
- */
-
-int /* O - 0 on success, -1 on failure */
-mxmlSetElement(mxml_node_t *node, /* I - Node to set */
- const char *name) /* I - New name string */
-{
- /*
- * Range check input...
- */
-
- if (!node || node->type != MXML_ELEMENT || !name)
- return (-1);
-
- /*
- * Free any old element value and set the new value...
- */
-
- if (node->value.element.name)
- free(node->value.element.name);
-
- node->value.element.name = strdup(name);
-
- return (0);
-}
-
-
-/*
- * 'mxmlSetInteger()' - Set the value of an integer node.
- *
- * The node is not changed if it (or its first child) is not an integer node.
- */
-
-int /* O - 0 on success, -1 on failure */
-mxmlSetInteger(mxml_node_t *node, /* I - Node to set */
- int integer) /* I - Integer value */
-{
- /*
- * Range check input...
- */
-
- if (node && node->type == MXML_ELEMENT &&
- node->child && node->child->type == MXML_INTEGER)
- node = node->child;
-
- if (!node || node->type != MXML_INTEGER)
- return (-1);
-
- /*
- * Set the new value and return...
- */
-
- node->value.integer = integer;
-
- return (0);
-}
-
-
-/*
- * 'mxmlSetOpaque()' - Set the value of an opaque node.
- *
- * The node is not changed if it (or its first child) is not an opaque node.
- */
-
-int /* O - 0 on success, -1 on failure */
-mxmlSetOpaque(mxml_node_t *node, /* I - Node to set */
- const char *opaque) /* I - Opaque string */
-{
- /*
- * Range check input...
- */
-
- if (node && node->type == MXML_ELEMENT &&
- node->child && node->child->type == MXML_OPAQUE)
- node = node->child;
-
- if (!node || node->type != MXML_OPAQUE || !opaque)
- return (-1);
-
- /*
- * Free any old opaque value and set the new value...
- */
-
- if (node->value.opaque)
- free(node->value.opaque);
-
- node->value.opaque = strdup(opaque);
-
- return (0);
-}
-
-
-/*
- * 'mxmlSetReal()' - Set the value of a real number node.
- *
- * The node is not changed if it (or its first child) is not a real number node.
- */
-
-int /* O - 0 on success, -1 on failure */
-mxmlSetReal(mxml_node_t *node, /* I - Node to set */
- double real) /* I - Real number value */
-{
- /*
- * Range check input...
- */
-
- if (node && node->type == MXML_ELEMENT &&
- node->child && node->child->type == MXML_REAL)
- node = node->child;
-
- if (!node || node->type != MXML_REAL)
- return (-1);
-
- /*
- * Set the new value and return...
- */
-
- node->value.real = real;
-
- return (0);
-}
-
-
-/*
- * 'mxmlSetText()' - Set the value of a text node.
- *
- * The node is not changed if it (or its first child) is not a text node.
- */
-
-int /* O - 0 on success, -1 on failure */
-mxmlSetText(mxml_node_t *node, /* I - Node to set */
- int whitespace, /* I - 1 = leading whitespace, 0 = no whitespace */
- const char *string) /* I - String */
-{
- /*
- * Range check input...
- */
-
- if (node && node->type == MXML_ELEMENT &&
- node->child && node->child->type == MXML_TEXT)
- node = node->child;
-
- if (!node || node->type != MXML_TEXT || !string)
- return (-1);
-
- /*
- * Free any old string value and set the new value...
- */
-
- if (node->value.text.string)
- free(node->value.text.string);
-
- node->value.text.whitespace = whitespace;
- node->value.text.string = strdup(string);
-
- return (0);
-}
-
-
-/*
- * 'mxmlSetTextf()' - Set the value of a text node to a formatted string.
- *
- * The node is not changed if it (or its first child) is not a text node.
- */
-
-int /* O - 0 on success, -1 on failure */
-mxmlSetTextf(mxml_node_t *node, /* I - Node to set */
- int whitespace, /* I - 1 = leading whitespace, 0 = no whitespace */
- const char *format, /* I - Printf-style format string */
- ...) /* I - Additional arguments as needed */
-{
- va_list ap; /* Pointer to arguments */
-
-
- /*
- * Range check input...
- */
-
- if (node && node->type == MXML_ELEMENT &&
- node->child && node->child->type == MXML_TEXT)
- node = node->child;
-
- if (!node || node->type != MXML_TEXT || !format)
- return (-1);
-
- /*
- * Free any old string value and set the new value...
- */
-
- if (node->value.text.string)
- free(node->value.text.string);
-
- va_start(ap, format);
-
- node->value.text.whitespace = whitespace;
- node->value.text.string = _mxml_strdupf(format, ap);
-
- va_end(ap);
-
- return (0);
-}
-
-
-/*
- * 'mxmlSetUserData()' - Set the user data pointer for a node.
- *
- * @since Mini-XML 2.7@
- */
-
-int /* O - 0 on success, -1 on failure */
-mxmlSetUserData(mxml_node_t *node, /* I - Node to set */
- void *data) /* I - User data pointer */
-{
- /*
- * Range check input...
- */
-
- if (!node)
- return (-1);
-
- /*
- * Set the user data pointer and return...
- */
-
- node->user_data = data;
- return (0);
-}
-
-
-/*
- * End of "$Id: mxml-set.c 441 2011-12-09 23:49:00Z mike $".
- */
+++ /dev/null
-/*
- * "$Id: mxml-string.c 424 2010-12-25 16:21:50Z mike $"
- *
- * String functions for Mini-XML, a small XML-like file parsing library.
- *
- * Copyright 2003-2010 by Michael R Sweet.
- *
- * These coded instructions, statements, and computer programs are the
- * property of Michael R Sweet and are protected by Federal copyright
- * law. Distribution and use rights are outlined in the file "COPYING"
- * which should have been included with this file. If this file is
- * missing or damaged, see the license at:
- *
- * http://www.minixml.org/
- *
- * Contents:
- *
- * _mxml_snprintf() - Format a string.
- * _mxml_strdup() - Duplicate a string.
- * _mxml_strdupf() - Format and duplicate a string.
- * _mxml_vsnprintf() - Format a string into a fixed size buffer.
- * _mxml_vstrdupf() - Format and duplicate a string.
- */
-
-/*
- * Include necessary headers...
- */
-
-#include "config.h"
-
-
-/*
- * The va_copy macro is part of C99, but many compilers don't implement it.
- * Provide a "direct assignment" implmentation when va_copy isn't defined...
- */
-
-#ifndef va_copy
-# ifdef __va_copy
-# define va_copy(dst,src) __va_copy(dst,src)
-# else
-# define va_copy(dst,src) memcpy(&dst, &src, sizeof(va_list))
-# endif /* __va_copy */
-#endif /* va_copy */
-
-
-#ifndef HAVE_SNPRINTF
-/*
- * '_mxml_snprintf()' - Format a string.
- */
-
-int /* O - Number of bytes formatted */
-_mxml_snprintf(char *buffer, /* I - Output buffer */
- size_t bufsize, /* I - Size of output buffer */
- const char *format, /* I - Printf-style format string */
- ...) /* I - Additional arguments as needed */
-{
- va_list ap; /* Argument list */
- int bytes; /* Number of bytes formatted */
-
-
- va_start(ap, format);
- bytes = vsnprintf(buffer, bufsize, format, ap);
- va_end(ap);
-
- return (bytes);
-}
-#endif /* !HAVE_SNPRINTF */
-
-
-/*
- * '_mxml_strdup()' - Duplicate a string.
- */
-
-#ifndef HAVE_STRDUP
-char * /* O - New string pointer */
-_mxml_strdup(const char *s) /* I - String to duplicate */
-{
- char *t; /* New string pointer */
-
-
- if (s == NULL)
- return (NULL);
-
- if ((t = malloc(strlen(s) + 1)) == NULL)
- return (NULL);
-
- return (strcpy(t, s));
-}
-#endif /* !HAVE_STRDUP */
-
-
-/*
- * '_mxml_strdupf()' - Format and duplicate a string.
- */
-
-char * /* O - New string pointer */
-_mxml_strdupf(const char *format, /* I - Printf-style format string */
- ...) /* I - Additional arguments as needed */
-{
- va_list ap; /* Pointer to additional arguments */
- char *s; /* Pointer to formatted string */
-
-
- /*
- * Get a pointer to the additional arguments, format the string,
- * and return it...
- */
-
- va_start(ap, format);
- s = _mxml_vstrdupf(format, ap);
- va_end(ap);
-
- return (s);
-}
-
-
-#ifndef HAVE_VSNPRINTF
-/*
- * '_mxml_vsnprintf()' - Format a string into a fixed size buffer.
- */
-
-int /* O - Number of bytes formatted */
-_mxml_vsnprintf(char *buffer, /* O - Output buffer */
- size_t bufsize, /* O - Size of output buffer */
- const char *format, /* I - Printf-style format string */
- va_list ap) /* I - Pointer to additional arguments */
-{
- char *bufptr, /* Pointer to position in buffer */
- *bufend, /* Pointer to end of buffer */
- sign, /* Sign of format width */
- size, /* Size character (h, l, L) */
- type; /* Format type character */
- int width, /* Width of field */
- prec; /* Number of characters of precision */
- char tformat[100], /* Temporary format string for sprintf() */
- *tptr, /* Pointer into temporary format */
- temp[1024]; /* Buffer for formatted numbers */
- char *s; /* Pointer to string */
- int slen; /* Length of string */
- int bytes; /* Total number of bytes needed */
-
-
- /*
- * Loop through the format string, formatting as needed...
- */
-
- bufptr = buffer;
- bufend = buffer + bufsize - 1;
- bytes = 0;
-
- while (*format)
- {
- if (*format == '%')
- {
- tptr = tformat;
- *tptr++ = *format++;
-
- if (*format == '%')
- {
- if (bufptr && bufptr < bufend) *bufptr++ = *format;
- bytes ++;
- format ++;
- continue;
- }
- else if (strchr(" -+#\'", *format))
- {
- *tptr++ = *format;
- sign = *format++;
- }
- else
- sign = 0;
-
- if (*format == '*')
- {
- /*
- * Get width from argument...
- */
-
- format ++;
- width = va_arg(ap, int);
-
- snprintf(tptr, sizeof(tformat) - (tptr - tformat), "%d", width);
- tptr += strlen(tptr);
- }
- else
- {
- width = 0;
-
- while (isdigit(*format & 255))
- {
- if (tptr < (tformat + sizeof(tformat) - 1))
- *tptr++ = *format;
-
- width = width * 10 + *format++ - '0';
- }
- }
-
- if (*format == '.')
- {
- if (tptr < (tformat + sizeof(tformat) - 1))
- *tptr++ = *format;
-
- format ++;
-
- if (*format == '*')
- {
- /*
- * Get precision from argument...
- */
-
- format ++;
- prec = va_arg(ap, int);
-
- snprintf(tptr, sizeof(tformat) - (tptr - tformat), "%d", prec);
- tptr += strlen(tptr);
- }
- else
- {
- prec = 0;
-
- while (isdigit(*format & 255))
- {
- if (tptr < (tformat + sizeof(tformat) - 1))
- *tptr++ = *format;
-
- prec = prec * 10 + *format++ - '0';
- }
- }
- }
- else
- prec = -1;
-
- if (*format == 'l' && format[1] == 'l')
- {
- size = 'L';
-
- if (tptr < (tformat + sizeof(tformat) - 2))
- {
- *tptr++ = 'l';
- *tptr++ = 'l';
- }
-
- format += 2;
- }
- else if (*format == 'h' || *format == 'l' || *format == 'L')
- {
- if (tptr < (tformat + sizeof(tformat) - 1))
- *tptr++ = *format;
-
- size = *format++;
- }
-
- if (!*format)
- break;
-
- if (tptr < (tformat + sizeof(tformat) - 1))
- *tptr++ = *format;
-
- type = *format++;
- *tptr = '\0';
-
- switch (type)
- {
- case 'E' : /* Floating point formats */
- case 'G' :
- case 'e' :
- case 'f' :
- case 'g' :
- if ((width + 2) > sizeof(temp))
- break;
-
- sprintf(temp, tformat, va_arg(ap, double));
-
- bytes += strlen(temp);
-
- if (bufptr)
- {
- if ((bufptr + strlen(temp)) > bufend)
- {
- strncpy(bufptr, temp, (size_t)(bufend - bufptr));
- bufptr = bufend;
- }
- else
- {
- strcpy(bufptr, temp);
- bufptr += strlen(temp);
- }
- }
- break;
-
- case 'B' : /* Integer formats */
- case 'X' :
- case 'b' :
- case 'd' :
- case 'i' :
- case 'o' :
- case 'u' :
- case 'x' :
- if ((width + 2) > sizeof(temp))
- break;
-
-#ifdef HAVE_LONG_LONG
- if (size == 'L')
- sprintf(temp, tformat, va_arg(ap, long long));
- else
-#endif /* HAVE_LONG_LONG */
- sprintf(temp, tformat, va_arg(ap, int));
-
- bytes += strlen(temp);
-
- if (bufptr)
- {
- if ((bufptr + strlen(temp)) > bufend)
- {
- strncpy(bufptr, temp, (size_t)(bufend - bufptr));
- bufptr = bufend;
- }
- else
- {
- strcpy(bufptr, temp);
- bufptr += strlen(temp);
- }
- }
- break;
-
- case 'p' : /* Pointer value */
- if ((width + 2) > sizeof(temp))
- break;
-
- sprintf(temp, tformat, va_arg(ap, void *));
-
- bytes += strlen(temp);
-
- if (bufptr)
- {
- if ((bufptr + strlen(temp)) > bufend)
- {
- strncpy(bufptr, temp, (size_t)(bufend - bufptr));
- bufptr = bufend;
- }
- else
- {
- strcpy(bufptr, temp);
- bufptr += strlen(temp);
- }
- }
- break;
-
- case 'c' : /* Character or character array */
- bytes += width;
-
- if (bufptr)
- {
- if (width <= 1)
- *bufptr++ = va_arg(ap, int);
- else
- {
- if ((bufptr + width) > bufend)
- width = bufend - bufptr;
-
- memcpy(bufptr, va_arg(ap, char *), (size_t)width);
- bufptr += width;
- }
- }
- break;
-
- case 's' : /* String */
- if ((s = va_arg(ap, char *)) == NULL)
- s = "(null)";
-
- slen = strlen(s);
- if (slen > width && prec != width)
- width = slen;
-
- bytes += width;
-
- if (bufptr)
- {
- if ((bufptr + width) > bufend)
- width = bufend - bufptr;
-
- if (slen > width)
- slen = width;
-
- if (sign == '-')
- {
- strncpy(bufptr, s, (size_t)slen);
- memset(bufptr + slen, ' ', (size_t)(width - slen));
- }
- else
- {
- memset(bufptr, ' ', (size_t)(width - slen));
- strncpy(bufptr + width - slen, s, (size_t)slen);
- }
-
- bufptr += width;
- }
- break;
-
- case 'n' : /* Output number of chars so far */
- *(va_arg(ap, int *)) = bytes;
- break;
- }
- }
- else
- {
- bytes ++;
-
- if (bufptr && bufptr < bufend)
- *bufptr++ = *format;
-
- format ++;
- }
- }
-
- /*
- * Nul-terminate the string and return the number of characters needed.
- */
-
- *bufptr = '\0';
-
- return (bytes);
-}
-#endif /* !HAVE_VSNPRINTF */
-
-
-/*
- * '_mxml_vstrdupf()' - Format and duplicate a string.
- */
-
-char * /* O - New string pointer */
-_mxml_vstrdupf(const char *format, /* I - Printf-style format string */
- va_list ap) /* I - Pointer to additional arguments */
-{
- int bytes; /* Number of bytes required */
- char *buffer, /* String buffer */
- temp[256]; /* Small buffer for first vsnprintf */
- va_list apcopy; /* Copy of argument list */
-
-
- /*
- * First format with a tiny buffer; this will tell us how many bytes are
- * needed...
- */
-
- va_copy(apcopy, ap);
- bytes = vsnprintf(temp, sizeof(temp), format, apcopy);
-
- if (bytes < sizeof(temp))
- {
- /*
- * Hey, the formatted string fits in the tiny buffer, so just dup that...
- */
-
- return (strdup(temp));
- }
-
- /*
- * Allocate memory for the whole thing and reformat to the new, larger
- * buffer...
- */
-
- if ((buffer = calloc(1, bytes + 1)) != NULL)
- vsnprintf(buffer, bytes + 1, format, ap);
-
- /*
- * Return the new string...
- */
-
- return (buffer);
-}
-
-
-/*
- * End of "$Id: mxml-string.c 424 2010-12-25 16:21:50Z mike $".
- */
+++ /dev/null
-/*
- * "$Id: mxml.h 427 2011-01-03 02:03:29Z mike $"
- *
- * Header file for Mini-XML, a small XML-like file parsing library.
- *
- * Copyright 2003-2011 by Michael R Sweet.
- *
- * These coded instructions, statements, and computer programs are the
- * property of Michael R Sweet and are protected by Federal copyright
- * law. Distribution and use rights are outlined in the file "COPYING"
- * which should have been included with this file. If this file is
- * missing or damaged, see the license at:
- *
- * http://www.minixml.org/
- */
-
-/*
- * Prevent multiple inclusion...
- */
-
-#ifndef _mxml_h_
-# define _mxml_h_
-
-/*
- * Include necessary headers...
- */
-
-# include <stdio.h>
-# include <stdlib.h>
-# include <string.h>
-# include <ctype.h>
-# include <errno.h>
-
-
-/*
- * Constants...
- */
-
-# define MXML_TAB 8 /* Tabs every N columns */
-
-# define MXML_NO_CALLBACK 0 /* Don't use a type callback */
-# define MXML_INTEGER_CALLBACK mxml_integer_cb
- /* Treat all data as integers */
-# define MXML_OPAQUE_CALLBACK mxml_opaque_cb
- /* Treat all data as opaque */
-# define MXML_REAL_CALLBACK mxml_real_cb
- /* Treat all data as real numbers */
-# define MXML_TEXT_CALLBACK 0 /* Treat all data as text */
-# define MXML_IGNORE_CALLBACK mxml_ignore_cb
- /* Ignore all non-element content */
-
-# define MXML_NO_PARENT 0 /* No parent for the node */
-
-# define MXML_DESCEND 1 /* Descend when finding/walking */
-# define MXML_NO_DESCEND 0 /* Don't descend when finding/walking */
-# define MXML_DESCEND_FIRST -1 /* Descend for first find */
-
-# define MXML_WS_BEFORE_OPEN 0 /* Callback for before open tag */
-# define MXML_WS_AFTER_OPEN 1 /* Callback for after open tag */
-# define MXML_WS_BEFORE_CLOSE 2 /* Callback for before close tag */
-# define MXML_WS_AFTER_CLOSE 3 /* Callback for after close tag */
-
-# define MXML_ADD_BEFORE 0 /* Add node before specified node */
-# define MXML_ADD_AFTER 1 /* Add node after specified node */
-# define MXML_ADD_TO_PARENT NULL /* Add node relative to parent */
-
-
-/*
- * Data types...
- */
-
-typedef enum mxml_sax_event_e /**** SAX event type. ****/
-{
- MXML_SAX_CDATA, /* CDATA node */
- MXML_SAX_COMMENT, /* Comment node */
- MXML_SAX_DATA, /* Data node */
- MXML_SAX_DIRECTIVE, /* Processing directive node */
- MXML_SAX_ELEMENT_CLOSE, /* Element closed */
- MXML_SAX_ELEMENT_OPEN /* Element opened */
-} mxml_sax_event_t;
-
-typedef enum mxml_type_e /**** The XML node type. ****/
-{
- MXML_IGNORE = -1, /* Ignore/throw away node @since Mini-XML 2.3@ */
- MXML_ELEMENT, /* XML element with attributes */
- MXML_INTEGER, /* Integer value */
- MXML_OPAQUE, /* Opaque string */
- MXML_REAL, /* Real value */
- MXML_TEXT, /* Text fragment */
- MXML_CUSTOM /* Custom data @since Mini-XML 2.1@ */
-} mxml_type_t;
-
-typedef void (*mxml_custom_destroy_cb_t)(void *);
- /**** Custom data destructor ****/
-
-typedef void (*mxml_error_cb_t)(const char *);
- /**** Error callback function ****/
-
-typedef struct mxml_attr_s /**** An XML element attribute value. @private@ ****/
-{
- char *name; /* Attribute name */
- char *value; /* Attribute value */
-} mxml_attr_t;
-
-typedef struct mxml_element_s /**** An XML element value. @private@ ****/
-{
- char *name; /* Name of element */
- int num_attrs; /* Number of attributes */
- mxml_attr_t *attrs; /* Attributes */
-} mxml_element_t;
-
-typedef struct mxml_text_s /**** An XML text value. @private@ ****/
-{
- int whitespace; /* Leading whitespace? */
- char *string; /* Fragment string */
-} mxml_text_t;
-
-typedef struct mxml_custom_s /**** An XML custom value. @private@ ****/
-{
- void *data; /* Pointer to (allocated) custom data */
- mxml_custom_destroy_cb_t destroy; /* Pointer to destructor function */
-} mxml_custom_t;
-
-typedef union mxml_value_u /**** An XML node value. @private@ ****/
-{
- mxml_element_t element; /* Element */
- int integer; /* Integer number */
- char *opaque; /* Opaque string */
- double real; /* Real number */
- mxml_text_t text; /* Text fragment */
- mxml_custom_t custom; /* Custom data @since Mini-XML 2.1@ */
-} mxml_value_t;
-
-struct mxml_node_s /**** An XML node. @private@ ****/
-{
- mxml_type_t type; /* Node type */
- struct mxml_node_s *next; /* Next node under same parent */
- struct mxml_node_s *prev; /* Previous node under same parent */
- struct mxml_node_s *parent; /* Parent node */
- struct mxml_node_s *child; /* First child node */
- struct mxml_node_s *last_child; /* Last child node */
- mxml_value_t value; /* Node value */
- int ref_count; /* Use count */
- void *user_data; /* User data */
-};
-
-typedef struct mxml_node_s mxml_node_t; /**** An XML node. ****/
-
-struct mxml_index_s /**** An XML node index. @private@ ****/
-{
- char *attr; /* Attribute used for indexing or NULL */
- int num_nodes; /* Number of nodes in index */
- int alloc_nodes; /* Allocated nodes in index */
- int cur_node; /* Current node */
- mxml_node_t **nodes; /* Node array */
-};
-
-typedef struct mxml_index_s mxml_index_t;
- /**** An XML node index. ****/
-
-typedef int (*mxml_custom_load_cb_t)(mxml_node_t *, const char *);
- /**** Custom data load callback function ****/
-
-typedef char *(*mxml_custom_save_cb_t)(mxml_node_t *);
- /**** Custom data save callback function ****/
-
-typedef int (*mxml_entity_cb_t)(const char *);
- /**** Entity callback function */
-
-typedef mxml_type_t (*mxml_load_cb_t)(mxml_node_t *);
- /**** Load callback function ****/
-
-typedef const char *(*mxml_save_cb_t)(mxml_node_t *, int);
- /**** Save callback function ****/
-
-typedef void (*mxml_sax_cb_t)(mxml_node_t *, mxml_sax_event_t, void *);
- /**** SAX callback function ****/
-
-
-/*
- * C++ support...
- */
-
-# ifdef __cplusplus
-extern "C" {
-# endif /* __cplusplus */
-
-/*
- * Prototypes...
- */
-
-extern void mxmlAdd(mxml_node_t *parent, int where,
- mxml_node_t *child, mxml_node_t *node);
-extern void mxmlDelete(mxml_node_t *node);
-extern void mxmlElementDeleteAttr(mxml_node_t *node,
- const char *name);
-extern const char *mxmlElementGetAttr(mxml_node_t *node, const char *name);
-extern void mxmlElementSetAttr(mxml_node_t *node, const char *name,
- const char *value);
-extern void mxmlElementSetAttrf(mxml_node_t *node, const char *name,
- const char *format, ...)
-# ifdef __GNUC__
-__attribute__ ((__format__ (__printf__, 3, 4)))
-# endif /* __GNUC__ */
-;
-extern int mxmlEntityAddCallback(mxml_entity_cb_t cb);
-extern const char *mxmlEntityGetName(int val);
-extern int mxmlEntityGetValue(const char *name);
-extern void mxmlEntityRemoveCallback(mxml_entity_cb_t cb);
-extern mxml_node_t *mxmlFindElement(mxml_node_t *node, mxml_node_t *top,
- const char *name, const char *attr,
- const char *value, int descend);
-extern mxml_node_t *mxmlFindPath(mxml_node_t *node, const char *path);
-extern const char *mxmlGetCDATA(mxml_node_t *node);
-extern const void *mxmlGetCustom(mxml_node_t *node);
-extern const char *mxmlGetElement(mxml_node_t *node);
-extern mxml_node_t *mxmlGetFirstChild(mxml_node_t *node);
-extern int mxmlGetInteger(mxml_node_t *node);
-extern mxml_node_t *mxmlGetLastChild(mxml_node_t *node);
-extern mxml_node_t *mxmlGetNextSibling(mxml_node_t *node);
-extern const char *mxmlGetOpaque(mxml_node_t *node);
-extern mxml_node_t *mxmlGetParent(mxml_node_t *node);
-extern mxml_node_t *mxmlGetPrevSibling(mxml_node_t *node);
-extern double mxmlGetReal(mxml_node_t *node);
-extern int mxmlGetRefCount(mxml_node_t *node);
-extern const char *mxmlGetText(mxml_node_t *node, int *whitespace);
-extern mxml_type_t mxmlGetType(mxml_node_t *node);
-extern void *mxmlGetUserData(mxml_node_t *node);
-extern void mxmlIndexDelete(mxml_index_t *ind);
-extern mxml_node_t *mxmlIndexEnum(mxml_index_t *ind);
-extern mxml_node_t *mxmlIndexFind(mxml_index_t *ind,
- const char *element,
- const char *value);
-extern int mxmlIndexGetCount(mxml_index_t *ind);
-extern mxml_index_t *mxmlIndexNew(mxml_node_t *node, const char *element,
- const char *attr);
-extern mxml_node_t *mxmlIndexReset(mxml_index_t *ind);
-extern mxml_node_t *mxmlLoadFd(mxml_node_t *top, int fd,
- mxml_type_t (*cb)(mxml_node_t *));
-extern mxml_node_t *mxmlLoadFile(mxml_node_t *top, FILE *fp,
- mxml_type_t (*cb)(mxml_node_t *));
-extern mxml_node_t *mxmlLoadString(mxml_node_t *top, const char *s,
- mxml_type_t (*cb)(mxml_node_t *));
-extern mxml_node_t *mxmlNewCDATA(mxml_node_t *parent, const char *string);
-extern mxml_node_t *mxmlNewCustom(mxml_node_t *parent, void *data,
- mxml_custom_destroy_cb_t destroy);
-extern mxml_node_t *mxmlNewElement(mxml_node_t *parent, const char *name);
-extern mxml_node_t *mxmlNewInteger(mxml_node_t *parent, int integer);
-extern mxml_node_t *mxmlNewOpaque(mxml_node_t *parent, const char *opaque);
-extern mxml_node_t *mxmlNewReal(mxml_node_t *parent, double real);
-extern mxml_node_t *mxmlNewText(mxml_node_t *parent, int whitespace,
- const char *string);
-extern mxml_node_t *mxmlNewTextf(mxml_node_t *parent, int whitespace,
- const char *format, ...)
-# ifdef __GNUC__
-__attribute__ ((__format__ (__printf__, 3, 4)))
-# endif /* __GNUC__ */
-;
-extern mxml_node_t *mxmlNewXML(const char *version);
-extern int mxmlRelease(mxml_node_t *node);
-extern void mxmlRemove(mxml_node_t *node);
-extern int mxmlRetain(mxml_node_t *node);
-extern char *mxmlSaveAllocString(mxml_node_t *node,
- mxml_save_cb_t cb);
-extern int mxmlSaveFd(mxml_node_t *node, int fd,
- mxml_save_cb_t cb);
-extern int mxmlSaveFile(mxml_node_t *node, FILE *fp,
- mxml_save_cb_t cb);
-extern int mxmlSaveString(mxml_node_t *node, char *buffer,
- int bufsize, mxml_save_cb_t cb);
-extern mxml_node_t *mxmlSAXLoadFd(mxml_node_t *top, int fd,
- mxml_type_t (*cb)(mxml_node_t *),
- mxml_sax_cb_t sax, void *sax_data);
-extern mxml_node_t *mxmlSAXLoadFile(mxml_node_t *top, FILE *fp,
- mxml_type_t (*cb)(mxml_node_t *),
- mxml_sax_cb_t sax, void *sax_data);
-extern mxml_node_t *mxmlSAXLoadString(mxml_node_t *top, const char *s,
- mxml_type_t (*cb)(mxml_node_t *),
- mxml_sax_cb_t sax, void *sax_data);
-extern int mxmlSetCDATA(mxml_node_t *node, const char *data);
-extern int mxmlSetCustom(mxml_node_t *node, void *data,
- mxml_custom_destroy_cb_t destroy);
-extern void mxmlSetCustomHandlers(mxml_custom_load_cb_t load,
- mxml_custom_save_cb_t save);
-extern int mxmlSetElement(mxml_node_t *node, const char *name);
-extern void mxmlSetErrorCallback(mxml_error_cb_t cb);
-extern int mxmlSetInteger(mxml_node_t *node, int integer);
-extern int mxmlSetOpaque(mxml_node_t *node, const char *opaque);
-extern int mxmlSetReal(mxml_node_t *node, double real);
-extern int mxmlSetText(mxml_node_t *node, int whitespace,
- const char *string);
-extern int mxmlSetTextf(mxml_node_t *node, int whitespace,
- const char *format, ...)
-# ifdef __GNUC__
-__attribute__ ((__format__ (__printf__, 3, 4)))
-# endif /* __GNUC__ */
-;
-extern int mxmlSetUserData(mxml_node_t *node, void *data);
-extern void mxmlSetWrapMargin(int column);
-extern mxml_node_t *mxmlWalkNext(mxml_node_t *node, mxml_node_t *top,
- int descend);
-extern mxml_node_t *mxmlWalkPrev(mxml_node_t *node, mxml_node_t *top,
- int descend);
-
-
-/*
- * Semi-private functions...
- */
-
-extern void mxml_error(const char *format, ...);
-extern mxml_type_t mxml_ignore_cb(mxml_node_t *node);
-extern mxml_type_t mxml_integer_cb(mxml_node_t *node);
-extern mxml_type_t mxml_opaque_cb(mxml_node_t *node);
-extern mxml_type_t mxml_real_cb(mxml_node_t *node);
-
-
-/*
- * C++ support...
- */
-
-# ifdef __cplusplus
-}
-# endif /* __cplusplus */
-#endif /* !_mxml_h_ */
-
-
-/*
- * End of "$Id: mxml.h 427 2011-01-03 02:03:29Z mike $".
- */