OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [services/] [profile/] [gprof/] [v2_0/] [src/] [profile.c] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      profile.c
4
//
5
//      Application profiling support
6
//
7
//==========================================================================
8
//####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 2002 Gary Thomas
12
//
13
// eCos is free software; you can redistribute it and/or modify it under
14
// the terms of the GNU General Public License as published by the Free
15
// Software Foundation; either version 2 or (at your option) any later version.
16
//
17
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20
// for more details.
21
//
22
// You should have received a copy of the GNU General Public License along
23
// with eCos; if not, write to the Free Software Foundation, Inc.,
24
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25
//
26
// As a special exception, if other files instantiate templates or use macros
27
// or inline functions from this file, or you compile this file and link it
28
// with other works to produce a work based on this file, this file does not
29
// by itself cause the resulting work to be covered by the GNU General Public
30
// License. However the source code for this file must still be made available
31
// in accordance with section (3) of the GNU General Public License.
32
//
33
// This exception does not invalidate any other reasons why a work based on
34
// this file might be covered by the GNU General Public License.
35
//
36
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37
// at http://sources.redhat.com/ecos/ecos-license/
38
// -------------------------------------------
39
//####ECOSGPLCOPYRIGHTEND####
40
//==========================================================================
41
//#####DESCRIPTIONBEGIN####
42
//
43
// Author(s):    Gary Thomas
44
// Contributors: 
45
// Date:         2002-11-14
46
// Purpose:      Application profiling support
47
// Description:  
48
//
49
//####DESCRIPTIONEND####
50
//
51
//===========================================================================
52
#include <pkgconf/profile_gprof.h>
53
 
54
#include <stdlib.h>
55
#include <cyg/infra/diag.h>
56
#include <network.h>
57
#include <tftp_support.h>
58
#include <cyg/profile/profile.h>
59
#include <cyg/profile/gmon_out.h>
60
 
61
static int num_buckets;
62
static unsigned short *profile;
63
static int bucket_size, bucket_shift;
64
static unsigned long start_addr, end_addr;
65
static int enabled;
66
static int tftp_server_id;
67
static int prof_rate;
68
 
69
static int profile_open(const char *, int);
70
static int profile_close(int);
71
static int profile_write(int, const void *, int);
72
static int profile_read(int, void *, int);
73
 
74
struct tftpd_fileops profile_fileops = {
75
    profile_open, profile_close, profile_write, profile_read
76
};
77
 
78
struct _file {
79
    unsigned char      *pos, *eof, *data;
80
    int                 flags;
81
    int                 mode;
82
};
83
#define FILE_OPEN 0x0001
84
 
85
#define NUM_FILES 1
86
static struct _file files[NUM_FILES];
87
 
88
static inline struct _file *
89
profile_fp(int fd)
90
{
91
    struct _file *fp;
92
    if ((fd < 0) || (fd >= NUM_FILES)) return (struct _file *)0;
93
    fp = &files[fd];
94
    if (!(fp->flags & FILE_OPEN)) return (struct _file *)0;
95
    return fp;
96
}
97
 
98
static int
99
profile_open(const char *fn, int flags)
100
{
101
    int fd = 0;
102
    struct _file *fp;
103
    int len = sizeof(struct gmon_hdr) + sizeof(struct gmon_hist_hdr) + (num_buckets*2) + 1;
104
    struct gmon_hdr _hdr;
105
    struct gmon_hist_hdr _hist_hdr;
106
    unsigned char *bp;
107
    int version = GMON_VERSION;
108
    int hist_size = num_buckets;
109
    int file_type = -1;
110
 
111
    fp = files;
112
    if (fp->flags & FILE_OPEN) {
113
        // File already open
114
        return -1;
115
    }
116
    if (!(flags & O_RDONLY)) {
117
        // Only read supported
118
        return -1;
119
    }
120
    if (strcmp(fn, "PROFILE.DAT") == 0) {
121
        file_type = 0;
122
    }
123
    if (file_type < 0) {
124
        // No supported file
125
        return -1;
126
    }
127
    // Set up file info
128
    enabled = 0;
129
    switch (file_type) { // In case another type ever supported
130
    case 0: // profile data
131
        fp->data = malloc(len);
132
        if (!fp->data) {
133
            diag_printf("Can't allocate buffer for profile data!\n");
134
            return -1;
135
        }
136
        fp->flags = FILE_OPEN;
137
        fp->mode = flags;
138
        fp->pos = fp->data;
139
        fp->eof = fp->pos + len;
140
        // Fill in profile data
141
        bp = fp->data;
142
        memset(&_hdr, 0, sizeof(_hdr));
143
        strcpy(_hdr.cookie, GMON_MAGIC);
144
        memcpy(_hdr.version, &version, sizeof(version));
145
        memcpy(bp, &_hdr, sizeof(_hdr));
146
        bp += sizeof(_hdr);
147
        memcpy(&_hist_hdr.low_pc, &start_addr, sizeof(start_addr));
148
        memcpy(&_hist_hdr.high_pc, &end_addr, sizeof(end_addr));
149
        memcpy(&_hist_hdr.hist_size, &hist_size, sizeof(hist_size));
150
        memcpy(&_hist_hdr.prof_rate, &prof_rate, sizeof(prof_rate));
151
        strcpy(_hist_hdr.dimen, "seconds");
152
        _hist_hdr.dimen_abbrev = 's';
153
        *bp++ = GMON_TAG_TIME_HIST;
154
        memcpy(bp, &_hist_hdr, sizeof(_hist_hdr));
155
        bp += sizeof(_hist_hdr);
156
        memcpy(bp, profile, (num_buckets*2));
157
        memset(profile, 0, (num_buckets*2));
158
        break;
159
    }
160
    return fd;
161
}
162
 
163
static int
164
profile_close(int fd)
165
{
166
    struct _file *fp = profile_fp(fd);
167
    if (!fp) return -1;
168
    if (fp->data) free(fp->data);
169
    fp->flags = 0;  // No longer open
170
    enabled = 1;
171
    return 0;
172
}
173
 
174
static int
175
profile_write(int fd, const void *buf, int len)
176
{
177
    return -1;
178
}
179
 
180
static int
181
profile_read(int fd, void *buf, int len)
182
{
183
    struct _file *fp = profile_fp(fd);
184
    int res;
185
    if (!fp) return -1;
186
    res = fp->eof - fp->pos;  // Number of bytes left in "file"
187
    if (res > len) res = len;
188
    if (res <= 0) return 0;  // End of file
189
    bcopy(fp->pos, buf, res);
190
    fp->pos += res;
191
    return res;
192
}
193
 
194
void
195
__profile_hit(unsigned long pc)
196
{
197
    int bucket;
198
    if (enabled) {
199
        if ((pc >= start_addr) && (pc <= end_addr)) {
200
            bucket = (pc - start_addr) >> bucket_shift;
201
            if (profile[bucket] < (unsigned short)0xFFFF) {
202
                profile[bucket]++;
203
            }
204
        }
205
    }
206
}
207
 
208
void
209
profile_on(void *_start, void *_end, int _bucket_size, int resolution)
210
{
211
    start_addr = (unsigned long)_start;
212
    end_addr = (unsigned long)_end;
213
    // Adjust bucket size to be a power of 2
214
    bucket_size = 1;
215
    bucket_shift = 0;
216
    while (bucket_size < _bucket_size) {
217
        bucket_size <<= 1;
218
        bucket_shift++;
219
    }
220
    if (bucket_size != _bucket_size) {
221
        bucket_size <<= 1;
222
        bucket_shift++;
223
    }
224
    // Calculate number of buckets
225
    num_buckets = ((end_addr - start_addr) + (bucket_size - 1)) / bucket_size;
226
    // Adjust end address so calculations come out
227
    end_addr = start_addr + (bucket_size * num_buckets);
228
    prof_rate = 1000000 / resolution;
229
    // Allocate buffer for profile data
230
    if (!(profile = malloc(num_buckets*2))) {
231
        diag_printf("Can't allocate profile buffer - ignored\n");
232
        return;
233
    }
234
    enabled = 1;
235
    diag_printf("Profile from %p..%p[%p], in %d buckets of size %d\n",
236
                start_addr, end_addr, _end, num_buckets, bucket_size);
237
 
238
    hal_enable_profile_timer(resolution);
239
 
240
    // Create a TFTP server to provide the data
241
    tftp_server_id = tftpd_start(CYGNUM_PROFILE_TFTP_PORT, &profile_fileops);
242
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.