Mercurial > ecos
changeset 424:abb983ee4de0
Add application-level profiling package
| author | gthomas |
|---|---|
| date | Thu, 14 Nov 2002 23:49:08 +0000 |
| parents | d175f4be3ab6 |
| children | cd7e3413ad01 |
| files | packages/ChangeLog packages/NEWS packages/ecos.db packages/services/cpuload/current/cdl/cpuload.cdl packages/services/profile/current/ChangeLog packages/services/profile/current/cdl/profile.cdl packages/services/profile/current/include/gmon_out.h packages/services/profile/current/include/profile.h packages/services/profile/current/src/profile.c |
| diffstat | 9 files changed, 531 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/packages/ChangeLog +++ b/packages/ChangeLog @@ -1,3 +1,7 @@ +2002-11-14 Gary Thomas <gthomas@ecoscentric.com> + + * ecos.db: Add application profiling package. + 2002-11-14 Mark Salter <msalter@redhat.com> * ecos.db: Add flash package for AM33 ASB2303.
--- a/packages/NEWS +++ b/packages/NEWS @@ -1,3 +1,4 @@ +* New package for application level profiling (histogram only) * Support for NPWR Linux Engine (Xscale IOP310) from Team ASA * Support for Allied Telesyn TS1000 (PowerPC 855T based design) * Yoshinori Sato has contributed a watchdog driver for the Hitachi H8/300H.
--- a/packages/ecos.db +++ b/packages/ecos.db @@ -1581,6 +1581,14 @@ This package measures the CPU load over and 10 second. All loads are returned as a percentage, ie 0-100. This is only a rough measure." } + +package CYGPKG_PROFILE { + alias { "Application profile support" profile } + directory services/profile + script profile.cdl + description " +This package instruments applications to collect profiling data." +} package CYGPKG_UITRON { alias { "uITRON compatibility" uitron }
--- a/packages/services/cpuload/current/cdl/cpuload.cdl +++ b/packages/services/cpuload/current/cdl/cpuload.cdl @@ -63,7 +63,7 @@ cdl_package CYGPKG_CPULOAD { modes etc, will cause these results to be wrong." cdl_option CYGPKG_CPULOAD_TESTS { - display "POSIX CRC tests" + display "CPU load measurement tests" flavor data no_define calculated { "tests/cpuload.c" }
new file mode 100644 --- /dev/null +++ b/packages/services/profile/current/ChangeLog @@ -0,0 +1,41 @@ +2002-11-14 Gary Thomas <gthomas@ecoscentric.com> + + * src/profile.c: + * include/profile.h: + * include/gmon_out.h: + * cdl/profile.cdl: New package to support application profiling. + +//=========================================================================== +//####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#### +//===========================================================================
new file mode 100644 --- /dev/null +++ b/packages/services/profile/current/cdl/profile.cdl @@ -0,0 +1,82 @@ +# ==================================================================== +# +# profile.cdl +# +# cpu load measurements +# +# ==================================================================== +#####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 +# Original data: Gary Thomas +# Contributors: +# Date: 2002-11-14 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_PROFILE { + display "Gather runtime profile statistics" + requires CYGPKG_NET + requires CYGPKG_MEMALLOC + requires { CYGPKG_PROFILE_TIMER != 0 } + + include_dir cyg/infra + + compile profile.c + + description " + This package enables runtime profiling of an application. + The actual profile collection must be turned on by the application, + once it has been initialized. The data collected is exported via + a TFTP connection to the target." + + cdl_interface CYGPKG_PROFILE_TIMER { + display "High resolution timer, implemented by platform" + description " + Profiling requires access to a high resolution timer which + is platform dependent." + } + + cdl_option CYGPKG_PROFILE_TESTS { + display "Profiling tests" + flavor data + no_define + calculated { "tests/profile.c" } + } +} +
new file mode 100644 --- /dev/null +++ b/packages/services/profile/current/include/gmon_out.h @@ -0,0 +1,82 @@ +// Slightly adapted for eCos environment + +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Mosberger <davidm@cs.arizona.edu>. + + The GNU C 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. + + The GNU C 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 the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This file specifies the format of gmon.out files. It should have + as few external dependencies as possible as it is going to be included + in many different programs. That is, minimize the number of #include's. + + A gmon.out file consists of a header (defined by gmon_hdr) followed by + a sequence of records. Each record starts with a one-byte tag + identifying the type of records, followed by records specific data. */ + +#ifndef _SYS_GMON_OUT_H +#define _SYS_GMON_OUT_H 1 + +//#include <features.h> + +#define GMON_MAGIC "gmon" /* magic cookie */ +#define GMON_VERSION 1 /* version number */ + +/* For profiling shared object we need a new format. */ +#define GMON_SHOBJ_VERSION 0x1ffff + +//__BEGIN_DECLS + +/* + * Raw header as it appears on file (without padding). This header + * always comes first in gmon.out and is then followed by a series + * records defined below. + */ +struct gmon_hdr + { + char cookie[4]; + char version[4]; + char spare[3 * 4]; + }; + +/* types of records in this file: */ +typedef enum + { + GMON_TAG_TIME_HIST = 0, + GMON_TAG_CG_ARC = 1, + GMON_TAG_BB_COUNT = 2 + } GMON_Record_Tag; + +struct gmon_hist_hdr + { + char low_pc[sizeof (char *)]; /* base pc address of sample buffer */ + char high_pc[sizeof (char *)]; /* max pc address of sampled buffer */ + char hist_size[4]; /* size of sample buffer */ + char prof_rate[4]; /* profiling clock rate */ + char dimen[15]; /* phys. dim., usually "seconds" */ + char dimen_abbrev; /* usually 's' for "seconds" */ + }; + +struct gmon_cg_arc_record + { + char from_pc[sizeof (char *)]; /* address within caller's body */ + char self_pc[sizeof (char *)]; /* address within callee's body */ + char count[4]; /* number of arc traversals */ + }; + +//__END_DECLS + +#endif /* sys/gmon_out.h */
new file mode 100644 --- /dev/null +++ b/packages/services/profile/current/include/profile.h @@ -0,0 +1,70 @@ +#ifndef CYGONCE_PROFILE_H +#define CYGONCE_PROFILE_H + +//========================================================================== +// +// profile.h +// +// 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): gthomas +// Contributors: +// Date: 2002-11-14 +// Purpose: Define profiling support +// Description: +// +// Usage: +// #include <cyg/infra/profile.h> +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +// Enable profiling +extern void profile_on(void *start_addr, void *end_addr, + int bucket_size, int sample_resolution); + +// Callback used by timer routine +extern void profile_hit(unsigned long pc); + +// Timer setup routine, used when enabling profiling +extern void hal_enable_profile_timer(int resolution); + +#endif // CYGONCE_PROFILE_H
new file mode 100644 --- /dev/null +++ b/packages/services/profile/current/src/profile.c @@ -0,0 +1,242 @@ +//========================================================================== +// +// 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.h> + +#include <stdlib.h> +#include <cyg/infra/diag.h> +#include <network.h> +#include <tftp_support.h> +#include <cyg/infra/profile.h> +#include <cyg/infra/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 1 +static 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 int +profile_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 int +profile_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 int +profile_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; + } + 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(0, &profile_fileops); +}
