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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [hal/] [synth/] [i386linux/] [current/] [src/] [profile.c] - Blame information for rev 834

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//=============================================================================
2
//
3
//      profile.c
4
//
5
//      Support for profiling on x86 synthetic target
6
//
7
//=============================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 2003, 2005 Free Software Foundation, Inc.                  
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      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//=============================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):    bartv
43
// Contributors: bartv
44
// Date:         2003-10-12
45
//
46
//####DESCRIPTIONEND####
47
//=============================================================================
48
 
49
#include <pkgconf/system.h>
50
#ifdef CYGPKG_PROFILE_GPROF
51
#include <pkgconf/hal_synth.h>
52
#include <pkgconf/hal_synth_i386.h>
53
#include <cyg/infra/cyg_type.h>
54
#include <cyg/infra/cyg_ass.h>
55
#include <cyg/hal/hal_io.h>
56
#include <cyg/hal/hal_intr.h>
57
#include <cyg/profile/profile.h>
58
 
59
#if 1
60
// Profiling support.
61
//
62
// The profile timer uses the ITIMER_PROF, which means we get a SIGPROF
63
// signal at the desired rate. The signal handler can obtain the address
64
// of the interrupted code via a sigcontext structure. The contents of
65
// the sigcontext structure and exactly how it gets passed to the signal
66
// handler depends on the architecture, hence this code is x86-specific.
67
//
68
// The results of this profiling code seem a lot poorer than on other
69
// targets, but it is not clear why. There may be some subtle
70
// interaction between the system and profiling clocks.
71
static void
72
synth_prof_sighandler(int sig, struct cyg_hal_sys_sigcontext context)
73
{
74
    __profile_hit((CYG_ADDRWORD) context.hal_eip);
75
    CYG_UNUSED_PARAM(int, sig);
76
}
77
 
78
int
79
hal_enable_profile_timer(int resolution)
80
{
81
    struct cyg_hal_sys_sigaction    action;
82
    struct cyg_hal_sys_sigset_t     mask;
83
    struct cyg_hal_sys_itimerval    timer;
84
 
85
    // We want profiling to be an atomic operation. __profile_hit() is
86
    // a very simple function which should return quickly, and there
87
    // is no need for a DSR or context switching. Hence everything
88
    // including SIGIO and SIGALRM are blocked, effectively giving the
89
    // profiling timer the highest priority.
90
    action.hal_mask     = 0xffffffff;
91
    action.hal_flags    = CYG_HAL_SYS_SA_RESTORER;
92
    action.hal_handler  = (void (*)(int)) &synth_prof_sighandler;
93
    action.hal_restorer = &cyg_hal_sys_restore;
94
 
95
    if (0 != cyg_hal_sys_sigaction(CYG_HAL_SYS_SIGPROF, &action, (struct cyg_hal_sys_sigaction*) 0)) {
96
        CYG_FAIL("Failed to install signal handler for SIGPROF");
97
    }
98
 
99
    // The resolution is limited by the underlying 100Hz system clock,
100
    // there is no hardware timer which can generate faster clock
101
    // interrupts.
102
    if (resolution < 10000) {
103
        resolution = 10000;
104
    } else {
105
        resolution  = (resolution + 5000) / 10000;
106
        resolution *= 10000;
107
    }
108
    timer.hal_it_interval.hal_tv_sec    = 0;
109
    timer.hal_it_interval.hal_tv_usec   = resolution;
110
    timer.hal_it_value.hal_tv_sec       = 0;
111
    timer.hal_it_value.hal_tv_usec      = resolution;
112
    if (0 != cyg_hal_sys_setitimer(CYG_HAL_SYS_ITIMER_PROF, &timer, (struct cyg_hal_sys_itimerval*) 0)) {
113
        CYG_FAIL("Failed to initialize the profiling itimer");
114
    }
115
 
116
    // Now unblock SIGPROF
117
    CYG_HAL_SYS_SIGEMPTYSET(&mask);
118
    CYG_HAL_SYS_SIGADDSET(&mask, CYG_HAL_SYS_SIGPROF);
119
    if (0 != cyg_hal_sys_sigprocmask(CYG_HAL_SYS_SIG_UNBLOCK, &mask, (cyg_hal_sys_sigset_t*)0)) {
120
        CYG_FAIL("Failed to unblock SIGPROF");
121
    }
122
 
123
    return resolution;
124
}
125
 
126
#else
127
 
128
// An alternative implementation that overloads the SIGALRM handler
129
// rather than using SIGPROF. It does not seem to work any better.
130
static void (*synth_profile_old_alrm_sighandler)(int);
131
 
132
static void
133
synth_profile_alrm_sighandler(int sig, struct cyg_hal_sys_sigcontext context)
134
{
135
    __profile_hit((CYG_ADDRWORD) context.hal_eip);
136
    (*synth_profile_old_alrm_sighandler)(sig);
137
}
138
 
139
int
140
hal_enable_profile_timer(int resolution)
141
{
142
    struct cyg_hal_sys_sigaction    action;
143
 
144
    if (0 != cyg_hal_sys_sigaction(CYG_HAL_SYS_SIGALRM, (const struct cyg_hal_sys_sigaction*)0, &action)) {
145
        CYG_FAIL("Failed to retrieve old signal handler for SIGALRM");
146
    }
147
    synth_profile_old_alrm_sighandler   = action.hal_handler;
148
    action.hal_handler = (void (*)(int)) &synth_profile_alrm_sighandler;
149
    if (0 != cyg_hal_sys_sigaction(CYG_HAL_SYS_SIGALRM, &action, (struct cyg_hal_sys_sigaction*)0)) {
150
        CYG_FAIL("Failed to install new signal handler for SIGALRM");
151
    }
152
 
153
    return CYGNUM_HAL_RTC_PERIOD;
154
}
155
 
156
#endif
157
 
158
// mcount() can be implemented largely using compiler built-ins. However
159
// there are two complications. The generic profiling code assumes
160
// __profile_mcount() is called with interrupts disabled. Blocking interrupts
161
// won't stop the low-level signal handlers, so mcount() calls from those
162
// may get lost because of the nesting test but that is fairly harmless.
163
// Those signal handlers will complete before control returns here, i.e.
164
// we have strict nesting, so there is no risk of the nested flag remaining
165
// set while a context switch occurs.  Also if eCos itself is built with
166
// -pg then the compiler will insert a recursive call to mcount(), and
167
// we have to guard against that.
168
void
169
mcount(void)
170
{
171
    static int  nested = 0;
172
    int         enabled;
173
 
174
    HAL_DISABLE_INTERRUPTS(enabled);
175
    if (!nested) {
176
        nested = 1;
177
        __profile_mcount((CYG_ADDRWORD)__builtin_return_address(1),
178
                         (CYG_ADDRWORD)__builtin_return_address(0));
179
        nested = 0;
180
    }
181
    HAL_RESTORE_INTERRUPTS(enabled);
182
}
183
 
184
#endif

powered by: WebSVN 2.1.0

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