/* $Header: preempt.c,v 1.1 87/03/11 15:59:05 mikew Exp $ */
/* $Source: /afs/andrew.cmu.edu/usr7/kazar/afs/lwp/RCS/preempt.c,v $ */

#ifndef lint
static char *rcsid = "$Header: preempt.c,v 1.1 87/03/11 15:59:05 mikew Exp $";
#endif

/*
 * P_R_P_Q_# (C) COPYRIGHT IBM CORPORATION 1987
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */

/*******************************************************************\
* 								    *
* 	Information Technology Center				    *
* 	Carnegie-Mellon University				    *
* 								    *
* 	Bradley White and M. Satyanarayanan			    *
\*******************************************************************/

#include <sys/time.h>
#include <signal.h>
#include "lwp.h"
#include "preempt.h"

char PRE_Block = 0;		/* used in lwp.c and process.s */

static AlarmHandler(sig, code, scp)
    int sig, code;
    struct sigcontext *scp;
    {
    if (PRE_Block == 0 && lwp_cpptr->level == 0)
	{
	PRE_BeginCritical();
	sigsetmask(scp->sc_mask);
	LWP_DispatchProcess();
	PRE_EndCritical();
	}
    
    }

int PRE_InitPreempt(slice)
    struct timeval *slice;
    {
    struct itimerval itv;
    struct sigvec vec;

    if (lwp_cpptr == 0) return (LWP_EINIT);
    
    if (slice == 0)
	{
	itv.it_interval.tv_sec = itv.it_value.tv_sec = DEFAULTSLICE;
	itv.it_interval.tv_usec = itv.it_value.tv_usec = 0;
	}
    else
	{
	itv.it_interval = itv.it_value = *slice;
	}

    vec.sv_handler = AlarmHandler;
    vec.sv_mask = vec.sv_onstack = 0;

    if ((sigvec(SIGALRM, &vec, (struct sigvec *)0) == -1) ||
	(setitimer(ITIMER_REAL, &itv, (struct itimerval *) 0) == -1))
	return(LWP_ESYSTEM);

    return(LWP_SUCCESS);
    }

int PRE_EndPreempt()
    {
    struct itimerval itv;
    struct sigvec vec;

    if (lwp_cpptr == 0) return (LWP_EINIT);
    
    itv.it_value.tv_sec = itv.it_value.tv_usec = 0;

    vec.sv_handler = SIG_DFL;;
    vec.sv_mask = vec.sv_onstack = 0;

    if ((setitimer(ITIMER_REAL, &itv, (struct itimerval *) 0) == -1) ||
	(sigvec(SIGALRM, &vec, (struct sigvec *)0) == -1))
	return(LWP_ESYSTEM);

    return(LWP_SUCCESS);
    }
