📄 profile.c
字号:
//==========================================================================//// profile.c//// Application profiling support////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 2002 Gary Thomas//// eCos is free software; you can redistribute it and/or modify it under// the terms of the GNU General Public License as published by the Free// Software Foundation; either version 2 or (at your option) any later version.//// eCos 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 General Public License// for more details.//// You should have received a copy of the GNU General Public License along// with eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// As a special exception, if other files instantiate templates or use macros// or inline functions from this file, or you compile this file and link it// with other works to produce a work based on this file, this file does not// by itself cause the resulting work to be covered by the GNU General Public// License. However the source code for this file must still be made available// in accordance with section (3) of the GNU General Public License.//// This exception does not invalidate any other reasons why a work based on// this file might be covered by the GNU General Public License.//// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.// at http://sources.redhat.com/ecos/ecos-license/// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s): Gary Thomas// Contributors: // Date: 2002-11-14// Purpose: Application profiling support// Description: ////####DESCRIPTIONEND####////===========================================================================#include <pkgconf/profile_gprof.h>#include <stdlib.h>#include <string.h>#include <cyg/infra/diag.h>#include <network.h>#include <tftp_support.h>#include <cyg/profile/profile.h>#include <cyg/profile/gmon_out.h>static int num_buckets;static unsigned short *profile;static int bucket_size, bucket_shift;static unsigned long start_addr, end_addr;static int enabled;static int tftp_server_id;static int prof_rate;static int profile_open(const char *, int);static int profile_close(int);static int profile_write(int, const void *, int);static int profile_read(int, void *, int);struct tftpd_fileops profile_fileops = { profile_open, profile_close, profile_write, profile_read};struct _file { unsigned char *pos, *eof, *data; int flags; int mode;};#define FILE_OPEN 0x0001#define NUM_FILES 1static struct _file files[NUM_FILES];static inline struct _file *profile_fp(int fd){ struct _file *fp; if ((fd < 0) || (fd >= NUM_FILES)) return (struct _file *)0; fp = &files[fd]; if (!(fp->flags & FILE_OPEN)) return (struct _file *)0; return fp;}static intprofile_open(const char *fn, int flags){ int fd = 0; struct _file *fp; int len = sizeof(struct gmon_hdr) + sizeof(struct gmon_hist_hdr) + (num_buckets*2) + 1; struct gmon_hdr _hdr; struct gmon_hist_hdr _hist_hdr; unsigned char *bp; int version = GMON_VERSION; int hist_size = num_buckets; int file_type = -1; fp = files; if (fp->flags & FILE_OPEN) { // File already open return -1; } if (!(flags & O_RDONLY)) { // Only read supported return -1; } if (strcmp(fn, "PROFILE.DAT") == 0) { file_type = 0; } if (file_type < 0) { // No supported file return -1; } // Set up file info enabled = 0; switch (file_type) { // In case another type ever supported case 0: // profile data fp->data = malloc(len); if (!fp->data) { diag_printf("Can't allocate buffer for profile data!\n"); return -1; } fp->flags = FILE_OPEN; fp->mode = flags; fp->pos = fp->data; fp->eof = fp->pos + len; // Fill in profile data bp = fp->data; memset(&_hdr, 0, sizeof(_hdr)); strcpy(_hdr.cookie, GMON_MAGIC); memcpy(_hdr.version, &version, sizeof(version)); memcpy(bp, &_hdr, sizeof(_hdr)); bp += sizeof(_hdr); memcpy(&_hist_hdr.low_pc, &start_addr, sizeof(start_addr)); memcpy(&_hist_hdr.high_pc, &end_addr, sizeof(end_addr)); memcpy(&_hist_hdr.hist_size, &hist_size, sizeof(hist_size)); memcpy(&_hist_hdr.prof_rate, &prof_rate, sizeof(prof_rate)); strcpy(_hist_hdr.dimen, "seconds"); _hist_hdr.dimen_abbrev = 's'; *bp++ = GMON_TAG_TIME_HIST; memcpy(bp, &_hist_hdr, sizeof(_hist_hdr)); bp += sizeof(_hist_hdr); memcpy(bp, profile, (num_buckets*2)); memset(profile, 0, (num_buckets*2)); break; } return fd;}static intprofile_close(int fd){ struct _file *fp = profile_fp(fd); if (!fp) return -1; if (fp->data) free(fp->data); fp->flags = 0; // No longer open enabled = 1; return 0;}static int profile_write(int fd, const void *buf, int len){ return -1;}static intprofile_read(int fd, void *buf, int len){ struct _file *fp = profile_fp(fd); int res; if (!fp) return -1; res = fp->eof - fp->pos; // Number of bytes left in "file" if (res > len) res = len; if (res <= 0) return 0; // End of file bcopy(fp->pos, buf, res); fp->pos += res; return res;}void__profile_hit(unsigned long pc){ int bucket; if (enabled) { if ((pc >= start_addr) && (pc <= end_addr)) { bucket = (pc - start_addr) >> bucket_shift; if (profile[bucket] < (unsigned short)0xFFFF) { profile[bucket]++; } } }}void profile_on(void *_start, void *_end, int _bucket_size, int resolution){ start_addr = (unsigned long)_start; end_addr = (unsigned long)_end; // Adjust bucket size to be a power of 2 bucket_size = 1; bucket_shift = 0; while (bucket_size < _bucket_size) { bucket_size <<= 1; bucket_shift++; } if (bucket_size != _bucket_size) { bucket_size <<= 1; bucket_shift++; } // Calculate number of buckets num_buckets = ((end_addr - start_addr) + (bucket_size - 1)) / bucket_size; // Adjust end address so calculations come out end_addr = start_addr + (bucket_size * num_buckets); prof_rate = 1000000 / resolution; // Allocate buffer for profile data if (!(profile = malloc(num_buckets*2))) { diag_printf("Can't allocate profile buffer - ignored\n"); return; } memset(profile, 0, (num_buckets*2)); enabled = 1; diag_printf("Profile from %p..%p[%p], in %d buckets of size %d\n", start_addr, end_addr, _end, num_buckets, bucket_size); hal_enable_profile_timer(resolution); // Create a TFTP server to provide the data tftp_server_id = tftpd_start(CYGNUM_PROFILE_TFTP_PORT, &profile_fileops);}// EOF profile.c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -