Interrupt Handler in C - HOW??

Alan J Peakall alan at earwax.OZ
Fri Mar 10 22:53:41 AEST 1989


In article <318 at h.cs.wvu.wvnet.edu>,
 dymm at b.cs.wvu.wvnet.edu (David Dymm) writes:
> 
> I would like to write an interrupt handling mechanism
> in 'C' to work in the following way:
> 
> 1) Set up the signal facility:
> 
> 	signal (SIGALRM, alarm_handler)
> 
> 2) Set the alarm:
> 
> 	ualarm (100000, 0)  <== This will send a signal after
> 				100,0000 microseconds.
> 
> 3) The interrupt handler "alarm_handler" is called with
>     the signal mechanism when the alarm timer times out.
>     Let's call "location A" the place where we were in
>     the code when we were interrupted by the timer.
> 
>     When "alarm_handler" has finished its local processing,
>     I do NOT want to return control back to where the
>     interrupt occurred!!!!
>     Instead, I want to "longjmp" to another function in the
>     program.  When that function has  completed its work,
>     I want to return to "location A".
> 
> 
> The question is:  How do I return to "location A" ???
> 
> I have looked at the "sigstack" mechanism, and also at
> the definitions for "sigcontext" and "sigstack" in "signal.h".
> But I do not see how to put this all together to accomplish
> my task.  The system saves the state of the process on the
> signal stack when "signal" causes control to jump to 
> "alarm_handler".  How do I get at that information AND more
> importantly, how do I use that information to accomplish
> my task.
> 
> Any ideas???

If you are on an architecture on which <int>s and <void *>s are freely
convertible and the usual implementation of <setjmp> obtains (ie jmp_buf
declared as

	#define	_JBLEN	10	/*  or some other number  */
	typedef	int	jmp_buf[_JBLEN];
)
the following should work:

/*  handler.c  --  immediate interrupt handler  */

#include <setjmp.h>

extern	jmp_buf	jmp_buf_in_other_function;

int alarm_handler(int signo)
{ static jmp_buf recover;
  int returnval;	/*  assumed non-zero  */

  /*  local processing  */ ;

  if (!(returnval = setjmp(recover)))
    longjmp(jmp_buf_in_other_function, (int) recover);
				/*  to auxiliary function	*/
  else return returnval;	/*  to location 'A"  		*/
}

/*  otherfunction.c  --  supplementary interrupt handling & whatever else  */

#include <setjmp.h>

jmp_buf	jmp_buf_in_other_function;

void other_function()
{ int *recover;		/*  when invoked abnormally holds recover point	*/
  int returnval;	/*  computed in this case - assumed non-zero	*/

  if (recover = (int *) setjmp(jmp_buf_in_other_function))
  { /*  further processing for interrupt  */
    longjmp(recover, returnval);
  }
  else
  { /*  usual processing  */
  }
}

this will be marginally less efficient than the use of <sigcontext> but
considerably more portable, as the latter is not machine independent even
within a given UNIX implementation let alone portable to all strains of
UNIX-like systems. The <setjmp> implementation on which the above solution
relies is more widely supported and even for those cases where the above does
not work exactly as given, it is more readable (and thus more easily
modifiable) than code that references details of the raw hardware itself.



More information about the Comp.unix.wizards mailing list