Main Page | Namespace List | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

timeslice.c

Go to the documentation of this file.
00001 /*!
00002  * @file timeslice.c
00003  *
00004  * @brief JVM one millisecond time slice timer.
00005  *
00006  * The @link rjvm.timeslice_expired pjvm->timeslice_expired@endlink
00007  * flag is set by the periodic @b SIGALRM herein and tested in the JVM
00008  * virtual instruction inner loop to decide when a thread has finished
00009  * using its time slice.
00010  *
00011  * @verbatim
00012    function              flag value             meaning
00013    --------              ----------             -------
00014   
00015    timeslice_init()      set rfalse             initial value
00016   
00017    timeslice_tick()      set rtrue              time slice finished
00018   
00019    jvm_run()             rfalse                 keep running this slice
00020                          rtrue                  time slice finished
00021    @endverbatim
00022  *
00023  *
00024  * @section Control
00025  *
00026  * \$URL: https://svn.apache.org/path/name/timeslice.c $ \$Id: timeslice.c 0 09/28/2005 dlydick $
00027  *
00028  * Copyright 2005 The Apache Software Foundation
00029  * or its licensors, as applicable.
00030  *
00031  * Licensed under the Apache License, Version 2.0 ("the License");
00032  * you may not use this file except in compliance with the License.
00033  * You may obtain a copy of the License at
00034  *
00035  *     http://www.apache.org/licenses/LICENSE-2.0
00036  *
00037  * Unless required by applicable law or agreed to in writing,
00038  * software distributed under the License is distributed on an
00039  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
00040  * either express or implied.
00041  *
00042  * See the License for the specific language governing permissions
00043  * and limitations under the License.
00044  *
00045  * @version \$LastChangedRevision: 0 $
00046  *
00047  * @date \$LastChangedDate: 09/28/2005 $
00048  *
00049  * @author \$LastChangedBy: dlydick $
00050  *         Original code contributed by Daniel Lydick on 09/28/2005.
00051  *
00052  * @section Reference
00053  *
00054  */
00055 
00056 #include "arch.h"
00057 ARCH_COPYRIGHT_APACHE(timeslice, c, "$URL: https://svn.apache.org/path/name/timeslice.c $ $Id: timeslice.c 0 09/28/2005 dlydick $");
00058 
00059 
00060 #include <unistd.h>
00061 #include <signal.h>
00062 
00063 #define _REENTRANT
00064 #include <pthread.h>
00065 #include <thread.h> /* WATCH OUT!  /usr/include, not application .h */
00066 
00067 #include "jvmcfg.h"
00068 #include "classfile.h"
00069 #include "jvm.h"
00070 #include "exit.h" 
00071 #include "util.h"
00072 
00073 
00074 /*!
00075  * @brief Thread control structure for use by
00076  * @c @b pthread_create(3), etc.
00077  */
00078 static pthread_t posix_thread_id;
00079 
00080 /*!
00081  * @brief Start the time slicing mechanism at JVM init time
00082  *
00083  *
00084  * @b Parameters: @link #rvoid rvoid@endlink
00085  *
00086  *
00087  *       @returns @link #rvoid rvoid@endlink
00088  *
00089  */
00090 rvoid timeslice_init()
00091 {
00092     /* Time slice has not expired */
00093     pjvm->timeslice_expired = rfalse;
00094 
00095     /*
00096      * Initialize the @link rthread#sleeptim rthread.sleeptime@endlink
00097      * lock w/ defult attributes
00098      */
00099     pthread_mutex_init(&pjvm->sleeplock, (void *) rnull);
00100 
00101     int rc = pthread_create(&posix_thread_id,
00102                             (void *) rnull,
00103                             timeslice_run,
00104                             (void *) rnull);
00105 
00106     if (0 != rc)
00107     {
00108         sysErrMsg("timeslice_init", "Cannot start timer");
00109         exit_jvm(EXIT_TIMESLICE_START);
00110 /*NOTREACHED*/
00111     }
00112 
00113     /* Declare this module initialized */
00114     jvm_timeslice_initialized = rtrue;
00115 
00116     return;
00117 
00118 } /* END of timeslice_init() */
00119 
00120 
00121 /*!
00122  * @brief Retrieve a thread's @link rthread#sleeptime sleeptime@endlink
00123  * value @e safely during read of that variable on a given thread.
00124  *
00125  *
00126  * @param  thridx   Thread index of thread to read its 
00127  *                  @link rthread#sleeptime sleeptime@endlink
00128  *                  value
00129  *
00130  *
00131  * @returns remaining sleep time, in timer ticks
00132  *
00133  */
00134 jlong timeslice_get_thread_sleeptime(jvm_thread_index thridx)
00135 {
00136     jlong rc;
00137 
00138     /* Lock out the @e world while retrieving any thread's sleep time */
00139     pthread_mutex_lock(&pjvm->sleeplock);
00140 
00141     rc = THREAD(thridx).sleeptime;
00142 
00143     /* Unlock the @e world after sleep time retrieved */
00144     pthread_mutex_unlock(&pjvm->sleeplock);
00145 
00146     /* Report sleep time value */
00147     return(rc);
00148 
00149 } /* END of timeslice_get_thread_sleeptime() */
00150 
00151 
00152 /*!
00153  * @brief Length of time slice interval as used by
00154  * @c @b setitimer(2).
00155  */
00156 static struct itimerval timeslice_period;
00157 
00158 
00159 /*!
00160  * @brief Interval timer handler for the @b signal(SIGALRM) event.
00161  *
00162  *
00163  * @b Parameters: @link #rvoid rvoid@endlink
00164  *
00165  *
00166  *       @returns @link #rvoid rvoid@endlink
00167  *
00168  *
00169  * @warning Eclipse users need to remember that setting a combination
00170  *          of the value of @link #JVMCFG_TIMESLICE_PERIOD_ENABLE
00171             JVMCFG_TIMESLICE_PERIOD_ENABLE@endlink
00172  *          to @link #rtrue rtrue@endlink, the value
00173  *          of @link #JVMCFG_TIMESLICE_PERIOD_SECONDS
00174             JVMCFG_TIMESLICE_PERIOD_SECONDS@endlink to zero (0), and
00175  *          the value of @link #JVMCFG_TIMESLICE_PERIOD_MICROSECONDS
00176             JVMCFG_TIMESLICE_PERIOD_MICROSECONDS@endlink to a low
00177  *          milliseconds value is @e certain to interfere with the
00178  *          proper operation of the GDB debug process due to the high
00179  *          frequency of thread context changes per second.
00180  *          The debug session @b will terminate without rhyme nor
00181  *          reason.  Setting the period to several seconds will
00182  *          elminate this problem at the expense of time slicing
00183  *          on a normal basis.  For unit testing, this is not a
00184  *          problem.  For integration testing, you are on your own....
00185  *
00186  */
00187 
00188 static void timeslice_tick(/* void --GCC won't allow this declaration*/)
00189 {
00190     /* Suppress SIGALRM until finished with this handler */
00191     signal(SIGALRM, SIG_IGN);
00192 
00193     /* Debug report of timer.  Use ONLY for SLOW INTERVALS! */
00194     if (JVMCFG_TIMESLICE_DEBUG_REPORT_MIN_SECONDS != 0) /* 0:= disable*/
00195     {
00196         if (JVMCFG_TIMESLICE_DEBUG_REPORT_MIN_SECONDS <=
00197             timeslice_period.it_interval.tv_sec)
00198         {
00199             sysDbgMsg(DML9, "timeslice_tick", "tick");
00200         }
00201     }
00202 
00203     /*
00204      * Process signal by telling JVM to go to next time slice.
00205      * Also decrement sleep interval timers for sleeping, joining,
00206      * and waiting threads.
00207      */
00208     pjvm->timeslice_expired = rtrue;
00209     threadutil_update_sleeptime_interval();
00210 
00211     /* Set next SIGALARM for next tick of the time slice timer */
00212     signal(SIGALRM, timeslice_tick);
00213 
00214 } /* END of timeslice_tick() */
00215 
00216 
00217 /*!
00218  * @brief Interval timer thread.
00219  *
00220  *
00221  * @param  dummy The @c @b setitimer(2) system call requires
00222  *               a <b><code>(void *)</code></b> that has no
00223  *               meaning here.
00224  *
00225  *
00226  * @returns The required <b><code>(void *)</code></b> is passed back,
00227  *          but this function never returns until the time slice
00228  *          thread is killed.
00229  *
00230  */
00231 void *timeslice_run(void *dummy)
00232 {
00233     /* Start timer and make its first tick one period from now */
00234     timeslice_period.it_interval.tv_sec =
00235                                         JVMCFG_TIMESLICE_PERIOD_SECONDS;
00236     timeslice_period.it_interval.tv_usec =
00237                                    JVMCFG_TIMESLICE_PERIOD_MICROSECONDS;
00238     timeslice_period.it_value.tv_sec =
00239                                         JVMCFG_TIMESLICE_PERIOD_SECONDS;
00240     timeslice_period.it_value.tv_usec =
00241                                    JVMCFG_TIMESLICE_PERIOD_MICROSECONDS;
00242 
00243     /* If timer is configured to run, get it going */
00244     if (rtrue == JVMCFG_TIMESLICE_PERIOD_ENABLE)
00245     {
00246 
00247         /*
00248          * Set initial SIGALARM for timer_tick(),
00249          * arm timer to generate it.
00250          */
00251         signal(SIGALRM, timeslice_tick);
00252 
00253         int rc = setitimer(ITIMER_REAL,
00254                            &timeslice_period,
00255                            (void *) rnull);
00256 
00257         if (0 != rc)
00258         {
00259             sysErrMsg("timeslice_run", "Cannot start interval timer");
00260             exit_jvm(EXIT_TIMESLICE_START);
00261 /*NOTREACHED*/
00262         }
00263     }
00264 
00265     /*
00266      * Do nothing except wait on timer ticks.
00267      * Eventually, the main process exits and
00268      * this thread will die along with it without
00269      * ever having left the while() loop.
00270      *
00271      * If timer is not configured to run, this loop
00272      * will never see SIGALRM and timer ticks.
00273      */
00274 
00275     while(rtrue)
00276     {
00277         yield();
00278     }
00279 
00280 /*NOTREACHED*/
00281     return((void *) rnull);
00282 
00283 } /* END of timeslice_run() */
00284 
00285 
00286 /*!
00287  * @brief Shut down the time slicing mechanism for JVM shutdown.
00288  *
00289  *
00290  * @b Parameters: @link #rvoid rvoid@endlink
00291  *
00292  *
00293  *       @returns @link #rvoid rvoid@endlink
00294  *
00295  */
00296 rvoid timeslice_shutdown(rvoid)
00297 {
00298     /* Suppress SIGALRM so future tick does not happen AT ALL */
00299     signal(SIGALRM, SIG_IGN);
00300 
00301     /* Ignore error */
00302     pthread_cancel(posix_thread_id);
00303 
00304     /*! @todo Is this necessary at JVM shutdown time? */
00305     /* pthread_mutex_destroy(&pjvm->sleeplock); */
00306 
00307     /* Declare this module uninitialized */
00308     jvm_timeslice_initialized = rfalse;
00309 
00310     return;
00311 
00312 } /* END of timeslice_shutdown() */
00313 
00314 
00315 /* EOF */
00316 

Generated on Fri Sep 30 18:59:35 2005 by  doxygen 1.4.4