initial-freebsd-port-work-20010414
[openafs.git] / src / lwp / preempt.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #ifndef lint
11 #endif
12 /*******************************************************************\
13 *                                                                   *
14 *       Information Technology Center                               *
15 *       Carnegie-Mellon University                                  *
16 *                                                                   *
17 \*******************************************************************/
18 #include <afs/param.h>
19
20 #if defined(AFS_LINUX20_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
21 int PRE_Block = 0;
22 #else
23 #include <sys/time.h>
24 #include <signal.h>
25 #include <ucontext.h>
26 #include "lwp.h"
27 #include "preempt.h"
28
29 #if defined(AFS_OSF_ENV) || defined(AFS_S390_LINUX20_ENV)
30 int PRE_Block = 0;              /* used in lwp.c and process.s */
31 #else
32 char PRE_Block = 0;             /* used in lwp.c and process.s */
33 #endif
34
35 static void AlarmHandler(sig, st, scp)
36     int sig;
37     siginfo_t *st;
38     ucontext_t *scp;
39     {
40     if (PRE_Block == 0 && lwp_cpptr->level == 0)
41         {
42         PRE_BeginCritical();
43         sigprocmask(SIG_SETMASK, &scp->uc_sigmask, NULL);
44         LWP_DispatchProcess();
45         PRE_EndCritical();
46         }
47     
48     }
49
50 int PRE_InitPreempt(slice)
51     struct timeval *slice;
52     {
53     struct itimerval itv;
54     struct sigaction action;
55
56     if (lwp_cpptr == 0) return (LWP_EINIT);
57     
58     if (slice == 0)
59         {
60         itv.it_interval.tv_sec = itv.it_value.tv_sec = DEFAULTSLICE;
61         itv.it_interval.tv_usec = itv.it_value.tv_usec = 0;
62         }
63     else
64         {
65         itv.it_interval = itv.it_value = *slice;
66         }
67
68     bzero((char *)&action, sizeof(action));
69     action.sa_sigaction = AlarmHandler;
70     action.sa_flags = SA_SIGINFO;
71
72     if ((sigaction(SIGALRM, &action, (struct sigaction *)0) == -1) ||
73         (setitimer(ITIMER_REAL, &itv, (struct itimerval *) 0) == -1))
74         return(LWP_ESYSTEM);
75
76     return(LWP_SUCCESS);
77     }
78
79 int PRE_EndPreempt()
80     {
81     struct itimerval itv;
82     struct sigaction action;
83
84     if (lwp_cpptr == 0) return (LWP_EINIT);
85     
86     itv.it_value.tv_sec = itv.it_value.tv_usec = 0;
87
88     bzero((char *)&action, sizeof(action));
89     action.sa_handler = SIG_DFL;
90
91     if ((setitimer(ITIMER_REAL, &itv, (struct itimerval *) 0) == -1) ||
92         (sigaction(SIGALRM, &action, (struct sigaction *)0) == -1))
93         return(LWP_ESYSTEM);
94
95     return(LWP_SUCCESS);
96     }
97
98 #endif /* AFS_LINUX20_ENV */