Michael Kolesov
|
InterruptAttach and InterruptWait source
|
Michael Kolesov
12/25/2009 1:20 PM
post44414
|
InterruptAttach and InterruptWait source
Hello,
I cannot find source code of InterruptAttach and InterruptWait functions. Is it available?
Regards,
Mike
|
|
|
Thomas Haupt
|
Re: InterruptAttach and InterruptWait source
|
Thomas Haupt
12/25/2009 4:57 PM
post44415
|
Re: InterruptAttach and InterruptWait source
Hi,
InterruptAttach and InterruptWait are kernel calls. The definition for these two can be found in /lib/c/kercalls/
mkkercalls , lines 141 and 144, respectively. The 'source' code (or rather, the code-generation code) is mainly to be
found in the file
$(CPU)/template
Regards,
- Thomas
|
|
|
Michael Kolesov
|
Re: InterruptAttach and InterruptWait source
|
Michael Kolesov
12/26/2009 5:27 AM
post44416
|
Re: InterruptAttach and InterruptWait source
Thank you Thomas!
Regards,
Mike
|
|
|
Neil Schellenberger(deleted)
|
Re: InterruptAttach and InterruptWait source
|
Neil Schellenberger(deleted)
12/28/2009 11:18 AM
post44423
|
Re: InterruptAttach and InterruptWait source
On Fri, 2009-12-25 at 16:57 -0500, Thomas Haupt wrote:
> InterruptAttach and InterruptWait are kernel calls. The definition for
> these two can be found in /lib/c/kercalls/mkkercalls , lines 141 and
> 144, respectively. The 'source' code (or rather, the code-generation
> code) is mainly to be found in the file
> $(CPU)/template
As you may already have worked out from Thomas' good advice, the "real"
implementation for these kernel calls is found in
services/system/ker/ker_interrupt.c (ker_interrupt_attach() and
ker_interrupt_wait() respectively).
Regards,
Neil
|
|
|
Michael Kolesov
|
Re: InterruptAttach and InterruptWait source
|
Michael Kolesov
12/29/2009 2:57 AM
post44430
|
Re: InterruptAttach and InterruptWait source
Thanks, Neil.
I've asked because I prefer to do "printf" (or step by gdb) in ISR of driver code. Tracing is not so convenient for me.
Today I use simple emulation of InterruptAttach call via code with InterruptWait and InterruptAttachEvent in separate
thread. But I need to include this implementation of "my InterruptAttach" every time in my driver while debugging. So I
thought to include it in my own "isr_debug_enabled" version of libc to have no changes in original code of a driver.
Now I see it is not so easy as I thought :).. Another way I see to put lib with my code before libc.so during build
process.. I had not check if it could work..
Regards,
Mike
|
|
|
Neil Schellenberger(deleted)
|
Re: InterruptAttach and InterruptWait source
|
Neil Schellenberger(deleted)
12/29/2009 11:33 AM
post44439
|
Re: InterruptAttach and InterruptWait source
You may be able to use LD_PRELOAD to arrange to load your debugging
version first, but it may depend on exactly what your code needs to do.
|
|
|
Thomas Haupt
|
Re: InterruptAttach and InterruptWait source
|
Thomas Haupt
12/29/2009 1:51 PM
post44441
|
Re: InterruptAttach and InterruptWait source
I was tempted to suggest LD_PRELOAD as well, it would work well for overloading selected libc functions.
Problem is that your own implementation of InterruptAttach() would want to do an InterruptAttachEvent() - and that in
turn uses InterruptAttach() with a NULL handler function and a sigevent for the data.
So to not end up in an infinite recursion, you'd need to call the 'real' InterruptAttach() when the <handler> argument
is NULL -- but how could you do that?
Of course, you could integrate appropriate kernel calls for all platforms into your lib - then you could use it by mere
dynamic preloading.
If don't want to go that way, you could still 'wrap' the InterruptAttach() function at link time; look at ld's '--wrap'
option.
You'd call your own function __wrap_InterruptAttach() and could (from within that) still call __real_InterruptAttach()
to do the work. At build time, you'd have to feed '-Wl,--wrap InterruptAttach' to qcc. Of course, that would at least
require a relink.
- Thomas
|
|
|
Neil Schellenberger(deleted)
|
Re: InterruptAttach and InterruptWait source
|
Neil Schellenberger(deleted)
12/29/2009 5:42 PM
post44445
|
Re: InterruptAttach and InterruptWait source
Thomas makes some really excellent points, all of which are viable.
Depending on exactly what you're doing, you may be able to get away with
an LD_PRELOAD coupled with a dlopen()/dlsym() redirect to the real
InterruptAttach() - but as Thomas points out, it is probably simpler to
just code the kernel call directly :-)
Since you have access to the object code, the -Wl,--wrap= option would
probably be simplest. And, with a little sleight-of-hand, it could be
made to work both without needing to relink: put __real_foo() in a
shared library and either manually swap libraries or use LD_PRELOAD to
switch them. (Depending on exactly what else you're wrapping, if
anything, you may need to statically link some bits of libc, though, so
that they also redirect through the wrapped function.)
Regards,
Neil
|
|
|
Michael Kolesov
|
Re: InterruptAttach and InterruptWait source
|
Michael Kolesov
12/30/2009 3:48 AM
post44452
|
Re: InterruptAttach and InterruptWait source
Oh.. I have not thought about infinite loop.. It could be a bug :) Thanks.
Direct kernel call rewriting sounds good but I am not sure how to design it in my case.. at this moment..
'--wrap' option is interesting too. I will try both.
Since "debug" part of driver code is my own research and it's not in release code I don't think any license could be
disturb if I publish "debug" one.
//--------------------------------------------------------------------------------------------------
// To init interrupt I use following code:
pub.isr_handler = can_intr;
pub.isr_area = devinfo;
ccan_isr_wrapper();
// ..instead of
devinfo->iidsys = InterruptAttach( pub.irq, can_intr, devinfo, 0, 0);
if(devinfo->iidsys == -1)
{
perror("InterruptAttach irqsys");
exit(EXIT_FAILURE);
}
// "pub" and "spec" are just shared global structures
// Below you could see how wrapper works
/*
* Service InterruptAttach ISR in InterrruptAttachEvent wrapper
* This is for debugging purpose. You can debug your ISR step by step
* and after that put it to InterruptAttach for speed or let it stands
* as is. You must set following settings before:
* pub.irq
* pub.isr_handler
* pub.isr_area
*/
int ccan_isr_wrapper( void )
{
pthread_attr_t attr;
int rez = 0;
// Create thread for ISR
pthread_attr_init( &attr );
pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );
rez = pthread_create( &spec.isr_tid, &attr, &ccan_isr_thread, NULL );
return rez; // see errno for detail
}
/*
* Separate thread for ISR handling
*/
void* ccan_isr_thread( void * arg )
{
struct sigevent si, *rsi;
SIGEV_INTR_INIT( &si );
InterruptAttachEvent( pub.irq, &si, 0 );
spec.isr_run = 1;
while( spec.isr_run )
{
InterruptWait( 0, NULL );
rsi = (*pub.isr_handler)( pub.isr_area, spec.iid );
if( rsi != NULL )
{
if( SIGEV_GET_TYPE( rsi ) == SIGEV_PULSE)
{
MsgSendPulse( rsi->sigev_coid, rsi->sigev_priority, rsi->sigev_code, rsi->sigev_value.sival_int );
}
}
InterruptUnmask( pub.irq, spec.iid );
}
InterruptDetach( spec.iid );
return NULL;
}
//--------------------------------------------------------------------------------------------------
Regards,
Mike
|
|
|
Michael Kolesov
|
Re: InterruptAttach and InterruptWait source
|
Michael Kolesov
12/30/2009 4:37 AM
post44453
|
Re: InterruptAttach and InterruptWait source
Oh.. I have not thought about infinite loop.. It could be a bug :)
Thanks.
Direct kernel call rewriting sounds good but I am sure how to design
it in my way.. at this moment..
Wrap option is interesting too. I will try to look at both.
Since "debug" part of driver code is my own research and it's not in
release code I don't think any license could be disturb if I publish
"debug" one.
//--------------------------------------------------------------------------------------------------
// To init interrupt I use following code:
pub.isr_handler = can_intr;
pub.isr_area = devinfo;
ccan_isr_wrapper();
// ..instead of
devinfo->iidsys = InterruptAttach( pub.irq, can_intr, devinfo, 0, 0);
if(devinfo->iidsys == -1)
{
perror("InterruptAttach irqsys");
exit(EXIT_FAILURE);
}
// "pub" and "spec" are just shared global structures
// Below you could see how wrapper works
/*
* Service InterruptAttach ISR in InterrruptAttachEvent wrapper
* This for debugging purpose. You can debug your ISR step by step
* and after that put it to InterruptAttach for speed or let it stands
* as is. You must set following settings before:
* pub.irq
* pub.isr_handler
* pub.isr_area
*/
int ccan_isr_wrapper( void )
{
pthread_attr_t attr;
int rez = 0;
// Create thread for ISR
pthread_attr_init( &attr );
pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );
rez = pthread_create( &spec.isr_tid, &attr, &ccan_isr_thread, NULL );
return rez; // see errno for detail
}
/*
* Separate thread for ISR handling
*/
void* ccan_isr_thread( void * arg )
{
struct sigevent si, *rsi;
SIGEV_INTR_INIT( &si );
InterruptAttachEvent( pub.irq, &si, 0 );
spec.isr_run = 1;
while( spec.isr_run )
{
InterruptWait( 0, NULL );
rsi = (*pub.isr_handler)( pub.isr_area, spec.iid );
if( rsi != NULL )
{
if( SIGEV_GET_TYPE( rsi ) == SIGEV_PULSE)
{
MsgSendPulse( rsi->sigev_coid, rsi->sigev_priority, rsi-
>sigev_code, rsi->sigev_value.sival_int );
}
}
InterruptUnmask( pub.irq, spec.iid );
}
InterruptDetach( spec.iid );
return NULL;
}
//--------------------------------------------------------------------------------------------------
Regards,
Mike
|
|
|
Thomas Haupt
|
Re: InterruptAttach and InterruptWait source
|
Thomas Haupt
12/30/2009 12:37 PM
post44460
|
Re: InterruptAttach and InterruptWait source
Hi Mike,
as Neil so nicely pointed out, you might be able to get the original address off InterruptAttach using dlopen() and
dlsym() . I tried that, and it seems to work fine -- see code snippet below. You'd have to add your own flesh to these
bones; also, I'd consider using pulses instead of INTR events; that way, you could carry back information about which
interrupt had fired.
The solution shown below can be put into a shared lib and preloaded using LD_PRELOAD - this way, you wouldn't even have
to relink your applications.
Regards,
- Thomas
-----------------------------------------------------------------------------------------
#include <stdio.h>
#include <errno.h>
#include <dlfcn.h>
#include <sys/neutrino.h>
int InterruptAttach( int intr, const struct sigevent *(* handler)(void *, int),
const void * area, int size, unsigned flags ) {
static int (*ia)( int intr, const struct sigevent *(* handler)(void *, int),
const void * area, int size, unsigned flags );
static void *hdl;
static int inhere;
int res = 0;
if ( NULL == ia ) {
if ( NULL == ( hdl = dlopen( "libc.so.3", RTLD_NOW | RTLD_GLOBAL ) ) )
return -1;
if ( NULL == ( ia = dlsym( hdl, "InterruptAttach" ) ) )
return -1;
}
/* ISR provided and not recursive? */
if ( handler && ! inhere ) {
inhere = 1; /* Inhibit recursion */
/* Do your stuff here */
errno = ENOSYS; /* This is while nothing's implemented */
res = -1;
inhere = 0; /* All recursion avoided */
return res;
}
return ia( intr, handler, area, size, flags );
}
|
|
|
|